mirror of
https://github.com/libretro/Genesis-Plus-GX-Wide.git
synced 2024-11-23 16:29:49 +00:00
[Core]
------ * improved 68k accuracy (initial reset timing + auto-vectored interrupts handling). * modified Z80 & 68k cores to directly use external cycle count instead of intermediate counters. * improved Z80 & 68k cpu execution/synchronization accuracy, now use Master Clock as common clock reference. * improved PSG & FM chips synchronization with CPU execution (fixed point precision). * completely rewrote sound output processing & mixing: sound chips are now clocked with exact output frame rate to ensure 100% smooth video & audio playback, with no lag or skipping, while still rendering an accurate number of samples per frame. This will also make fast-forward implementation (video AND sound) more trivial. * improved color accuracy in VDP highlight mode to match results observed on real hardware. * improved sprites processing timing accuracy: fixes (un)masked sprites in Mickey Mania (3D level), Sonic 2 (VS mode). * improved horizontal blanking & HINT/VINT occurrence timing accuracy, as measured on real hardware. * improved H-Counter accuracy in 40-cell mode, as measured on real hardware. * optimized Z80 bus status signals * usual code cleanup [GCN/WII] --------- fixed ASNDLIB exit when returning to game fixed audio/video startup sync modified audio back-end engine according to new audio processing core (see above)
This commit is contained in:
parent
ac4de61944
commit
2b78421402
40
HISTORY.txt
40
HISTORY.txt
@ -8,32 +8,56 @@ Genesis Plus GX 1.4.0 (??/??/????) (Eke-Eke)
|
||||
* modified SN76489 cut-off frequency
|
||||
* added an option to boost SN76489 Noise Channel
|
||||
* removed outdated Gens YM2612 core
|
||||
* improved YM2612 core general accuracy (SSG-EG, CSM mode,...) (based upon Nemesis recent tests on real MD)
|
||||
* improved YM2612 core general accuracy (SSG-EG, CSM mode,...) (based upon Nemesis recent tests on real hardware)
|
||||
* improved YM2612 LFO emulation accuracy (fixes "Spider-Man & Venom : Separation Anxiety" intro music)
|
||||
* fixed YM2612 context saving/loading.
|
||||
* added 3-Band EQ for fully configurable sound filtering (thanks to Neil C)
|
||||
* implemented faster FIR resampler, dropped libsamplerate support (thanks to Blargg & AamirM)
|
||||
* improved VDP sprite masking emulation: fixes 3D level in Mickey Mania (thanks to Nemesis for his sprite test program)
|
||||
|
||||
* improved VDP sprite masking accuracy (thanks to Nemesis for his sprite test program)
|
||||
* improved HBLANK flag timing accuracy: fixes Mega Turrican (Sky level)
|
||||
* added support for CRAM writes during horizontal blanking.
|
||||
* fixed 2-Cell vertical scrolling when column 0 is shifted.
|
||||
* added support for 2-Cell vertical scrolling in Interlaced 2 mode.
|
||||
* fixed lightgun auto detection: fixes cursor position in Lethal Enforcers II
|
||||
* improved DIVU/DVIS (thanks to Jorge Cwik) & MULU/MULS 68000 instructions timing accuracy
|
||||
|
||||
* improved DIVU/DVIS (thanks to Jorge Cwik) & MULU/MULS 68k instructions timing accuracy
|
||||
* updated Z80 core to last version (fixes interrupt Mode 0 timing and some BIT instructions)
|
||||
* fixed some Z80 instructions timing
|
||||
|
||||
* fixed Backup Memory support in some games using serial EEPROM
|
||||
* fixed Realtec mapper support: fix sound in Balloon Boy / Funny World
|
||||
* added Game Genie hardware emulation (Game Genie ROM is now fully supported, see README for more details)
|
||||
* added Action Replay hardware emulation (Action replay ROM is now fully supported, see README for more details)
|
||||
* added S&K "Lock-On" hardware emulation ("lock" any games to Sonic & Knuckles)
|
||||
* added Cartridge "hot swap" feature (swap games without reseting the virtual console)
|
||||
* various code cleanup & core optimizations
|
||||
|
||||
* lots of code cleanup & optimization
|
||||
|
||||
|
||||
* improved 68k accuracy (initial reset timing + auto-vectored interrupts handling).
|
||||
* modified Z80 & 68k cores to directly use external cycle count instead of intermediate counters.
|
||||
* improved Z80 & 68k cpu execution/synchronization accuracy, now use Master Clock as common clock reference.
|
||||
* improved PSG & FM chips synchronization with CPU execution (fixed point precision).
|
||||
|
||||
* completely rewrote sound output processing & mixing: sound chips are now clocked with exact output framerate
|
||||
to ensure 100% smooth video & audio playback, with no lag or skipping, while still rendering an accurate number
|
||||
of samples per frame. This would also make fast-forward implementation (video AND sound) more trivial.
|
||||
|
||||
* improved color accuracy in VDP highlight mode to match results observed on real hardware.
|
||||
* improved sprites processing timing accuracy: fixes (un)masked sprites in Mickey Mania (3D level), Sonic 2 (VS mode).
|
||||
* improved horizontal blanking & HINT/VINT occurence timing accuracy, as measured on real hardware.
|
||||
* improved H-Counter accuraccy in 40-cell mode, as measured on real hardware.
|
||||
|
||||
[Gamecube/Wii]
|
||||
|
||||
* improved audio/video synchronization: fixes video skipping issues in 60Hz modes
|
||||
* fixed stability issues and some potential memory leaks
|
||||
* improved audio/video synchronization (see above)
|
||||
* improved reset button behavior, now works much more like the real Genesis reset button
|
||||
* fixed stability issues and some memory leaks
|
||||
* added internal screenshot feature
|
||||
* improved lightgun cursors
|
||||
* implemented new FONT & GUI engines: use internal IPL FONT, GX hardware & multithreading for fast rendering.
|
||||
* implemented new interface: incl. IR pointing, game snapshots, menu effects, sound effects, BGM...
|
||||
* new FONT & GUI engines: use internal IPL FONT, GX hardware rendering, sound support & multithreading.
|
||||
* new emulator interface design: incl. IR pointing, game snapshots, menu effects, sound effects, BGM...
|
||||
(check the README for more details)
|
||||
|
||||
|
||||
|
@ -25,28 +25,17 @@
|
||||
|
||||
t_input input;
|
||||
|
||||
/*****************************************************************************
|
||||
* LIGHTGUN specific functions
|
||||
*
|
||||
*****************************************************************************/
|
||||
/* H counter values for a 256-pixel wide display (342 pixel max.) */
|
||||
static const uint8 hc_256[171] = {
|
||||
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
|
||||
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F,
|
||||
0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F,
|
||||
0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F,
|
||||
0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F,
|
||||
0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A, 0x5B, 0x5C, 0x5D, 0x5E, 0x5F,
|
||||
0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F,
|
||||
0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7A, 0x7B, 0x7C, 0x7D, 0x7E, 0x7F,
|
||||
0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8A, 0x8B, 0x8C, 0x8D, 0x8E, 0x8F,
|
||||
0x90, 0x91, 0x92, 0x93,
|
||||
0xE9, 0xEA, 0xEB, 0xEC, 0xED, 0xEE, 0xEF,
|
||||
0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7, 0xF8, 0xF9, 0xFA, 0xFB, 0xFC, 0xFD, 0xFE, 0xFF
|
||||
};
|
||||
|
||||
/* H counter values for a 320-pixel wide display (420 pixels max.) */
|
||||
static const uint8 hc_320[210] = {
|
||||
/************************************************************************************/
|
||||
/* */
|
||||
/* H-counter values returned in H40 & H32 modes */
|
||||
/* */
|
||||
/* Inside VDP, dot counter register is 9-bit, with only upper 8 bits being returned */
|
||||
/* */
|
||||
/* The number of dots per raster line is 342 in H32 mode and 420 in H40 mode */
|
||||
/* */
|
||||
/************************************************************************************/
|
||||
static const uint8 hc_320[210] =
|
||||
{
|
||||
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
|
||||
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F,
|
||||
0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F,
|
||||
@ -64,6 +53,26 @@ static const uint8 hc_320[210] = {
|
||||
0xFE, 0xFF
|
||||
};
|
||||
|
||||
static const uint8 hc_256[171] =
|
||||
{
|
||||
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
|
||||
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F,
|
||||
0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F,
|
||||
0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F,
|
||||
0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F,
|
||||
0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A, 0x5B, 0x5C, 0x5D, 0x5E, 0x5F,
|
||||
0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F,
|
||||
0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7A, 0x7B, 0x7C, 0x7D, 0x7E, 0x7F,
|
||||
0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8A, 0x8B, 0x8C, 0x8D, 0x8E, 0x8F,
|
||||
0x90, 0x91, 0x92, 0x93,
|
||||
0xE9, 0xEA, 0xEB, 0xEC, 0xED, 0xEE, 0xEF,
|
||||
0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7, 0xF8, 0xF9, 0xFA, 0xFB, 0xFC, 0xFD, 0xFE, 0xFF
|
||||
};
|
||||
|
||||
/*****************************************************************************
|
||||
* LIGHTGUN specific functions
|
||||
*
|
||||
*****************************************************************************/
|
||||
static inline void lightgun_reset(int num)
|
||||
{
|
||||
input.analog[num][0] = bitmap.viewport.w >> 1;
|
||||
|
104
source/genesis.c
104
source/genesis.c
@ -23,16 +23,14 @@
|
||||
|
||||
#include "shared.h"
|
||||
|
||||
uint8 bios_rom[0x10000]; /* BIOS rom */
|
||||
uint8 work_ram[0x10000]; /* 68K work RAM */
|
||||
uint8 zram[0x2000]; /* Z80 work RAM */
|
||||
uint8 zbusreq; /* /BUSREQ from Z80 */
|
||||
uint8 zreset; /* /RESET to Z80 */
|
||||
uint8 zbusack; /* /BUSACK to Z80 */
|
||||
uint8 zirq; /* /IRQ to Z80 */
|
||||
uint32 zbank; /* Address of Z80 bank window */
|
||||
uint8 gen_running;
|
||||
int32 resetline;
|
||||
uint8 bios_rom[0x10000]; /* OS ROM */
|
||||
uint8 work_ram[0x10000]; /* 68K RAM */
|
||||
uint8 zram[0x2000]; /* Z80 RAM */
|
||||
uint32 zirq; /* /IRQ to Z80 */
|
||||
uint32 zstate; /* Z80 bus state (d0 = BUSACK, d1 = /RESET) */
|
||||
uint32 zbank; /* Z80 bank window address */
|
||||
uint32 gen_running; /* 0: cpu are in locked state */
|
||||
int32 resetline; /* soft reset is triggered on a random line (X-Men 2, Eternal Champions) */
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
/* Init, reset, shutdown functions */
|
||||
@ -132,28 +130,24 @@ void gen_reset(uint32 hard_reset)
|
||||
memset (work_ram, 0x00, sizeof (work_ram));
|
||||
memset (zram, 0x00, sizeof (zram));
|
||||
|
||||
/* TMSS BIOS */
|
||||
/* TMSS BIOS support */
|
||||
if (config.bios_enabled == 3)
|
||||
{
|
||||
m68k_memory_map[0].base = bios_rom;
|
||||
}
|
||||
|
||||
count_m68k = 0;
|
||||
count_z80 = 0;
|
||||
/* Reset CPU cycle counts */
|
||||
mcycles_68k = 0;
|
||||
mcycles_z80 = 0;
|
||||
}
|
||||
|
||||
resetline = -1; /* clear !RESET */
|
||||
gen_running = 1; /* System is running */
|
||||
zreset = 0; /* Z80 is reset */
|
||||
zbusreq = 0; /* Z80 has control of the Z bus */
|
||||
zbusack = 1; /* Z80 is busy using the Z bus */
|
||||
zirq = 0; /* No interrupts occuring */
|
||||
zbank = 0; /* Assume default bank is $000000-$007FFF */
|
||||
zstate = 0; /* Z80 is reset & has control of the bus */
|
||||
zirq = 0; /* No interrupts occuring */
|
||||
zbank = 0; /* Assume default bank is $000000-$007FFF */
|
||||
|
||||
/* reset CPUs */
|
||||
/* Reset CPUs */
|
||||
resetline = -1;
|
||||
gen_running = 1;
|
||||
m68k_pulse_reset();
|
||||
z80_reset();
|
||||
fm_reset();
|
||||
}
|
||||
|
||||
void gen_shutdown(void)
|
||||
@ -166,74 +160,66 @@ void gen_shutdown(void)
|
||||
-----------------------------------------------------------------------*/
|
||||
void gen_busreq_w(uint32 state)
|
||||
{
|
||||
uint32 z80_cycles_to_run;
|
||||
|
||||
if (state)
|
||||
{
|
||||
/* Bus Request */
|
||||
if (!zbusreq && zreset)
|
||||
/* Bus requested */
|
||||
if (zstate == 1)
|
||||
{
|
||||
/* Z80 stopped */
|
||||
/* z80 was ON during the last 68k cycles */
|
||||
/* we execute the appropriate number of z80 cycles */
|
||||
z80_cycles_to_run = line_z80 + ((count_m68k - line_m68k)*7)/15;
|
||||
current_z80 = z80_cycles_to_run - count_z80;
|
||||
if (current_z80 > 0) count_z80 += z80_execute(current_z80);
|
||||
/* Z80 is stopped */
|
||||
/* Z80 was ON during the last 68k cycles */
|
||||
z80_run(mcycles_68k);
|
||||
}
|
||||
|
||||
/* update Z80 bus status */
|
||||
zstate |= 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Bus released */
|
||||
if (zbusreq && zreset)
|
||||
if (zstate == 3)
|
||||
{
|
||||
/* Z80 started */
|
||||
/* z80 was OFF during the last 68k cycles */
|
||||
/* we burn the appropriate number of z80 cycles */
|
||||
z80_cycles_to_run = line_z80 + ((count_m68k - line_m68k)*7)/15;
|
||||
count_z80 = z80_cycles_to_run;
|
||||
/* Z80 is restarted */
|
||||
/* Z80 was OFF during the last 68k cycles */
|
||||
mcycles_z80 = mcycles_68k;
|
||||
}
|
||||
}
|
||||
|
||||
zbusreq = state;
|
||||
zbusack = 1 ^ (zbusreq & zreset);
|
||||
/* update Z80 bus status */
|
||||
zstate &= 1;
|
||||
}
|
||||
}
|
||||
|
||||
void gen_reset_w(uint32 state)
|
||||
{
|
||||
uint32 z80_cycles_to_run;
|
||||
|
||||
if (state)
|
||||
{
|
||||
/* stop RESET process */
|
||||
if (!zbusreq && !zreset)
|
||||
if (!zstate)
|
||||
{
|
||||
/* Z80 started */
|
||||
/* z80 was OFF during the last 68k cycles */
|
||||
/* we burn the appropriate number of z80 cycles */
|
||||
z80_cycles_to_run = line_z80 + ((count_m68k - line_m68k)*7)/15;
|
||||
count_z80 = z80_cycles_to_run;
|
||||
/* Z80 is restarted */
|
||||
/* Z80 was OFF during the last cycles */
|
||||
mcycles_z80 = mcycles_68k;
|
||||
}
|
||||
|
||||
/* update Z80 bus status */
|
||||
zstate |= 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* start RESET process */
|
||||
if (!zbusreq && zreset)
|
||||
if (zstate == 1)
|
||||
{
|
||||
/* Z80 stopped */
|
||||
/* z80 was ON during the last 68k cycles */
|
||||
/* we execute the appropriate number of z80 cycles */
|
||||
z80_cycles_to_run = line_z80 + ((count_m68k - line_m68k)*7)/15;
|
||||
current_z80 = z80_cycles_to_run - count_z80;
|
||||
if (current_z80 > 0) count_z80 += z80_execute(current_z80);
|
||||
z80_run(mcycles_68k);
|
||||
}
|
||||
|
||||
/* Reset Z80 & YM2612 */
|
||||
z80_reset();
|
||||
fm_reset();
|
||||
}
|
||||
|
||||
zreset = state;
|
||||
zbusack = 1 ^ (zbusreq & zreset);
|
||||
/* update Z80 bus status */
|
||||
zstate &= 2;
|
||||
}
|
||||
}
|
||||
|
||||
void gen_bank_w (uint32 state)
|
||||
|
@ -28,12 +28,10 @@
|
||||
extern uint8 bios_rom[0x10000];
|
||||
extern uint8 work_ram[0x10000];
|
||||
extern uint8 zram[0x2000];
|
||||
extern uint8 zbusreq;
|
||||
extern uint8 zbusack;
|
||||
extern uint8 zreset;
|
||||
extern uint8 zirq;
|
||||
extern uint32 zirq;
|
||||
extern uint32 zbank;
|
||||
extern uint8 gen_running;
|
||||
extern uint32 zstate;
|
||||
extern uint32 gen_running;
|
||||
extern int32 resetline;
|
||||
|
||||
/* Function prototypes */
|
||||
|
@ -740,9 +740,15 @@ static void soundmenu ()
|
||||
sprintf (items[0].text, "High-Quality FM: %s", config.hq_fm ? "ON":"OFF");
|
||||
if (cart.romsize)
|
||||
{
|
||||
/* save YM2612 context */
|
||||
unsigned char *temp = memalign(32,YM2612GetContextSize());
|
||||
if (temp) memcpy(temp, YM2612GetContextPtr(), YM2612GetContextSize());
|
||||
audio_init(48000,vdp_pal?50.0:(1000000.0/16715.0));
|
||||
|
||||
/* reinitialize audio timings */
|
||||
audio_init(snd.sample_rate,snd.frame_rate);
|
||||
sound_init();
|
||||
|
||||
/* restore YM2612 context */
|
||||
if (temp)
|
||||
{
|
||||
YM2612Restore(temp);
|
||||
@ -923,13 +929,26 @@ static void systemmenu ()
|
||||
/* force region & cpu mode */
|
||||
set_region();
|
||||
|
||||
/* reinitialize timings */
|
||||
system_init();
|
||||
memfile_autoload(config.sram_auto,-1);
|
||||
/* update framerate */
|
||||
float framerate;
|
||||
if (vdp_pal)
|
||||
framerate = 50.0;
|
||||
else
|
||||
framerate = ((config.tv_mode == 0) || (config.tv_mode == 2)) ? (1000000.0/16715.0) : 60.0;
|
||||
|
||||
/* save YM2612 context */
|
||||
unsigned char *temp = memalign(32,YM2612GetContextSize());
|
||||
if (temp)
|
||||
memcpy(temp, YM2612GetContextPtr(), YM2612GetContextSize());
|
||||
audio_init(48000,vdp_pal?50.0:(1000000.0/16715.0));
|
||||
|
||||
/* reinitialize all timings */
|
||||
audio_init(snd.sample_rate, framerate);
|
||||
system_init();
|
||||
|
||||
/* restore SRAM */
|
||||
memfile_autoload(config.sram_auto,-1);
|
||||
|
||||
/* restore YM2612 context */
|
||||
if (temp)
|
||||
{
|
||||
YM2612Restore(temp);
|
||||
@ -937,7 +956,7 @@ static void systemmenu ()
|
||||
}
|
||||
|
||||
/* reinitialize HVC tables */
|
||||
vctab = (vdp_pal) ? ((reg[1] & 8) ? vc_pal_240 : vc_pal_224) : vc_ntsc_224;
|
||||
vctab = vdp_pal ? ((reg[1] & 8) ? vc_pal_240 : vc_pal_224) : vc_ntsc_224;
|
||||
hctab = (reg[12] & 1) ? cycle2hc40 : cycle2hc32;
|
||||
|
||||
/* reinitialize overscan area */
|
||||
@ -963,8 +982,8 @@ static void systemmenu ()
|
||||
sprintf (items[3].text, "System BIOS: %s", (config.bios_enabled & 1) ? "ON":"OFF");
|
||||
if (cart.romsize)
|
||||
{
|
||||
system_init ();
|
||||
system_reset ();
|
||||
system_init();
|
||||
system_reset();
|
||||
memfile_autoload(config.sram_auto,-1);
|
||||
}
|
||||
break;
|
||||
@ -984,9 +1003,9 @@ static void systemmenu ()
|
||||
|
||||
if (cart.romsize)
|
||||
{
|
||||
system_reset (); /* clear any patches first */
|
||||
system_init ();
|
||||
system_reset ();
|
||||
system_reset(); /* clear any patches first */
|
||||
system_init();
|
||||
system_reset();
|
||||
memfile_autoload(config.sram_auto,-1);
|
||||
}
|
||||
break;
|
||||
@ -1035,8 +1054,7 @@ static void videomenu ()
|
||||
else
|
||||
sprintf (items[1].text, "TV Mode: 50/60HZ");
|
||||
|
||||
sprintf (items[2].text, "Bilinear Filter: %s",
|
||||
config.bilinear ? " ON" : "OFF");
|
||||
sprintf (items[2].text, "Bilinear Filter: %s", config.bilinear ? " ON" : "OFF");
|
||||
|
||||
if (config.ntsc == 1)
|
||||
sprintf (items[3].text, "NTSC Filter: COMPOSITE");
|
||||
@ -1047,15 +1065,14 @@ static void videomenu ()
|
||||
else
|
||||
sprintf (items[3].text, "NTSC Filter: OFF");
|
||||
|
||||
sprintf (items[4].text, "Borders: %s",
|
||||
config.overscan ? "ON" : "OFF");
|
||||
sprintf (items[4].text, "Borders: %s", config.overscan ? "ON" : "OFF");
|
||||
|
||||
if (config.aspect == 1)
|
||||
sprintf (items[5].text,"Aspect: ORIGINAL (4:3)");
|
||||
else if (config.aspect == 2)
|
||||
sprintf (items[5].text, "Aspect: ORIGINAL (16:9)");
|
||||
else
|
||||
sprintf (items[5].text, "Aspect: SCALED");
|
||||
sprintf (items[5].text, "Aspect: SCALE");
|
||||
|
||||
sprintf (items[6].text, "Screen Position: (%s%02d,%s%02d)",
|
||||
(config.xshift < 0) ? "":"+", config.xshift,
|
||||
@ -1104,20 +1121,49 @@ static void videomenu ()
|
||||
break;
|
||||
|
||||
case 1: /*** tv mode ***/
|
||||
if (config.render == 2) break;
|
||||
config.tv_mode = (config.tv_mode + 1) % 3;
|
||||
if (config.tv_mode == 0)
|
||||
sprintf (items[1].text, "TV Mode: 60HZ");
|
||||
else if (config.tv_mode == 1)
|
||||
sprintf (items[1].text, "TV Mode: 50HZ");
|
||||
if (config.render != 2)
|
||||
{
|
||||
config.tv_mode = (config.tv_mode + 1) % 3;
|
||||
|
||||
/* update framerate */
|
||||
float framerate;
|
||||
if (vdp_pal)
|
||||
framerate = 50.0;
|
||||
else
|
||||
framerate = ((config.tv_mode == 0) || (config.tv_mode == 2)) ? (1000000.0/16715.0) : 60.0;
|
||||
|
||||
/* save YM2612 context */
|
||||
unsigned char *temp = memalign(32,YM2612GetContextSize());
|
||||
if (temp)
|
||||
memcpy(temp, YM2612GetContextPtr(), YM2612GetContextSize());
|
||||
|
||||
/* reinitialize audio timings */
|
||||
audio_init(snd.sample_rate, framerate);
|
||||
sound_init();
|
||||
|
||||
/* restore YM2612 context */
|
||||
if (temp)
|
||||
{
|
||||
YM2612Restore(temp);
|
||||
free(temp);
|
||||
}
|
||||
|
||||
if (config.tv_mode == 0)
|
||||
sprintf (items[1].text, "TV Mode: 60HZ");
|
||||
else if (config.tv_mode == 1)
|
||||
sprintf (items[1].text, "TV Mode: 50HZ");
|
||||
else
|
||||
sprintf (items[1].text, "TV Mode: 50/60HZ");
|
||||
}
|
||||
else
|
||||
sprintf (items[1].text, "TV Mode: 50/60HZ");
|
||||
{
|
||||
GUI_WaitPrompt("Error","Progressive Mode is 60hz only !\n");
|
||||
}
|
||||
break;
|
||||
|
||||
case 2: /*** bilinear filtering ***/
|
||||
config.bilinear ^= 1;
|
||||
sprintf (items[2].text, "Bilinear Filter: %s",
|
||||
config.bilinear ? " ON" : "OFF");
|
||||
sprintf (items[2].text, "Bilinear Filter: %s", config.bilinear ? " ON" : "OFF");
|
||||
break;
|
||||
|
||||
case 3: /*** NTSC filter ***/
|
||||
@ -1134,8 +1180,7 @@ static void videomenu ()
|
||||
|
||||
case 4: /*** overscan emulation ***/
|
||||
config.overscan ^= 1;
|
||||
sprintf (items[4].text, "Overscan Color: %s",
|
||||
config.overscan ? "ORIGINAL" : "BLACK");
|
||||
sprintf (items[4].text, "Borders: %s", config.overscan ? "ON" : "OFF");
|
||||
break;
|
||||
|
||||
case 5: /*** aspect ratio ***/
|
||||
@ -1189,6 +1234,10 @@ static void videomenu ()
|
||||
(config.xshift < 0) ? "":"+", config.xshift,
|
||||
(config.yshift < 0) ? "":"+", config.yshift);
|
||||
}
|
||||
else
|
||||
{
|
||||
GUI_WaitPrompt("Error","Please load a game first !\n");
|
||||
}
|
||||
break;
|
||||
|
||||
case 7: /*** screen scaling ***/
|
||||
@ -1213,6 +1262,10 @@ static void videomenu ()
|
||||
(config.xscale < 0) ? "":"+", config.xscale,
|
||||
(config.yscale < 0) ? "":"+", config.yscale);
|
||||
}
|
||||
else
|
||||
{
|
||||
GUI_WaitPrompt("Error","Please load a game first !\n");
|
||||
}
|
||||
break;
|
||||
|
||||
case -1:
|
||||
@ -2402,8 +2455,8 @@ void MainMenu (void)
|
||||
GUI_DeleteMenu(m);
|
||||
gxClearScreen((GXColor)BLACK);
|
||||
gxSetScreen();
|
||||
audio_init(snd.sample_rate,snd.frame_rate);
|
||||
system_init();
|
||||
audio_init(48000,vdp_pal?50.0:(1000000.0/16715.0));
|
||||
system_reset();
|
||||
memfile_autoload(config.sram_auto,-1);
|
||||
quit = 1;
|
||||
|
@ -25,7 +25,7 @@
|
||||
#include "shared.h"
|
||||
|
||||
/* DMA soundbuffers (required to be 32-bytes aligned)
|
||||
Length is dimensionned for one frame of emulation (see below)
|
||||
Length is dimensionned for one frame of emulation (800/808 samples @60hz, 960 samples@50Hz)
|
||||
To prevent audio clashes, we use double buffering technique:
|
||||
one buffer is the active DMA buffer
|
||||
the other one is the current work buffer (updated during frame emulation)
|
||||
@ -36,15 +36,6 @@ u8 soundbuffer[2][3840] ATTRIBUTE_ALIGN(32);
|
||||
/* Current work soundbuffer */
|
||||
u8 mixbuffer;
|
||||
|
||||
/* Next DMA length */
|
||||
static u32 dma_len;
|
||||
|
||||
/* Current delta between output & expected sample counts */
|
||||
static int delta;
|
||||
|
||||
/* Expected sample count x 100 */
|
||||
static u32 dma_sync;
|
||||
|
||||
/* audio DMA status */
|
||||
static u8 audioStarted = 0;
|
||||
|
||||
@ -98,38 +89,14 @@ void gx_audio_Shutdown(void)
|
||||
/***
|
||||
gx_audio_Update
|
||||
|
||||
This function is called at the end of each frame
|
||||
Genesis Plus only provides sound data on completion of each frame.
|
||||
DMA sync and switching ensure we never access the active DMA buffer and sound clashes never happen
|
||||
This function retrieves samples for the frame then set the next DMA parameters
|
||||
Parameters will be taken in account only when current DMA operation is over
|
||||
***/
|
||||
void gx_audio_Update(void)
|
||||
void gx_audio_Update(int size)
|
||||
{
|
||||
/* current DMA length */
|
||||
u32 size = dma_len;
|
||||
|
||||
/* VIDEO interrupt synchronization: we approximate next DMA length (see below) */
|
||||
/* In 50Hz mode, VSYNC period is 19967 usec which is approx 958.42 samples */
|
||||
/* In 60Hz mode, VSYNC period is 16715 usec which is approx. 802.32 samples */
|
||||
/* DMA length should be a multiple of 32 bytes so we use either 800 or 808 samples */
|
||||
if (dma_sync)
|
||||
{
|
||||
/* current samples delay */
|
||||
delta += (size * 100) - dma_sync;
|
||||
|
||||
/* adjust next DMA length */
|
||||
if (delta < 0) dma_len = 808;
|
||||
else dma_len = 800;
|
||||
}
|
||||
|
||||
/* retrieve audio samples */
|
||||
audio_update(size);
|
||||
|
||||
/* set next DMA soundbuffer */
|
||||
s16 *sb = (s16 *)(soundbuffer[mixbuffer]);
|
||||
mixbuffer ^= 1;
|
||||
size = size << 2;
|
||||
DCFlushRange((void *)sb, size);
|
||||
AUDIO_InitDMA((u32) sb, size);
|
||||
|
||||
@ -140,7 +107,8 @@ void gx_audio_Update(void)
|
||||
{
|
||||
audioStarted = 1;
|
||||
AUDIO_StartDMA();
|
||||
if (frameticker > 1) frameticker = 1;
|
||||
if (frameticker > 1)
|
||||
frameticker = 1;
|
||||
}
|
||||
}
|
||||
|
||||
@ -156,29 +124,16 @@ void gx_audio_Start(void)
|
||||
PauseOgg(1);
|
||||
StopOgg();
|
||||
ASND_Pause(1);
|
||||
AUDIO_StopDMA ();
|
||||
AUDIO_RegisterDMACallback(NULL);
|
||||
ASND_End();
|
||||
audioStarted = 0;
|
||||
|
||||
/* initialize default DMA length */
|
||||
/* PAL (50Hz): 20000 us period --> 960 samples/frame @48kHz */
|
||||
/* NTSC (60Hz): 16667 us period --> 800 samples/frame @48kHz */
|
||||
dma_len = vdp_pal ? 960 : 800;
|
||||
dma_sync = 0;
|
||||
mixbuffer = 0;
|
||||
delta = 0;
|
||||
|
||||
/* reset sound buffers */
|
||||
memset(soundbuffer, 0, 2 * 3840);
|
||||
|
||||
/* By default, use audio DMA to synchronize frame emulation */
|
||||
if (gc_pal | vdp_pal) AUDIO_RegisterDMACallback(ai_callback);
|
||||
|
||||
/* 60hz video mode requires synchronization with Video interrupt */
|
||||
/* VSYNC period is 16715 us which is approx. 802.32 samples */
|
||||
/* to prevent audio/video desynchronization, we approximate the exact */
|
||||
/* number of samples by changing audio DMA length on each frame */
|
||||
else dma_sync = 80232;
|
||||
if (gc_pal | vdp_pal)
|
||||
AUDIO_RegisterDMACallback(ai_callback);
|
||||
}
|
||||
|
||||
/***
|
||||
|
@ -32,6 +32,6 @@ extern void gx_audio_Init(void);
|
||||
extern void gx_audio_Shutdown(void);
|
||||
extern void gx_audio_Start(void);
|
||||
extern void gx_audio_Stop(void);
|
||||
extern void gx_audio_Update(void);
|
||||
extern void gx_audio_Update(int size);
|
||||
|
||||
#endif
|
||||
|
@ -1283,9 +1283,11 @@ void gx_video_Start(void)
|
||||
|
||||
/* VSYNC callbacks */
|
||||
/* in 60hz mode we use VSYNC to synchronize frame emulation */
|
||||
if (!gc_pal && !vdp_pal) VIDEO_SetPreRetraceCallback(vi_callback);
|
||||
if (!gc_pal && !vdp_pal)
|
||||
VIDEO_SetPreRetraceCallback(vi_callback);
|
||||
VIDEO_SetPostRetraceCallback(NULL);
|
||||
VIDEO_Flush();
|
||||
VIDEO_WaitVSync();
|
||||
|
||||
/* interlaced/progressive mode */
|
||||
if (config.render == 2)
|
||||
|
@ -125,10 +125,20 @@ void reloadrom (int size, char *name)
|
||||
}
|
||||
else
|
||||
{
|
||||
system_init (); /* Initialize System */
|
||||
audio_init(48000,vdp_pal?50.0:(1000000.0/16715.0));
|
||||
ClearGGCodes (); /* Clear Game Genie patches */
|
||||
system_reset (); /* System Power ON */
|
||||
/* initialize audio back-end */
|
||||
/* 60hz video mode requires synchronization with Video Interrupt. */
|
||||
/* VSYNC period is 16715 us on Wii/Gamecube (approx. 802.32 samples per frame) */
|
||||
float framerate;
|
||||
if (vdp_pal)
|
||||
framerate = 50.0;
|
||||
else
|
||||
framerate = ((config.tv_mode == 0) || (config.tv_mode == 2)) ? (1000000.0/16715.0) : 60.0;
|
||||
audio_init(48000, framerate);
|
||||
|
||||
/* System Power ON */
|
||||
system_init ();
|
||||
ClearGGCodes ();
|
||||
system_reset ();
|
||||
}
|
||||
}
|
||||
|
||||
@ -164,6 +174,7 @@ int main (int argc, char *argv[])
|
||||
DI_Init();
|
||||
#endif
|
||||
|
||||
int size;
|
||||
|
||||
/* initialize hardware */
|
||||
gx_video_Init();
|
||||
@ -265,9 +276,6 @@ int main (int argc, char *argv[])
|
||||
/* skip frame */
|
||||
frameticker-=2;
|
||||
system_frame (1);
|
||||
|
||||
/* update audio only */
|
||||
gx_audio_Update();
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -277,11 +285,14 @@ int main (int argc, char *argv[])
|
||||
|
||||
/* render frame */
|
||||
system_frame (0);
|
||||
|
||||
/* update video & audio */
|
||||
gx_video_Update();
|
||||
gx_audio_Update();
|
||||
}
|
||||
|
||||
/* retrieve audio samples */
|
||||
size = audio_update();
|
||||
|
||||
/* update video & audio */
|
||||
gx_video_Update();
|
||||
gx_audio_Update(size * 4);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
613
source/hvc.h
613
source/hvc.h
@ -261,149 +261,494 @@ uint8 vc_pal_240[313] = {
|
||||
0xF7, 0xF8, 0xF9, 0xFA, 0xFB, 0xFC, 0xFD, 0xFE, 0xFF
|
||||
};
|
||||
|
||||
/*
|
||||
VDP timing for an NTSC Genesis in display mode 5.
|
||||
Version 0.4 (11/29/00)
|
||||
/***************************************************************/
|
||||
/* */
|
||||
/* H-counter timings in H40 & H32 modes (starts from HINT) */
|
||||
/* */
|
||||
/* There are exactly 3420 Master Clock counts per raster line. */
|
||||
/* */
|
||||
/* in H32 mode, dot clock is divided from MCLK (MCLK/10). */
|
||||
/* in H40 mode, dot clock is divided from EDCLK (EDCLK/2). */
|
||||
/* */
|
||||
/* EDCLK (external dot clock ?) is generated outside the VDP: */
|
||||
/* During HSYNC, it is oscillating between MCLK/10 and MCLK/8, */
|
||||
/* otherwise it is fixed to MCLK/8. */
|
||||
/* */
|
||||
/***************************************************************/
|
||||
|
||||
by Charles MacDonald
|
||||
WWW: http://cgfm2.emuviews.com
|
||||
uint8 cycle2hc40[3420] =
|
||||
{
|
||||
/* end of active display (16 pixels -> 128 Mcycles) , HINT triggered , Vcounter jump */
|
||||
0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5,
|
||||
0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6,
|
||||
0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7,
|
||||
0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8,
|
||||
0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9,
|
||||
0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
|
||||
0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab,
|
||||
0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac,
|
||||
|
||||
Unpublished work Copyright 2000 Charles MacDonald
|
||||
/* right border (14 pixels -> 112 Mcycles) */
|
||||
0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad,
|
||||
0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae,
|
||||
0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf,
|
||||
0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0,
|
||||
0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb1,
|
||||
0xb2, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2,
|
||||
0xb3, 0xb3, 0xb3, 0xb3, 0xb3, 0xb3, 0xb3, 0xb3, 0xb3, 0xb3, 0xb3, 0xb3, 0xb3, 0xb3, 0xb3, 0xb3,
|
||||
|
||||
Description 32-cell 40-cell
|
||||
----------------------------------------------------------------------------
|
||||
Range 00-93, E9-FF 00-B6, E4-FF
|
||||
Display area 00-7F 00-9F
|
||||
V counter increment 84, 85 A4, A5
|
||||
V-blanking in 86, 87 A7, A8
|
||||
V-blanking out 86, 87 A7, A8
|
||||
H-blanking in 93, E9 B2, E4
|
||||
H-blanking out 06, 07 06, 07
|
||||
/* right blanking (9 pixels -> 72 Mcycles) , VDP status HBLANK flag set */
|
||||
0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4,
|
||||
0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5,
|
||||
0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6,
|
||||
0xe5, 0xe5, 0xe5, 0xe5, 0xe5, 0xe5, 0xe5, 0xe5, 0xe5, 0xe5, 0xe5, 0xe5, 0xe5, 0xe5, 0xe5, 0xe5,
|
||||
0xe6, 0xe6, 0xe6, 0xe6, 0xe6, 0xe6, 0xe6, 0xe6,
|
||||
|
||||
Comma seperated values show the H counter value before an event occurs,
|
||||
and then the H counter value immediately after.
|
||||
/* horizontal sync (32 pixels -> 313 Mcycles) */
|
||||
0xe6, 0xe6, 0xe6, 0xe6, 0xe6, 0xe6, 0xe6, 0xe6,
|
||||
0xe6, 0xe7, 0xe7, 0xe7, 0xe7, 0xe7, 0xe7, 0xe7, 0xe7, 0xe7, 0xe7, 0xe7, 0xe7, 0xe7, 0xe7, 0xe7,
|
||||
0xe7, 0xe7, 0xe7, 0xe7, 0xe7, 0xe8, 0xe8, 0xe8, 0xe8, 0xe8, 0xe8, 0xe8, 0xe8, 0xe8, 0xe8, 0xe8,
|
||||
0xe8, 0xe8, 0xe8, 0xe8, 0xe8, 0xe8, 0xe8, 0xe8, 0xe8, 0xe9, 0xe9, 0xe9, 0xe9, 0xe9, 0xe9, 0xe9,
|
||||
0xe9, 0xe9, 0xe9, 0xe9, 0xe9, 0xe9, 0xe9, 0xe9, 0xe9, 0xe9, 0xe9, 0xe9, 0xe9, 0xea, 0xea, 0xea,
|
||||
0xea, 0xea, 0xea, 0xea, 0xea, 0xea, 0xea, 0xea, 0xea, 0xea, 0xea, 0xea, 0xea, 0xea, 0xea, 0xeb,
|
||||
0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb,
|
||||
0xeb, 0xeb, 0xeb, 0xec, 0xec, 0xec, 0xec, 0xec, 0xec, 0xec, 0xec, 0xec, 0xec, 0xec, 0xec, 0xec,
|
||||
0xec, 0xec, 0xec, 0xec, 0xec, 0xec, 0xec, 0xed, 0xed, 0xed, 0xed, 0xed, 0xed, 0xed, 0xed, 0xed,
|
||||
0xed, 0xed, 0xed, 0xed, 0xed, 0xed, 0xed, 0xed, 0xed, 0xed, 0xed, 0xee, 0xee, 0xee, 0xee, 0xee,
|
||||
0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xef, 0xef,
|
||||
0xef, 0xef, 0xef, 0xef, 0xef, 0xef, 0xef, 0xef, 0xef, 0xef, 0xef, 0xef, 0xef, 0xef, 0xef, 0xef,
|
||||
0xef, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0,
|
||||
0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1,
|
||||
0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2,
|
||||
0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf3, 0xf3, 0xf3,
|
||||
0xf3, 0xf3, 0xf3, 0xf3, 0xf3, 0xf3, 0xf3, 0xf3, 0xf3, 0xf3, 0xf3, 0xf3, 0xf3, 0xf3, 0xf3, 0xf4,
|
||||
0xf4, 0xf4, 0xf4, 0xf4, 0xf4, 0xf4, 0xf4, 0xf4, 0xf4, 0xf4, 0xf4, 0xf4, 0xf4, 0xf4, 0xf4, 0xf4,
|
||||
0xf4, 0xf4, 0xf4, 0xf5, 0xf5, 0xf5, 0xf5, 0xf5, 0xf5, 0xf5, 0xf5, 0xf5, 0xf5, 0xf5, 0xf5, 0xf5,
|
||||
0xf5, 0xf5, 0xf5, 0xf5, 0xf5, 0xf5, 0xf5, 0xf6, 0xf6, 0xf6, 0xf6, 0xf6, 0xf6, 0xf6, 0xf6, 0xf6,
|
||||
0xf6,
|
||||
|
||||
These values shouldn't be considered 100% accurate, they are probably
|
||||
off by one or two.
|
||||
/* left blanking (32 pixels -> 259 Mcycles) */
|
||||
0xf6, 0xf6, 0xf6, 0xf6, 0xf6, 0xf6, 0xf6, 0xf6, 0xf6, 0xf6, 0xf7, 0xf7, 0xf7, 0xf7, 0xf7,
|
||||
0xf7, 0xf7, 0xf7, 0xf7, 0xf7, 0xf7, 0xf7, 0xf7, 0xf7, 0xf7, 0xf7, 0xf7, 0xf8, 0xf8, 0xf8, 0xf8,
|
||||
0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf9, 0xf9, 0xf9, 0xf9,
|
||||
0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xfa, 0xfa, 0xfa, 0xfa,
|
||||
0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0xfb, 0xfb, 0xfb, 0xfb,
|
||||
0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfc, 0xfc, 0xfc, 0xfc,
|
||||
0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfd, 0xfd, 0xfd, 0xfd,
|
||||
0xfd, 0xfd, 0xfd, 0xfd, 0xfd, 0xfd, 0xfd, 0xfd, 0xfd, 0xfd, 0xfd, 0xfd, 0xfe, 0xfe, 0xfe, 0xfe,
|
||||
0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00,
|
||||
/* Vertical Interrupt triggered */
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01,
|
||||
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02,
|
||||
0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x03, 0x03, 0x03, 0x03,
|
||||
0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x04, 0x04, 0x04, 0x04,
|
||||
0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x05, 0x05, 0x05, 0x05,
|
||||
0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x06, 0x06, 0x06, 0x06,
|
||||
0x06, 0x06, 0x06, 0x06,
|
||||
|
||||
Each H counter unit is equivalent to two pixels.
|
||||
/* left border (13 pixels -> 104 Mcycles) , VDP status HBLANK flag cleared */
|
||||
0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x07, 0x07, 0x07, 0x07,
|
||||
0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x08, 0x08, 0x08, 0x08,
|
||||
0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x09, 0x09, 0x09, 0x09,
|
||||
0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x0a, 0x0a, 0x0a, 0x0a,
|
||||
0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0b, 0x0b, 0x0b, 0x0b,
|
||||
0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0c, 0x0c, 0x0c, 0x0c,
|
||||
0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c,
|
||||
|
||||
The gaps at 93-E9 and B6-E4 are where the H counter 'jumps' ahead.
|
||||
The H counter will never actually be set to the values 94-E8 or B7-E3.
|
||||
Perhaps this is the horizontal retrace period.
|
||||
|
||||
Interestingly enough, the timing values for the 32-cell display mode
|
||||
are identical to that of the SMS.
|
||||
|
||||
It would appear that in 40-cell mode, the horizontal blanking period
|
||||
is shorter as the active display period takes more time.
|
||||
|
||||
The V-blanking flag can also be forcibly set by disabling the display
|
||||
through bit 6 of register #1.
|
||||
|
||||
|
||||
--------------------------------------------------------------------------
|
||||
H counter
|
||||
|
||||
Now for some additional information on the horizontal aspects of the
|
||||
display, taken from the TMS9918 manual and my tests on a NTSC Genesis.
|
||||
Be warned that a real SMS may have different results.
|
||||
|
||||
The H counter is 9 bits, and reading it returns the upper 8 bits. This is
|
||||
because a scanline consists of 342 pixels, which couldn't be represented
|
||||
with an 8-bit counter. Each scanline is divided up as follows:
|
||||
|
||||
Pixels H.Cnt Description
|
||||
256 : 00-7F : Active display
|
||||
15 : 80-87 : Right border
|
||||
8 : 87-8B : Right blanking
|
||||
26 : 8B-ED : Horizontal sync
|
||||
2 : ED-EE : Left blanking
|
||||
14 : EE-F5 : Color burst
|
||||
8 : F5-F9 : Left blanking
|
||||
13 : F9-FF : Left border
|
||||
|
||||
Here's a description of what these areas look like:
|
||||
|
||||
Active display - Where the display generated by the VDP goes.
|
||||
Right border - Filled with border color from VDP register $07.
|
||||
Right blanking - Filled with a light black color. (like display was blanked)
|
||||
Horizontal sync - Filled with a pure black color. (like display was turned off)
|
||||
Left blanking - Filled with the border color from VDP register $07.
|
||||
Color burst - Filled with a dark brown/orange color.
|
||||
Left blanking - Filled with a light black color. (like display was blanked)
|
||||
Left border - Filled with the border color from VDP register $07.
|
||||
|
||||
*/
|
||||
|
||||
uint8 cycle2hc32[488] = {
|
||||
0x85, 0x85, 0x86, 0x86, 0x87, 0x87, 0x87, 0x88, 0x88, 0x88, 0x89, 0x89, 0x89, 0x8A, 0x8A, 0x8A,
|
||||
0x8B, 0x8B, 0x8B, 0x8C, 0x8C, 0x8D, 0x8D, 0x8D, 0x8E, 0x8E, 0x8E, 0x8F, 0x8F, 0x8F, 0x90, 0x90,
|
||||
0x90, 0x91, 0x91, 0x91, 0x92, 0x92, 0x92, 0x93, 0x93,
|
||||
0xE9, 0xE9, 0xE9, 0xEA, 0xEA, 0xEA,
|
||||
0xEB, 0xEB, 0xEB, 0xEC, 0xEC, 0xEC, 0xED, 0xED, 0xED, 0xEE, 0xEE, 0xEE, 0xEF, 0xEF, 0xF0, 0xF0,
|
||||
0xF0, 0xF1, 0xF1, 0xF1, 0xF2, 0xF2, 0xF2, 0xF3, 0xF3, 0xF3, 0xF4, 0xF4, 0xF4, 0xF5, 0xF5, 0xF6,
|
||||
0xF6, 0xF6, 0xF7, 0xF7, 0xF7, 0xF8, 0xF8, 0xF8, 0xF9, 0xF9, 0xF9, 0xFA, 0xFA, 0xFA, 0xFB, 0xFB,
|
||||
0xFB, 0xFC, 0xFC, 0xFD, 0xFD, 0xFD, 0xFE, 0xFE, 0xFE, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x01,
|
||||
0x01, 0x01, 0x02, 0x02, 0x02, 0x03, 0x03, 0x03, 0x04, 0x04, 0x04, 0x05, 0x05, 0x05, 0x06, 0x06,
|
||||
0x07, 0x07, 0x07, 0x08, 0x08, 0x08, 0x09, 0x09, 0x09, 0x0A, 0x0A, 0x0A, 0x0B, 0x0B, 0x0B, 0x0C,
|
||||
0x0C, 0x0C, 0x0D, 0x0D, 0x0E, 0x0E, 0x0E, 0x0F, 0x0F, 0x0F, 0x10, 0x10, 0x10, 0x11, 0x11, 0x11,
|
||||
0x12, 0x12, 0x12, 0x13, 0x13, 0x13, 0x14, 0x14, 0x15, 0x15, 0x15, 0x16, 0x16, 0x16, 0x17, 0x17,
|
||||
0x17, 0x18, 0x18, 0x18, 0x19, 0x19, 0x19, 0x1A, 0x1A, 0x1B, 0x1B, 0x1B, 0x1C, 0x1C, 0x1C, 0x1D,
|
||||
0x1D, 0x1D, 0x1E, 0x1E, 0x1E, 0x1F, 0x1F, 0x1F, 0x20, 0x20, 0x20, 0x21, 0x21, 0x22, 0x22, 0x22,
|
||||
0x23, 0x23, 0x23, 0x24, 0x24, 0x24, 0x25, 0x25, 0x25, 0x26, 0x26, 0x26, 0x27, 0x27, 0x27, 0x28,
|
||||
0x28, 0x29, 0x29, 0x29, 0x2A, 0x2A, 0x2A, 0x2B, 0x2B, 0x2B, 0x2C, 0x2C, 0x2C, 0x2D, 0x2D, 0x2D,
|
||||
0x2E, 0x2E, 0x2F, 0x2F, 0x2F, 0x30, 0x30, 0x30, 0x31, 0x31, 0x31, 0x32, 0x32, 0x32, 0x33, 0x33,
|
||||
0x33, 0x34, 0x34, 0x34, 0x35, 0x35, 0x36, 0x36, 0x36, 0x37, 0x37, 0x37, 0x38, 0x38, 0x38, 0x39,
|
||||
0x39, 0x39, 0x3A, 0x3A, 0x3A, 0x3B, 0x3B, 0x3B, 0x3C, 0x3C, 0x3D, 0x3D, 0x3D, 0x3E, 0x3E, 0x3E,
|
||||
0x3F, 0x3F, 0x3F, 0x40, 0x40, 0x40, 0x41, 0x41, 0x41, 0x42, 0x42, 0x42, 0x43, 0x43, 0x44, 0x44,
|
||||
0x44, 0x45, 0x45, 0x45, 0x46, 0x46, 0x46, 0x47, 0x47, 0x47, 0x48, 0x48, 0x48, 0x49, 0x49, 0x4A,
|
||||
0x4A, 0x4A, 0x4B, 0x4B, 0x4B, 0x4C, 0x4C, 0x4C, 0x4D, 0x4D, 0x4D, 0x4E, 0x4E, 0x4E, 0x4F, 0x4F,
|
||||
0x4F, 0x50, 0x50, 0x51, 0x51, 0x51, 0x52, 0x52, 0x52, 0x53, 0x53, 0x53, 0x54, 0x54, 0x54, 0x55,
|
||||
0x55, 0x55, 0x56, 0x56, 0x56, 0x57, 0x57, 0x58, 0x58, 0x58, 0x59, 0x59, 0x59, 0x5A, 0x5A, 0x5A,
|
||||
0x5B, 0x5B, 0x5B, 0x5C, 0x5C, 0x5C, 0x5D, 0x5D, 0x5E, 0x5E, 0x5E, 0x5F, 0x5F, 0x5F, 0x60, 0x60,
|
||||
0x60, 0x61, 0x61, 0x61, 0x62, 0x62, 0x62, 0x63, 0x63, 0x63, 0x64, 0x64, 0x65, 0x65, 0x65, 0x66,
|
||||
0x66, 0x66, 0x67, 0x67, 0x67, 0x68, 0x68, 0x68, 0x69, 0x69, 0x69, 0x6A, 0x6A, 0x6A, 0x6B, 0x6B,
|
||||
0x6C, 0x6C, 0x6C, 0x6D, 0x6D, 0x6D, 0x6E, 0x6E, 0x6E, 0x6F, 0x6F, 0x6F, 0x70, 0x70, 0x70, 0x71,
|
||||
0x71, 0x72, 0x72, 0x72, 0x73, 0x73, 0x73, 0x74, 0x74, 0x74, 0x75, 0x75, 0x75, 0x76, 0x76, 0x76,
|
||||
0x77, 0x77, 0x77, 0x78, 0x78, 0x79, 0x79, 0x79, 0x7A, 0x7A, 0x7A, 0x7B, 0x7B, 0x7B, 0x7C, 0x7C,
|
||||
0x7C, 0x7D, 0x7D, 0x7D, 0x7E, 0x7E, 0x7E, 0x7F, 0x7F, 0x80, 0x80, 0x80, 0x81, 0x81, 0x81, 0x82,
|
||||
0x82, 0x82, 0x83, 0x83, 0x83, 0x84, 0x84, 0x84, 0x85,
|
||||
/* remaining active display (304 pixels -> 2432 Mcycles) */
|
||||
0x0d, 0x0d, 0x0d, 0x0d,
|
||||
0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0e, 0x0e, 0x0e, 0x0e,
|
||||
0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0f, 0x0f, 0x0f, 0x0f,
|
||||
0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x10, 0x10, 0x10, 0x10,
|
||||
0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x11, 0x11, 0x11, 0x11,
|
||||
0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x12, 0x12, 0x12, 0x12,
|
||||
0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x13, 0x13, 0x13, 0x13,
|
||||
0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x14, 0x14, 0x14, 0x14,
|
||||
0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x15, 0x15, 0x15, 0x15,
|
||||
0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x16, 0x16, 0x16, 0x16,
|
||||
0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x17, 0x17, 0x17, 0x17,
|
||||
0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x18, 0x18, 0x18, 0x18,
|
||||
0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x19, 0x19, 0x19, 0x19,
|
||||
0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x1a, 0x1a, 0x1a, 0x1a,
|
||||
0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1b, 0x1b, 0x1b, 0x1b,
|
||||
0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1c, 0x1c, 0x1c, 0x1c,
|
||||
0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1d, 0x1d, 0x1d, 0x1d,
|
||||
0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1e, 0x1e, 0x1e, 0x1e,
|
||||
0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1f, 0x1f, 0x1f, 0x1f,
|
||||
0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x20, 0x20, 0x20, 0x20,
|
||||
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x21, 0x21, 0x21, 0x21,
|
||||
0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x22, 0x22, 0x22, 0x22,
|
||||
0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x23, 0x23, 0x23, 0x23,
|
||||
0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x24, 0x24, 0x24, 0x24,
|
||||
0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x25, 0x25, 0x25, 0x25,
|
||||
0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x26, 0x26, 0x26, 0x26,
|
||||
0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x27, 0x27, 0x27, 0x27,
|
||||
0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x28, 0x28, 0x28, 0x28,
|
||||
0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x29, 0x29, 0x29, 0x29,
|
||||
0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x2a, 0x2a, 0x2a, 0x2a,
|
||||
0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2b, 0x2b, 0x2b, 0x2b,
|
||||
0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2c, 0x2c, 0x2c, 0x2c,
|
||||
0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2d, 0x2d, 0x2d, 0x2d,
|
||||
0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2e, 0x2e, 0x2e, 0x2e,
|
||||
0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2f, 0x2f, 0x2f, 0x2f,
|
||||
0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x30, 0x30, 0x30, 0x30,
|
||||
0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x31, 0x31, 0x31, 0x31,
|
||||
0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x32, 0x32, 0x32, 0x32,
|
||||
0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x33, 0x33, 0x33, 0x33,
|
||||
0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x34, 0x34, 0x34, 0x34,
|
||||
0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x35, 0x35, 0x35, 0x35,
|
||||
0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x36, 0x36, 0x36, 0x36,
|
||||
0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x37, 0x37, 0x37, 0x37,
|
||||
0x37, 0x37, 0x37, 0x37, 0x37, 0x37, 0x37, 0x37, 0x37, 0x37, 0x37, 0x37, 0x38, 0x38, 0x38, 0x38,
|
||||
0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x39, 0x39, 0x39, 0x39,
|
||||
0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x3a, 0x3a, 0x3a, 0x3a,
|
||||
0x3a, 0x3a, 0x3a, 0x3a, 0x3a, 0x3a, 0x3a, 0x3a, 0x3a, 0x3a, 0x3a, 0x3a, 0x3b, 0x3b, 0x3b, 0x3b,
|
||||
0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3c, 0x3c, 0x3c, 0x3c,
|
||||
0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3d, 0x3d, 0x3d, 0x3d,
|
||||
0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3e, 0x3e, 0x3e, 0x3e,
|
||||
0x3e, 0x3e, 0x3e, 0x3e, 0x3e, 0x3e, 0x3e, 0x3e, 0x3e, 0x3e, 0x3e, 0x3e, 0x3f, 0x3f, 0x3f, 0x3f,
|
||||
0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x40, 0x40, 0x40, 0x40,
|
||||
0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x41, 0x41, 0x41, 0x41,
|
||||
0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x42, 0x42, 0x42, 0x42,
|
||||
0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x43, 0x43, 0x43, 0x43,
|
||||
0x43, 0x43, 0x43, 0x43, 0x43, 0x43, 0x43, 0x43, 0x43, 0x43, 0x43, 0x43, 0x44, 0x44, 0x44, 0x44,
|
||||
0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x45, 0x45, 0x45, 0x45,
|
||||
0x45, 0x45, 0x45, 0x45, 0x45, 0x45, 0x45, 0x45, 0x45, 0x45, 0x45, 0x45, 0x46, 0x46, 0x46, 0x46,
|
||||
0x46, 0x46, 0x46, 0x46, 0x46, 0x46, 0x46, 0x46, 0x46, 0x46, 0x46, 0x46, 0x47, 0x47, 0x47, 0x47,
|
||||
0x47, 0x47, 0x47, 0x47, 0x47, 0x47, 0x47, 0x47, 0x47, 0x47, 0x47, 0x47, 0x48, 0x48, 0x48, 0x48,
|
||||
0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x49, 0x49, 0x49, 0x49,
|
||||
0x49, 0x49, 0x49, 0x49, 0x49, 0x49, 0x49, 0x49, 0x49, 0x49, 0x49, 0x49, 0x4a, 0x4a, 0x4a, 0x4a,
|
||||
0x4a, 0x4a, 0x4a, 0x4a, 0x4a, 0x4a, 0x4a, 0x4a, 0x4a, 0x4a, 0x4a, 0x4a, 0x4b, 0x4b, 0x4b, 0x4b,
|
||||
0x4b, 0x4b, 0x4b, 0x4b, 0x4b, 0x4b, 0x4b, 0x4b, 0x4b, 0x4b, 0x4b, 0x4b, 0x4c, 0x4c, 0x4c, 0x4c,
|
||||
0x4c, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c, 0x4d, 0x4d, 0x4d, 0x4d,
|
||||
0x4d, 0x4d, 0x4d, 0x4d, 0x4d, 0x4d, 0x4d, 0x4d, 0x4d, 0x4d, 0x4d, 0x4d, 0x4e, 0x4e, 0x4e, 0x4e,
|
||||
0x4e, 0x4e, 0x4e, 0x4e, 0x4e, 0x4e, 0x4e, 0x4e, 0x4e, 0x4e, 0x4e, 0x4e, 0x4f, 0x4f, 0x4f, 0x4f,
|
||||
0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x50, 0x50, 0x50, 0x50,
|
||||
0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x51, 0x51, 0x51, 0x51,
|
||||
0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x52, 0x52, 0x52, 0x52,
|
||||
0x52, 0x52, 0x52, 0x52, 0x52, 0x52, 0x52, 0x52, 0x52, 0x52, 0x52, 0x52, 0x53, 0x53, 0x53, 0x53,
|
||||
0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x54, 0x54, 0x54, 0x54,
|
||||
0x54, 0x54, 0x54, 0x54, 0x54, 0x54, 0x54, 0x54, 0x54, 0x54, 0x54, 0x54, 0x55, 0x55, 0x55, 0x55,
|
||||
0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x56, 0x56, 0x56, 0x56,
|
||||
0x56, 0x56, 0x56, 0x56, 0x56, 0x56, 0x56, 0x56, 0x56, 0x56, 0x56, 0x56, 0x57, 0x57, 0x57, 0x57,
|
||||
0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x58, 0x58, 0x58, 0x58,
|
||||
0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0x59, 0x59, 0x59, 0x59,
|
||||
0x59, 0x59, 0x59, 0x59, 0x59, 0x59, 0x59, 0x59, 0x59, 0x59, 0x59, 0x59, 0x5a, 0x5a, 0x5a, 0x5a,
|
||||
0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5b, 0x5b, 0x5b, 0x5b,
|
||||
0x5b, 0x5b, 0x5b, 0x5b, 0x5b, 0x5b, 0x5b, 0x5b, 0x5b, 0x5b, 0x5b, 0x5b, 0x5c, 0x5c, 0x5c, 0x5c,
|
||||
0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5d, 0x5d, 0x5d, 0x5d,
|
||||
0x5d, 0x5d, 0x5d, 0x5d, 0x5d, 0x5d, 0x5d, 0x5d, 0x5d, 0x5d, 0x5d, 0x5d, 0x5e, 0x5e, 0x5e, 0x5e,
|
||||
0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5f, 0x5f, 0x5f, 0x5f,
|
||||
0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x60, 0x60, 0x60, 0x60,
|
||||
0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x61, 0x61, 0x61, 0x61,
|
||||
0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x62, 0x62, 0x62, 0x62,
|
||||
0x62, 0x62, 0x62, 0x62, 0x62, 0x62, 0x62, 0x62, 0x62, 0x62, 0x62, 0x62, 0x63, 0x63, 0x63, 0x63,
|
||||
0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x64, 0x64, 0x64, 0x64,
|
||||
0x64, 0x64, 0x64, 0x64, 0x64, 0x64, 0x64, 0x64, 0x64, 0x64, 0x64, 0x64, 0x65, 0x65, 0x65, 0x65,
|
||||
0x65, 0x65, 0x65, 0x65, 0x65, 0x65, 0x65, 0x65, 0x65, 0x65, 0x65, 0x65, 0x66, 0x66, 0x66, 0x66,
|
||||
0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x67, 0x67, 0x67, 0x67,
|
||||
0x67, 0x67, 0x67, 0x67, 0x67, 0x67, 0x67, 0x67, 0x67, 0x67, 0x67, 0x67, 0x68, 0x68, 0x68, 0x68,
|
||||
0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x69, 0x69, 0x69, 0x69,
|
||||
0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x6a, 0x6a, 0x6a, 0x6a,
|
||||
0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6b, 0x6b, 0x6b, 0x6b,
|
||||
0x6b, 0x6b, 0x6b, 0x6b, 0x6b, 0x6b, 0x6b, 0x6b, 0x6b, 0x6b, 0x6b, 0x6b, 0x6c, 0x6c, 0x6c, 0x6c,
|
||||
0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6d, 0x6d, 0x6d, 0x6d,
|
||||
0x6d, 0x6d, 0x6d, 0x6d, 0x6d, 0x6d, 0x6d, 0x6d, 0x6d, 0x6d, 0x6d, 0x6d, 0x6e, 0x6e, 0x6e, 0x6e,
|
||||
0x6e, 0x6e, 0x6e, 0x6e, 0x6e, 0x6e, 0x6e, 0x6e, 0x6e, 0x6e, 0x6e, 0x6e, 0x6f, 0x6f, 0x6f, 0x6f,
|
||||
0x6f, 0x6f, 0x6f, 0x6f, 0x6f, 0x6f, 0x6f, 0x6f, 0x6f, 0x6f, 0x6f, 0x6f, 0x70, 0x70, 0x70, 0x70,
|
||||
0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x71, 0x71, 0x71, 0x71,
|
||||
0x71, 0x71, 0x71, 0x71, 0x71, 0x71, 0x71, 0x71, 0x71, 0x71, 0x71, 0x71, 0x72, 0x72, 0x72, 0x72,
|
||||
0x72, 0x72, 0x72, 0x72, 0x72, 0x72, 0x72, 0x72, 0x72, 0x72, 0x72, 0x72, 0x73, 0x73, 0x73, 0x73,
|
||||
0x73, 0x73, 0x73, 0x73, 0x73, 0x73, 0x73, 0x73, 0x73, 0x73, 0x73, 0x73, 0x74, 0x74, 0x74, 0x74,
|
||||
0x74, 0x74, 0x74, 0x74, 0x74, 0x74, 0x74, 0x74, 0x74, 0x74, 0x74, 0x74, 0x75, 0x75, 0x75, 0x75,
|
||||
0x75, 0x75, 0x75, 0x75, 0x75, 0x75, 0x75, 0x75, 0x75, 0x75, 0x75, 0x75, 0x76, 0x76, 0x76, 0x76,
|
||||
0x76, 0x76, 0x76, 0x76, 0x76, 0x76, 0x76, 0x76, 0x76, 0x76, 0x76, 0x76, 0x77, 0x77, 0x77, 0x77,
|
||||
0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x78, 0x78, 0x78, 0x78,
|
||||
0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x79, 0x79, 0x79, 0x79,
|
||||
0x79, 0x79, 0x79, 0x79, 0x79, 0x79, 0x79, 0x79, 0x79, 0x79, 0x79, 0x79, 0x7a, 0x7a, 0x7a, 0x7a,
|
||||
0x7a, 0x7a, 0x7a, 0x7a, 0x7a, 0x7a, 0x7a, 0x7a, 0x7a, 0x7a, 0x7a, 0x7a, 0x7b, 0x7b, 0x7b, 0x7b,
|
||||
0x7b, 0x7b, 0x7b, 0x7b, 0x7b, 0x7b, 0x7b, 0x7b, 0x7b, 0x7b, 0x7b, 0x7b, 0x7c, 0x7c, 0x7c, 0x7c,
|
||||
0x7c, 0x7c, 0x7c, 0x7c, 0x7c, 0x7c, 0x7c, 0x7c, 0x7c, 0x7c, 0x7c, 0x7c, 0x7d, 0x7d, 0x7d, 0x7d,
|
||||
0x7d, 0x7d, 0x7d, 0x7d, 0x7d, 0x7d, 0x7d, 0x7d, 0x7d, 0x7d, 0x7d, 0x7d, 0x7e, 0x7e, 0x7e, 0x7e,
|
||||
0x7e, 0x7e, 0x7e, 0x7e, 0x7e, 0x7e, 0x7e, 0x7e, 0x7e, 0x7e, 0x7e, 0x7e, 0x7f, 0x7f, 0x7f, 0x7f,
|
||||
0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x80, 0x80, 0x80, 0x80,
|
||||
0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x81, 0x81, 0x81, 0x81,
|
||||
0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x82, 0x82, 0x82, 0x82,
|
||||
0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x83, 0x83, 0x83, 0x83,
|
||||
0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x84, 0x84, 0x84, 0x84,
|
||||
0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x85, 0x85, 0x85, 0x85,
|
||||
0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x86, 0x86, 0x86, 0x86,
|
||||
0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x87, 0x87, 0x87, 0x87,
|
||||
0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x88, 0x88, 0x88, 0x88,
|
||||
0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x89, 0x89, 0x89, 0x89,
|
||||
0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x8a, 0x8a, 0x8a, 0x8a,
|
||||
0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8b, 0x8b, 0x8b, 0x8b,
|
||||
0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8c, 0x8c, 0x8c, 0x8c,
|
||||
0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8d, 0x8d, 0x8d, 0x8d,
|
||||
0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8e, 0x8e, 0x8e, 0x8e,
|
||||
0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8f, 0x8f, 0x8f, 0x8f,
|
||||
0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x90, 0x90, 0x90, 0x90,
|
||||
0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x91, 0x91, 0x91, 0x91,
|
||||
0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x92, 0x92, 0x92, 0x92,
|
||||
0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x93, 0x93, 0x93, 0x93,
|
||||
0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x94, 0x94, 0x94, 0x94,
|
||||
0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x95, 0x95, 0x95, 0x95,
|
||||
0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x96, 0x96, 0x96, 0x96,
|
||||
0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x97, 0x97, 0x97, 0x97,
|
||||
0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x98, 0x98, 0x98, 0x98,
|
||||
0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x99, 0x99, 0x99, 0x99,
|
||||
0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x9a, 0x9a, 0x9a, 0x9a,
|
||||
0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9b, 0x9b, 0x9b, 0x9b,
|
||||
0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9c, 0x9c, 0x9c, 0x9c,
|
||||
0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9c, 0x9d, 0x9d, 0x9d, 0x9d,
|
||||
0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9e, 0x9e, 0x9e, 0x9e,
|
||||
0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9f, 0x9f, 0x9f, 0x9f,
|
||||
0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0xa0, 0xa0, 0xa0, 0xa0,
|
||||
0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa1, 0xa1, 0xa1, 0xa1,
|
||||
0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa2, 0xa2, 0xa2, 0xa2,
|
||||
0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa3, 0xa3, 0xa3, 0xa3,
|
||||
0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa4, 0xa4, 0xa4, 0xa4,
|
||||
0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4,
|
||||
};
|
||||
|
||||
uint8 cycle2hc40[488] = {
|
||||
0xA4, 0xA5, 0xA5, 0xA6, 0xA6, 0xA7, 0xA7, 0xA7, 0xA8, 0xA8, 0xA9, 0xA9, 0xAA, 0xAA, 0xAA, 0xAB,
|
||||
0xAB, 0xAC, 0xAC, 0xAD, 0xAD, 0xAD, 0xAE, 0xAE, 0xAF, 0xAF, 0xB0, 0xB0, 0xB1, 0xB1, 0xB1, 0xB2,
|
||||
0xB2, 0xB3, 0xB3, 0xB4, 0xB4, 0xB4, 0xB5, 0xB5, 0xB6, 0xB6,
|
||||
0xE4, 0xE4, 0xE4, 0xE5, 0xE5, 0xE6, 0xE6,
|
||||
0xE7, 0xE7, 0xE7, 0xE8, 0xE8, 0xE9, 0xE9, 0xEA, 0xEA, 0xEB, 0xEB, 0xEB, 0xEC, 0xEC, 0xED, 0xED,
|
||||
0xEE, 0xEE, 0xEE, 0xEF, 0xEF, 0xF0, 0xF0, 0xF1, 0xF1, 0xF1, 0xF2, 0xF2, 0xF3, 0xF3, 0xF4, 0xF4,
|
||||
0xF4, 0xF5, 0xF5, 0xF6, 0xF6, 0xF7, 0xF7, 0xF7, 0xF8, 0xF8, 0xF9, 0xF9, 0xFA, 0xFA, 0xFB, 0xFB,
|
||||
0xFB, 0xFC, 0xFC, 0xFD, 0xFD, 0xFE, 0xFE, 0xFE, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x01, 0x01, 0x02,
|
||||
0x02, 0x03, 0x03, 0x03, 0x04, 0x04, 0x05, 0x05, 0x06, 0x06, 0x06, 0x07, 0x07, 0x08, 0x08, 0x09,
|
||||
0x09, 0x09, 0x0A, 0x0A, 0x0B, 0x0B, 0x0C, 0x0C, 0x0C, 0x0D, 0x0D, 0x0E, 0x0E, 0x0F, 0x0F, 0x10,
|
||||
0x10, 0x10, 0x11, 0x11, 0x12, 0x12, 0x13, 0x13, 0x13, 0x14, 0x14, 0x15, 0x15, 0x16, 0x16, 0x16,
|
||||
0x17, 0x17, 0x18, 0x18, 0x19, 0x19, 0x19, 0x1A, 0x1A, 0x1B, 0x1B, 0x1C, 0x1C, 0x1C, 0x1D, 0x1D,
|
||||
0x1E, 0x1E, 0x1F, 0x1F, 0x20, 0x20, 0x20, 0x21, 0x21, 0x22, 0x22, 0x23, 0x23, 0x23, 0x24, 0x24,
|
||||
0x25, 0x25, 0x26, 0x26, 0x26, 0x27, 0x27, 0x28, 0x28, 0x29, 0x29, 0x29, 0x2A, 0x2A, 0x2B, 0x2B,
|
||||
0x2C, 0x2C, 0x2D, 0x2D, 0x2D, 0x2E, 0x2E, 0x2F, 0x2F, 0x30, 0x30, 0x30, 0x31, 0x31, 0x32, 0x32,
|
||||
0x33, 0x33, 0x33, 0x34, 0x34, 0x35, 0x35, 0x36, 0x36, 0x36, 0x37, 0x37, 0x38, 0x38, 0x39, 0x39,
|
||||
0x39, 0x3A, 0x3A, 0x3B, 0x3B, 0x3C, 0x3C, 0x3D, 0x3D, 0x3D, 0x3E, 0x3E, 0x3F, 0x3F, 0x40, 0x40,
|
||||
0x40, 0x41, 0x41, 0x42, 0x42, 0x43, 0x43, 0x43, 0x44, 0x44, 0x45, 0x45, 0x46, 0x46, 0x46, 0x47,
|
||||
0x47, 0x48, 0x48, 0x49, 0x49, 0x4A, 0x4A, 0x4A, 0x4B, 0x4B, 0x4C, 0x4C, 0x4D, 0x4D, 0x4D, 0x4E,
|
||||
0x4E, 0x4F, 0x4F, 0x50, 0x50, 0x50, 0x51, 0x51, 0x52, 0x52, 0x53, 0x53, 0x53, 0x54, 0x54, 0x55,
|
||||
0x55, 0x56, 0x56, 0x56, 0x57, 0x57, 0x58, 0x58, 0x59, 0x59, 0x5A, 0x5A, 0x5A, 0x5B, 0x5B, 0x5C,
|
||||
0x5C, 0x5D, 0x5D, 0x5D, 0x5E, 0x5E, 0x5F, 0x5F, 0x60, 0x60, 0x60, 0x61, 0x61, 0x62, 0x62, 0x63,
|
||||
0x63, 0x63, 0x64, 0x64, 0x65, 0x65, 0x66, 0x66, 0x67, 0x67, 0x67, 0x68, 0x68, 0x69, 0x69, 0x6A,
|
||||
0x6A, 0x6A, 0x6B, 0x6B, 0x6C, 0x6C, 0x6D, 0x6D, 0x6D, 0x6E, 0x6E, 0x6F, 0x6F, 0x70, 0x70, 0x70,
|
||||
0x71, 0x71, 0x72, 0x72, 0x73, 0x73, 0x73, 0x74, 0x74, 0x75, 0x75, 0x76, 0x76, 0x77, 0x77, 0x77,
|
||||
0x78, 0x78, 0x79, 0x79, 0x7A, 0x7A, 0x7A, 0x7B, 0x7B, 0x7C, 0x7C, 0x7D, 0x7D, 0x7D, 0x7E, 0x7E,
|
||||
0x7F, 0x7F, 0x80, 0x80, 0x80, 0x81, 0x81, 0x82, 0x82, 0x83, 0x83, 0x84, 0x84, 0x84, 0x85, 0x85,
|
||||
0x86, 0x86, 0x87, 0x87, 0x87, 0x88, 0x88, 0x89, 0x89, 0x8A, 0x8A, 0x8A, 0x8B, 0x8B, 0x8C, 0x8C,
|
||||
0x8D, 0x8D, 0x8D, 0x8E, 0x8E, 0x8F, 0x8F, 0x90, 0x90, 0x90, 0x91, 0x91, 0x92, 0x92, 0x93, 0x93,
|
||||
0x94, 0x94, 0x94, 0x95, 0x95, 0x96, 0x96, 0x97, 0x97, 0x97, 0x98, 0x98, 0x99, 0x99, 0x9A, 0x9A,
|
||||
0x9A, 0x9B, 0x9B, 0x9C, 0x9C, 0x9D, 0x9D, 0x9D, 0x9E, 0x9E, 0x9F, 0x9F, 0xA0, 0xA0, 0xA1, 0xA1,
|
||||
0xA1, 0xA2, 0xA2, 0xA3, 0xA3, 0xA4, 0xA4,
|
||||
uint8 cycle2hc32[3420] =
|
||||
{
|
||||
/* end of active display (16 pixels -> 160 Mcycles) , HINT triggered ? , Vcounter jump */
|
||||
0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85,
|
||||
0x85, 0x85, 0x85, 0x85, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86,
|
||||
0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87,
|
||||
0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x88, 0x88, 0x88, 0x88,
|
||||
0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88,
|
||||
0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89,
|
||||
0x89, 0x89, 0x89, 0x89, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a,
|
||||
0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b,
|
||||
0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8c, 0x8c, 0x8c, 0x8c,
|
||||
0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c,
|
||||
|
||||
/* right border (14 pixels -> 140 Mcycles) */
|
||||
0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d,
|
||||
0x8d, 0x8d, 0x8d, 0x8d, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e,
|
||||
0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f,
|
||||
0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x90, 0x90, 0x90, 0x90,
|
||||
0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90,
|
||||
0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91,
|
||||
0x91, 0x91, 0x91, 0x91, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92,
|
||||
0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93,
|
||||
0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93,
|
||||
|
||||
/* right blanking (9 pixels -> 90 Mcycles) , VDP status HBLANK flag set */
|
||||
0xe9, 0xe9, 0xe9, 0xe9,
|
||||
0xe9, 0xe9, 0xe9, 0xe9, 0xe9, 0xe9, 0xe9, 0xe9, 0xe9, 0xe9, 0xe9, 0xe9, 0xe9, 0xe9, 0xe9, 0xe9,
|
||||
0xea, 0xea, 0xea, 0xea, 0xea, 0xea, 0xea, 0xea, 0xea, 0xea, 0xea, 0xea, 0xea, 0xea, 0xea, 0xea,
|
||||
0xea, 0xea, 0xea, 0xea, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb,
|
||||
0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xec, 0xec, 0xec, 0xec, 0xec, 0xec, 0xec, 0xec,
|
||||
0xec, 0xec, 0xec, 0xec, 0xec, 0xec, 0xec, 0xec, 0xec, 0xec, 0xec, 0xec, 0xed, 0xed, 0xed, 0xed,
|
||||
0xed, 0xed, 0xed, 0xed, 0xed, 0xed,
|
||||
|
||||
/* horizontal sync (26 pixels -> 260 Mcycles) */
|
||||
0xed, 0xed, 0xed, 0xed, 0xed, 0xed, 0xed, 0xed, 0xed, 0xed,
|
||||
0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee,
|
||||
0xee, 0xee, 0xee, 0xee, 0xef, 0xef, 0xef, 0xef, 0xef, 0xef, 0xef, 0xef, 0xef, 0xef, 0xef, 0xef,
|
||||
0xef, 0xef, 0xef, 0xef, 0xef, 0xef, 0xef, 0xef, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0,
|
||||
0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf1, 0xf1, 0xf1, 0xf1,
|
||||
0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1,
|
||||
0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2,
|
||||
0xf2, 0xf2, 0xf2, 0xf2, 0xf3, 0xf3, 0xf3, 0xf3, 0xf3, 0xf3, 0xf3, 0xf3, 0xf3, 0xf3, 0xf3, 0xf3,
|
||||
0xf3, 0xf3, 0xf3, 0xf3, 0xf3, 0xf3, 0xf3, 0xf3, 0xf4, 0xf4, 0xf4, 0xf4, 0xf4, 0xf4, 0xf4, 0xf4,
|
||||
0xf4, 0xf4, 0xf4, 0xf4, 0xf4, 0xf4, 0xf4, 0xf4, 0xf4, 0xf4, 0xf4, 0xf4, 0xf5, 0xf5, 0xf5, 0xf5,
|
||||
0xf5, 0xf5, 0xf5, 0xf5, 0xf5, 0xf5, 0xf5, 0xf5, 0xf5, 0xf5, 0xf5, 0xf5, 0xf5, 0xf5, 0xf5, 0xf5,
|
||||
0xf6, 0xf6, 0xf6, 0xf6, 0xf6, 0xf6, 0xf6, 0xf6, 0xf6, 0xf6, 0xf6, 0xf6, 0xf6, 0xf6, 0xf6, 0xf6,
|
||||
0xf6, 0xf6, 0xf6, 0xf6, 0xf7, 0xf7, 0xf7, 0xf7, 0xf7, 0xf7, 0xf7, 0xf7, 0xf7, 0xf7, 0xf7, 0xf7,
|
||||
0xf7, 0xf7, 0xf7, 0xf7, 0xf7, 0xf7, 0xf7, 0xf7, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8,
|
||||
0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf9, 0xf9, 0xf9, 0xf9,
|
||||
0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9,
|
||||
0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa,
|
||||
|
||||
/* left blanking (24 pixels -> 240 Mcycles) */
|
||||
0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa,
|
||||
0xfa, 0xfa, 0xfa, 0xfa, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
|
||||
0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc,
|
||||
0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfd, 0xfd, 0xfd, 0xfd,
|
||||
0xfd, 0xfd, 0xfd, 0xfd, 0xfd, 0xfd, 0xfd, 0xfd, 0xfd, 0xfd, 0xfd, 0xfd, 0xfd, 0xfd, 0xfd, 0xfd,
|
||||
0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe,
|
||||
0xfe, 0xfe, 0xfe, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01,
|
||||
0x01, 0x01, 0x01, 0x01,
|
||||
/* Vertical Interrupt triggered ? */
|
||||
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
|
||||
0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
|
||||
0x02, 0x02, 0x02, 0x02, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
|
||||
0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
|
||||
0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x05, 0x05, 0x05, 0x05,
|
||||
0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
|
||||
0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
|
||||
|
||||
/* left border (13 pixels -> 130 Mcycles) , VDP status HBLANK flag cleared */
|
||||
0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
|
||||
0x06, 0x06, 0x06, 0x06, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
|
||||
0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08,
|
||||
0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x09, 0x09, 0x09, 0x09,
|
||||
0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09,
|
||||
0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a,
|
||||
0x0a, 0x0a, 0x0a, 0x0a, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b,
|
||||
0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c,
|
||||
0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c,
|
||||
|
||||
/* remaining active display (240 pixels -> 2400 Mcycles) */
|
||||
0x0d, 0x0d, 0x0d, 0x0d,
|
||||
0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d,
|
||||
0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e,
|
||||
0x0e, 0x0e, 0x0e, 0x0e, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f,
|
||||
0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
|
||||
0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x11, 0x11, 0x11, 0x11,
|
||||
0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
|
||||
0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12,
|
||||
0x12, 0x12, 0x12, 0x12, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13,
|
||||
0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14,
|
||||
0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x15, 0x15, 0x15, 0x15,
|
||||
0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15,
|
||||
0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16,
|
||||
0x16, 0x16, 0x16, 0x16, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17,
|
||||
0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
|
||||
0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x19, 0x19, 0x19, 0x19,
|
||||
0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19,
|
||||
0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a,
|
||||
0x1a, 0x1a, 0x1a, 0x1a, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b,
|
||||
0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c,
|
||||
0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1d, 0x1d, 0x1d, 0x1d,
|
||||
0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d,
|
||||
0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
|
||||
0x1e, 0x1e, 0x1e, 0x1e, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f,
|
||||
0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
|
||||
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x21, 0x21, 0x21, 0x21,
|
||||
0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21,
|
||||
0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22,
|
||||
0x22, 0x22, 0x22, 0x22, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23,
|
||||
0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24,
|
||||
0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x25, 0x25, 0x25, 0x25,
|
||||
0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25,
|
||||
0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26,
|
||||
0x26, 0x26, 0x26, 0x26, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27,
|
||||
0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28,
|
||||
0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x29, 0x29, 0x29, 0x29,
|
||||
0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29,
|
||||
0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a,
|
||||
0x2a, 0x2a, 0x2a, 0x2a, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b,
|
||||
0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c,
|
||||
0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2d, 0x2d, 0x2d, 0x2d,
|
||||
0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d,
|
||||
0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e,
|
||||
0x2e, 0x2e, 0x2e, 0x2e, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f,
|
||||
0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
|
||||
0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x31, 0x31, 0x31, 0x31,
|
||||
0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31,
|
||||
0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32,
|
||||
0x32, 0x32, 0x32, 0x32, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33,
|
||||
0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34,
|
||||
0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x35, 0x35, 0x35, 0x35,
|
||||
0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35,
|
||||
0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
|
||||
0x36, 0x36, 0x36, 0x36, 0x37, 0x37, 0x37, 0x37, 0x37, 0x37, 0x37, 0x37, 0x37, 0x37, 0x37, 0x37,
|
||||
0x37, 0x37, 0x37, 0x37, 0x37, 0x37, 0x37, 0x37, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38,
|
||||
0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x39, 0x39, 0x39, 0x39,
|
||||
0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39,
|
||||
0x3a, 0x3a, 0x3a, 0x3a, 0x3a, 0x3a, 0x3a, 0x3a, 0x3a, 0x3a, 0x3a, 0x3a, 0x3a, 0x3a, 0x3a, 0x3a,
|
||||
0x3a, 0x3a, 0x3a, 0x3a, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b,
|
||||
0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c,
|
||||
0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3d, 0x3d, 0x3d, 0x3d,
|
||||
0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d,
|
||||
0x3e, 0x3e, 0x3e, 0x3e, 0x3e, 0x3e, 0x3e, 0x3e, 0x3e, 0x3e, 0x3e, 0x3e, 0x3e, 0x3e, 0x3e, 0x3e,
|
||||
0x3e, 0x3e, 0x3e, 0x3e, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f,
|
||||
0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40,
|
||||
0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x41, 0x41, 0x41, 0x41,
|
||||
0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41,
|
||||
0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42,
|
||||
0x42, 0x42, 0x42, 0x42, 0x43, 0x43, 0x43, 0x43, 0x43, 0x43, 0x43, 0x43, 0x43, 0x43, 0x43, 0x43,
|
||||
0x43, 0x43, 0x43, 0x43, 0x43, 0x43, 0x43, 0x43, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44,
|
||||
0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x45, 0x45, 0x45, 0x45,
|
||||
0x45, 0x45, 0x45, 0x45, 0x45, 0x45, 0x45, 0x45, 0x45, 0x45, 0x45, 0x45, 0x45, 0x45, 0x45, 0x45,
|
||||
0x46, 0x46, 0x46, 0x46, 0x46, 0x46, 0x46, 0x46, 0x46, 0x46, 0x46, 0x46, 0x46, 0x46, 0x46, 0x46,
|
||||
0x46, 0x46, 0x46, 0x46, 0x47, 0x47, 0x47, 0x47, 0x47, 0x47, 0x47, 0x47, 0x47, 0x47, 0x47, 0x47,
|
||||
0x47, 0x47, 0x47, 0x47, 0x47, 0x47, 0x47, 0x47, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48,
|
||||
0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x49, 0x49, 0x49, 0x49,
|
||||
0x49, 0x49, 0x49, 0x49, 0x49, 0x49, 0x49, 0x49, 0x49, 0x49, 0x49, 0x49, 0x49, 0x49, 0x49, 0x49,
|
||||
0x4a, 0x4a, 0x4a, 0x4a, 0x4a, 0x4a, 0x4a, 0x4a, 0x4a, 0x4a, 0x4a, 0x4a, 0x4a, 0x4a, 0x4a, 0x4a,
|
||||
0x4a, 0x4a, 0x4a, 0x4a, 0x4b, 0x4b, 0x4b, 0x4b, 0x4b, 0x4b, 0x4b, 0x4b, 0x4b, 0x4b, 0x4b, 0x4b,
|
||||
0x4b, 0x4b, 0x4b, 0x4b, 0x4b, 0x4b, 0x4b, 0x4b, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c,
|
||||
0x4c, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c, 0x4d, 0x4d, 0x4d, 0x4d,
|
||||
0x4d, 0x4d, 0x4d, 0x4d, 0x4d, 0x4d, 0x4d, 0x4d, 0x4d, 0x4d, 0x4d, 0x4d, 0x4d, 0x4d, 0x4d, 0x4d,
|
||||
0x4e, 0x4e, 0x4e, 0x4e, 0x4e, 0x4e, 0x4e, 0x4e, 0x4e, 0x4e, 0x4e, 0x4e, 0x4e, 0x4e, 0x4e, 0x4e,
|
||||
0x4e, 0x4e, 0x4e, 0x4e, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f,
|
||||
0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50,
|
||||
0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x51, 0x51, 0x51, 0x51,
|
||||
0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51,
|
||||
0x52, 0x52, 0x52, 0x52, 0x52, 0x52, 0x52, 0x52, 0x52, 0x52, 0x52, 0x52, 0x52, 0x52, 0x52, 0x52,
|
||||
0x52, 0x52, 0x52, 0x52, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53,
|
||||
0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x54, 0x54, 0x54, 0x54, 0x54, 0x54, 0x54, 0x54,
|
||||
0x54, 0x54, 0x54, 0x54, 0x54, 0x54, 0x54, 0x54, 0x54, 0x54, 0x54, 0x54, 0x55, 0x55, 0x55, 0x55,
|
||||
0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
|
||||
0x56, 0x56, 0x56, 0x56, 0x56, 0x56, 0x56, 0x56, 0x56, 0x56, 0x56, 0x56, 0x56, 0x56, 0x56, 0x56,
|
||||
0x56, 0x56, 0x56, 0x56, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57,
|
||||
0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58,
|
||||
0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0x59, 0x59, 0x59, 0x59,
|
||||
0x59, 0x59, 0x59, 0x59, 0x59, 0x59, 0x59, 0x59, 0x59, 0x59, 0x59, 0x59, 0x59, 0x59, 0x59, 0x59,
|
||||
0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a,
|
||||
0x5a, 0x5a, 0x5a, 0x5a, 0x5b, 0x5b, 0x5b, 0x5b, 0x5b, 0x5b, 0x5b, 0x5b, 0x5b, 0x5b, 0x5b, 0x5b,
|
||||
0x5b, 0x5b, 0x5b, 0x5b, 0x5b, 0x5b, 0x5b, 0x5b, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c,
|
||||
0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5d, 0x5d, 0x5d, 0x5d,
|
||||
0x5d, 0x5d, 0x5d, 0x5d, 0x5d, 0x5d, 0x5d, 0x5d, 0x5d, 0x5d, 0x5d, 0x5d, 0x5d, 0x5d, 0x5d, 0x5d,
|
||||
0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e,
|
||||
0x5e, 0x5e, 0x5e, 0x5e, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f,
|
||||
0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60,
|
||||
0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x61, 0x61, 0x61, 0x61,
|
||||
0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61,
|
||||
0x62, 0x62, 0x62, 0x62, 0x62, 0x62, 0x62, 0x62, 0x62, 0x62, 0x62, 0x62, 0x62, 0x62, 0x62, 0x62,
|
||||
0x62, 0x62, 0x62, 0x62, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
|
||||
0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x64, 0x64, 0x64, 0x64, 0x64, 0x64, 0x64, 0x64,
|
||||
0x64, 0x64, 0x64, 0x64, 0x64, 0x64, 0x64, 0x64, 0x64, 0x64, 0x64, 0x64, 0x65, 0x65, 0x65, 0x65,
|
||||
0x65, 0x65, 0x65, 0x65, 0x65, 0x65, 0x65, 0x65, 0x65, 0x65, 0x65, 0x65, 0x65, 0x65, 0x65, 0x65,
|
||||
0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66,
|
||||
0x66, 0x66, 0x66, 0x66, 0x67, 0x67, 0x67, 0x67, 0x67, 0x67, 0x67, 0x67, 0x67, 0x67, 0x67, 0x67,
|
||||
0x67, 0x67, 0x67, 0x67, 0x67, 0x67, 0x67, 0x67, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68,
|
||||
0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x69, 0x69, 0x69, 0x69,
|
||||
0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69,
|
||||
0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a,
|
||||
0x6a, 0x6a, 0x6a, 0x6a, 0x6b, 0x6b, 0x6b, 0x6b, 0x6b, 0x6b, 0x6b, 0x6b, 0x6b, 0x6b, 0x6b, 0x6b,
|
||||
0x6b, 0x6b, 0x6b, 0x6b, 0x6b, 0x6b, 0x6b, 0x6b, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c,
|
||||
0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6d, 0x6d, 0x6d, 0x6d,
|
||||
0x6d, 0x6d, 0x6d, 0x6d, 0x6d, 0x6d, 0x6d, 0x6d, 0x6d, 0x6d, 0x6d, 0x6d, 0x6d, 0x6d, 0x6d, 0x6d,
|
||||
0x6e, 0x6e, 0x6e, 0x6e, 0x6e, 0x6e, 0x6e, 0x6e, 0x6e, 0x6e, 0x6e, 0x6e, 0x6e, 0x6e, 0x6e, 0x6e,
|
||||
0x6e, 0x6e, 0x6e, 0x6e, 0x6f, 0x6f, 0x6f, 0x6f, 0x6f, 0x6f, 0x6f, 0x6f, 0x6f, 0x6f, 0x6f, 0x6f,
|
||||
0x6f, 0x6f, 0x6f, 0x6f, 0x6f, 0x6f, 0x6f, 0x6f, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70,
|
||||
0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x71, 0x71, 0x71, 0x71,
|
||||
0x71, 0x71, 0x71, 0x71, 0x71, 0x71, 0x71, 0x71, 0x71, 0x71, 0x71, 0x71, 0x71, 0x71, 0x71, 0x71,
|
||||
0x72, 0x72, 0x72, 0x72, 0x72, 0x72, 0x72, 0x72, 0x72, 0x72, 0x72, 0x72, 0x72, 0x72, 0x72, 0x72,
|
||||
0x72, 0x72, 0x72, 0x72, 0x73, 0x73, 0x73, 0x73, 0x73, 0x73, 0x73, 0x73, 0x73, 0x73, 0x73, 0x73,
|
||||
0x73, 0x73, 0x73, 0x73, 0x73, 0x73, 0x73, 0x73, 0x74, 0x74, 0x74, 0x74, 0x74, 0x74, 0x74, 0x74,
|
||||
0x74, 0x74, 0x74, 0x74, 0x74, 0x74, 0x74, 0x74, 0x74, 0x74, 0x74, 0x74, 0x75, 0x75, 0x75, 0x75,
|
||||
0x75, 0x75, 0x75, 0x75, 0x75, 0x75, 0x75, 0x75, 0x75, 0x75, 0x75, 0x75, 0x75, 0x75, 0x75, 0x75,
|
||||
0x76, 0x76, 0x76, 0x76, 0x76, 0x76, 0x76, 0x76, 0x76, 0x76, 0x76, 0x76, 0x76, 0x76, 0x76, 0x76,
|
||||
0x76, 0x76, 0x76, 0x76, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77,
|
||||
0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78,
|
||||
0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x79, 0x79, 0x79, 0x79,
|
||||
0x79, 0x79, 0x79, 0x79, 0x79, 0x79, 0x79, 0x79, 0x79, 0x79, 0x79, 0x79, 0x79, 0x79, 0x79, 0x79,
|
||||
0x7a, 0x7a, 0x7a, 0x7a, 0x7a, 0x7a, 0x7a, 0x7a, 0x7a, 0x7a, 0x7a, 0x7a, 0x7a, 0x7a, 0x7a, 0x7a,
|
||||
0x7a, 0x7a, 0x7a, 0x7a, 0x7b, 0x7b, 0x7b, 0x7b, 0x7b, 0x7b, 0x7b, 0x7b, 0x7b, 0x7b, 0x7b, 0x7b,
|
||||
0x7b, 0x7b, 0x7b, 0x7b, 0x7b, 0x7b, 0x7b, 0x7b, 0x7c, 0x7c, 0x7c, 0x7c, 0x7c, 0x7c, 0x7c, 0x7c,
|
||||
0x7c, 0x7c, 0x7c, 0x7c, 0x7c, 0x7c, 0x7c, 0x7c, 0x7c, 0x7c, 0x7c, 0x7c, 0x7d, 0x7d, 0x7d, 0x7d,
|
||||
0x7d, 0x7d, 0x7d, 0x7d, 0x7d, 0x7d, 0x7d, 0x7d, 0x7d, 0x7d, 0x7d, 0x7d, 0x7d, 0x7d, 0x7d, 0x7d,
|
||||
0x7e, 0x7e, 0x7e, 0x7e, 0x7e, 0x7e, 0x7e, 0x7e, 0x7e, 0x7e, 0x7e, 0x7e, 0x7e, 0x7e, 0x7e, 0x7e,
|
||||
0x7e, 0x7e, 0x7e, 0x7e, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f,
|
||||
0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
|
||||
0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x81, 0x81, 0x81, 0x81,
|
||||
0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81,
|
||||
0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82,
|
||||
0x82, 0x82, 0x82, 0x82, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83,
|
||||
0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84,
|
||||
0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84,
|
||||
};
|
||||
|
||||
uint8 *vctab;
|
||||
|
@ -382,10 +382,27 @@ void set_region ()
|
||||
}
|
||||
|
||||
/* Force region setting */
|
||||
if (config.region_detect == 1) region_code = REGION_USA;
|
||||
else if (config.region_detect == 2) region_code = REGION_EUROPE;
|
||||
else if (config.region_detect == 3) region_code = REGION_JAPAN_NTSC;
|
||||
else if (config.region_detect == 4) region_code = REGION_JAPAN_PAL;
|
||||
if (config.region_detect == 1)
|
||||
region_code = REGION_USA;
|
||||
else if (config.region_detect == 2)
|
||||
region_code = REGION_EUROPE;
|
||||
else if (config.region_detect == 3)
|
||||
region_code = REGION_JAPAN_NTSC;
|
||||
else if (config.region_detect == 4)
|
||||
region_code = REGION_JAPAN_PAL;
|
||||
|
||||
/* Set VDP default mode */
|
||||
switch (region_code)
|
||||
{
|
||||
case REGION_EUROPE:
|
||||
case REGION_JAPAN_PAL:
|
||||
vdp_pal = 1;
|
||||
break;
|
||||
|
||||
default:
|
||||
vdp_pal = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
|
@ -318,23 +318,25 @@ void m68k_pulse_reset(void);
|
||||
|
||||
/* execute num_cycles worth of instructions. returns number of cycles used */
|
||||
//int m68k_execute(int num_cycles);
|
||||
void m68k_run (int cyc);
|
||||
|
||||
/* run until global cycle count is reached */
|
||||
void m68k_run(unsigned int cycles);
|
||||
|
||||
/* These functions let you read/write/modify the number of cycles left to run
|
||||
* while m68k_execute() is running.
|
||||
* These are useful if the 68k accesses a memory-mapped port on another device
|
||||
* that requires immediate processing by another CPU.
|
||||
*/
|
||||
int m68k_cycles_run(void); /* Number of cycles run so far */
|
||||
int m68k_cycles_remaining(void); /* Number of cycles left */
|
||||
void m68k_modify_timeslice(int cycles); /* Modify cycles left */
|
||||
void m68k_end_timeslice(void); /* End timeslice now */
|
||||
//int m68k_cycles_run(void); /* Number of cycles run so far */
|
||||
//int m68k_cycles_remaining(void); /* Number of cycles left */
|
||||
//void m68k_modify_timeslice(int cycles); /* Modify cycles left */
|
||||
//void m68k_end_timeslice(void); /* End timeslice now */
|
||||
|
||||
/* Set the IPL0-IPL2 pins on the CPU (IRQ).
|
||||
* A transition from < 7 to 7 will cause a non-maskable interrupt (NMI).
|
||||
* Setting IRQ to 0 will clear an interrupt request.
|
||||
*/
|
||||
//void m68k_set_irq(unsigned int int_level);
|
||||
void m68k_set_irq(unsigned int int_level);
|
||||
|
||||
|
||||
/* Halt the CPU as if you pulsed the HALT pin. */
|
||||
|
@ -43,8 +43,8 @@ extern void m68040_fpu_op1(void);
|
||||
/* ================================= DATA ================================= */
|
||||
/* ======================================================================== */
|
||||
|
||||
int m68ki_initial_cycles;
|
||||
int m68ki_remaining_cycles = 0; /* Number of clocks remaining */
|
||||
//int m68ki_initial_cycles;
|
||||
//int m68ki_remaining_cycles = 0; /* Number of clocks remaining */
|
||||
uint m68ki_tracing = 0;
|
||||
uint m68ki_address_space;
|
||||
|
||||
@ -777,10 +777,11 @@ void m68k_set_cpu_type(unsigned int cpu_type)
|
||||
}
|
||||
|
||||
/* Execute a single instruction */
|
||||
INLINE int m68k_execute(void)
|
||||
//INLINE int m68k_execute(void)
|
||||
INLINE void m68k_execute(void)
|
||||
{
|
||||
/* Set our pool of clock cycles available */
|
||||
SET_CYCLES(0);
|
||||
//SET_CYCLES(0);
|
||||
|
||||
/* Set tracing accodring to T1. (T0 is done inside instruction) */
|
||||
m68ki_trace_t1(); /* auto-disable (see m68kcpu.h) */
|
||||
@ -803,15 +804,14 @@ INLINE int m68k_execute(void)
|
||||
m68ki_exception_if_trace(); /* auto-disable (see m68kcpu.h) */
|
||||
|
||||
/* return how many clocks we used */
|
||||
return - GET_CYCLES();
|
||||
|
||||
//return - GET_CYCLES();
|
||||
}
|
||||
|
||||
/* ASG: rewrote so that the int_level is a mask of the IPL0/IPL1/IPL2 bits */
|
||||
/* KS: Modified so that IPL* bits match with mask positions in the SR
|
||||
* and cleaned out remenants of the interrupt controller.
|
||||
*/
|
||||
INLINE void m68k_set_irq(unsigned int int_level)
|
||||
void m68k_set_irq(unsigned int int_level)
|
||||
{
|
||||
uint old_level = CPU_INT_LEVEL;
|
||||
CPU_INT_LEVEL = int_level << 8;
|
||||
@ -830,50 +830,50 @@ extern void error(char *format, ...);
|
||||
#endif
|
||||
extern uint8 irq_status;
|
||||
|
||||
void m68k_run (int cyc)
|
||||
void m68k_run (unsigned int cycles)
|
||||
{
|
||||
int temp;
|
||||
unsigned int int_level;
|
||||
|
||||
/* Return point if we had an address error */
|
||||
m68ki_set_address_error_trap(); /* auto-disable (see m68kcpu.h) */
|
||||
|
||||
while (count_m68k < cyc)
|
||||
while (mcycles_68k < cycles)
|
||||
{
|
||||
/* Make sure we're not stopped */
|
||||
if(CPU_STOPPED)
|
||||
{
|
||||
mcycles_68k = cycles;
|
||||
return;
|
||||
}
|
||||
|
||||
/* check interrupt updates */
|
||||
if (irq_status & 0x10)
|
||||
{
|
||||
irq_status &= ~0x10;
|
||||
|
||||
temp = irq_status & 6;
|
||||
int_level = irq_status & 6;
|
||||
|
||||
/* hardware latency */
|
||||
if (irq_status & 0x40)
|
||||
count_m68k += m68k_execute();
|
||||
m68k_execute();
|
||||
|
||||
#ifdef LOGVDP
|
||||
error("[%d(%d)][%d(%d)] IRQ Level = %d (%d cycles)(%x)\n", v_counter, count_m68k/488, count_m68k, count_m68k%488,temp, m68ki_remaining_cycles,m68k_get_reg (NULL, M68K_REG_PC));
|
||||
error("[%d(%d)][%d(%d)] IRQ Level = %d (%x)\n", v_counter, mcycles_68k/3420, mcycles_68k, mcycles_68k%3420,int_level,m68k_get_reg (NULL, M68K_REG_PC));
|
||||
#endif
|
||||
/* interrupt level */
|
||||
m68k_set_irq(temp);
|
||||
}
|
||||
/* update IRQ level */
|
||||
CPU_INT_LEVEL = int_level << 8;
|
||||
m68ki_check_interrupts();
|
||||
|
||||
if (mcycles_68k >= cycles)
|
||||
return;
|
||||
|
||||
/* Make sure we're not stopped */
|
||||
if(CPU_STOPPED)
|
||||
{
|
||||
count_m68k = cyc;
|
||||
REG_PPC = REG_PC;
|
||||
return;
|
||||
}
|
||||
|
||||
/* execute a single instruction */
|
||||
count_m68k += m68k_execute();
|
||||
m68k_execute();
|
||||
}
|
||||
|
||||
/* set previous PC to current PC for the next entry into the loop */
|
||||
REG_PPC = REG_PC;
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
int m68k_cycles_run(void)
|
||||
{
|
||||
return m68ki_initial_cycles - GET_CYCLES();
|
||||
@ -883,20 +883,22 @@ int m68k_cycles_remaining(void)
|
||||
{
|
||||
return GET_CYCLES();
|
||||
}
|
||||
*/
|
||||
|
||||
/* Change the timeslice */
|
||||
/*
|
||||
void m68k_modify_timeslice(int cycles)
|
||||
{
|
||||
m68ki_initial_cycles += cycles;
|
||||
ADD_CYCLES(cycles);
|
||||
}
|
||||
|
||||
|
||||
void m68k_end_timeslice(void)
|
||||
{
|
||||
m68ki_initial_cycles = GET_CYCLES();
|
||||
SET_CYCLES(0);
|
||||
}
|
||||
*/
|
||||
|
||||
void m68k_init(void)
|
||||
{
|
||||
@ -904,7 +906,7 @@ void m68k_init(void)
|
||||
|
||||
/* The first call to this function initializes the opcode handler jump table */
|
||||
if(!emulation_initialized)
|
||||
{
|
||||
{
|
||||
m68ki_build_opcode_table();
|
||||
emulation_initialized = 1;
|
||||
}
|
||||
@ -925,7 +927,7 @@ void m68k_pulse_reset(void)
|
||||
{
|
||||
/* Clear all stop levels and eat up all remaining cycles */
|
||||
CPU_STOPPED = 0;
|
||||
SET_CYCLES(0);
|
||||
//SET_CYCLES(0);
|
||||
|
||||
CPU_RUN_MODE = RUN_MODE_BERR_AERR_RESET;
|
||||
|
||||
@ -953,6 +955,8 @@ void m68k_pulse_reset(void)
|
||||
m68ki_jump(REG_PC);
|
||||
|
||||
CPU_RUN_MODE = RUN_MODE_NORMAL;
|
||||
|
||||
USE_CYCLES(CYC_EXCEPTION[EXCEPTION_RESET]);
|
||||
}
|
||||
|
||||
/* Pulse the HALT line on the CPU */
|
||||
|
@ -33,8 +33,6 @@
|
||||
#include <setjmp.h>
|
||||
#endif /* M68K_EMULATE_ADDRESS_ERROR */
|
||||
|
||||
extern unsigned int count_m68k;
|
||||
|
||||
/* ======================================================================== */
|
||||
/* ==================== ARCHITECTURE-DEPENDANT DEFINES ==================== */
|
||||
/* ======================================================================== */
|
||||
@ -562,10 +560,6 @@ extern unsigned int count_m68k;
|
||||
if(setjmp(m68ki_aerr_trap) != 0) \
|
||||
{ \
|
||||
m68ki_exception_address_error(); \
|
||||
if(CPU_STOPPED) \
|
||||
{ \
|
||||
SET_CYCLES(0); \
|
||||
} \
|
||||
}
|
||||
|
||||
#define m68ki_check_address_error(ADDR, WRITE_MODE, FC) \
|
||||
@ -799,12 +793,15 @@ extern unsigned int count_m68k;
|
||||
|
||||
/* ---------------------------- Cycle Counting ---------------------------- */
|
||||
|
||||
/*
|
||||
#define ADD_CYCLES(A) m68ki_remaining_cycles += (A)
|
||||
#define USE_CYCLES(A) m68ki_remaining_cycles -= (A)
|
||||
#define SET_CYCLES(A) m68ki_remaining_cycles = A
|
||||
#define GET_CYCLES() m68ki_remaining_cycles
|
||||
#define USE_ALL_CYCLES() m68ki_remaining_cycles = 0
|
||||
*/
|
||||
|
||||
#define USE_CYCLES(A) mcycles_68k += (7 * (A))
|
||||
|
||||
|
||||
/* ----------------------------- Read / Write ----------------------------- */
|
||||
@ -917,9 +914,10 @@ typedef struct
|
||||
|
||||
} m68ki_cpu_core;
|
||||
|
||||
extern unsigned int mcycles_68k;
|
||||
|
||||
extern m68ki_cpu_core m68ki_cpu;
|
||||
extern sint m68ki_remaining_cycles;
|
||||
//extern sint m68ki_remaining_cycles;
|
||||
extern uint m68ki_tracing;
|
||||
extern const uint8 m68ki_shift_8_table[];
|
||||
extern const uint16 m68ki_shift_16_table[];
|
||||
@ -2042,16 +2040,10 @@ INLINE void m68ki_exception_interrupt(uint int_level)
|
||||
|
||||
m68ki_jump(new_pc);
|
||||
|
||||
/* Defer cycle counting until later */
|
||||
count_m68k += CYC_EXCEPTION[vector];
|
||||
|
||||
//#if !M68K_EMULATE_INT_ACK
|
||||
/* Automatically clear IRQ if we are not using an acknowledge scheme */
|
||||
CPU_INT_LEVEL = 0;
|
||||
//#endif /* M68K_EMULATE_INT_ACK */
|
||||
/* Update cycle count now */
|
||||
USE_CYCLES(CYC_EXCEPTION[vector]);
|
||||
}
|
||||
|
||||
|
||||
/* ASG: Check for interrupts */
|
||||
INLINE void m68ki_check_interrupts(void)
|
||||
{
|
||||
|
@ -31065,7 +31065,7 @@ static void m68k_op_stop(void)
|
||||
m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */
|
||||
CPU_STOPPED |= STOP_LEVEL_STOP;
|
||||
m68ki_set_sr(new_sr);
|
||||
m68ki_remaining_cycles = 0;
|
||||
//m68ki_remaining_cycles = 0;
|
||||
return;
|
||||
}
|
||||
m68ki_exception_privilege_violation();
|
||||
|
141
source/mem68k.c
141
source/mem68k.c
@ -68,7 +68,8 @@ void m68k_lockup_w_8 (uint32 address, uint32 data)
|
||||
error ("Lockup %08X = %02X (%08X)\n", address, data, m68k_get_reg (NULL, M68K_REG_PC));
|
||||
#endif
|
||||
gen_running = config.force_dtack;
|
||||
if (!gen_running) m68k_end_timeslice ();
|
||||
if (!gen_running)
|
||||
m68k_pulse_halt ();
|
||||
}
|
||||
|
||||
void m68k_lockup_w_16 (uint32 address, uint32 data)
|
||||
@ -77,7 +78,8 @@ void m68k_lockup_w_16 (uint32 address, uint32 data)
|
||||
error ("Lockup %08X = %04X (%08X)\n", address, data, m68k_get_reg (NULL, M68K_REG_PC));
|
||||
#endif
|
||||
gen_running = config.force_dtack;
|
||||
if (!gen_running) m68k_end_timeslice ();
|
||||
if (!gen_running)
|
||||
m68k_pulse_halt ();
|
||||
}
|
||||
|
||||
uint32 m68k_lockup_r_8 (uint32 address)
|
||||
@ -86,7 +88,8 @@ uint32 m68k_lockup_r_8 (uint32 address)
|
||||
error ("Lockup %08X.b (%08X)\n", address, m68k_get_reg (NULL, M68K_REG_PC));
|
||||
#endif
|
||||
gen_running = config.force_dtack;
|
||||
if (!gen_running) m68k_end_timeslice ();
|
||||
if (!gen_running)
|
||||
m68k_pulse_halt ();
|
||||
return -1;
|
||||
}
|
||||
|
||||
@ -96,7 +99,8 @@ uint32 m68k_lockup_r_16 (uint32 address)
|
||||
error ("Lockup %08X.w (%08X)\n", address, m68k_get_reg (NULL, M68K_REG_PC));
|
||||
#endif
|
||||
gen_running = config.force_dtack;
|
||||
if (!gen_running) m68k_end_timeslice ();
|
||||
if (!gen_running)
|
||||
m68k_pulse_halt ();
|
||||
return -1;
|
||||
}
|
||||
|
||||
@ -111,28 +115,32 @@ static int pico_page[7] = {0x00,0x01,0x03,0x07,0x0F,0x1F,0x3F};
|
||||
|
||||
uint32 eeprom_read_byte(uint32 address)
|
||||
{
|
||||
if (address == eeprom.type.sda_out_adr) return eeprom_read(address, 0);
|
||||
else return READ_BYTE(cart.rom, address);
|
||||
if (address == eeprom.type.sda_out_adr)
|
||||
return eeprom_read(address, 0);
|
||||
return READ_BYTE(cart.rom, address);
|
||||
}
|
||||
|
||||
uint32 eeprom_read_word(uint32 address)
|
||||
{
|
||||
if (address == (eeprom.type.sda_out_adr & 0xfffffe)) return eeprom_read(address, 1);
|
||||
else return *(uint16 *)(cart.rom + address);
|
||||
if (address == (eeprom.type.sda_out_adr & 0xfffffe))
|
||||
return eeprom_read(address, 1);
|
||||
return *(uint16 *)(cart.rom + address);
|
||||
}
|
||||
|
||||
void eeprom_write_byte(uint32 address, uint32 data)
|
||||
{
|
||||
if ((address == eeprom.type.sda_in_adr) || (address == eeprom.type.scl_adr))
|
||||
eeprom_write(address, data, 0);
|
||||
else m68k_unused_8_w(address, data);
|
||||
else
|
||||
m68k_unused_8_w(address, data);
|
||||
}
|
||||
|
||||
void eeprom_write_word(uint32 address, uint32 data)
|
||||
{
|
||||
if ((address == (eeprom.type.sda_in_adr&0xfffffe)) || (address == (eeprom.type.scl_adr&0xfffffe)))
|
||||
eeprom_write(address, data, 1);
|
||||
else m68k_unused_16_w (address, data);
|
||||
else
|
||||
m68k_unused_16_w (address, data);
|
||||
}
|
||||
|
||||
|
||||
@ -140,16 +148,19 @@ void eeprom_write_word(uint32 address, uint32 data)
|
||||
|
||||
uint32 z80_read_byte(uint32 address)
|
||||
{
|
||||
if (zbusack) return m68k_read_bus_8(address);
|
||||
/* Z80 bus is available ? */
|
||||
if (zstate ^ 3)
|
||||
return m68k_read_bus_8(address);
|
||||
|
||||
switch ((address >> 13) & 3)
|
||||
{
|
||||
case 2: /* YM2612 */
|
||||
return fm_read(0, address & 3);
|
||||
return fm_read(mcycles_68k, address & 3);
|
||||
|
||||
case 3: /* MISC */
|
||||
if ((address & 0xff00) == 0x7f00) return m68k_lockup_r_8(address); /* VDP */
|
||||
else return (m68k_read_bus_8(address) | 0xff);
|
||||
if ((address & 0xff00) == 0x7f00)
|
||||
return m68k_lockup_r_8(address); /* VDP */
|
||||
return (m68k_read_bus_8(address) | 0xff);
|
||||
|
||||
default: /* ZRAM */
|
||||
return zram[address & 0x1fff];
|
||||
@ -158,19 +169,22 @@ uint32 z80_read_byte(uint32 address)
|
||||
|
||||
uint32 z80_read_word(uint32 address)
|
||||
{
|
||||
if (zbusack) return m68k_read_bus_16(address);
|
||||
/* Z80 bus is available ? */
|
||||
if (zstate ^ 3)
|
||||
return m68k_read_bus_16(address);
|
||||
|
||||
switch ((address >> 13) & 3)
|
||||
{
|
||||
case 2: /* YM2612 */
|
||||
{
|
||||
int temp = fm_read(0, address & 3);
|
||||
int temp = fm_read(mcycles_68k, address & 3);
|
||||
return (temp << 8 | temp);
|
||||
}
|
||||
|
||||
case 3: /* MISC */
|
||||
if ((address & 0xff00) == 0x7f00) return m68k_lockup_r_16(address); /* VDP */
|
||||
else return (m68k_read_bus_16(address) | 0xffff);
|
||||
if ((address & 0xff00) == 0x7f00)
|
||||
return m68k_lockup_r_16(address); /* VDP */
|
||||
return (m68k_read_bus_16(address) | 0xffff);
|
||||
|
||||
default: /* ZRAM */
|
||||
{
|
||||
@ -182,7 +196,8 @@ uint32 z80_read_word(uint32 address)
|
||||
|
||||
void z80_write_byte(uint32 address, uint32 data)
|
||||
{
|
||||
if (zbusack)
|
||||
/* Z80 bus is available ? */
|
||||
if (zstate ^ 3)
|
||||
{
|
||||
m68k_unused_8_w(address, data);
|
||||
return;
|
||||
@ -191,7 +206,7 @@ void z80_write_byte(uint32 address, uint32 data)
|
||||
switch ((address >> 13) & 3)
|
||||
{
|
||||
case 2: /* YM2612 */
|
||||
fm_write(0, address & 3, data);
|
||||
fm_write(mcycles_68k, address & 3, data);
|
||||
return;
|
||||
|
||||
case 3:
|
||||
@ -212,15 +227,15 @@ void z80_write_byte(uint32 address, uint32 data)
|
||||
|
||||
default: /* ZRAM */
|
||||
zram[address & 0x1fff] = data;
|
||||
count_m68k++; /* Z80 bus latency (Pacman 2: New Adventures) */
|
||||
mcycles_68k+=8; /* Z80 bus latency (Pacman 2: New Adventures) */
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void z80_write_word(uint32 address, uint32 data)
|
||||
{
|
||||
/* Z80 still hold the bus ? */
|
||||
if (zbusack)
|
||||
/* Z80 bus is available ? */
|
||||
if (zstate ^ 3)
|
||||
{
|
||||
m68k_unused_16_w(address, data);
|
||||
return;
|
||||
@ -229,7 +244,7 @@ void z80_write_word(uint32 address, uint32 data)
|
||||
switch ((address >> 13) & 3)
|
||||
{
|
||||
case 2: /* YM2612 */
|
||||
fm_write (0, address & 3, data >> 8);
|
||||
fm_write (mcycles_68k, address & 3, data >> 8);
|
||||
return;
|
||||
|
||||
case 3:
|
||||
@ -262,17 +277,21 @@ uint32 ctrl_io_read_byte(uint32 address)
|
||||
switch ((address >> 8) & 0xff)
|
||||
{
|
||||
case 0x00: /* I/O chip */
|
||||
if (address & 0xe0) return m68k_read_bus_8(address);
|
||||
else return (io_read((address >> 1) & 0x0f));
|
||||
if (address & 0xe0)
|
||||
return m68k_read_bus_8(address);
|
||||
return (io_read((address >> 1) & 0x0f));
|
||||
|
||||
case 0x11: /* BUSACK */
|
||||
if (address & 1) return m68k_read_bus_8(address);
|
||||
else return ((m68k_read_pcrelative_8(REG_PC) & 0xfe) | zbusack);
|
||||
if (address & 1)
|
||||
return m68k_read_bus_8(address);
|
||||
if (zstate ^ 3)
|
||||
return (m68k_read_pcrelative_8(REG_PC) | 0x01);
|
||||
return (m68k_read_pcrelative_8(REG_PC) & 0xfe);
|
||||
|
||||
case 0x30: /* TIME */
|
||||
if (cart.hw.time_r)
|
||||
return ((address & 1) ? (cart.hw.time_r(address) & 0xff) : (cart.hw.time_r(address) >> 8));
|
||||
else return m68k_read_bus_8(address);
|
||||
return m68k_read_bus_8(address);
|
||||
|
||||
case 0x10: /* MEMORY MODE */
|
||||
case 0x12: /* RESET */
|
||||
@ -294,23 +313,28 @@ uint32 ctrl_io_read_word(uint32 address)
|
||||
{
|
||||
case 0x00: /* I/O chip */
|
||||
{
|
||||
if (address & 0xe0) return m68k_read_bus_16(address);
|
||||
if (address & 0xe0)
|
||||
return m68k_read_bus_16(address);
|
||||
int temp = io_read((address >> 1) & 0x0f);
|
||||
return (temp << 8 | temp);
|
||||
}
|
||||
|
||||
case 0x11: /* BUSACK */
|
||||
return ((m68k_read_pcrelative_16(REG_PC) & 0xfeff) | (zbusack << 8));
|
||||
if (zstate ^ 3)
|
||||
return (m68k_read_pcrelative_16(REG_PC) | 0x100);
|
||||
return (m68k_read_pcrelative_16(REG_PC) & 0xfeff);
|
||||
|
||||
case 0x30: /* TIME */
|
||||
if (cart.hw.time_r) return cart.hw.time_r(address);
|
||||
else return m68k_read_bus_16(address);
|
||||
if (cart.hw.time_r)
|
||||
return cart.hw.time_r(address);
|
||||
return m68k_read_bus_16(address);
|
||||
|
||||
case 0x50: /* SVP */
|
||||
if (svp)
|
||||
{
|
||||
if ((address & 0xfd) == 0) return svp->ssp1601.gr[SSP_XST].h;
|
||||
else if ((address & 0xff) == 4)
|
||||
if ((address & 0xfd) == 0)
|
||||
return svp->ssp1601.gr[SSP_XST].h;
|
||||
if ((address & 0xff) == 4)
|
||||
{
|
||||
uint32 temp = svp->ssp1601.gr[SSP_PM0].h;
|
||||
svp->ssp1601.gr[SSP_PM0].h &= ~1;
|
||||
@ -337,18 +361,24 @@ void ctrl_io_write_byte(uint32 address, uint32 data)
|
||||
switch ((address >> 8) & 0xff)
|
||||
{
|
||||
case 0x00: /* I/O chip */
|
||||
if ((address & 0xe1) == 0x01) io_write((address >> 1) & 0x0f, data); /* get /LWR only */
|
||||
else m68k_unused_8_w(address, data);
|
||||
if ((address & 0xe1) == 0x01)
|
||||
io_write((address >> 1) & 0x0f, data); /* get /LWR only */
|
||||
else
|
||||
m68k_unused_8_w(address, data);
|
||||
return;
|
||||
|
||||
case 0x11: /* BUSREQ */
|
||||
if (address & 1) m68k_unused_8_w(address, data);
|
||||
else gen_busreq_w(data & 1);
|
||||
if (address & 1)
|
||||
m68k_unused_8_w(address, data);
|
||||
else
|
||||
gen_busreq_w(data & 1);
|
||||
return;
|
||||
|
||||
case 0x12: /* RESET */
|
||||
if (address & 1) m68k_unused_8_w(address, data);
|
||||
else gen_reset_w(data & 1);
|
||||
if (address & 1)
|
||||
m68k_unused_8_w(address, data);
|
||||
else
|
||||
gen_reset_w(data & 1);
|
||||
return;
|
||||
|
||||
case 0x30: /* TIME */
|
||||
@ -368,7 +398,10 @@ void ctrl_io_write_byte(uint32 address, uint32 data)
|
||||
memset(cart.rom, 0xff, cart.romsize);
|
||||
}
|
||||
}
|
||||
else m68k_unused_8_w (address, data);
|
||||
else
|
||||
{
|
||||
m68k_unused_8_w (address, data);
|
||||
}
|
||||
return;
|
||||
|
||||
case 0x10: /* MEMORY MODE */
|
||||
@ -390,8 +423,10 @@ void ctrl_io_write_word(uint32 address, uint32 data)
|
||||
switch ((address >> 8) & 0xff)
|
||||
{
|
||||
case 0x00: /* I/O chip */
|
||||
if (address & 0xe0) m68k_unused_16_w (address, data);
|
||||
else io_write ((address >> 1) & 0x0f, data & 0xff);
|
||||
if (address & 0xe0)
|
||||
m68k_unused_16_w (address, data);
|
||||
else
|
||||
io_write ((address >> 1) & 0x0f, data & 0xff);
|
||||
return;
|
||||
|
||||
case 0x11: /* BUSREQ */
|
||||
@ -405,7 +440,10 @@ void ctrl_io_write_word(uint32 address, uint32 data)
|
||||
case 0x50: /* SVP REGISTERS */
|
||||
if (svp)
|
||||
{
|
||||
if (address & 0xfd) m68k_unused_16_w(address, data);
|
||||
if (address & 0xfd)
|
||||
{
|
||||
m68k_unused_16_w(address, data);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* just guessing here (Notaz) */
|
||||
@ -414,7 +452,10 @@ void ctrl_io_write_word(uint32 address, uint32 data)
|
||||
svp->ssp1601.emu_status &= ~SSP_WAIT_PM0;
|
||||
}
|
||||
}
|
||||
else m68k_unused_16_w (address, data);
|
||||
else
|
||||
{
|
||||
m68k_unused_16_w (address, data);
|
||||
}
|
||||
return;
|
||||
|
||||
case 0x30: /* TIME */
|
||||
@ -523,8 +564,10 @@ void vdp_write_byte(uint32 address, uint32 data)
|
||||
|
||||
case 0x10: /* PSG */
|
||||
case 0x14:
|
||||
if (address & 1) psg_write(0, data);
|
||||
else m68k_unused_8_w(address, data);
|
||||
if (address & 1)
|
||||
psg_write(mcycles_68k, data);
|
||||
else
|
||||
m68k_unused_8_w(address, data);
|
||||
return;
|
||||
|
||||
case 0x18: /* Unused */
|
||||
@ -555,7 +598,7 @@ void vdp_write_word(uint32 address, uint32 data)
|
||||
|
||||
case 0x10: /* PSG */
|
||||
case 0x14:
|
||||
psg_write(0, data & 0xff);
|
||||
psg_write(mcycles_68k, data & 0xff);
|
||||
return;
|
||||
|
||||
case 0x18: /* Unused */
|
||||
|
@ -65,17 +65,19 @@ uint32 zbank_read_ctrl_io(uint32 address)
|
||||
switch ((address >> 8) & 0xff)
|
||||
{
|
||||
case 0x00: /* I/O chip */
|
||||
if (address & 0xe0) return zbank_unused_r(address);
|
||||
else return (io_read((address >> 1) & 0x0f));
|
||||
if (address & 0xe0)
|
||||
return zbank_unused_r(address);
|
||||
return (io_read((address >> 1) & 0x0f));
|
||||
|
||||
case 0x11: /* BUSACK */
|
||||
if (address & 1) return zbank_unused_r(address);
|
||||
else return (0xfe | zbusack);
|
||||
if (address & 1)
|
||||
return zbank_unused_r(address);
|
||||
return 0xff;
|
||||
|
||||
case 0x30: /* TIME */
|
||||
if (cart.hw.time_r)
|
||||
return ((address & 1) ? (cart.hw.time_r(address) & 0xff) : (cart.hw.time_r(address) >> 8));
|
||||
else return zbank_unused_r(address);
|
||||
return zbank_unused_r(address);
|
||||
|
||||
case 0x10: /* MEMORY MODE */
|
||||
case 0x12: /* RESET */
|
||||
@ -96,18 +98,24 @@ void zbank_write_ctrl_io(uint32 address, uint32 data)
|
||||
switch ((address >> 8) & 0xff)
|
||||
{
|
||||
case 0x00: /* I/O chip */
|
||||
if ((address & 0xe1) == 0x01) io_write((address >> 1) & 0x0f, data); /* get /LWR only */
|
||||
else zbank_unused_w(address, data);
|
||||
if ((address & 0xe1) == 0x01)
|
||||
io_write((address >> 1) & 0x0f, data); /* get /LWR only */
|
||||
else
|
||||
zbank_unused_w(address, data);
|
||||
return;
|
||||
|
||||
case 0x11: /* BUSREQ */
|
||||
if (address & 1) zbank_unused_w(address, data);
|
||||
else gen_busreq_w(data & 1);
|
||||
if (address & 1)
|
||||
zbank_unused_w(address, data);
|
||||
else
|
||||
gen_busreq_w(data & 1);
|
||||
return;
|
||||
|
||||
case 0x12: /* RESET */
|
||||
if (address & 1) zbank_unused_w(address, data);
|
||||
else gen_reset_w(data & 1);
|
||||
if (address & 1)
|
||||
zbank_unused_w(address, data);
|
||||
else
|
||||
gen_reset_w(data & 1);
|
||||
return;
|
||||
|
||||
case 0x30: /* TIME */
|
||||
@ -127,7 +135,10 @@ void zbank_write_ctrl_io(uint32 address, uint32 data)
|
||||
memset(cart.rom, 0xff, cart.romsize);
|
||||
}
|
||||
}
|
||||
else zbank_unused_w (address, data);
|
||||
else
|
||||
{
|
||||
zbank_unused_w (address, data);
|
||||
}
|
||||
return;
|
||||
|
||||
case 0x10: /* MEMORY MODE */
|
||||
@ -195,8 +206,10 @@ void zbank_write_vdp(uint32 address, uint32 data)
|
||||
|
||||
case 0x10: /* PSG */
|
||||
case 0x14:
|
||||
if (address & 1) psg_write(1, data);
|
||||
else zbank_unused_w(address, data);
|
||||
if (address & 1)
|
||||
psg_write(mcycles_z80, data);
|
||||
else
|
||||
zbank_unused_w(address, data);
|
||||
return;
|
||||
|
||||
case 0x18: /* Unused */
|
||||
|
@ -109,8 +109,10 @@ static inline void z80_vdp_w(unsigned int address, unsigned int data)
|
||||
|
||||
case 0x10: /* PSG */
|
||||
case 0x14:
|
||||
if (address & 1) psg_write(1, data);
|
||||
else z80_unused_w(address, data);
|
||||
if (address & 1)
|
||||
psg_write(mcycles_z80, data);
|
||||
else
|
||||
z80_unused_w(address, data);
|
||||
return;
|
||||
|
||||
case 0x18: /* Unused */
|
||||
@ -139,18 +141,20 @@ unsigned int cpu_readmem16(unsigned int address)
|
||||
return zram[address & 0x1fff];
|
||||
|
||||
case 2: /* YM2612 */
|
||||
return fm_read(1, address & 3);
|
||||
return fm_read(mcycles_68k, address & 3);
|
||||
|
||||
case 3: /* VDP */
|
||||
if ((address >> 8) == 0x7f) return z80_vdp_r (address);
|
||||
if ((address >> 8) == 0x7f)
|
||||
return z80_vdp_r (address);
|
||||
return z80_unused_r(address);
|
||||
|
||||
default: /* V-bus bank */
|
||||
{
|
||||
address = zbank | (address & 0x7fff);
|
||||
int slot = address >> 16;
|
||||
if (zbank_memory_map[slot].read) return (*zbank_memory_map[slot].read)(address);
|
||||
else return READ_BYTE(m68k_memory_map[slot].base, address&0xffff);
|
||||
if (zbank_memory_map[slot].read)
|
||||
return (*zbank_memory_map[slot].read)(address);
|
||||
return READ_BYTE(m68k_memory_map[slot].base, address&0xffff);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -166,7 +170,7 @@ void cpu_writemem16(unsigned int address, unsigned int data)
|
||||
return;
|
||||
|
||||
case 2: /* YM2612 */
|
||||
fm_write(1, address & 3, data);
|
||||
fm_write(mcycles_z80, address & 3, data);
|
||||
return;
|
||||
|
||||
case 3: /* Bank register and VDP */
|
||||
@ -190,8 +194,10 @@ void cpu_writemem16(unsigned int address, unsigned int data)
|
||||
{
|
||||
address = zbank | (address & 0x7fff);
|
||||
int slot = address >> 16;
|
||||
if (zbank_memory_map[slot].write) (*zbank_memory_map[slot].write)(address, data);
|
||||
else WRITE_BYTE(m68k_memory_map[slot].base, address&0xffff, data);
|
||||
if (zbank_memory_map[slot].write)
|
||||
(*zbank_memory_map[slot].write)(address, data);
|
||||
else
|
||||
WRITE_BYTE(m68k_memory_map[slot].base, address&0xffff, data);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -307,17 +307,20 @@ static __inline__ void WRITE_LONG(void *address, uint32 data)
|
||||
}
|
||||
|
||||
|
||||
/**************************************************/
|
||||
/* Pixel creation macros */
|
||||
/* Input is four bits each (R,G,B), 12 bits total */
|
||||
/* Color range depends on the S/TE mode: */
|
||||
/* */
|
||||
/* normal mode : xxx0 (0-14) */
|
||||
/* shadow mode : 0xxx (0-7) */
|
||||
/* highlight mode: 1xxx - 1 (7-14) */
|
||||
/* */
|
||||
/* with xxx0 = original 4-bits CRAM value */
|
||||
/**************************************************/
|
||||
/************************************************/
|
||||
/* Pixel creation macros */
|
||||
/* each R,G,B color channel is 4-bits with a */
|
||||
/* total of 15 different intensity levels. */
|
||||
/* */
|
||||
/* Color intensity depends on the S/TE mode: */
|
||||
/* */
|
||||
/* normal : xxx0 (0-14) */
|
||||
/* shadow : 0xxx (0-7) */
|
||||
/* highlight: 1xxx - 1 (7-14) */
|
||||
/* */
|
||||
/* with xxx0 = original 4-bits CRAM value */
|
||||
/* */
|
||||
/************************************************/
|
||||
#ifndef NGC
|
||||
|
||||
/* 8:8:8 RGB */
|
||||
@ -330,7 +333,8 @@ static __inline__ void WRITE_LONG(void *address, uint32 data)
|
||||
#endif
|
||||
|
||||
/* 5:6:5 RGB */
|
||||
#define MAKE_PIXEL_16(r,g,b) ((r) << 12 | (g) << 7 | (b) << 1)
|
||||
/* 4-bit color intensity is dithered to match 5-bit or 6-bit equivalent */
|
||||
#define MAKE_PIXEL_16(r,g,b) ((r) << 12 | ((r) >> 3) << 11 | (g) << 7 | ((g) >> 2) << 5 | (b) << 1 | (b) >> 3)
|
||||
|
||||
/* Clip data */
|
||||
static clip_t clip[2];
|
||||
@ -383,7 +387,7 @@ static uint8 ntb_buf[0x200]; /* Plane B line buffer */
|
||||
static uint8 obj_buf[0x200]; /* Object layer line buffer */
|
||||
|
||||
/* Sprite line buffer data */
|
||||
static uint32 object_index_count;
|
||||
uint32 object_index_count;
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
/* Look-up table functions (handles priority between layers pixels) */
|
||||
@ -1505,8 +1509,9 @@ static void render_obj(uint32 line, uint8 *buf, uint8 *table)
|
||||
{
|
||||
xpos = object_info[count].xpos & 0x1ff;
|
||||
|
||||
/* sprite masking (ignore the 1st sprite) */
|
||||
if (xpos) spr_over = 1;
|
||||
/* sprite masking (requires at least one sprite with xpos > 0) */
|
||||
if (xpos)
|
||||
spr_over = 1;
|
||||
else if (spr_over)
|
||||
{
|
||||
spr_over = 0;
|
||||
@ -1517,7 +1522,7 @@ static void render_obj(uint32 line, uint8 *buf, uint8 *table)
|
||||
width = sizetab[(size >> 2) & 3];
|
||||
|
||||
/* update pixel count (off-screen sprites included) */
|
||||
pixelcount += xpos ? width : (width * 2);
|
||||
pixelcount += width;
|
||||
|
||||
if(((xpos + width) >= left) && (xpos < right) && !mask)
|
||||
{
|
||||
@ -1595,8 +1600,9 @@ static void render_obj_im2(uint32 line, uint32 odd, uint8 *buf, uint8 *table)
|
||||
{
|
||||
xpos = object_info[count].xpos & 0x1ff;
|
||||
|
||||
/* sprite masking (ignore the 1st sprite) */
|
||||
if (xpos) spr_over = 1;
|
||||
/* sprite masking (requires at least one sprite with xpos > 0) */
|
||||
if (xpos)
|
||||
spr_over = 1;
|
||||
else if(spr_over)
|
||||
{
|
||||
spr_over = 0;
|
||||
@ -1607,7 +1613,7 @@ static void render_obj_im2(uint32 line, uint32 odd, uint8 *buf, uint8 *table)
|
||||
width = sizetab[(size >> 2) & 3];
|
||||
|
||||
/* update pixel count (off-screen sprites included) */
|
||||
pixelcount += xpos ? width : (width * 2);
|
||||
pixelcount += width;
|
||||
|
||||
if(((xpos + width) >= left) && (xpos < right) && !mask)
|
||||
{
|
||||
@ -1629,14 +1635,16 @@ static void render_obj_im2(uint32 line, uint32 odd, uint8 *buf, uint8 *table)
|
||||
|
||||
/* number of tiles to draw */
|
||||
/* adjusted for sprite limit */
|
||||
if (pixelcount > bitmap.viewport.w) width -= (pixelcount - bitmap.viewport.w);
|
||||
if (pixelcount > bitmap.viewport.w)
|
||||
width -= (pixelcount - bitmap.viewport.w);
|
||||
width >>= 3;
|
||||
|
||||
for(column = 0; column < width; column += 1, lb+=8)
|
||||
{
|
||||
index = (name + s[column]) & 0x3ff;
|
||||
offs = index << 7 | attr_mask << 6 | v_line;
|
||||
if(attr & 0x1000) offs ^= 0x40;
|
||||
if(attr & 0x1000)
|
||||
offs ^= 0x40;
|
||||
src = &bg_pattern_cache[offs];
|
||||
DRAW_SPRITE_TILE;
|
||||
}
|
||||
@ -1662,9 +1670,11 @@ void render_init(void)
|
||||
int bx, ax, i;
|
||||
|
||||
/* Allocate and align pixel look-up tables */
|
||||
if (lut_base == NULL) lut_base = malloc ((LUT_MAX * LUT_SIZE) + LUT_SIZE);
|
||||
if (lut_base == NULL)
|
||||
lut_base = malloc ((LUT_MAX * LUT_SIZE) + LUT_SIZE);
|
||||
lut[0] = (uint8 *) (((uint32) lut_base + LUT_SIZE) & ~(LUT_SIZE - 1));
|
||||
for (i = 1; i < LUT_MAX; i += 1) lut[i] = lut[0] + (i * LUT_SIZE);
|
||||
for (i = 1; i < LUT_MAX; i += 1)
|
||||
lut[i] = lut[0] + (i * LUT_SIZE);
|
||||
|
||||
/* Make pixel look-up table data */
|
||||
for (bx = 0; bx < 0x100; bx += 1)
|
||||
@ -1722,7 +1732,8 @@ void render_reset(void)
|
||||
|
||||
void render_shutdown(void)
|
||||
{
|
||||
if(lut_base) free(lut_base);
|
||||
if(lut_base)
|
||||
free(lut_base);
|
||||
}
|
||||
|
||||
|
||||
@ -1736,7 +1747,8 @@ void render_line(uint32 line, uint32 overscan)
|
||||
uint32 x_offset = bitmap.viewport.x;
|
||||
|
||||
/* display OFF */
|
||||
if (reg[0] & 0x01) return;
|
||||
if (reg[0] & 0x01)
|
||||
return;
|
||||
|
||||
/* background color (blanked display or vertical borders) */
|
||||
if (!(reg[1] & 0x40) || overscan)
|
||||
@ -1761,28 +1773,32 @@ void render_line(uint32 line, uint32 overscan)
|
||||
uint32 odd = odd_frame;
|
||||
|
||||
/* render BG layers */
|
||||
if(reg[11] & 4) render_bg_im2_vs(line, width, odd);
|
||||
else render_bg_im2(line, width, odd);
|
||||
if(reg[11] & 4)
|
||||
render_bg_im2_vs(line, width, odd);
|
||||
else
|
||||
render_bg_im2(line, width, odd);
|
||||
|
||||
if (reg[12] & 8)
|
||||
{
|
||||
/* Shadow & Highlight */
|
||||
merge(&nta_buf[0x20], &ntb_buf[0x20], &bg_buf[0x20], lut[2], width);
|
||||
memset(&obj_buf[0x20], 0, width);
|
||||
if (object_index_count) render_obj_im2(line, odd, obj_buf, lut[3]);
|
||||
render_obj_im2(line, odd, obj_buf, lut[3]);
|
||||
merge(&obj_buf[0x20], &bg_buf[0x20], &lb[0x20], lut[4], width);
|
||||
}
|
||||
else
|
||||
{
|
||||
merge(&nta_buf[0x20], &ntb_buf[0x20], &lb[0x20], lut[0], width);
|
||||
if (object_index_count) render_obj_im2(line, odd, lb, lut[1]);
|
||||
render_obj_im2(line, odd, lb, lut[1]);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* render BG layers */
|
||||
if(reg[11] & 4) render_bg_vs(line, width);
|
||||
else render_bg(line, width);
|
||||
if(reg[11] & 4)
|
||||
render_bg_vs(line, width);
|
||||
else
|
||||
render_bg(line, width);
|
||||
|
||||
if(reg[12] & 8)
|
||||
{
|
||||
@ -1818,13 +1834,16 @@ void remap_buffer(uint32 line, uint32 width)
|
||||
line = (line + bitmap.viewport.y) % lines_per_frame;
|
||||
|
||||
/* double resolution mode */
|
||||
if (config.render && interlaced) line = (line * 2) + odd_frame;
|
||||
if (config.render && interlaced)
|
||||
line = (line * 2) + odd_frame;
|
||||
|
||||
/* NTSC Filter */
|
||||
if (config.ntsc)
|
||||
{
|
||||
if (reg[12]&1) md_ntsc_blit(&md_ntsc, ( MD_NTSC_IN_T const * )pixel_16, tmp_buf+0x20-bitmap.viewport.x, width, line);
|
||||
else sms_ntsc_blit(&sms_ntsc, ( SMS_NTSC_IN_T const * )pixel_16, tmp_buf+0x20-bitmap.viewport.x, width, line);
|
||||
if (reg[12]&1)
|
||||
md_ntsc_blit(&md_ntsc, ( MD_NTSC_IN_T const * )pixel_16, tmp_buf+0x20-bitmap.viewport.x, width, line);
|
||||
else
|
||||
sms_ntsc_blit(&sms_ntsc, ( SMS_NTSC_IN_T const * )pixel_16, tmp_buf+0x20-bitmap.viewport.x, width, line);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -1928,7 +1947,8 @@ void parse_satb(uint32 line)
|
||||
/* sprite limit (max. 16 or 20 sprites displayed per line) */
|
||||
if(object_index_count == limit)
|
||||
{
|
||||
if(vint_pending == 0) status |= 0x40;
|
||||
if(vint_pending == 0)
|
||||
status |= 0x40;
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -24,6 +24,9 @@
|
||||
#ifndef _RENDER_H_
|
||||
#define _RENDER_H_
|
||||
|
||||
/* Global variables */
|
||||
extern uint32 object_index_count;
|
||||
|
||||
/* Function prototypes */
|
||||
extern void render_init(void);
|
||||
extern void render_reset(void);
|
||||
|
@ -104,7 +104,7 @@ void Fir_Resampler_clear()
|
||||
if ( buffer_size )
|
||||
{
|
||||
write_pos = &buffer [WRITE_OFFSET];
|
||||
memset( buffer, 0, WRITE_OFFSET * sizeof (sample_t) );
|
||||
memset( buffer, 0, buffer_size * sizeof (sample_t) );
|
||||
}
|
||||
}
|
||||
|
||||
@ -143,6 +143,8 @@ double Fir_Resampler_time_ratio( double new_factor )
|
||||
pos = 0.0;
|
||||
input_per_cycle = 0;
|
||||
|
||||
memset(impulses, 0, MAX_RES*WIDTH*sizeof(sample_t));
|
||||
|
||||
for ( i = 0; i < res; i++ )
|
||||
{
|
||||
gen_sinc( ROLLOFF, (int) (WIDTH * filter + 1) & ~1, pos, filter,
|
||||
@ -200,10 +202,9 @@ void Fir_Resampler_write( long count )
|
||||
assert( write_pos <= ( buffer + buffer_size ) );
|
||||
}
|
||||
|
||||
int Fir_Resampler_read( sample_t** out, long count )
|
||||
int Fir_Resampler_read( sample_t* out, long count )
|
||||
{
|
||||
sample_t* out_l = out[0];
|
||||
sample_t* out_r = out[1];
|
||||
sample_t* out_ = out;
|
||||
sample_t* in = buffer;
|
||||
sample_t* end_pos = write_pos;
|
||||
unsigned long skip = skip_bits >> imp_phase;
|
||||
@ -258,8 +259,8 @@ int Fir_Resampler_read( sample_t** out, long count )
|
||||
remain = res;
|
||||
}
|
||||
|
||||
*out_l++ = (sample_t) l;
|
||||
*out_r++ = (sample_t) r;
|
||||
*out++ = (sample_t) l;
|
||||
*out++ = (sample_t) r;
|
||||
}
|
||||
while ( in <= end_pos );
|
||||
}
|
||||
@ -270,7 +271,7 @@ int Fir_Resampler_read( sample_t** out, long count )
|
||||
write_pos = &buffer [left];
|
||||
memmove( buffer, in, left * sizeof *in );
|
||||
|
||||
return out_l - out[0];
|
||||
return out - out_;
|
||||
}
|
||||
|
||||
int Fir_Resampler_input_needed( long output_count )
|
||||
|
@ -23,7 +23,7 @@ extern sample_t* Fir_Resampler_buffer( void );
|
||||
extern int Fir_Resampler_written( void );
|
||||
extern int Fir_Resampler_avail( void );
|
||||
extern void Fir_Resampler_write( long count );
|
||||
extern int Fir_Resampler_read( sample_t** out, long count );
|
||||
extern int Fir_Resampler_read( sample_t* out, long count );
|
||||
extern int Fir_Resampler_input_needed( long output_count );
|
||||
extern int Fir_Resampler_skip_input( long count );
|
||||
|
||||
|
@ -109,10 +109,10 @@ static const int PSGVolumeValues[2][16] = {
|
||||
|
||||
static SN76489_Context SN76489;
|
||||
|
||||
void SN76489_Init(int PSGClockValue, int SamplingRate)
|
||||
void SN76489_Init(float PSGClockValue, int SamplingRate)
|
||||
{
|
||||
SN76489_Context *p = &SN76489;
|
||||
p->dClock=(float)PSGClockValue/16/SamplingRate;
|
||||
p->dClock=PSGClockValue/16.0/SamplingRate;
|
||||
SN76489_Config(MUTE_ALLON, VOL_FULL, FB_SEGAVDP, SRW_SEGAVDP, config.psgBoostNoise);
|
||||
SN76489_Reset();
|
||||
}
|
||||
|
@ -16,7 +16,7 @@
|
||||
#define _SN76489_H_
|
||||
|
||||
/* Function prototypes */
|
||||
extern void SN76489_Init(int PSGClockValue, int SamplingRate);
|
||||
extern void SN76489_Init(float PSGClockValue, int SamplingRate);
|
||||
extern void SN76489_Reset(void);
|
||||
extern void SN76489_Shutdown(void);
|
||||
extern void SN76489_SetContext(uint8 *data);
|
||||
|
@ -24,105 +24,229 @@
|
||||
#include "shared.h"
|
||||
#include "Fir_Resampler.h"
|
||||
|
||||
/* cycle-accurate samples */
|
||||
static int m68cycles_per_sample[2];
|
||||
/* Cycle-accurate samples */
|
||||
static unsigned int psg_cycles_ratio;
|
||||
static unsigned int psg_cycles_count;
|
||||
static unsigned int fm_cycles_ratio;
|
||||
static unsigned int fm_cycles_count;
|
||||
|
||||
/* return the number of samples that should be retrieved */
|
||||
static inline int fm_sample_cnt(uint8 z80)
|
||||
/* Run FM chip for required M-cycles */
|
||||
static inline void fm_update(unsigned int cycles)
|
||||
{
|
||||
if (z80) return ((((count_z80 + current_z80 - z80_ICount) * 15) / (m68cycles_per_sample[0] * 7)) - snd.fm.pos);
|
||||
else return ((count_m68k / m68cycles_per_sample[0]) - snd.fm.pos);
|
||||
}
|
||||
/* convert to 21.11 fixed point */
|
||||
cycles <<= 11;
|
||||
|
||||
static inline int psg_sample_cnt(uint8 z80)
|
||||
{
|
||||
if (z80) return ((((count_z80 + current_z80 - z80_ICount) * 15) / (m68cycles_per_sample[1] * 7)) - snd.psg.pos);
|
||||
else return ((count_m68k / m68cycles_per_sample[1]) - snd.psg.pos);
|
||||
}
|
||||
|
||||
/* run FM chip for n samples */
|
||||
static inline void fm_update(int cnt)
|
||||
{
|
||||
if (cnt > 0)
|
||||
if (cycles > fm_cycles_count)
|
||||
{
|
||||
YM2612Update(cnt);
|
||||
snd.fm.pos += cnt;
|
||||
/* period to run */
|
||||
cycles -= fm_cycles_count;
|
||||
|
||||
/* update cycle count */
|
||||
fm_cycles_count += cycles;
|
||||
|
||||
/* number of samples during period */
|
||||
uint32 cnt = cycles / fm_cycles_ratio;
|
||||
|
||||
/* remaining cycles */
|
||||
uint32 remain = cycles % fm_cycles_ratio;
|
||||
if (remain)
|
||||
{
|
||||
/* one sample ahead */
|
||||
fm_cycles_count += fm_cycles_ratio - remain;
|
||||
cnt++;
|
||||
}
|
||||
|
||||
/* select input sample buffer */
|
||||
int16 *buffer = Fir_Resampler_buffer();
|
||||
if (buffer)
|
||||
{
|
||||
Fir_Resampler_write(cnt << 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
buffer = snd.fm.pos;
|
||||
snd.fm.pos += (cnt << 1);
|
||||
}
|
||||
|
||||
/* run FM chip & get samples */
|
||||
YM2612Update(buffer, cnt);
|
||||
}
|
||||
}
|
||||
|
||||
/* run PSG chip for n samples */
|
||||
static inline void psg_update(int cnt)
|
||||
/* Run PSG chip for required M-cycles */
|
||||
static inline void psg_update(unsigned int cycles)
|
||||
{
|
||||
if (cnt > 0)
|
||||
/* convert to 21.11 fixed point */
|
||||
cycles <<= 11;
|
||||
|
||||
if (cycles > psg_cycles_count)
|
||||
{
|
||||
SN76489_Update(snd.psg.buffer + snd.psg.pos, cnt);
|
||||
/* period to run */
|
||||
cycles -= psg_cycles_count;
|
||||
|
||||
/* update cycle count */
|
||||
psg_cycles_count += cycles;
|
||||
|
||||
/* number of samples during period */
|
||||
uint32 cnt = cycles / psg_cycles_ratio;
|
||||
|
||||
/* remaining cycles */
|
||||
uint32 remain = cycles % psg_cycles_ratio;
|
||||
if (remain)
|
||||
{
|
||||
/* one sample ahead */
|
||||
psg_cycles_count += psg_cycles_ratio - remain;
|
||||
cnt++;
|
||||
}
|
||||
|
||||
/* run PSG chip & get samples */
|
||||
SN76489_Update(snd.psg.pos, cnt);
|
||||
snd.psg.pos += cnt;
|
||||
}
|
||||
}
|
||||
|
||||
/* initialize sound chips emulation */
|
||||
void sound_init(int rate, double fps)
|
||||
/* Initialize sound chips emulation */
|
||||
void sound_init(void)
|
||||
{
|
||||
double vclk = (vdp_pal ? (double)CLOCK_PAL : (double)CLOCK_NTSC) / 7.0; /* 68000 and YM2612 clock */
|
||||
double zclk = (vdp_pal ? (double)CLOCK_PAL : (double)CLOCK_NTSC) / 15.0; /* Z80 and SN76489 clock */
|
||||
/* Number of M-cycles executed per second. */
|
||||
/* */
|
||||
/* The original Genesis would run exactly 53693175 M-cycles (53203424 for PAL), with */
|
||||
/* 3420 M-cycles per line and 262 (313 for PAL) lines per frame, which gives an exact */
|
||||
/* framerate of 59.92 (49.70 for PAL) fps. */
|
||||
/* */
|
||||
/* On some systems, the output framerate is not exactly 60 or 50 fps because we need */
|
||||
/* 100% smooth video and therefore frame emulation is synchronized with VSYNC, which */
|
||||
/* period is never exactly 1/60 or 1/50 seconds. */
|
||||
/* */
|
||||
/* For optimal sound rendering, input samplerate (number of samples rendered per frame) */
|
||||
/* is the exact output samplerate (number of samples played per second) divided by the */
|
||||
/* exact output framerate (number of frames emulated per seconds). */
|
||||
/* */
|
||||
/* This ensure there is no audio skipping or lag between emulated frames, while keeping */
|
||||
/* accurate timings for sound chips execution & synchronization. */
|
||||
/* */
|
||||
double mclk = MCYCLES_PER_LINE * lines_per_frame * snd.frame_rate;
|
||||
|
||||
/* cycle-accurate FM & PSG samples */
|
||||
m68cycles_per_sample[0] = (int)(((double)m68cycles_per_line * (double)lines_per_frame * fps/ (double)rate) + 0.5);
|
||||
m68cycles_per_sample[1] = m68cycles_per_sample[0];
|
||||
/* For better accuracy, sound chips run in synchronization with 68k and Z80 cpus */
|
||||
/* These values give the exact number of M-cycles between 2 rendered samples. */
|
||||
/* we use 21.11 fixed point precision (max. mcycle value is 3420*313 i.e 21 bits max) */
|
||||
psg_cycles_ratio = (int)((mclk / (double) snd.sample_rate) * 2048.0);
|
||||
fm_cycles_ratio = psg_cycles_ratio;
|
||||
fm_cycles_count = 0;
|
||||
psg_cycles_count = 0;
|
||||
|
||||
/* YM2612 is emulated at its original frequency (VLCK/144) */
|
||||
/* Initialize core emulation (input clock based on input frequency for 100% accuracy) */
|
||||
/* By default, both chips are running at the output frequency. */
|
||||
SN76489_Init(mclk/15.0,snd.sample_rate);
|
||||
YM2612Init(mclk/7.0,snd.sample_rate);
|
||||
|
||||
/* In HQ mode, YM2612 is running at its original rate (one sample each 144*7 M-cycles) */
|
||||
/* FM stream is resampled to the output frequency at the end of a frame. */
|
||||
if (config.hq_fm)
|
||||
{
|
||||
/* "real" ratio is (vclk/144.0)/(rate) but since we need perfect synchronization between video & audio
|
||||
on the target system, we are not exactly running at the real genesis framerate but the target
|
||||
framerate (which is calculated so that no video or audio frameskip occur)
|
||||
*/
|
||||
Fir_Resampler_time_ratio((double)m68cycles_per_line * (double)lines_per_frame * fps / 144.0 / (double)rate);
|
||||
|
||||
m68cycles_per_sample[0] = 144;
|
||||
|
||||
fm_cycles_ratio = 144 * 7 * (1 << 11);
|
||||
Fir_Resampler_time_ratio(mclk / (double)snd.sample_rate / (144.0 * 7.0));
|
||||
}
|
||||
|
||||
/* initialize sound chips */
|
||||
SN76489_Init((int)zclk,rate);
|
||||
YM2612Init((int)vclk,rate);
|
||||
}
|
||||
|
||||
void sound_update(int fm_len, int psg_len)
|
||||
{
|
||||
/* update last samples (if needed) */
|
||||
fm_update(fm_len - snd.fm.pos);
|
||||
psg_update(psg_len - snd.psg.pos);
|
||||
|
||||
/* reset samples count */
|
||||
snd.fm.pos = 0;
|
||||
snd.psg.pos = 0;
|
||||
#ifdef LOG_SOUND
|
||||
error("%d mcycles per PSG samples\n", psg_cycles_ratio);
|
||||
error("%d mcycles per FM samples\n", fm_cycles_ratio);
|
||||
#endif
|
||||
}
|
||||
|
||||
/* reset FM chip */
|
||||
/* Reset sound chips emulation */
|
||||
void sound_reset(void)
|
||||
{
|
||||
YM2612ResetChip();
|
||||
SN76489_Reset();
|
||||
fm_cycles_count = 0;
|
||||
psg_cycles_count = 0;
|
||||
}
|
||||
|
||||
/* End of frame update, return the number of samples run so far. */
|
||||
int sound_update(unsigned int cycles)
|
||||
{
|
||||
/* run PSG chip until end of frame */
|
||||
psg_update(cycles);
|
||||
|
||||
/* number of available samples */
|
||||
int size = snd.psg.pos - snd.psg.buffer;
|
||||
|
||||
#ifdef LOG_SOUND
|
||||
error("%d PSG samples available\n",snd.psg.pos - snd.psg.buffer);
|
||||
#endif
|
||||
|
||||
/* FM resampling */
|
||||
if (config.hq_fm)
|
||||
{
|
||||
/* resynchronize FM & PSG chips */
|
||||
int remain = Fir_Resampler_input_needed(size << 1) >> 1;
|
||||
|
||||
/* get remaining FM samples */
|
||||
if (remain > 0)
|
||||
{
|
||||
YM2612Update(Fir_Resampler_buffer(), remain);
|
||||
Fir_Resampler_write(remain << 1);
|
||||
}
|
||||
|
||||
fm_cycles_count = psg_cycles_count;
|
||||
|
||||
#ifdef LOG_SOUND
|
||||
error("%d FM samples available\n",Fir_Resampler_written() >> 1);
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
/* run FM chip until end of frame */
|
||||
fm_update(cycles);
|
||||
|
||||
#ifdef LOG_SOUND
|
||||
error("%d FM samples available\n",(snd.fm.pos - snd.fm.buffer)>>1);
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef LOG_SOUND
|
||||
error("%lu PSG cycles run\n",psg_cycles_count);
|
||||
error("%lu FM cycles run \n",fm_cycles_count);
|
||||
#endif
|
||||
|
||||
/* adjust PSG & FM cycle counts */
|
||||
psg_cycles_count -= (cycles << 11);
|
||||
fm_cycles_count -= (cycles << 11);
|
||||
|
||||
#ifdef LOG_SOUND
|
||||
error("%lu PSG cycles left\n",psg_cycles_count);
|
||||
error("%lu FM cycles left\n",fm_cycles_count);
|
||||
#endif
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
/* Reset FM chip during 68k execution */
|
||||
void fm_reset(void)
|
||||
{
|
||||
fm_update(fm_sample_cnt(0));
|
||||
fm_update(mcycles_68k);
|
||||
YM2612ResetChip();
|
||||
}
|
||||
|
||||
/* write FM chip */
|
||||
void fm_write(unsigned int cpu, unsigned int address, unsigned int data)
|
||||
/* Write FM chip */
|
||||
void fm_write(unsigned int cycles, unsigned int address, unsigned int data)
|
||||
{
|
||||
if (address & 1) fm_update(fm_sample_cnt(cpu));
|
||||
if (address & 1)
|
||||
fm_update(cycles);
|
||||
YM2612Write(address, data);
|
||||
}
|
||||
|
||||
/* read FM status */
|
||||
unsigned int fm_read(unsigned int cpu, unsigned int address)
|
||||
/* Read FM status */
|
||||
unsigned int fm_read(unsigned int cycles, unsigned int address)
|
||||
{
|
||||
fm_update(fm_sample_cnt(cpu));
|
||||
fm_update(cycles);
|
||||
return YM2612Read();
|
||||
}
|
||||
|
||||
/* write PSG chip */
|
||||
void psg_write(unsigned int cpu, unsigned int data)
|
||||
/* Write PSG chip */
|
||||
void psg_write(unsigned int cycles, unsigned int data)
|
||||
{
|
||||
psg_update(psg_sample_cnt(cpu));
|
||||
psg_update(cycles);
|
||||
SN76489_Write(data);
|
||||
}
|
||||
|
@ -25,11 +25,12 @@
|
||||
#define _SOUND_H_
|
||||
|
||||
/* Function prototypes */
|
||||
extern void sound_init(int rate, double fps);
|
||||
extern void sound_update(int fm_len, int psg_len);
|
||||
extern void sound_init(void);
|
||||
extern void sound_reset(void);
|
||||
extern int sound_update(unsigned int cycles);
|
||||
extern void fm_reset(void);
|
||||
extern void fm_write(unsigned int cpu, unsigned int address, unsigned int data);
|
||||
extern unsigned int fm_read(unsigned int cpu, unsigned int address);
|
||||
extern void psg_write(unsigned int cpu, unsigned int data);
|
||||
extern void fm_write(unsigned int cycles, unsigned int address, unsigned int data);
|
||||
extern unsigned int fm_read(unsigned int cycles, unsigned int address);
|
||||
extern void psg_write(unsigned int cycles, unsigned int data);
|
||||
|
||||
#endif /* _SOUND_H_ */
|
||||
|
@ -554,7 +554,7 @@ typedef struct
|
||||
|
||||
typedef struct
|
||||
{
|
||||
UINT32 clock; /* master clock (Hz) */
|
||||
float clock; /* master clock (Hz) */
|
||||
UINT32 rate; /* sampling rate (Hz) */
|
||||
UINT16 address; /* address register */
|
||||
UINT8 status; /* status flag */
|
||||
@ -1775,7 +1775,7 @@ static void init_timetables(double freqbase)
|
||||
static void OPNSetPres(int pres)
|
||||
{
|
||||
/* frequency base (ratio between FM original samplerate & desired output samplerate)*/
|
||||
double freqbase = ((double) ym2612.OPN.ST.clock / (double) ym2612.OPN.ST.rate) / ((double) pres);
|
||||
double freqbase = ym2612.OPN.ST.clock / ym2612.OPN.ST.rate / pres;
|
||||
|
||||
/* YM2612 running at original frequency (~53267 Hz) */
|
||||
if (config.hq_fm) freqbase = 1.0;
|
||||
@ -1913,7 +1913,7 @@ static void init_tables(void)
|
||||
|
||||
|
||||
/* initialize ym2612 emulator(s) */
|
||||
int YM2612Init(int clock, int rate)
|
||||
int YM2612Init(float clock, int rate)
|
||||
{
|
||||
memset(&ym2612,0,sizeof(YM2612));
|
||||
init_tables();
|
||||
@ -2017,24 +2017,10 @@ unsigned int YM2612Read(void)
|
||||
}
|
||||
|
||||
/* Generate 16 bits samples for ym2612 */
|
||||
void YM2612Update(int length)
|
||||
void YM2612Update(short int *buffer, int length)
|
||||
{
|
||||
int i;
|
||||
int lt,rt;
|
||||
int16 *bufL = 0;
|
||||
int16 *bufR = 0;
|
||||
|
||||
/* Output samples buffers */
|
||||
int16 *bufFIR = Fir_Resampler_buffer();
|
||||
if (bufFIR)
|
||||
{
|
||||
bufFIR += (snd.fm.pos << 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
bufL = snd.fm.buffer[0] + snd.fm.pos;
|
||||
bufR = snd.fm.buffer[1] + snd.fm.pos;
|
||||
}
|
||||
|
||||
/* refresh PG increments and EG rates if required */
|
||||
refresh_fc_eg_chan(&ym2612.CH[0]);
|
||||
@ -2139,16 +2125,8 @@ void YM2612Update(int length)
|
||||
// Limit(rt,MAXOUT,MINOUT);
|
||||
|
||||
/* buffering */
|
||||
if (bufFIR)
|
||||
{
|
||||
*bufFIR++ = lt;
|
||||
*bufFIR++ = rt;
|
||||
}
|
||||
else
|
||||
{
|
||||
*bufL++ = lt;
|
||||
*bufR++ = rt;
|
||||
}
|
||||
*buffer++ = lt;
|
||||
*buffer++ = rt;
|
||||
|
||||
/* CSM mode: if CSM Key ON has occured, CSM Key OFF need to be sent */
|
||||
/* only if Timer A does not overflow again (i.e CSM Key ON not set again) */
|
||||
@ -2186,7 +2164,7 @@ unsigned int YM2612GetContextSize(void)
|
||||
void YM2612Restore(unsigned char *buffer)
|
||||
{
|
||||
/* save current timings */
|
||||
int clock = ym2612.OPN.ST.clock;
|
||||
float clock = ym2612.OPN.ST.clock;
|
||||
int rate = ym2612.OPN.ST.rate;
|
||||
|
||||
/* restore internal state */
|
||||
|
@ -19,9 +19,9 @@
|
||||
#endif
|
||||
|
||||
|
||||
extern int YM2612Init(int baseclock, int rate);
|
||||
extern int YM2612Init(float clock, int rate);
|
||||
extern int YM2612ResetChip(void);
|
||||
extern void YM2612Update(int length);
|
||||
extern void YM2612Update(short int*buffer, int length);
|
||||
extern void YM2612Write(unsigned int a, unsigned int v);
|
||||
extern unsigned int YM2612Read(void);
|
||||
extern unsigned char *YM2612GetContextPtr(void);
|
||||
|
@ -59,10 +59,8 @@ int state_load(unsigned char *buffer)
|
||||
// GENESIS
|
||||
load_param(work_ram, sizeof(work_ram));
|
||||
load_param(zram, sizeof(zram));
|
||||
load_param(&zbusreq, sizeof(zbusreq));
|
||||
load_param(&zreset, sizeof(zreset));
|
||||
load_param(&zstate, sizeof(zstate));
|
||||
load_param(&zbank, sizeof(zbank));
|
||||
zbusack = 1 ^(zbusreq & zreset);
|
||||
|
||||
// IO
|
||||
load_param(io_reg, sizeof(io_reg));
|
||||
@ -134,8 +132,7 @@ int state_save(unsigned char *buffer)
|
||||
// GENESIS
|
||||
save_param(work_ram, sizeof(work_ram));
|
||||
save_param(zram, sizeof(zram));
|
||||
save_param(&zbusreq, sizeof(zbusreq));
|
||||
save_param(&zreset, sizeof(zreset));
|
||||
save_param(&zstate, sizeof(zstate));
|
||||
save_param(&zbank, sizeof(zbank));
|
||||
|
||||
// IO
|
||||
|
279
source/system.c
279
source/system.c
@ -30,12 +30,10 @@
|
||||
/* Global variables */
|
||||
t_bitmap bitmap;
|
||||
t_snd snd;
|
||||
uint32 count_m68k;
|
||||
uint32 line_m68k;
|
||||
uint32 hint_m68k;
|
||||
uint32 count_z80;
|
||||
uint32 line_z80;
|
||||
int32 current_z80;
|
||||
uint32 mcycles_vdp;
|
||||
uint32 mcycles_z80;
|
||||
uint32 mcycles_68k;
|
||||
uint32 hint_68k;
|
||||
uint8 system_hw;
|
||||
|
||||
/****************************************************************
|
||||
@ -56,7 +54,7 @@ void audio_set_equalizer(void)
|
||||
****************************************************************/
|
||||
static int llp,rrp;
|
||||
|
||||
void audio_update (int size)
|
||||
int audio_update (void)
|
||||
{
|
||||
int i, l, r;
|
||||
int ll = llp;
|
||||
@ -68,26 +66,45 @@ void audio_update (int size)
|
||||
uint32 factora = (config.lp_range << 16) / 100;
|
||||
uint32 factorb = 0x10000 - factora;
|
||||
|
||||
int16 *fm[2] = {snd.fm.buffer[0],snd.fm.buffer[1]};
|
||||
int16 *psg = snd.psg.buffer;
|
||||
int16 *fm = snd.fm.buffer;
|
||||
int16 *psg = snd.psg.buffer;
|
||||
|
||||
#ifdef NGC
|
||||
int16 *sb = (int16 *) soundbuffer[mixbuffer];
|
||||
#endif
|
||||
|
||||
/* resampling */
|
||||
/* get number of available samples */
|
||||
int size = sound_update(mcycles_vdp);
|
||||
|
||||
/* return an aligned number of samples */
|
||||
size &= ~7;
|
||||
|
||||
if (config.hq_fm)
|
||||
{
|
||||
int len = Fir_Resampler_input_needed(size << 1);
|
||||
sound_update(len >> 1,size);
|
||||
Fir_Resampler_write(len);
|
||||
/* resample into FM output buffer */
|
||||
Fir_Resampler_read(fm,size);
|
||||
|
||||
#ifdef LOG_SOUND
|
||||
error("%d FM samples remaining\n",Fir_Resampler_written() >> 1);
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
sound_update(size,size);
|
||||
{
|
||||
/* adjust remaining samples in FM output buffer*/
|
||||
snd.fm.pos -= (size << 1);
|
||||
|
||||
#ifdef LOG_SOUND
|
||||
error("%d FM samples remaining\n",(snd.fm.pos - snd.fm.buffer)>>1);
|
||||
#endif
|
||||
}
|
||||
|
||||
/* adjust remaining samples in PSG output buffer*/
|
||||
snd.psg.pos -= size;
|
||||
|
||||
#ifdef LOG_SOUND
|
||||
error("%d PSG samples remaining\n",snd.psg.pos - snd.psg.buffer);
|
||||
#endif
|
||||
|
||||
/* mix samples */
|
||||
for (i = 0; i < size; i ++)
|
||||
{
|
||||
@ -95,8 +112,8 @@ void audio_update (int size)
|
||||
l = r = ((*psg++) * psg_preamp)/100;
|
||||
|
||||
/* FM samples (stereo) */
|
||||
l += (*fm[0]++ * fm_preamp)/100;
|
||||
r += (*fm[1]++ * fm_preamp)/100;
|
||||
l += (*fm++ * fm_preamp)/100;
|
||||
r += (*fm++ * fm_preamp)/100;
|
||||
|
||||
/* filtering */
|
||||
if (filter & 1)
|
||||
@ -130,15 +147,25 @@ void audio_update (int size)
|
||||
#endif
|
||||
}
|
||||
|
||||
/* save delayed samples */
|
||||
/* save delayed samples for next frame */
|
||||
llp = ll;
|
||||
rrp = rr;
|
||||
|
||||
/* save remaining samples for next frame */
|
||||
memcpy(snd.fm.buffer, fm, (snd.fm.pos - snd.fm.buffer) << 1);
|
||||
memcpy(snd.psg.buffer, psg, (snd.psg.pos - snd.psg.buffer) << 1);
|
||||
|
||||
#ifdef LOG_SOUND
|
||||
error("%d samples returned\n\n",size);
|
||||
#endif
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
/****************************************************************
|
||||
* AUDIO System initialization
|
||||
****************************************************************/
|
||||
int audio_init (int rate, double fps)
|
||||
int audio_init (int samplerate, float framerate)
|
||||
{
|
||||
/* Shutdown first */
|
||||
audio_shutdown();
|
||||
@ -146,61 +173,91 @@ int audio_init (int rate, double fps)
|
||||
/* Clear the sound data context */
|
||||
memset(&snd, 0, sizeof (snd));
|
||||
|
||||
/* Make sure the requested sample rate is valid */
|
||||
if (!rate || ((rate < 8000) | (rate > 48000))) return (-1);
|
||||
snd.sample_rate = rate;
|
||||
/* Default settings */
|
||||
snd.sample_rate = samplerate;
|
||||
snd.frame_rate = framerate;
|
||||
|
||||
/* Calculate the sound buffer size (for one frame) */
|
||||
snd.buffer_size = (int)(samplerate / framerate) + 32;
|
||||
|
||||
#ifndef NGC
|
||||
/* Calculate the sound buffer size (for one frame) */
|
||||
snd.buffer_size = (rate / vdp_rate);
|
||||
|
||||
/* Output buffers */
|
||||
snd.buffer[0] = (int16 *) malloc(SND_SIZE);
|
||||
snd.buffer[1] = (int16 *) malloc(SND_SIZE);
|
||||
if (!snd.buffer[0] || !snd.buffer[1]) return (-1);
|
||||
#else
|
||||
/* Calculate the sound buffer size (for one frame) */
|
||||
snd.buffer_size = (rate / vdp_rate) + 32;
|
||||
if (!snd.buffer[0] || !snd.buffer[1])
|
||||
return (-1);
|
||||
#endif
|
||||
|
||||
/* SN76489 stream buffers */
|
||||
snd.psg.buffer = (int16 *)malloc (SND_SIZE);
|
||||
if (!snd.psg.buffer) return (-1);
|
||||
snd.psg.buffer = (int16 *) malloc(SND_SIZE);
|
||||
if (!snd.psg.buffer)
|
||||
return (-1);
|
||||
|
||||
/* YM2612 stream buffers */
|
||||
snd.fm.buffer[0] = (int16 *)malloc (SND_SIZE);
|
||||
snd.fm.buffer[1] = (int16 *)malloc (SND_SIZE);
|
||||
if (!snd.fm.buffer[0] || !snd.fm.buffer[1]) return (-1);
|
||||
snd.fm.buffer = (int16 *) malloc(SND_SIZE * 2);
|
||||
if (!snd.fm.buffer)
|
||||
return (-1);
|
||||
|
||||
/* Resampling buffer */
|
||||
if (config.hq_fm)
|
||||
{
|
||||
if (!Fir_Resampler_initialize(4096)) return (-1);
|
||||
if (!Fir_Resampler_initialize(4096))
|
||||
return (-1);
|
||||
}
|
||||
|
||||
/* 3 band EQ */
|
||||
audio_set_equalizer();
|
||||
|
||||
/* Set audio enable flag */
|
||||
snd.enabled = 1;
|
||||
|
||||
/* Initialize Sound Chips emulation */
|
||||
sound_init(rate,fps);
|
||||
/* Reset audio */
|
||||
audio_reset();
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
/****************************************************************
|
||||
* AUDIO System reset
|
||||
****************************************************************/
|
||||
void audio_reset(void)
|
||||
{
|
||||
/* Low-Pass filter */
|
||||
llp = 0;
|
||||
rrp = 0;
|
||||
|
||||
/* 3 band EQ */
|
||||
audio_set_equalizer();
|
||||
|
||||
/* audio buffers */
|
||||
Fir_Resampler_clear();
|
||||
snd.psg.pos = snd.psg.buffer;
|
||||
snd.fm.pos = snd.fm.buffer;
|
||||
#ifndef NGC
|
||||
if (snd.buffer[0])
|
||||
memset (snd.buffer[0], 0, SND_SIZE);
|
||||
if (snd.buffer[1])
|
||||
memset (snd.buffer[1], 0, SND_SIZE);
|
||||
#endif
|
||||
if (snd.psg.buffer)
|
||||
memset (snd.psg.buffer, 0, SND_SIZE);
|
||||
if (snd.fm.buffer)
|
||||
memset (snd.fm.buffer, 0, SND_SIZE * 2);
|
||||
}
|
||||
|
||||
/****************************************************************
|
||||
* AUDIO System shutdown
|
||||
****************************************************************/
|
||||
void audio_shutdown(void)
|
||||
{
|
||||
/* Sound buffers */
|
||||
if (snd.buffer[0]) free(snd.buffer[0]);
|
||||
if (snd.buffer[1]) free(snd.buffer[1]);
|
||||
if (snd.fm.buffer[0]) free(snd.fm.buffer[0]);
|
||||
if (snd.fm.buffer[1]) free(snd.fm.buffer[1]);
|
||||
if (snd.psg.buffer) free(snd.psg.buffer);
|
||||
#ifndef NGC
|
||||
if (snd.buffer[0])
|
||||
free(snd.buffer[0]);
|
||||
if (snd.buffer[1])
|
||||
free(snd.buffer[1]);
|
||||
#endif
|
||||
if (snd.fm.buffer)
|
||||
free(snd.fm.buffer);
|
||||
if (snd.psg.buffer)
|
||||
free(snd.psg.buffer);
|
||||
|
||||
/* Resampling buffer */
|
||||
Fir_Resampler_shutdown();
|
||||
@ -219,6 +276,9 @@ void system_init (void)
|
||||
|
||||
/* Cartridge hardware */
|
||||
cart_hw_init();
|
||||
|
||||
/* Sound Chips hardware */
|
||||
sound_init();
|
||||
}
|
||||
|
||||
/****************************************************************
|
||||
@ -231,17 +291,15 @@ void system_reset (void)
|
||||
|
||||
/* Genesis hardware */
|
||||
gen_reset(1);
|
||||
SN76489_Reset();
|
||||
io_reset();
|
||||
vdp_reset();
|
||||
render_reset();
|
||||
|
||||
/* Clear Sound Buffers */
|
||||
if (snd.psg.buffer) memset (snd.psg.buffer, 0, SND_SIZE);
|
||||
if (snd.fm.buffer[0]) memset (snd.fm.buffer[0], 0, SND_SIZE);
|
||||
if (snd.fm.buffer[1]) memset (snd.fm.buffer[1], 0, SND_SIZE);
|
||||
Fir_Resampler_clear();
|
||||
llp = rrp = 0;
|
||||
/* Sound chips */
|
||||
sound_reset();
|
||||
|
||||
/* Audio System */
|
||||
audio_reset();
|
||||
}
|
||||
|
||||
/****************************************************************
|
||||
@ -265,15 +323,6 @@ int system_frame (int do_skip)
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint32 aim_m68k = 0;
|
||||
uint32 aim_z80 = 0;
|
||||
|
||||
/* reset cycles counts */
|
||||
count_m68k = 0;
|
||||
count_z80 = 0;
|
||||
fifo_write_cnt = 0;
|
||||
fifo_lastwrite = 0;
|
||||
|
||||
/* update display settings */
|
||||
int line;
|
||||
int reset = resetline;
|
||||
@ -291,17 +340,21 @@ int system_frame (int do_skip)
|
||||
odd_frame ^= 1;
|
||||
|
||||
/* clear VBLANK and DMA flags */
|
||||
status &= 0xFFF5;
|
||||
status &= 0xFFE5;
|
||||
|
||||
/* even/odd field flag (interlaced modes only) */
|
||||
if (odd_frame && interlaced) status |= 0x0010;
|
||||
else status &= 0xFFEF;
|
||||
if (odd_frame && interlaced)
|
||||
status |= 0x0010;
|
||||
|
||||
/* reload HCounter */
|
||||
int h_counter = reg[10];
|
||||
|
||||
/* parse sprites for line 0 (done on last line) */
|
||||
parse_satb (0x80);
|
||||
/* reset VDP FIFO */
|
||||
fifo_write_cnt = 0;
|
||||
fifo_lastwrite = 0;
|
||||
|
||||
/* reset line cycle count */
|
||||
mcycles_vdp = 0;
|
||||
|
||||
/* process scanlines */
|
||||
for (line = 0; line < lines_per_frame; line ++)
|
||||
@ -312,14 +365,10 @@ int system_frame (int do_skip)
|
||||
/* update 6-Buttons or Menacer */
|
||||
input_update();
|
||||
|
||||
/* update CPU cycle counters */
|
||||
hint_m68k = count_m68k;
|
||||
line_m68k = aim_m68k;
|
||||
line_z80 = aim_z80;
|
||||
aim_z80 += z80cycles_per_line;
|
||||
aim_m68k += m68cycles_per_line;
|
||||
/* 68k line cycle count */
|
||||
hint_68k = mcycles_68k;
|
||||
|
||||
/* Soft Reset ? */
|
||||
/* Soft Reset line */
|
||||
if (line == reset)
|
||||
{
|
||||
/* Pro Action Replay (switch at "Trainer" position) */
|
||||
@ -329,6 +378,10 @@ int system_frame (int do_skip)
|
||||
gen_reset(0);
|
||||
}
|
||||
|
||||
/* update VDP DMA */
|
||||
if (dma_length)
|
||||
vdp_update_dma();
|
||||
|
||||
/* active display */
|
||||
if (line <= vdp_height)
|
||||
{
|
||||
@ -337,27 +390,16 @@ int system_frame (int do_skip)
|
||||
{
|
||||
h_counter = reg[10];
|
||||
hint_pending = 1;
|
||||
if (reg[0] & 0x10) irq_status = (irq_status & ~0x40) | 0x14;
|
||||
|
||||
/* adjust timings to take further decrement in account (see below) */
|
||||
if ((line != 0) || (h_counter == 0)) aim_m68k += 36;
|
||||
if (reg[0] & 0x10)
|
||||
irq_status = (irq_status & ~0x40) | 0x14;
|
||||
}
|
||||
|
||||
/* HINT will be triggered on next line, approx. 36 cycles before VDP starts line rendering */
|
||||
/* during this period, any VRAM or VSRAM writes should NOT be taken in account before next line */
|
||||
/* as a result, line is rendered immediately after HINT and current line is shortened */
|
||||
/* CRAM and VDP register writes that could occur during HBLANK are handled separately */
|
||||
/* fix Striker, Zero the Kamikaze Squirell */
|
||||
if ((line < vdp_height) && (h_counter == 0)) aim_m68k -= 36;
|
||||
|
||||
/* update DMA timings */
|
||||
if (dma_length) vdp_update_dma();
|
||||
|
||||
/* vertical retrace */
|
||||
if (line == vdp_height)
|
||||
{
|
||||
/* render overscan */
|
||||
if ((line < end_line) && (!do_skip)) render_line(line, 1);
|
||||
if (line < end_line)
|
||||
render_line(line, 1);
|
||||
|
||||
/* update inputs (doing this here fix Warriors of Eternal Sun) */
|
||||
osd_input_Update();
|
||||
@ -367,39 +409,38 @@ int system_frame (int do_skip)
|
||||
|
||||
/* Z80 interrupt is 16ms period (one frame) and 64us length (one scanline) */
|
||||
zirq = 1;
|
||||
z80_set_irq_line(0, ASSERT_LINE);
|
||||
z80_set_irq_line(0, ASSERT_LINE);
|
||||
|
||||
/* delay between HINT, VBLANK and VINT (Dracula, OutRunners, VR Troopers) */
|
||||
m68k_run(line_m68k + 84);
|
||||
if (zreset && !zbusreq)
|
||||
{
|
||||
current_z80 = line_z80 + 39 - count_z80;
|
||||
if (current_z80 > 0) count_z80 += z80_execute(current_z80);
|
||||
}
|
||||
else count_z80 = line_z80 + 39;
|
||||
|
||||
/* V Interrupt */
|
||||
/* delay between VINT flag & V Interrupt (Ex-Mutants, Tyrant) */
|
||||
m68k_run(mcycles_vdp + 588);
|
||||
status |= 0x80;
|
||||
|
||||
/* 36 cycles latency after VINT occurence flag (Ex-Mutants, Tyrant) */
|
||||
m68k_run(line_m68k + 113);
|
||||
/* delay between VBLANK flag & V Interrupt (Dracula, OutRunners, VR Troopers) */
|
||||
m68k_run(mcycles_vdp + 788);
|
||||
if (zstate == 1)
|
||||
z80_run(mcycles_vdp + 788);
|
||||
else
|
||||
mcycles_z80 = mcycles_vdp + 788;
|
||||
|
||||
/* V Interrupt */
|
||||
vint_pending = 1;
|
||||
if (reg[1] & 0x20) irq_status = (irq_status & ~0x40) | 0x36;
|
||||
if (reg[1] & 0x20)
|
||||
irq_status = (irq_status & ~0x40) | 0x36;
|
||||
}
|
||||
else if (!do_skip)
|
||||
{
|
||||
/* render scanline and parse sprites for line n+1 */
|
||||
/* sprites are processed during horizontal blanking */
|
||||
parse_satb(0x80 + line);
|
||||
|
||||
/* render scanline */
|
||||
render_line(line, 0);
|
||||
if (line < (vdp_height-1)) parse_satb(0x81 + line);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* update DMA timings */
|
||||
if (dma_length) vdp_update_dma();
|
||||
|
||||
/* render overscan */
|
||||
if ((!do_skip) && ((line < end_line) || (line >= start_line))) render_line(line, 1);
|
||||
if ((line < end_line) || (line >= start_line))
|
||||
render_line(line, 1);
|
||||
|
||||
/* clear any pending Z80 interrupt */
|
||||
if (zirq)
|
||||
@ -410,17 +451,23 @@ int system_frame (int do_skip)
|
||||
}
|
||||
|
||||
/* process line */
|
||||
m68k_run(aim_m68k);
|
||||
if (zreset == 1 && zbusreq == 0)
|
||||
{
|
||||
current_z80 = aim_z80 - count_z80;
|
||||
if (current_z80 > 0) count_z80 += z80_execute(current_z80);
|
||||
}
|
||||
else count_z80 = aim_z80;
|
||||
m68k_run(mcycles_vdp + MCYCLES_PER_LINE);
|
||||
if (zstate == 1)
|
||||
z80_run(mcycles_vdp + MCYCLES_PER_LINE);
|
||||
else
|
||||
mcycles_z80 = mcycles_vdp + MCYCLES_PER_LINE;
|
||||
|
||||
/* SVP chip */
|
||||
if (svp) ssp1601_run(SVP_cycles);
|
||||
if (svp)
|
||||
ssp1601_run(SVP_cycles);
|
||||
|
||||
/* update line cycle count */
|
||||
mcycles_vdp += MCYCLES_PER_LINE;
|
||||
}
|
||||
|
||||
/* adjust cpu cycle count for next frame */
|
||||
mcycles_68k -= mcycles_vdp;
|
||||
mcycles_z80 -= mcycles_vdp;
|
||||
|
||||
return gen_running;
|
||||
}
|
||||
|
@ -28,12 +28,7 @@
|
||||
#define SYSTEM_MEGADRIVE 1
|
||||
#define SYSTEM_PICO 2
|
||||
|
||||
/* CPU cycles increments */
|
||||
#define z80cycles_per_line 228
|
||||
#define m68cycles_per_line 488
|
||||
|
||||
#define CLOCK_NTSC 53693175
|
||||
#define CLOCK_PAL 53203424
|
||||
#define MCYCLES_PER_LINE 3420
|
||||
|
||||
typedef struct
|
||||
{
|
||||
@ -59,18 +54,19 @@ typedef struct
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int sample_rate; /* Sample rate (8000-48000) */
|
||||
int sample_rate; /* Output Sample rate (8000-48000) */
|
||||
float frame_rate; /* Output Frame rate (usually 50 or 60 frames per second) */
|
||||
int enabled; /* 1= sound emulation is enabled */
|
||||
int buffer_size; /* Size of sound buffer (in bytes) */
|
||||
int16 *buffer[2]; /* Signed 16-bit stereo sound data */
|
||||
struct
|
||||
{
|
||||
int pos;
|
||||
int16 *buffer[2];
|
||||
int16 *pos;
|
||||
int16 *buffer;
|
||||
} fm;
|
||||
struct
|
||||
{
|
||||
int pos;
|
||||
int16 *pos;
|
||||
int16 *buffer;
|
||||
} psg;
|
||||
} t_snd;
|
||||
@ -78,18 +74,17 @@ typedef struct
|
||||
/* Global variables */
|
||||
extern t_bitmap bitmap;
|
||||
extern t_snd snd;
|
||||
extern uint32 count_m68k;
|
||||
extern uint32 line_m68k;
|
||||
extern uint32 hint_m68k;
|
||||
extern uint32 count_z80;
|
||||
extern uint32 line_z80;
|
||||
extern int32 current_z80;
|
||||
extern uint32 mcycles_vdp;
|
||||
extern uint32 mcycles_z80;
|
||||
extern uint32 mcycles_68k;
|
||||
extern uint32 hint_68k;
|
||||
extern uint8 system_hw;
|
||||
|
||||
/* Function prototypes */
|
||||
extern int audio_init (int rate,double fps);
|
||||
extern int audio_init (int samplerate,float framerate);
|
||||
extern void audio_reset (void);
|
||||
extern void audio_shutdown (void);
|
||||
extern void audio_update (int len);
|
||||
extern int audio_update (void);
|
||||
extern void audio_set_equalizer(void);
|
||||
extern void system_init (void);
|
||||
extern void system_reset (void);
|
||||
|
@ -103,7 +103,7 @@ int main (int argc, char *argv[])
|
||||
|
||||
/* initialize emulation */
|
||||
system_init();
|
||||
audio_init(option.sndrate);
|
||||
audio_init(option.sndrate, vdp_pal ? 50 : 60);
|
||||
|
||||
f = fopen("./game.srm", "rb");
|
||||
if (f!=NULL)
|
||||
@ -132,8 +132,9 @@ int main (int argc, char *argv[])
|
||||
system_frame(1);
|
||||
}
|
||||
|
||||
audio_update(snd.buffer_size);
|
||||
if(option.sound) dos_update_audio();
|
||||
audio_update();
|
||||
if(option.sound)
|
||||
dos_update_audio();
|
||||
}
|
||||
|
||||
f = fopen("./game.srm", "wb");
|
||||
@ -366,11 +367,19 @@ void dos_update_input(void)
|
||||
{
|
||||
vdp_pal ^= 1;
|
||||
|
||||
/* reinitialize timings */
|
||||
system_init ();
|
||||
unsigned char *temp = malloc(YM2612GetContextSize());
|
||||
if (temp) memcpy(temp, YM2612GetContextPtr(), YM2612GetContextSize());
|
||||
audio_init(48000);
|
||||
/* save YM2612 context */
|
||||
unsigned char *temp = memalign(32,YM2612GetContextSize());
|
||||
if (temp)
|
||||
memcpy(temp, YM2612GetContextPtr(), YM2612GetContextSize());
|
||||
|
||||
/* reinitialize all timings */
|
||||
audio_init(snd.sample_rate, framerate);
|
||||
system_init();
|
||||
|
||||
/* restore SRAM */
|
||||
memfile_autoload(config.sram_auto,-1);
|
||||
|
||||
/* restore YM2612 context */
|
||||
if (temp)
|
||||
{
|
||||
YM2612Restore(temp);
|
||||
@ -378,7 +387,7 @@ void dos_update_input(void)
|
||||
}
|
||||
|
||||
/* reinitialize HVC tables */
|
||||
vctab = (vdp_pal) ? ((reg[1] & 8) ? vc_pal_240 : vc_pal_224) : vc_ntsc_224;
|
||||
vctab = vdp_pal ? ((reg[1] & 8) ? vc_pal_240 : vc_pal_224) : vc_ntsc_224;
|
||||
hctab = (reg[12] & 1) ? cycle2hc40 : cycle2hc32;
|
||||
|
||||
/* reinitialize overscan area */
|
||||
|
@ -12,7 +12,7 @@ NAME = gen_sdl.exe
|
||||
|
||||
CC = gcc
|
||||
CFLAGS = `sdl-config --cflags` -O6 -march=i686 -fomit-frame-pointer
|
||||
DEFINES = -DLSB_FIRST -DX86_ASM -DLOGERROR=1
|
||||
DEFINES = -DLSB_FIRST -DX86_ASM -DLOGERROR=1 -DLOGVDP=1
|
||||
INCLUDES = -I. -I.. -I../z80 -I../m68k -I../sound -I../cart_hw -I../cart_hw/svp -I../ntsc
|
||||
LIBS = `sdl-config --libs` -lz -lm
|
||||
|
||||
|
@ -304,19 +304,27 @@ static int sdl_control_update(SDLKey keystate)
|
||||
{
|
||||
vdp_pal ^= 1;
|
||||
|
||||
/* reinitialize timings */
|
||||
system_init ();
|
||||
unsigned char *temp = malloc(YM2612GetContextSize());
|
||||
if (temp) memcpy(temp, YM2612GetContextPtr(), YM2612GetContextSize());
|
||||
audio_init(SOUND_FREQUENCY);
|
||||
/* save YM2612 context */
|
||||
unsigned char *temp = memalign(32,YM2612GetContextSize());
|
||||
if (temp)
|
||||
memcpy(temp, YM2612GetContextPtr(), YM2612GetContextSize());
|
||||
|
||||
/* reinitialize all timings */
|
||||
audio_init(snd.sample_rate, framerate);
|
||||
system_init();
|
||||
|
||||
/* restore SRAM */
|
||||
memfile_autoload(config.sram_auto,-1);
|
||||
|
||||
/* restore YM2612 context */
|
||||
if (temp)
|
||||
{
|
||||
YM2612Restore(temp);
|
||||
free(temp);
|
||||
}
|
||||
|
||||
|
||||
/* reinitialize HVC tables */
|
||||
vctab = (vdp_pal) ? ((reg[1] & 8) ? vc_pal_240 : vc_pal_224) : vc_ntsc_224;
|
||||
vctab = vdp_pal ? ((reg[1] & 8) ? vc_pal_240 : vc_pal_224) : vc_ntsc_224;
|
||||
hctab = (reg[12] & 1) ? cycle2hc40 : cycle2hc32;
|
||||
|
||||
/* reinitialize overscan area */
|
||||
@ -528,8 +536,8 @@ int main (int argc, char **argv)
|
||||
SDL_UnlockSurface(sdl_video.surf_bitmap);
|
||||
|
||||
/* initialize emulation */
|
||||
audio_init(SOUND_FREQUENCY, vdp_pal ? 50 : 60);
|
||||
system_init();
|
||||
audio_init(SOUND_FREQUENCY);
|
||||
|
||||
/* load SRAM */
|
||||
f = fopen("./game.srm", "rb");
|
||||
@ -545,8 +553,9 @@ int main (int argc, char **argv)
|
||||
if(use_sound)
|
||||
SDL_PauseAudio(0);
|
||||
|
||||
/* 3 frames = 50 ms (60hz) or 60 ms (50hz) */
|
||||
if(sdl_sync.sem_sync)
|
||||
SDL_SetTimer(vdp_pal ? 60 : 50, sdl_sync_timer_callback); /* 3 frames = 50 ms (60hz) or 60 ms (50hz) */
|
||||
SDL_SetTimer(vdp_pal ? 60 : 50, sdl_sync_timer_callback);
|
||||
|
||||
/* emulation loop */
|
||||
while(running)
|
||||
|
190
source/vdp.c
190
source/vdp.c
@ -72,12 +72,10 @@ uint16 v_counter; /* VDP scanline counter */
|
||||
uint32 dma_length; /* Current DMA remaining bytes */
|
||||
int32 fifo_write_cnt; /* VDP writes fifo count */
|
||||
uint32 fifo_lastwrite; /* last VDP write cycle */
|
||||
uint8 fifo_latency; /* VDP write cycles latency */
|
||||
uint8 odd_frame; /* 1: odd field, 0: even field */
|
||||
uint8 im2_flag; /* 1= Interlace mode 2 is being used */
|
||||
uint8 interlaced; /* 1: Interlaced mode 1 or 2 */
|
||||
uint8 vdp_pal; /* 1: PAL , 0: NTSC (default) */
|
||||
uint8 vdp_rate; /* PAL: 50hz, NTSC: 60hz */
|
||||
uint16 lines_per_frame; /* PAL: 313 lines, NTSC: 262 lines */
|
||||
|
||||
|
||||
@ -89,7 +87,8 @@ static const uint16 row_mask_table[] = { 0x0FF, 0x1FF, 0x2FF, 0x3FF };
|
||||
static uint16 sat_base_mask; /* Base bits of SAT */
|
||||
static uint16 sat_addr_mask; /* Index bits of SAT */
|
||||
static uint32 dma_endCycles; /* 68k cycles to DMA end */
|
||||
static uint8 dma_type; /* DMA mode */
|
||||
static uint32 dma_type; /* DMA mode */
|
||||
static uint32 fifo_latency; /* CPU access latency */
|
||||
|
||||
/* DMA Timings
|
||||
|
||||
@ -141,21 +140,10 @@ static inline void dma_fill(unsigned int data);
|
||||
void vdp_init(void)
|
||||
{
|
||||
/* PAL/NTSC timings */
|
||||
switch (region_code)
|
||||
{
|
||||
case REGION_EUROPE:
|
||||
case REGION_JAPAN_PAL:
|
||||
vdp_pal = 1;
|
||||
vdp_rate = 50;
|
||||
lines_per_frame = 313;
|
||||
break;
|
||||
|
||||
default:
|
||||
vdp_pal = 0;
|
||||
vdp_rate = 60;
|
||||
lines_per_frame = 262;
|
||||
break;
|
||||
}
|
||||
if (vdp_pal)
|
||||
lines_per_frame = 313;
|
||||
else
|
||||
lines_per_frame = 262;
|
||||
}
|
||||
|
||||
void vdp_reset(void)
|
||||
@ -233,8 +221,8 @@ void vdp_reset(void)
|
||||
reg_w(15, 0x02); /* auto increment */
|
||||
}
|
||||
|
||||
/* default latency */
|
||||
fifo_latency = 27;
|
||||
/* default FIFO timing */
|
||||
fifo_latency = 192;
|
||||
}
|
||||
|
||||
void vdp_shutdown(void)
|
||||
@ -258,9 +246,10 @@ void vdp_restore(uint8 *vdp_regs)
|
||||
bitmap.viewport.y = config.overscan ? (((reg[1] & 8) ? 0 : 8) + (vdp_pal ? 24 : 0)) : 0;
|
||||
bitmap.viewport.changed = 1;
|
||||
|
||||
/* restore VDP timings */
|
||||
fifo_latency = (reg[12] & 1) ? 27 : 30;
|
||||
if ((code & 0x0F) == 0x01) fifo_latency = fifo_latency * 2;
|
||||
/* restore FIFO timings */
|
||||
fifo_latency = (reg[12] & 1) ? 192 : 210;
|
||||
if ((code & 0x0F) == 0x01)
|
||||
fifo_latency = fifo_latency * 2;
|
||||
|
||||
/* remake cache */
|
||||
for (i=0;i<0x800;i++)
|
||||
@ -295,21 +284,21 @@ void vdp_update_dma()
|
||||
int rate = dma_rates[index];
|
||||
|
||||
/* 68k cycles left */
|
||||
int left_cycles = (line_m68k + m68cycles_per_line) - count_m68k;
|
||||
int left_cycles = (mcycles_vdp + MCYCLES_PER_LINE) - mcycles_68k;
|
||||
if (left_cycles < 0) left_cycles = 0;
|
||||
|
||||
/* DMA bytes left */
|
||||
int dma_bytes = (left_cycles * rate) / m68cycles_per_line;
|
||||
int dma_bytes = (left_cycles * rate) / MCYCLES_PER_LINE;
|
||||
|
||||
#ifdef LOGVDP
|
||||
error("[%d(%d)][%d(%d)] DMA type %d (%d access/line)-> %d access (%d remaining) (%x)\n", v_counter, count_m68k/488, count_m68k, count_m68k%488,dma_type, rate, dma_length, dma_bytes, m68k_get_reg (NULL, M68K_REG_PC));
|
||||
error("[%d(%d)][%d(%d)] DMA type %d (%d access/line)-> %d access (%d remaining) (%x)\n", v_counter, mcycles_68k/MCYCLES_PER_LINE, mcycles_68k, mcycles_68k%MCYCLES_PER_LINE,dma_type, rate, dma_length, dma_bytes, m68k_get_reg (NULL, M68K_REG_PC));
|
||||
#endif
|
||||
|
||||
/* determinate DMA length in CPU cycles */
|
||||
if (dma_length < dma_bytes)
|
||||
{
|
||||
/* DMA will be finished during this line */
|
||||
dma_cycles = (dma_length * m68cycles_per_line) / rate;
|
||||
dma_cycles = (dma_length * MCYCLES_PER_LINE) / rate;
|
||||
dma_length = 0;
|
||||
}
|
||||
else
|
||||
@ -324,7 +313,7 @@ void vdp_update_dma()
|
||||
{
|
||||
/* 68K COPY to V-RAM */
|
||||
/* 68K is frozen during DMA operation */
|
||||
count_m68k += dma_cycles;
|
||||
mcycles_68k += dma_cycles;
|
||||
|
||||
#ifdef LOGVDP
|
||||
error("-->CPU frozen for %d cycles\n", dma_cycles);
|
||||
@ -334,7 +323,7 @@ void vdp_update_dma()
|
||||
{
|
||||
/* VRAM Fill or VRAM Copy */
|
||||
/* set DMA end cyles count */
|
||||
dma_endCycles = count_m68k + dma_cycles;
|
||||
dma_endCycles = mcycles_68k + dma_cycles;
|
||||
|
||||
#ifdef LOGVDP
|
||||
error("-->DMA ends in %d cycles\n", dma_cycles);
|
||||
@ -348,7 +337,6 @@ void vdp_update_dma()
|
||||
/*--------------------------------------------------------------------------*/
|
||||
/* VDP Ports handler */
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
void vdp_ctrl_w(unsigned int data)
|
||||
{
|
||||
if (pending == 0)
|
||||
@ -398,18 +386,23 @@ void vdp_ctrl_w(unsigned int data)
|
||||
}
|
||||
}
|
||||
|
||||
/* FIFO emulation:
|
||||
---------------
|
||||
HDISP is 256*10/7 = approx. 366 cycles (same for both modes)
|
||||
this gives:
|
||||
H32: 16 accesses --> 366/16 = 23 cycles per access
|
||||
H40: 20 accesses --> 366/20 = 18 cycles per access
|
||||
/*
|
||||
FIFO emulation (Chaos Engine/Soldier of Fortune, Double Clutch)
|
||||
---------------------------------------------------------------
|
||||
|
||||
HDISP is 2560 mcycles (same in both modes)
|
||||
|
||||
CPU access per line is limited during active display:
|
||||
H32: 16 access --> 2560/16 = 160 cycles between access
|
||||
H40: 18 access --> 2560/18 = 142 cycles between access
|
||||
|
||||
FIFO access seems to require some additional cyles (VDP latency).
|
||||
|
||||
Also note that VRAM access are byte wide, so one VRAM write (word)
|
||||
takes twice CPU cycles.
|
||||
|
||||
VRAM access are byte wide --> VRAM writes takes 2x CPU cycles
|
||||
Memory access requires some additional cyles, the following values
|
||||
seems to work fine (see Chaos Engine/Soldier of Fortune)
|
||||
*/
|
||||
fifo_latency = (reg[12] & 1) ? 27 : 30;
|
||||
fifo_latency = (reg[12] & 1) ? 192 : 210;
|
||||
if ((code & 0x0F) == 0x01)
|
||||
fifo_latency = fifo_latency * 2;
|
||||
}
|
||||
@ -442,7 +435,7 @@ unsigned int vdp_ctrl_r(void)
|
||||
else status ^= 0x200;
|
||||
|
||||
/* update DMA Busy flag */
|
||||
if ((status & 2) && !dma_length && (count_m68k >= dma_endCycles))
|
||||
if ((status & 2) && !dma_length && (mcycles_68k >= dma_endCycles))
|
||||
status &= 0xFFFD;
|
||||
|
||||
unsigned int temp = status;
|
||||
@ -452,7 +445,7 @@ unsigned int vdp_ctrl_r(void)
|
||||
temp |= 0x08;
|
||||
|
||||
/* HBLANK flag (Sonic 3 and Sonic 2 "VS Modes", Lemmings 2, Mega Turrican) */
|
||||
if ((count_m68k % m68cycles_per_line) < 84)
|
||||
if ((mcycles_68k % MCYCLES_PER_LINE) < 588)
|
||||
temp |= 0x04;
|
||||
|
||||
/* clear pending flag */
|
||||
@ -462,21 +455,21 @@ unsigned int vdp_ctrl_r(void)
|
||||
status &= 0xFF9F;
|
||||
|
||||
#ifdef LOGVDP
|
||||
error("[%d(%d)][%d(%d)] VDP status read -> 0x%x (%x)\n", v_counter, count_m68k/488, count_m68k, count_m68k%488, temp, m68k_get_reg (NULL, M68K_REG_PC));
|
||||
error("[%d(%d)][%d(%d)] VDP status read -> 0x%x (%x)\n", v_counter, mcycles_68k/MCYCLES_PER_LINE, mcycles_68k, mcycles_68k%MCYCLES_PER_LINE, temp, m68k_get_reg (NULL, M68K_REG_PC));
|
||||
#endif
|
||||
return (temp);
|
||||
}
|
||||
|
||||
unsigned int vdp_hvc_r(void)
|
||||
{
|
||||
uint8 hc = (hc_latch & 0x100) ? (hc_latch & 0xFF) : hctab[count_m68k % m68cycles_per_line];
|
||||
uint8 hc = (hc_latch & 0x100) ? (hc_latch & 0xFF) : hctab[mcycles_68k%MCYCLES_PER_LINE];
|
||||
uint8 vc = vctab[v_counter];
|
||||
|
||||
/* interlace mode 2 */
|
||||
if (im2_flag) vc = (vc << 1) | ((vc >> 7) & 1);
|
||||
|
||||
#ifdef LOGVDP
|
||||
error("[%d(%d)][%d(%d)] VDP HVC Read -> 0x%04x (%x)\n", v_counter, count_m68k/488, count_m68k, count_m68k%488,(vc << 8) | hc, m68k_get_reg (NULL, M68K_REG_PC));
|
||||
error("[%d(%d)][%d(%d)] VDP HVC Read -> 0x%04x (%x)\n", v_counter, mcycles_68k/MCYCLES_PER_LINE, mcycles_68k, mcycles_68k%MCYCLES_PER_LINE,(vc << 8) | hc, m68k_get_reg (NULL, M68K_REG_PC));
|
||||
#endif
|
||||
return ((vc << 8) | hc);
|
||||
}
|
||||
@ -506,13 +499,13 @@ void vdp_data_w(unsigned int data)
|
||||
if (fifo_write_cnt == 0)
|
||||
{
|
||||
/* reset cycle counter */
|
||||
fifo_lastwrite = count_m68k;
|
||||
fifo_lastwrite = mcycles_68k;
|
||||
|
||||
/* FIFO is not empty anymore */
|
||||
status &= 0xFDFF;
|
||||
}
|
||||
|
||||
/* increase write counter */
|
||||
/* increase FIFO word count */
|
||||
fifo_write_cnt ++;
|
||||
|
||||
/* is FIFO full ? */
|
||||
@ -522,7 +515,7 @@ void vdp_data_w(unsigned int data)
|
||||
|
||||
/* VDP latency (Chaos Engine, Soldiers of Fortune, Double Clutch) */
|
||||
if (fifo_write_cnt > 4)
|
||||
count_m68k = fifo_lastwrite + fifo_latency;
|
||||
mcycles_68k = fifo_lastwrite + fifo_latency;
|
||||
}
|
||||
}
|
||||
|
||||
@ -542,7 +535,7 @@ unsigned int vdp_data_r(void)
|
||||
case 0x00: /* VRAM */
|
||||
temp = *(uint16 *) & vram[(addr & 0xFFFE)];
|
||||
#ifdef LOGVDP
|
||||
error("[%d(%d)][%d(%d)] VRAM 0x%x read -> 0x%x (%x)\n", v_counter, count_m68k/488, count_m68k, count_m68k%488, addr, temp, m68k_get_reg (NULL, M68K_REG_PC));
|
||||
error("[%d(%d)][%d(%d)] VRAM 0x%x read -> 0x%x (%x)\n", v_counter, mcycles_68k/MCYCLES_PER_LINE, mcycles_68k, mcycles_68k%MCYCLES_PER_LINE, addr, temp, m68k_get_reg (NULL, M68K_REG_PC));
|
||||
#endif
|
||||
break;
|
||||
|
||||
@ -550,14 +543,14 @@ unsigned int vdp_data_r(void)
|
||||
temp = *(uint16 *) & cram[(addr & 0x7E)];
|
||||
temp = UNPACK_CRAM (temp);
|
||||
#ifdef LOGVDP
|
||||
error("[%d(%d)][%d(%d)] CRAM 0x%x read -> 0x%x (%x)\n", v_counter, count_m68k/488, count_m68k, count_m68k%488, addr, temp, m68k_get_reg (NULL, M68K_REG_PC));
|
||||
error("[%d(%d)][%d(%d)] CRAM 0x%x read -> 0x%x (%x)\n", v_counter, mcycles_68k/MCYCLES_PER_LINE, mcycles_68k, mcycles_68k%MCYCLES_PER_LINE, addr, temp, m68k_get_reg (NULL, M68K_REG_PC));
|
||||
#endif
|
||||
break;
|
||||
|
||||
case 0x04: /* VSRAM */
|
||||
temp = *(uint16 *) & vsram[(addr & 0x7E)];
|
||||
#ifdef LOGVDP
|
||||
error("[%d(%d)][%d(%d)] VSRAM 0x%x read -> 0x%x (%x)\n", v_counter, count_m68k/488, count_m68k, count_m68k%488, addr, temp, m68k_get_reg (NULL, M68K_REG_PC));
|
||||
error("[%d(%d)][%d(%d)] VSRAM 0x%x read -> 0x%x (%x)\n", v_counter, mcycles_68k/MCYCLES_PER_LINE, mcycles_68k, mcycles_68k%MCYCLES_PER_LINE, addr, temp, m68k_get_reg (NULL, M68K_REG_PC));
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
@ -576,7 +569,7 @@ unsigned int vdp_data_r(void)
|
||||
int vdp_int_ack_callback(int int_level)
|
||||
{
|
||||
#ifdef LOGVDP
|
||||
error("[%d(%d)][%d(%d)] INT Level %d ack (%x)\n", v_counter, count_m68k/488, count_m68k, count_m68k%488,int_level, m68k_get_reg (NULL, M68K_REG_PC));
|
||||
error("[%d(%d)][%d(%d)] INT Level %d ack (%x)\n", v_counter, mcycles_68k/MCYCLES_PER_LINE, mcycles_68k, mcycles_68k%MCYCLES_PER_LINE,int_level, m68k_get_reg (NULL, M68K_REG_PC));
|
||||
#endif
|
||||
|
||||
/* VINT triggered ? */
|
||||
@ -597,11 +590,13 @@ int vdp_int_ack_callback(int int_level)
|
||||
}
|
||||
|
||||
/* update IRQ status */
|
||||
irq_status = 0x10;
|
||||
irq_status = 0;
|
||||
if (vint_pending && (reg[1] & 0x20))
|
||||
irq_status |= 6;
|
||||
irq_status |= 0x16;
|
||||
else if (hint_pending && (reg[0] & 0x10))
|
||||
irq_status |= 4;
|
||||
irq_status |= 0x14;
|
||||
else
|
||||
m68k_set_irq(0);
|
||||
|
||||
return M68K_INT_ACK_AUTOVECTOR;
|
||||
}
|
||||
@ -614,14 +609,15 @@ static inline void fifo_update()
|
||||
if (fifo_write_cnt > 0)
|
||||
{
|
||||
/* update FIFO reads */
|
||||
uint32 fifo_read = ((count_m68k - fifo_lastwrite) / fifo_latency);
|
||||
uint32 fifo_read = ((mcycles_68k - fifo_lastwrite) / fifo_latency);
|
||||
if (fifo_read > 0)
|
||||
{
|
||||
fifo_write_cnt -= fifo_read;
|
||||
if (fifo_write_cnt < 0) fifo_write_cnt = 0;
|
||||
if (fifo_write_cnt < 0)
|
||||
fifo_write_cnt = 0;
|
||||
|
||||
/* update cycle count */
|
||||
fifo_lastwrite += fifo_read*fifo_latency;
|
||||
fifo_lastwrite += (fifo_read * fifo_latency);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -636,7 +632,7 @@ static inline void data_w(unsigned int data)
|
||||
case 0x01: /* VRAM */
|
||||
|
||||
#ifdef LOGVDP
|
||||
error("[%d(%d)][%d(%d)] VRAM 0x%x write -> 0x%x (%x)\n", v_counter, count_m68k/488, count_m68k, count_m68k%488, addr, data, m68k_get_reg (NULL, M68K_REG_PC));
|
||||
error("[%d(%d)][%d(%d)] VRAM 0x%x write -> 0x%x (%x)\n", v_counter, mcycles_68k/MCYCLES_PER_LINE, mcycles_68k, mcycles_68k%MCYCLES_PER_LINE, addr, data, m68k_get_reg (NULL, M68K_REG_PC));
|
||||
#endif
|
||||
|
||||
/* Byte-swap data if A0 is set */
|
||||
@ -663,7 +659,7 @@ static inline void data_w(unsigned int data)
|
||||
case 0x03: /* CRAM */
|
||||
{
|
||||
#ifdef LOGVDP
|
||||
error("[%d(%d)][%d(%d)] CRAM 0x%x write -> 0x%x (%x)\n", v_counter, count_m68k/488, count_m68k, count_m68k%488, addr, data, m68k_get_reg (NULL, M68K_REG_PC));
|
||||
error("[%d(%d)][%d(%d)] CRAM 0x%x write -> 0x%x (%x)\n", v_counter, mcycles_68k/MCYCLES_PER_LINE, mcycles_68k, mcycles_68k%MCYCLES_PER_LINE, addr, data, m68k_get_reg (NULL, M68K_REG_PC));
|
||||
#endif
|
||||
uint16 *p = (uint16 *) &cram[(addr & 0x7E)];
|
||||
data = PACK_CRAM (data & 0x0EEE);
|
||||
@ -681,10 +677,10 @@ static inline void data_w(unsigned int data)
|
||||
if (border == index)
|
||||
color_update (0x00, *p);
|
||||
|
||||
/* CRAM modified during HBLANK */
|
||||
if (!(status & 8) && (reg[1]&0x40) && (count_m68k <= (line_m68k + 84)))
|
||||
/* CRAM modified during HBLANK (Striker, Zero the Kamikaze, etc) */
|
||||
if (!(status & 8) && (reg[1]& 0x40) && (mcycles_68k <= (mcycles_vdp + 860)))
|
||||
{
|
||||
/* remap current line (Striker) */
|
||||
/* remap current line */
|
||||
remap_buffer(v_counter,bitmap.viewport.w + 2*bitmap.viewport.x);
|
||||
#ifdef LOGVDP
|
||||
error("Line remapped\n");
|
||||
@ -699,7 +695,7 @@ static inline void data_w(unsigned int data)
|
||||
|
||||
case 0x05: /* VSRAM */
|
||||
#ifdef LOGVDP
|
||||
error("[%d(%d)][%d(%d)] VSRAM 0x%x write -> 0x%x (%x)\n", v_counter, count_m68k/488, count_m68k, count_m68k%488, addr, data, m68k_get_reg (NULL, M68K_REG_PC));
|
||||
error("[%d(%d)][%d(%d)] VSRAM 0x%x write -> 0x%x (%x)\n", v_counter, mcycles_68k/MCYCLES_PER_LINE, mcycles_68k, mcycles_68k%MCYCLES_PER_LINE, addr, data, m68k_get_reg (NULL, M68K_REG_PC));
|
||||
#endif
|
||||
*(uint16 *) &vsram[(addr & 0x7E)] = data;
|
||||
break;
|
||||
@ -716,14 +712,15 @@ static inline void data_w(unsigned int data)
|
||||
static inline void reg_w(unsigned int r, unsigned int d)
|
||||
{
|
||||
#ifdef LOGVDP
|
||||
error("[%d(%d)][%d(%d)] VDP register %d write -> 0x%x (%x)\n", v_counter, count_m68k/488, count_m68k, count_m68k%488, r, d, m68k_get_reg (NULL, M68K_REG_PC));
|
||||
error("[%d(%d)][%d(%d)] VDP register %d write -> 0x%x (%x)\n", v_counter, mcycles_68k/MCYCLES_PER_LINE, mcycles_68k, mcycles_68k%MCYCLES_PER_LINE, r, d, m68k_get_reg (NULL, M68K_REG_PC));
|
||||
#endif
|
||||
|
||||
/* See if Mode 4 (SMS mode) is enabled
|
||||
According to official doc, VDP registers #11 to #23 can not be written unless bit2 in register #1 is set
|
||||
Fix Captain Planet & Avengers (Alt version), Bass Master Classic Pro Edition (they incidentally activate Mode 4)
|
||||
*/
|
||||
if (!(reg[1] & 4) && (r > 10)) return;
|
||||
if (!(reg[1] & 4) && (r > 10))
|
||||
return;
|
||||
|
||||
switch(r)
|
||||
{
|
||||
@ -734,8 +731,10 @@ static inline void reg_w(unsigned int r, unsigned int d)
|
||||
{
|
||||
/* update IRQ status */
|
||||
irq_status = 0x50;
|
||||
if (vint_pending && (reg[1] & 0x20)) irq_status |= 0x26;
|
||||
else if (d & 0x10) irq_status |= 4;
|
||||
if (vint_pending && (reg[1] & 0x20))
|
||||
irq_status |= 0x26;
|
||||
else if (d & 0x10)
|
||||
irq_status |= 4;
|
||||
}
|
||||
|
||||
/* Palette bit */
|
||||
@ -759,8 +758,10 @@ static inline void reg_w(unsigned int r, unsigned int d)
|
||||
{
|
||||
/* update IRQ status */
|
||||
irq_status = 0x50;
|
||||
if (d & 0x20) irq_status |= 0x26;
|
||||
else if (hint_pending && (reg[0] & 0x10)) irq_status |= 4;
|
||||
if (d & 0x20)
|
||||
irq_status |= 0x26;
|
||||
else if (hint_pending && (reg[0] & 0x10))
|
||||
irq_status |= 4;
|
||||
}
|
||||
|
||||
/* See if the viewport height has actually been changed */
|
||||
@ -772,27 +773,34 @@ static inline void reg_w(unsigned int r, unsigned int d)
|
||||
if (config.overscan) bitmap.viewport.y = ((vdp_pal ? 288 : 240) - bitmap.viewport.h) / 2;
|
||||
|
||||
/* update VC table */
|
||||
if (vdp_pal) vctab = (d & 8) ? vc_pal_240 : vc_pal_224;
|
||||
if (vdp_pal)
|
||||
vctab = (d & 8) ? vc_pal_240 : vc_pal_224;
|
||||
}
|
||||
|
||||
/* Display enabled/blanked during "Horizontal Blanking" */
|
||||
/* Display status modified during Horizontal Blanking (Legend of Galahad, Lemmings 2, */
|
||||
/* Nigel Mansell's World Championship Racing, Deadly Moves, Power Athlete). */
|
||||
/* */
|
||||
/* Note that this is not entirely correct since we are cheating with the HBLANK period limits */
|
||||
/* and still redrawing the whole line. This is done because some game (PAL version of Nigel */
|
||||
/* Mansell's World Championship Racing actually) appear to disable display outside HBLANK. On */
|
||||
/* real hardware, the raster line would appear partially blanked. */
|
||||
if (((d&0x40) != (reg[1]&0x40)) && !(status & 8))
|
||||
{
|
||||
if (count_m68k <= (hint_m68k + 120))
|
||||
if (mcycles_68k <= (hint_68k + 860))
|
||||
{
|
||||
/* Fixes the following games :
|
||||
- Legend of Galahad, Lemmings 2, Nigel Mansell's World Championship Racing (display OFF)
|
||||
- Deadly Moves, Power Athlete (display ON)
|
||||
*/
|
||||
/* NB: This is not entirely correct since we are a little too tolerant with the HBLANK period limits
|
||||
while still redrawing the whole line. This is done because some games appear to write this
|
||||
register outside HBLANK: on real hardware, the line would appear partially blanked.
|
||||
*/
|
||||
reg[1] = d;
|
||||
render_line(v_counter, 0);
|
||||
#ifdef LOGVDP
|
||||
error("Line redrawn\n");
|
||||
error("Line redrawn (%d sprites) \n",object_index_count);
|
||||
#endif
|
||||
/* If display was disabled during HBLANK (Mickey Mania 3D level), sprite processing is limited */
|
||||
/* Below values have been deducted from testing on this game, accurate emulation would require */
|
||||
/* to know exact sprite (pre)processing timings. Hopefully, they don't seem to break any other */
|
||||
/* games, so they might not be so much inaccurate. */
|
||||
if ((d&0x40) && (mcycles_68k % MCYCLES_PER_LINE >= 360) && (object_index_count > 5))
|
||||
object_index_count = 5;
|
||||
|
||||
/* re-render line */
|
||||
render_line(v_counter, 0);
|
||||
}
|
||||
#ifdef LOGVDP
|
||||
else
|
||||
@ -837,10 +845,10 @@ static inline void reg_w(unsigned int r, unsigned int d)
|
||||
border = d;
|
||||
color_update(0x00, *(uint16 *)&cram[(border << 1)]);
|
||||
|
||||
/* background color modified during Horizontal Blanking */
|
||||
if (!(status & 8) && (count_m68k <= (line_m68k + 84)))
|
||||
/* Background color modified during Horizontal Blanking (Road Rash 1,2,3)*/
|
||||
if (!(status & 8) && (mcycles_68k <= (mcycles_vdp + 860)))
|
||||
{
|
||||
/* remap entire line (see Road Rash I,II,III) */
|
||||
/* remap colors */
|
||||
reg[7] = d;
|
||||
remap_buffer(v_counter,bitmap.viewport.w + 2*bitmap.viewport.x);
|
||||
#ifdef LOGVDP
|
||||
@ -994,7 +1002,8 @@ static inline void dma_vbus (void)
|
||||
{
|
||||
/* Return $FFFF only when the Z80 isn't hogging the Z-bus.
|
||||
(e.g. Z80 isn't reset and 68000 has the bus) */
|
||||
if (source <= 0xa0ffff) temp = (zbusack ? *(uint16 *)(work_ram + (source & 0xffff)) : 0xffff);
|
||||
if (source <= 0xa0ffff)
|
||||
temp = ((zstate ^ 3) ? *(uint16 *)(work_ram + (source & 0xffff)) : 0xffff);
|
||||
|
||||
/* The I/O chip and work RAM try to drive the data bus which results
|
||||
in both values being combined in random ways when read.
|
||||
@ -1006,7 +1015,8 @@ static inline void dma_vbus (void)
|
||||
}
|
||||
|
||||
/* All remaining locations access work RAM */
|
||||
else temp = *(uint16 *)(work_ram + (source & 0xffff));
|
||||
else
|
||||
temp = *(uint16 *)(work_ram + (source & 0xffff));
|
||||
|
||||
source += 2;
|
||||
source = ((base & 0xFE0000) | (source & 0x1FFFF));
|
||||
@ -1059,12 +1069,12 @@ static inline void dma_fill(unsigned int data)
|
||||
/* write MSB */
|
||||
data = (data >> 8) & 0xff;
|
||||
|
||||
/* detect internal SAT modification */
|
||||
/* intercept SAT writes */
|
||||
if ((addr & sat_base_mask) == satb)
|
||||
{
|
||||
do
|
||||
{
|
||||
/* update internal SAT (fix Battletech) */
|
||||
/* update internal SAT copy */
|
||||
WRITE_BYTE(sat, (addr & sat_addr_mask)^1, data);
|
||||
WRITE_BYTE(vram, addr^1, data);
|
||||
MARK_BG_DIRTY (addr);
|
||||
|
@ -59,12 +59,10 @@ extern uint16 v_counter;
|
||||
extern uint32 dma_length;
|
||||
extern int32 fifo_write_cnt;
|
||||
extern uint32 fifo_lastwrite;
|
||||
extern uint8 fifo_latency;
|
||||
extern uint8 im2_flag;
|
||||
extern uint8 interlaced;
|
||||
extern uint8 odd_frame;
|
||||
extern uint8 vdp_pal;
|
||||
extern uint8 vdp_rate;
|
||||
extern uint16 lines_per_frame;
|
||||
|
||||
extern uint8 *vctab;
|
||||
@ -72,8 +70,8 @@ extern uint8 *hctab;
|
||||
extern uint8 vc_ntsc_224[262];
|
||||
extern uint8 vc_pal_224[313];
|
||||
extern uint8 vc_pal_240[313];
|
||||
extern uint8 cycle2hc32[488];
|
||||
extern uint8 cycle2hc40[488];
|
||||
extern uint8 cycle2hc32[3420];
|
||||
extern uint8 cycle2hc40[3420];
|
||||
|
||||
/* Function prototypes */
|
||||
extern void vdp_init(void);
|
||||
|
159
source/z80/z80.c
159
source/z80/z80.c
@ -1,7 +1,7 @@
|
||||
/*****************************************************************************
|
||||
*
|
||||
* z80.c
|
||||
* Portable Z80 emulator V3.9
|
||||
* Portable Z80 emulator V3.9
|
||||
*
|
||||
* Copyright Juergen Buchmueller, all rights reserved.
|
||||
*
|
||||
@ -17,42 +17,42 @@
|
||||
* terms of its usage and license at any time, including retroactively
|
||||
* - This entire notice must remain in the source code.
|
||||
*
|
||||
* TODO:
|
||||
* - If LD A,I or LD A,R is interrupted, P/V flag gets reset, even if IFF2
|
||||
* was set before this instruction
|
||||
* - Ideally, the tiny differences between Z80 types should be supported,
|
||||
* currently known differences:
|
||||
* - LD A,I/R P/V flag reset glitch is fixed on CMOS Z80
|
||||
* - OUT (C),0 outputs 0 on NMOS Z80, $FF on CMOS Z80
|
||||
* - SCF/CCF X/Y flags is ((flags | A) & 0x28) on SGS/SHARP/ZiLOG NMOS Z80,
|
||||
* (flags & A & 0x28) on NEC NMOS Z80, other models unknown.
|
||||
* However, people from the Speccy scene mention that SCF/CCF X/Y results
|
||||
* are inconsistant and may be influenced by I and R registers.
|
||||
* This Z80 emulator assumes a ZiLOG NMOS model.
|
||||
* TODO:
|
||||
* - If LD A,I or LD A,R is interrupted, P/V flag gets reset, even if IFF2
|
||||
* was set before this instruction
|
||||
* - Ideally, the tiny differences between Z80 types should be supported,
|
||||
* currently known differences:
|
||||
* - LD A,I/R P/V flag reset glitch is fixed on CMOS Z80
|
||||
* - OUT (C),0 outputs 0 on NMOS Z80, $FF on CMOS Z80
|
||||
* - SCF/CCF X/Y flags is ((flags | A) & 0x28) on SGS/SHARP/ZiLOG NMOS Z80,
|
||||
* (flags & A & 0x28) on NEC NMOS Z80, other models unknown.
|
||||
* However, people from the Speccy scene mention that SCF/CCF X/Y results
|
||||
* are inconsistant and may be influenced by I and R registers.
|
||||
* This Z80 emulator assumes a ZiLOG NMOS model.
|
||||
*
|
||||
* Additional changes [Eke-Eke]:
|
||||
* - Discarded multi-chip support (unused)
|
||||
* - Fixed cycle counting for FD and DD prefixed instructions
|
||||
* - Fixed behavior of chained FD and DD prefixes (R register should be only incremented by one
|
||||
* - Implemented cycle-accurate INI/IND (needed by SMS emulation)
|
||||
* Changes in 3.9:
|
||||
* - Fixed cycle counts for LD IYL/IXL/IYH/IXH,n [Marshmellow]
|
||||
* - Fixed X/Y flags in CCF/SCF/BIT, ZEXALL is happy now [hap]
|
||||
* - Simplified DAA, renamed MEMPTR (3.8) to WZ, added TODO [hap]
|
||||
* - Fixed IM2 interrupt cycles [eke]
|
||||
* - Implemented cycle-accurate INI/IND (needed by SMS emulation)
|
||||
* Changes in 3.9:
|
||||
* - Fixed cycle counts for LD IYL/IXL/IYH/IXH,n [Marshmellow]
|
||||
* - Fixed X/Y flags in CCF/SCF/BIT, ZEXALL is happy now [hap]
|
||||
* - Simplified DAA, renamed MEMPTR (3.8) to WZ, added TODO [hap]
|
||||
* - Fixed IM2 interrupt cycles [eke]
|
||||
* Changes in 3.8 [Miodrag Milanovic]:
|
||||
* - Added MEMPTR register (according to informations provided
|
||||
* by Vladimir Kladov
|
||||
* - BIT n,(HL) now return valid values due to use of MEMPTR
|
||||
* - Fixed BIT 6,(XY+o) undocumented instructions
|
||||
* Changes in 3.7 [Aaron Giles]:
|
||||
* Changes in 3.7 [Aaron Giles]:
|
||||
* - Changed NMI handling. NMIs are now latched in set_irq_state
|
||||
* but are not taken there. Instead they are taken at the start of the
|
||||
* execute loop.
|
||||
* - Changed IRQ handling. IRQ state is set in set_irq_state but not taken
|
||||
* except during the inner execute loop.
|
||||
* - Removed x86 assembly hacks and obsolete timing loop catchers.
|
||||
* Changes in 3.6:
|
||||
* Changes in 3.6:
|
||||
* - Got rid of the code that would inexactly emulate a Z80, i.e. removed
|
||||
* all the #if Z80_EXACT #else branches.
|
||||
* - Removed leading underscores from local register name shortcuts as
|
||||
@ -60,23 +60,23 @@
|
||||
* - Renamed the registers inside the Z80 context to lower case to avoid
|
||||
* ambiguities (shortcuts would have had the same names as the fields
|
||||
* of the structure).
|
||||
* Changes in 3.5:
|
||||
* Changes in 3.5:
|
||||
* - Implemented OTIR, INIR, etc. without look-up table for PF flag.
|
||||
* [Ramsoft, Sean Young]
|
||||
* Changes in 3.4:
|
||||
* Changes in 3.4:
|
||||
* - Removed Z80-MSX specific code as it's not needed any more.
|
||||
* - Implemented DAA without look-up table [Ramsoft, Sean Young]
|
||||
* Changes in 3.3:
|
||||
* Changes in 3.3:
|
||||
* - Fixed undocumented flags XF & YF in the non-asm versions of CP,
|
||||
* and all the 16 bit arithmetic instructions. [Sean Young]
|
||||
* Changes in 3.2:
|
||||
* Changes in 3.2:
|
||||
* - Fixed undocumented flags XF & YF of RRCA, and CF and HF of
|
||||
* INI/IND/OUTI/OUTD/INIR/INDR/OTIR/OTDR [Sean Young]
|
||||
* Changes in 3.1:
|
||||
* Changes in 3.1:
|
||||
* - removed the REPEAT_AT_ONCE execution of LDIR/CPIR etc. opcodes
|
||||
* for readabilities sake and because the implementation was buggy
|
||||
* (and I was not able to find the difference)
|
||||
* Changes in 3.0:
|
||||
* Changes in 3.0:
|
||||
* - 'finished' switch to dynamically overrideable cycle count tables
|
||||
* Changes in 2.9:
|
||||
* - added methods to access and override the cycle count tables
|
||||
@ -202,7 +202,8 @@
|
||||
#define IFF2 Z80.iff2
|
||||
#define HALT Z80.halt
|
||||
|
||||
int z80_ICount;
|
||||
extern unsigned int mcycles_z80;
|
||||
|
||||
Z80_Regs Z80;
|
||||
static UINT32 EA;
|
||||
|
||||
@ -466,7 +467,7 @@ INLINE void BURNODD(int cycles, int opcodes, int cyclesum)
|
||||
if( cycles > 0 )
|
||||
{
|
||||
R += (cycles / cyclesum) * opcodes;
|
||||
z80_ICount -= (cycles / cyclesum) * cyclesum;
|
||||
mcycles_z80 += (cycles / cyclesum) * cyclesum * 15;
|
||||
}
|
||||
}
|
||||
|
||||
@ -478,7 +479,7 @@ INLINE void BURNODD(int cycles, int opcodes, int cyclesum)
|
||||
/***************************************************************
|
||||
* adjust cycle count by n T-states
|
||||
***************************************************************/
|
||||
#define CC(prefix,opcode) z80_ICount -= cc[Z80_TABLE_##prefix][opcode]
|
||||
#define CC(prefix,opcode) mcycles_z80 += cc[Z80_TABLE_##prefix][opcode] * 15
|
||||
|
||||
/***************************************************************
|
||||
* execute an opcode
|
||||
@ -950,20 +951,20 @@ INLINE UINT8 DEC(UINT8 value)
|
||||
/***************************************************************
|
||||
* DAA
|
||||
***************************************************************/
|
||||
#define DAA { \
|
||||
UINT8 a = A; \
|
||||
if (F & NF) { \
|
||||
if ((F&HF) | ((A&0xf)>9)) a-=6; \
|
||||
if ((F&CF) | (A>0x99)) a-=0x60; \
|
||||
} \
|
||||
else { \
|
||||
if ((F&HF) | ((A&0xf)>9)) a+=6; \
|
||||
if ((F&CF) | (A>0x99)) a+=0x60; \
|
||||
} \
|
||||
#define DAA { \
|
||||
UINT8 a = A; \
|
||||
if (F & NF) { \
|
||||
if ((F&HF) | ((A&0xf)>9)) a-=6; \
|
||||
if ((F&CF) | (A>0x99)) a-=0x60; \
|
||||
} \
|
||||
else { \
|
||||
if ((F&HF) | ((A&0xf)>9)) a+=6; \
|
||||
if ((F&CF) | (A>0x99)) a+=0x60; \
|
||||
} \
|
||||
\
|
||||
F = (F&(CF|NF)) | (A>0x99) | ((A^a)&HF) | SZP[a]; \
|
||||
A = a; \
|
||||
}
|
||||
F = (F&(CF|NF)) | (A>0x99) | ((A^a)&HF) | SZP[a]; \
|
||||
A = a; \
|
||||
}
|
||||
|
||||
/***************************************************************
|
||||
* AND n
|
||||
@ -2068,7 +2069,7 @@ OP(dd,1f) { illegal_1(); op_1f(); } /* DB DD
|
||||
|
||||
OP(dd,20) { illegal_1(); op_20(); } /* DB DD */
|
||||
OP(dd,21) { IX = ARG16(); } /* LD IX,w */
|
||||
OP(dd,22) { EA = ARG16(); WM16( EA, &Z80.ix ); WZ = EA+1; } /* LD (w),IX */
|
||||
OP(dd,22) { EA = ARG16(); WM16( EA, &Z80.ix ); WZ = EA+1; } /* LD (w),IX */
|
||||
OP(dd,23) { IX++; } /* INC IX */
|
||||
OP(dd,24) { HX = INC(HX); } /* INC HX */
|
||||
OP(dd,25) { HX = DEC(HX); } /* DEC HX */
|
||||
@ -2077,7 +2078,7 @@ OP(dd,27) { illegal_1(); op_27(); } /* DB DD
|
||||
|
||||
OP(dd,28) { illegal_1(); op_28(); } /* DB DD */
|
||||
OP(dd,29) { ADD16(ix,ix); } /* ADD IX,IX */
|
||||
OP(dd,2a) { EA = ARG16(); RM16( EA, &Z80.ix ); WZ = EA+1; } /* LD IX,(w) */
|
||||
OP(dd,2a) { EA = ARG16(); RM16( EA, &Z80.ix ); WZ = EA+1; } /* LD IX,(w) */
|
||||
OP(dd,2b) { IX--; } /* DEC IX */
|
||||
OP(dd,2c) { LX = INC(LX); } /* INC LX */
|
||||
OP(dd,2d) { LX = DEC(LX); } /* DEC LX */
|
||||
@ -2359,7 +2360,7 @@ OP(fd,1f) { illegal_1(); op_1f(); } /* DB FD
|
||||
|
||||
OP(fd,20) { illegal_1(); op_20(); } /* DB FD */
|
||||
OP(fd,21) { IY = ARG16(); } /* LD IY,w */
|
||||
OP(fd,22) { EA = ARG16(); WM16( EA, &Z80.iy ); WZ = EA+1; } /* LD (w),IY */
|
||||
OP(fd,22) { EA = ARG16(); WM16( EA, &Z80.iy ); WZ = EA+1; } /* LD (w),IY */
|
||||
OP(fd,23) { IY++; } /* INC IY */
|
||||
OP(fd,24) { HY = INC(HY); } /* INC HY */
|
||||
OP(fd,25) { HY = DEC(HY); } /* DEC HY */
|
||||
@ -2368,7 +2369,7 @@ OP(fd,27) { illegal_1(); op_27(); } /* DB FD
|
||||
|
||||
OP(fd,28) { illegal_1(); op_28(); } /* DB FD */
|
||||
OP(fd,29) { ADD16(iy,iy); } /* ADD IY,IY */
|
||||
OP(fd,2a) { EA = ARG16(); RM16( EA, &Z80.iy ); WZ = EA+1; } /* LD IY,(w) */
|
||||
OP(fd,2a) { EA = ARG16(); RM16( EA, &Z80.iy ); WZ = EA+1; } /* LD IY,(w) */
|
||||
OP(fd,2b) { IY--; } /* DEC IY */
|
||||
OP(fd,2c) { LY = INC(LY); } /* INC LY */
|
||||
OP(fd,2d) { LY = DEC(LY); } /* DEC LY */
|
||||
@ -2695,7 +2696,7 @@ OP(ed,3f) { illegal_2(); } /* DB ED
|
||||
OP(ed,40) { B = IN(BC); F = (F & CF) | SZP[B]; } /* IN B,(C) */
|
||||
OP(ed,41) { OUT(BC, B); } /* OUT (C),B */
|
||||
OP(ed,42) { SBC16( bc ); } /* SBC HL,BC */
|
||||
OP(ed,43) { EA = ARG16(); WM16( EA, &Z80.bc ); WZ = EA+1; } /* LD (w),BC */
|
||||
OP(ed,43) { EA = ARG16(); WM16( EA, &Z80.bc ); WZ = EA+1; } /* LD (w),BC */
|
||||
OP(ed,44) { NEG; } /* NEG */
|
||||
OP(ed,45) { RETN; } /* RETN; */
|
||||
OP(ed,46) { IM = 0; } /* IM 0 */
|
||||
@ -2704,7 +2705,7 @@ OP(ed,47) { LD_I_A; } /* LD I,A
|
||||
OP(ed,48) { C = IN(BC); F = (F & CF) | SZP[C]; } /* IN C,(C) */
|
||||
OP(ed,49) { OUT(BC, C); } /* OUT (C),C */
|
||||
OP(ed,4a) { ADC16( bc ); } /* ADC HL,BC */
|
||||
OP(ed,4b) { EA = ARG16(); RM16( EA, &Z80.bc ); WZ = EA+1; } /* LD BC,(w) */
|
||||
OP(ed,4b) { EA = ARG16(); RM16( EA, &Z80.bc ); WZ = EA+1; } /* LD BC,(w) */
|
||||
OP(ed,4c) { NEG; } /* NEG */
|
||||
OP(ed,4d) { RETI; } /* RETI */
|
||||
OP(ed,4e) { IM = 0; } /* IM 0 */
|
||||
@ -2713,7 +2714,7 @@ OP(ed,4f) { LD_R_A; } /* LD R,A
|
||||
OP(ed,50) { D = IN(BC); F = (F & CF) | SZP[D]; } /* IN D,(C) */
|
||||
OP(ed,51) { OUT(BC, D); } /* OUT (C),D */
|
||||
OP(ed,52) { SBC16( de ); } /* SBC HL,DE */
|
||||
OP(ed,53) { EA = ARG16(); WM16( EA, &Z80.de ); WZ = EA+1; } /* LD (w),DE */
|
||||
OP(ed,53) { EA = ARG16(); WM16( EA, &Z80.de ); WZ = EA+1; } /* LD (w),DE */
|
||||
OP(ed,54) { NEG; } /* NEG */
|
||||
OP(ed,55) { RETN; } /* RETN; */
|
||||
OP(ed,56) { IM = 1; } /* IM 1 */
|
||||
@ -2722,7 +2723,7 @@ OP(ed,57) { LD_A_I; } /* LD A,I
|
||||
OP(ed,58) { E = IN(BC); F = (F & CF) | SZP[E]; } /* IN E,(C) */
|
||||
OP(ed,59) { OUT(BC, E); } /* OUT (C),E */
|
||||
OP(ed,5a) { ADC16( de ); } /* ADC HL,DE */
|
||||
OP(ed,5b) { EA = ARG16(); RM16( EA, &Z80.de ); WZ = EA+1; } /* LD DE,(w) */
|
||||
OP(ed,5b) { EA = ARG16(); RM16( EA, &Z80.de ); WZ = EA+1; } /* LD DE,(w) */
|
||||
OP(ed,5c) { NEG; } /* NEG */
|
||||
OP(ed,5d) { RETI; } /* RETI */
|
||||
OP(ed,5e) { IM = 2; } /* IM 2 */
|
||||
@ -2731,7 +2732,7 @@ OP(ed,5f) { LD_A_R; } /* LD A,R
|
||||
OP(ed,60) { H = IN(BC); F = (F & CF) | SZP[H]; } /* IN H,(C) */
|
||||
OP(ed,61) { OUT(BC, H); } /* OUT (C),H */
|
||||
OP(ed,62) { SBC16( hl ); } /* SBC HL,HL */
|
||||
OP(ed,63) { EA = ARG16(); WM16( EA, &Z80.hl ); WZ = EA+1; } /* LD (w),HL */
|
||||
OP(ed,63) { EA = ARG16(); WM16( EA, &Z80.hl ); WZ = EA+1; } /* LD (w),HL */
|
||||
OP(ed,64) { NEG; } /* NEG */
|
||||
OP(ed,65) { RETN; } /* RETN; */
|
||||
OP(ed,66) { IM = 0; } /* IM 0 */
|
||||
@ -2740,7 +2741,7 @@ OP(ed,67) { RRD; } /* RRD (HL)
|
||||
OP(ed,68) { L = IN(BC); F = (F & CF) | SZP[L]; } /* IN L,(C) */
|
||||
OP(ed,69) { OUT(BC, L); } /* OUT (C),L */
|
||||
OP(ed,6a) { ADC16( hl ); } /* ADC HL,HL */
|
||||
OP(ed,6b) { EA = ARG16(); RM16( EA, &Z80.hl ); WZ = EA+1; } /* LD HL,(w) */
|
||||
OP(ed,6b) { EA = ARG16(); RM16( EA, &Z80.hl ); WZ = EA+1; } /* LD HL,(w) */
|
||||
OP(ed,6c) { NEG; } /* NEG */
|
||||
OP(ed,6d) { RETI; } /* RETI */
|
||||
OP(ed,6e) { IM = 0; } /* IM 0 */
|
||||
@ -2749,14 +2750,14 @@ OP(ed,6f) { RLD; } /* RLD (HL)
|
||||
OP(ed,70) { UINT8 res = IN(BC); F = (F & CF) | SZP[res]; } /* IN 0,(C) */
|
||||
OP(ed,71) { OUT(BC, 0); } /* OUT (C),0 */
|
||||
OP(ed,72) { SBC16( sp ); } /* SBC HL,SP */
|
||||
OP(ed,73) { EA = ARG16(); WM16( EA, &Z80.sp ); WZ = EA+1; } /* LD (w),SP */
|
||||
OP(ed,73) { EA = ARG16(); WM16( EA, &Z80.sp ); WZ = EA+1; } /* LD (w),SP */
|
||||
OP(ed,74) { NEG; } /* NEG */
|
||||
OP(ed,75) { RETN; } /* RETN; */
|
||||
OP(ed,76) { IM = 1; } /* IM 1 */
|
||||
OP(ed,77) { illegal_2(); } /* DB ED,77 */
|
||||
|
||||
OP(ed,78) { A = IN(BC); F = (F & CF) | SZP[A]; WZ = BC+1; } /* IN E,(C) */
|
||||
OP(ed,79) { OUT(BC, A); WZ = BC + 1; } /* OUT (C),A */
|
||||
OP(ed,78) { A = IN(BC); F = (F & CF) | SZP[A]; WZ = BC+1; } /* IN E,(C) */
|
||||
OP(ed,79) { OUT(BC, A); WZ = BC + 1; } /* OUT (C),A */
|
||||
OP(ed,7a) { ADC16( sp ); } /* ADC HL,SP */
|
||||
OP(ed,7b) { EA = ARG16(); RM16( EA, &Z80.sp ); WZ = EA+1; } /* LD SP,(w) */
|
||||
OP(ed,7c) { NEG; } /* NEG */
|
||||
@ -2914,7 +2915,7 @@ OP(ed,ff) { illegal_2(); } /* DB ED
|
||||
**********************************************************/
|
||||
OP(op,00) { } /* NOP */
|
||||
OP(op,01) { BC = ARG16(); } /* LD BC,w */
|
||||
OP(op,02) { WM( BC, A ); WZ_L = (BC + 1) & 0xFF; WZ_H = A; } /* LD (BC),A */
|
||||
OP(op,02) { WM( BC, A ); WZ_L = (BC + 1) & 0xFF; WZ_H = A; } /* LD (BC),A */
|
||||
OP(op,03) { BC++; } /* INC BC */
|
||||
OP(op,04) { B = INC(B); } /* INC B */
|
||||
OP(op,05) { B = DEC(B); } /* DEC B */
|
||||
@ -2923,7 +2924,7 @@ OP(op,07) { RLCA;
|
||||
|
||||
OP(op,08) { EX_AF; } /* EX AF,AF' */
|
||||
OP(op,09) { ADD16(hl, bc); } /* ADD HL,BC */
|
||||
OP(op,0a) { A = RM( BC ); WZ=BC+1; } /* LD A,(BC) */
|
||||
OP(op,0a) { A = RM( BC ); WZ=BC+1; } /* LD A,(BC) */
|
||||
OP(op,0b) { BC--; } /* DEC BC */
|
||||
OP(op,0c) { C = INC(C); } /* INC C */
|
||||
OP(op,0d) { C = DEC(C); } /* DEC C */
|
||||
@ -2932,7 +2933,7 @@ OP(op,0f) { RRCA;
|
||||
|
||||
OP(op,10) { B--; JR_COND( B, 0x10 ); } /* DJNZ o */
|
||||
OP(op,11) { DE = ARG16(); } /* LD DE,w */
|
||||
OP(op,12) { WM( DE, A ); WZ_L = (DE + 1) & 0xFF; WZ_H = A; } /* LD (DE),A */
|
||||
OP(op,12) { WM( DE, A ); WZ_L = (DE + 1) & 0xFF; WZ_H = A; } /* LD (DE),A */
|
||||
OP(op,13) { DE++; } /* INC DE */
|
||||
OP(op,14) { D = INC(D); } /* INC D */
|
||||
OP(op,15) { D = DEC(D); } /* DEC D */
|
||||
@ -2941,7 +2942,7 @@ OP(op,17) { RLA;
|
||||
|
||||
OP(op,18) { JR(); } /* JR o */
|
||||
OP(op,19) { ADD16(hl, de); } /* ADD HL,DE */
|
||||
OP(op,1a) { A = RM( DE ); WZ=DE+1; } /* LD A,(DE) */
|
||||
OP(op,1a) { A = RM( DE ); WZ=DE+1; } /* LD A,(DE) */
|
||||
OP(op,1b) { DE--; } /* DEC DE */
|
||||
OP(op,1c) { E = INC(E); } /* INC E */
|
||||
OP(op,1d) { E = DEC(E); } /* DEC E */
|
||||
@ -2950,7 +2951,7 @@ OP(op,1f) { RRA;
|
||||
|
||||
OP(op,20) { JR_COND( !(F & ZF), 0x20 ); } /* JR NZ,o */
|
||||
OP(op,21) { HL = ARG16(); } /* LD HL,w */
|
||||
OP(op,22) { EA = ARG16(); WM16( EA, &Z80.hl ); WZ = EA+1; } /* LD (w),HL */
|
||||
OP(op,22) { EA = ARG16(); WM16( EA, &Z80.hl ); WZ = EA+1; } /* LD (w),HL */
|
||||
OP(op,23) { HL++; } /* INC HL */
|
||||
OP(op,24) { H = INC(H); } /* INC H */
|
||||
OP(op,25) { H = DEC(H); } /* DEC H */
|
||||
@ -2959,7 +2960,7 @@ OP(op,27) { DAA;
|
||||
|
||||
OP(op,28) { JR_COND( F & ZF, 0x28 ); } /* JR Z,o */
|
||||
OP(op,29) { ADD16(hl, hl); } /* ADD HL,HL */
|
||||
OP(op,2a) { EA = ARG16(); RM16( EA, &Z80.hl ); WZ = EA+1; } /* LD HL,(w) */
|
||||
OP(op,2a) { EA = ARG16(); RM16( EA, &Z80.hl ); WZ = EA+1; } /* LD HL,(w) */
|
||||
OP(op,2b) { HL--; } /* DEC HL */
|
||||
OP(op,2c) { L = INC(L); } /* INC L */
|
||||
OP(op,2d) { L = DEC(L); } /* DEC L */
|
||||
@ -2968,7 +2969,7 @@ OP(op,2f) { A ^= 0xff; F = (F&(SF|ZF|PF|CF))|HF|NF|(A&(YF|XF));
|
||||
|
||||
OP(op,30) { JR_COND( !(F & CF), 0x30 ); } /* JR NC,o */
|
||||
OP(op,31) { SP = ARG16(); } /* LD SP,w */
|
||||
OP(op,32) { EA = ARG16(); WM( EA, A ); WZ_L=(EA+1)&0xFF;WZ_H=A; } /* LD (w),A */
|
||||
OP(op,32) { EA = ARG16(); WM( EA, A ); WZ_L=(EA+1)&0xFF;WZ_H=A; } /* LD (w),A */
|
||||
OP(op,33) { SP++; } /* INC SP */
|
||||
OP(op,34) { WM( HL, INC(RM(HL)) ); } /* INC (HL) */
|
||||
OP(op,35) { WM( HL, DEC(RM(HL)) ); } /* DEC (HL) */
|
||||
@ -2977,7 +2978,7 @@ OP(op,37) { F = (F & (SF|ZF|YF|XF|PF)) | CF | (A & (YF|XF));
|
||||
|
||||
OP(op,38) { JR_COND( F & CF, 0x38 ); } /* JR C,o */
|
||||
OP(op,39) { ADD16(hl, sp); } /* ADD HL,SP */
|
||||
OP(op,3a) { EA = ARG16(); A = RM( EA ); WZ = EA+1; } /* LD A,(w) */
|
||||
OP(op,3a) { EA = ARG16(); A = RM( EA ); WZ = EA+1; } /* LD A,(w) */
|
||||
OP(op,3b) { SP--; } /* DEC SP */
|
||||
OP(op,3c) { A = INC(A); } /* INC A */
|
||||
OP(op,3d) { A = DEC(A); } /* DEC A */
|
||||
@ -3138,7 +3139,7 @@ OP(op,c6) { ADD(ARG());
|
||||
OP(op,c7) { RST(0x00); } /* RST 0 */
|
||||
|
||||
OP(op,c8) { RET_COND( F & ZF, 0xc8 ); } /* RET Z */
|
||||
OP(op,c9) { POP( pc ); WZ=PCD; } /* RET */
|
||||
OP(op,c9) { POP( pc ); WZ=PCD; } /* RET */
|
||||
OP(op,ca) { JP_COND( F & ZF ); } /* JP Z,a */
|
||||
OP(op,cb) { R++; EXEC(cb,ROP()); } /* **** CB xx */
|
||||
OP(op,cc) { CALL_COND( F & ZF, 0xcc ); } /* CALL Z,a */
|
||||
@ -3158,7 +3159,7 @@ OP(op,d7) { RST(0x10);
|
||||
OP(op,d8) { RET_COND( F & CF, 0xd8 ); } /* RET C */
|
||||
OP(op,d9) { EXX; } /* EXX */
|
||||
OP(op,da) { JP_COND( F & CF ); } /* JP C,a */
|
||||
OP(op,db) { unsigned n = ARG() | (A << 8); A = IN( n ); WZ = n + 1; } /* IN A,(n) */
|
||||
OP(op,db) { unsigned n = ARG() | (A << 8); A = IN( n ); WZ = n + 1; } /* IN A,(n) */
|
||||
OP(op,dc) { CALL_COND( F & CF, 0xdc ); } /* CALL C,a */
|
||||
OP(op,dd) { R++; EXEC(dd,ROP()); } /* **** DD xx */
|
||||
OP(op,de) { SBC(ARG()); } /* SBC A,n */
|
||||
@ -3224,7 +3225,7 @@ static void take_interrupt(void)
|
||||
RM16( irq_vector, &Z80.pc );
|
||||
LOG(("Z80 #%d IM2 [$%04x] = $%04x\n",cpu_getactivecpu() , irq_vector, PCD));
|
||||
/* CALL $xxxx + 'interrupt latency' cycles */
|
||||
z80_ICount -= cc[Z80_TABLE_op][0xcd] + cc[Z80_TABLE_ex][0xff];
|
||||
mcycles_z80 += (cc[Z80_TABLE_op][0xcd] + cc[Z80_TABLE_ex][0xff]) * 15;
|
||||
}
|
||||
else
|
||||
/* Interrupt mode 1. RST 38h */
|
||||
@ -3234,7 +3235,7 @@ static void take_interrupt(void)
|
||||
PUSH( pc );
|
||||
PCD = 0x0038;
|
||||
/* RST $38 + 'interrupt latency' cycles */
|
||||
z80_ICount -= cc[Z80_TABLE_op][0xff] + cc[Z80_TABLE_ex][0xff];
|
||||
mcycles_z80 += (cc[Z80_TABLE_op][0xff] + cc[Z80_TABLE_ex][0xff]) * 15;
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -3248,18 +3249,18 @@ static void take_interrupt(void)
|
||||
PUSH( pc );
|
||||
PCD = irq_vector & 0xffff;
|
||||
/* CALL $xxxx + 'interrupt latency' cycles */
|
||||
z80_ICount -= cc[Z80_TABLE_op][0xcd] + cc[Z80_TABLE_ex][0xff];
|
||||
mcycles_z80 += (cc[Z80_TABLE_op][0xcd] + cc[Z80_TABLE_ex][0xff]) * 15;
|
||||
break;
|
||||
case 0xc30000: /* jump */
|
||||
PCD = irq_vector & 0xffff;
|
||||
/* JP $xxxx + 2 cycles */
|
||||
z80_ICount -= cc[Z80_TABLE_op][0xc3] + cc[Z80_TABLE_ex][0xff];
|
||||
mcycles_z80 += (cc[Z80_TABLE_op][0xc3] + cc[Z80_TABLE_ex][0xff]) * 15;
|
||||
break;
|
||||
default: /* rst (or other opcodes?) */
|
||||
PUSH( pc );
|
||||
PCD = irq_vector & 0x0038;
|
||||
/* RST $xx + 2 cycles */
|
||||
z80_ICount -= cc[Z80_TABLE_op][0xff] + cc[Z80_TABLE_ex][0xff];
|
||||
mcycles_z80 += (cc[Z80_TABLE_op][0xff] + cc[Z80_TABLE_ex][0xff]) * 15;
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -3404,12 +3405,10 @@ void z80_exit(void)
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Execute 'cycles' T-states. Return number of T-states really executed
|
||||
* Run until given cycle count
|
||||
****************************************************************************/
|
||||
int z80_execute(int cycles)
|
||||
void z80_run(int cycles)
|
||||
{
|
||||
z80_ICount = cycles;
|
||||
|
||||
/* check for NMIs on the way in; they can only be set externally */
|
||||
/* via timers, and can't be dynamically enabled, so it is safe */
|
||||
/* to just check here */
|
||||
@ -3422,25 +3421,23 @@ int z80_execute(int cycles)
|
||||
PUSH( pc );
|
||||
PCD = 0x0066;
|
||||
WZ=PCD;
|
||||
z80_ICount -= 11;
|
||||
mcycles_z80 += 11*15;
|
||||
Z80.nmi_pending = FALSE;
|
||||
}
|
||||
|
||||
while( z80_ICount > 0 )
|
||||
while( mcycles_z80 < cycles )
|
||||
{
|
||||
/* check for IRQs before each instruction */
|
||||
if (Z80.irq_state != CLEAR_LINE && IFF1 && !Z80.after_ei)
|
||||
take_interrupt();
|
||||
Z80.after_ei = FALSE;
|
||||
|
||||
if (z80_ICount > 0)
|
||||
if (mcycles_z80 < cycles)
|
||||
{
|
||||
R++;
|
||||
EXEC_INLINE(op,ROP());
|
||||
}
|
||||
}
|
||||
|
||||
return cycles - z80_ICount;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
@ -3453,7 +3450,7 @@ void z80_burn(int cycles)
|
||||
/* NOP takes 4 cycles per instruction */
|
||||
int n = (cycles + 3) / 4;
|
||||
R += n;
|
||||
z80_ICount -= 4 * n;
|
||||
mcycles_z80 += 4 * n * 15;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -40,13 +40,12 @@ typedef struct
|
||||
} Z80_Regs;
|
||||
|
||||
|
||||
extern int z80_ICount;
|
||||
extern Z80_Regs Z80;
|
||||
|
||||
void z80_init(int index, int clock, const void *config, int (*irqcallback)(int));
|
||||
void z80_reset (void);
|
||||
void z80_exit (void);
|
||||
int z80_execute(int cycles);
|
||||
void z80_run(int cycles);
|
||||
void z80_burn(int cycles);
|
||||
void z80_get_context (void *dst);
|
||||
void z80_set_context (void *src);
|
||||
|
Loading…
Reference in New Issue
Block a user