mirror of
https://github.com/ekeeke/Genesis-Plus-GX.git
synced 2024-11-09 04:15:14 +01: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
|
* modified SN76489 cut-off frequency
|
||||||
* added an option to boost SN76489 Noise Channel
|
* added an option to boost SN76489 Noise Channel
|
||||||
* removed outdated Gens YM2612 core
|
* 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)
|
* improved YM2612 LFO emulation accuracy (fixes "Spider-Man & Venom : Separation Anxiety" intro music)
|
||||||
* fixed YM2612 context saving/loading.
|
* fixed YM2612 context saving/loading.
|
||||||
* added 3-Band EQ for fully configurable sound filtering (thanks to Neil C)
|
* added 3-Band EQ for fully configurable sound filtering (thanks to Neil C)
|
||||||
* implemented faster FIR resampler, dropped libsamplerate support (thanks to Blargg & AamirM)
|
* 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.
|
* fixed 2-Cell vertical scrolling when column 0 is shifted.
|
||||||
* added support for 2-Cell vertical scrolling in Interlaced 2 mode.
|
* added support for 2-Cell vertical scrolling in Interlaced 2 mode.
|
||||||
* fixed lightgun auto detection: fixes cursor position in Lethal Enforcers II
|
* 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)
|
* 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 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 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 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 S&K "Lock-On" hardware emulation ("lock" any games to Sonic & Knuckles)
|
||||||
* added Cartridge "hot swap" feature (swap games without reseting the virtual console)
|
* 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]
|
[Gamecube/Wii]
|
||||||
|
|
||||||
* improved audio/video synchronization: fixes video skipping issues in 60Hz modes
|
* improved audio/video synchronization (see above)
|
||||||
* fixed stability issues and some potential memory leaks
|
* 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
|
* added internal screenshot feature
|
||||||
* improved lightgun cursors
|
* improved lightgun cursors
|
||||||
* implemented new FONT & GUI engines: use internal IPL FONT, GX hardware & multithreading for fast rendering.
|
* new FONT & GUI engines: use internal IPL FONT, GX hardware rendering, sound support & multithreading.
|
||||||
* implemented new interface: incl. IR pointing, game snapshots, menu effects, sound effects, BGM...
|
* new emulator interface design: incl. IR pointing, game snapshots, menu effects, sound effects, BGM...
|
||||||
(check the README for more details)
|
(check the README for more details)
|
||||||
|
|
||||||
|
|
||||||
|
@ -25,28 +25,17 @@
|
|||||||
|
|
||||||
t_input input;
|
t_input input;
|
||||||
|
|
||||||
/*****************************************************************************
|
/************************************************************************************/
|
||||||
* LIGHTGUN specific functions
|
/* */
|
||||||
*
|
/* H-counter values returned in H40 & H32 modes */
|
||||||
*****************************************************************************/
|
/* */
|
||||||
/* H counter values for a 256-pixel wide display (342 pixel max.) */
|
/* Inside VDP, dot counter register is 9-bit, with only upper 8 bits being returned */
|
||||||
static const uint8 hc_256[171] = {
|
/* */
|
||||||
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
|
/* The number of dots per raster line is 342 in H32 mode and 420 in H40 mode */
|
||||||
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,
|
static const uint8 hc_320[210] =
|
||||||
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] = {
|
|
||||||
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
|
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,
|
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,
|
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
|
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)
|
static inline void lightgun_reset(int num)
|
||||||
{
|
{
|
||||||
input.analog[num][0] = bitmap.viewport.w >> 1;
|
input.analog[num][0] = bitmap.viewport.w >> 1;
|
||||||
|
102
source/genesis.c
102
source/genesis.c
@ -23,16 +23,14 @@
|
|||||||
|
|
||||||
#include "shared.h"
|
#include "shared.h"
|
||||||
|
|
||||||
uint8 bios_rom[0x10000]; /* BIOS rom */
|
uint8 bios_rom[0x10000]; /* OS ROM */
|
||||||
uint8 work_ram[0x10000]; /* 68K work RAM */
|
uint8 work_ram[0x10000]; /* 68K RAM */
|
||||||
uint8 zram[0x2000]; /* Z80 work RAM */
|
uint8 zram[0x2000]; /* Z80 RAM */
|
||||||
uint8 zbusreq; /* /BUSREQ from Z80 */
|
uint32 zirq; /* /IRQ to Z80 */
|
||||||
uint8 zreset; /* /RESET to Z80 */
|
uint32 zstate; /* Z80 bus state (d0 = BUSACK, d1 = /RESET) */
|
||||||
uint8 zbusack; /* /BUSACK to Z80 */
|
uint32 zbank; /* Z80 bank window address */
|
||||||
uint8 zirq; /* /IRQ to Z80 */
|
uint32 gen_running; /* 0: cpu are in locked state */
|
||||||
uint32 zbank; /* Address of Z80 bank window */
|
int32 resetline; /* soft reset is triggered on a random line (X-Men 2, Eternal Champions) */
|
||||||
uint8 gen_running;
|
|
||||||
int32 resetline;
|
|
||||||
|
|
||||||
/*--------------------------------------------------------------------------*/
|
/*--------------------------------------------------------------------------*/
|
||||||
/* Init, reset, shutdown functions */
|
/* Init, reset, shutdown functions */
|
||||||
@ -132,28 +130,24 @@ void gen_reset(uint32 hard_reset)
|
|||||||
memset (work_ram, 0x00, sizeof (work_ram));
|
memset (work_ram, 0x00, sizeof (work_ram));
|
||||||
memset (zram, 0x00, sizeof (zram));
|
memset (zram, 0x00, sizeof (zram));
|
||||||
|
|
||||||
/* TMSS BIOS */
|
/* TMSS BIOS support */
|
||||||
if (config.bios_enabled == 3)
|
if (config.bios_enabled == 3)
|
||||||
{
|
|
||||||
m68k_memory_map[0].base = bios_rom;
|
m68k_memory_map[0].base = bios_rom;
|
||||||
|
|
||||||
|
/* Reset CPU cycle counts */
|
||||||
|
mcycles_68k = 0;
|
||||||
|
mcycles_z80 = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
count_m68k = 0;
|
zstate = 0; /* Z80 is reset & has control of the bus */
|
||||||
count_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 */
|
zirq = 0; /* No interrupts occuring */
|
||||||
zbank = 0; /* Assume default bank is $000000-$007FFF */
|
zbank = 0; /* Assume default bank is $000000-$007FFF */
|
||||||
|
|
||||||
/* reset CPUs */
|
/* Reset CPUs */
|
||||||
|
resetline = -1;
|
||||||
|
gen_running = 1;
|
||||||
m68k_pulse_reset();
|
m68k_pulse_reset();
|
||||||
z80_reset();
|
z80_reset();
|
||||||
fm_reset();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void gen_shutdown(void)
|
void gen_shutdown(void)
|
||||||
@ -166,74 +160,66 @@ void gen_shutdown(void)
|
|||||||
-----------------------------------------------------------------------*/
|
-----------------------------------------------------------------------*/
|
||||||
void gen_busreq_w(uint32 state)
|
void gen_busreq_w(uint32 state)
|
||||||
{
|
{
|
||||||
uint32 z80_cycles_to_run;
|
|
||||||
|
|
||||||
if (state)
|
if (state)
|
||||||
{
|
{
|
||||||
/* Bus Request */
|
/* Bus requested */
|
||||||
if (!zbusreq && zreset)
|
if (zstate == 1)
|
||||||
{
|
{
|
||||||
/* Z80 stopped */
|
/* Z80 is stopped */
|
||||||
/* z80 was ON during the last 68k cycles */
|
/* Z80 was ON during the last 68k cycles */
|
||||||
/* we execute the appropriate number of z80 cycles */
|
z80_run(mcycles_68k);
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* update Z80 bus status */
|
||||||
|
zstate |= 2;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* Bus released */
|
/* Bus released */
|
||||||
if (zbusreq && zreset)
|
if (zstate == 3)
|
||||||
{
|
{
|
||||||
/* Z80 started */
|
/* Z80 is restarted */
|
||||||
/* z80 was OFF during the last 68k cycles */
|
/* Z80 was OFF during the last 68k cycles */
|
||||||
/* we burn the appropriate number of z80 cycles */
|
mcycles_z80 = mcycles_68k;
|
||||||
z80_cycles_to_run = line_z80 + ((count_m68k - line_m68k)*7)/15;
|
|
||||||
count_z80 = z80_cycles_to_run;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
zbusreq = state;
|
/* update Z80 bus status */
|
||||||
zbusack = 1 ^ (zbusreq & zreset);
|
zstate &= 1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void gen_reset_w(uint32 state)
|
void gen_reset_w(uint32 state)
|
||||||
{
|
{
|
||||||
uint32 z80_cycles_to_run;
|
|
||||||
|
|
||||||
if (state)
|
if (state)
|
||||||
{
|
{
|
||||||
/* stop RESET process */
|
/* stop RESET process */
|
||||||
if (!zbusreq && !zreset)
|
if (!zstate)
|
||||||
{
|
{
|
||||||
/* Z80 started */
|
/* Z80 is restarted */
|
||||||
/* z80 was OFF during the last 68k cycles */
|
/* Z80 was OFF during the last cycles */
|
||||||
/* we burn the appropriate number of z80 cycles */
|
mcycles_z80 = mcycles_68k;
|
||||||
z80_cycles_to_run = line_z80 + ((count_m68k - line_m68k)*7)/15;
|
|
||||||
count_z80 = z80_cycles_to_run;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* update Z80 bus status */
|
||||||
|
zstate |= 1;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* start RESET process */
|
/* start RESET process */
|
||||||
if (!zbusreq && zreset)
|
if (zstate == 1)
|
||||||
{
|
{
|
||||||
/* Z80 stopped */
|
/* Z80 stopped */
|
||||||
/* z80 was ON during the last 68k cycles */
|
/* z80 was ON during the last 68k cycles */
|
||||||
/* we execute the appropriate number of z80 cycles */
|
z80_run(mcycles_68k);
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Reset Z80 & YM2612 */
|
/* Reset Z80 & YM2612 */
|
||||||
z80_reset();
|
z80_reset();
|
||||||
fm_reset();
|
fm_reset();
|
||||||
}
|
|
||||||
|
|
||||||
zreset = state;
|
/* update Z80 bus status */
|
||||||
zbusack = 1 ^ (zbusreq & zreset);
|
zstate &= 2;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void gen_bank_w (uint32 state)
|
void gen_bank_w (uint32 state)
|
||||||
|
@ -28,12 +28,10 @@
|
|||||||
extern uint8 bios_rom[0x10000];
|
extern uint8 bios_rom[0x10000];
|
||||||
extern uint8 work_ram[0x10000];
|
extern uint8 work_ram[0x10000];
|
||||||
extern uint8 zram[0x2000];
|
extern uint8 zram[0x2000];
|
||||||
extern uint8 zbusreq;
|
extern uint32 zirq;
|
||||||
extern uint8 zbusack;
|
|
||||||
extern uint8 zreset;
|
|
||||||
extern uint8 zirq;
|
|
||||||
extern uint32 zbank;
|
extern uint32 zbank;
|
||||||
extern uint8 gen_running;
|
extern uint32 zstate;
|
||||||
|
extern uint32 gen_running;
|
||||||
extern int32 resetline;
|
extern int32 resetline;
|
||||||
|
|
||||||
/* Function prototypes */
|
/* Function prototypes */
|
||||||
|
@ -740,9 +740,15 @@ static void soundmenu ()
|
|||||||
sprintf (items[0].text, "High-Quality FM: %s", config.hq_fm ? "ON":"OFF");
|
sprintf (items[0].text, "High-Quality FM: %s", config.hq_fm ? "ON":"OFF");
|
||||||
if (cart.romsize)
|
if (cart.romsize)
|
||||||
{
|
{
|
||||||
|
/* save YM2612 context */
|
||||||
unsigned char *temp = memalign(32,YM2612GetContextSize());
|
unsigned char *temp = memalign(32,YM2612GetContextSize());
|
||||||
if (temp) memcpy(temp, YM2612GetContextPtr(), 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)
|
if (temp)
|
||||||
{
|
{
|
||||||
YM2612Restore(temp);
|
YM2612Restore(temp);
|
||||||
@ -923,13 +929,26 @@ static void systemmenu ()
|
|||||||
/* force region & cpu mode */
|
/* force region & cpu mode */
|
||||||
set_region();
|
set_region();
|
||||||
|
|
||||||
/* reinitialize timings */
|
/* update framerate */
|
||||||
system_init();
|
float framerate;
|
||||||
memfile_autoload(config.sram_auto,-1);
|
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());
|
unsigned char *temp = memalign(32,YM2612GetContextSize());
|
||||||
if (temp)
|
if (temp)
|
||||||
memcpy(temp, YM2612GetContextPtr(), YM2612GetContextSize());
|
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)
|
if (temp)
|
||||||
{
|
{
|
||||||
YM2612Restore(temp);
|
YM2612Restore(temp);
|
||||||
@ -937,7 +956,7 @@ static void systemmenu ()
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* reinitialize HVC tables */
|
/* 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;
|
hctab = (reg[12] & 1) ? cycle2hc40 : cycle2hc32;
|
||||||
|
|
||||||
/* reinitialize overscan area */
|
/* reinitialize overscan area */
|
||||||
@ -963,8 +982,8 @@ static void systemmenu ()
|
|||||||
sprintf (items[3].text, "System BIOS: %s", (config.bios_enabled & 1) ? "ON":"OFF");
|
sprintf (items[3].text, "System BIOS: %s", (config.bios_enabled & 1) ? "ON":"OFF");
|
||||||
if (cart.romsize)
|
if (cart.romsize)
|
||||||
{
|
{
|
||||||
system_init ();
|
system_init();
|
||||||
system_reset ();
|
system_reset();
|
||||||
memfile_autoload(config.sram_auto,-1);
|
memfile_autoload(config.sram_auto,-1);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@ -984,9 +1003,9 @@ static void systemmenu ()
|
|||||||
|
|
||||||
if (cart.romsize)
|
if (cart.romsize)
|
||||||
{
|
{
|
||||||
system_reset (); /* clear any patches first */
|
system_reset(); /* clear any patches first */
|
||||||
system_init ();
|
system_init();
|
||||||
system_reset ();
|
system_reset();
|
||||||
memfile_autoload(config.sram_auto,-1);
|
memfile_autoload(config.sram_auto,-1);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@ -1035,8 +1054,7 @@ static void videomenu ()
|
|||||||
else
|
else
|
||||||
sprintf (items[1].text, "TV Mode: 50/60HZ");
|
sprintf (items[1].text, "TV Mode: 50/60HZ");
|
||||||
|
|
||||||
sprintf (items[2].text, "Bilinear Filter: %s",
|
sprintf (items[2].text, "Bilinear Filter: %s", config.bilinear ? " ON" : "OFF");
|
||||||
config.bilinear ? " ON" : "OFF");
|
|
||||||
|
|
||||||
if (config.ntsc == 1)
|
if (config.ntsc == 1)
|
||||||
sprintf (items[3].text, "NTSC Filter: COMPOSITE");
|
sprintf (items[3].text, "NTSC Filter: COMPOSITE");
|
||||||
@ -1047,15 +1065,14 @@ static void videomenu ()
|
|||||||
else
|
else
|
||||||
sprintf (items[3].text, "NTSC Filter: OFF");
|
sprintf (items[3].text, "NTSC Filter: OFF");
|
||||||
|
|
||||||
sprintf (items[4].text, "Borders: %s",
|
sprintf (items[4].text, "Borders: %s", config.overscan ? "ON" : "OFF");
|
||||||
config.overscan ? "ON" : "OFF");
|
|
||||||
|
|
||||||
if (config.aspect == 1)
|
if (config.aspect == 1)
|
||||||
sprintf (items[5].text,"Aspect: ORIGINAL (4:3)");
|
sprintf (items[5].text,"Aspect: ORIGINAL (4:3)");
|
||||||
else if (config.aspect == 2)
|
else if (config.aspect == 2)
|
||||||
sprintf (items[5].text, "Aspect: ORIGINAL (16:9)");
|
sprintf (items[5].text, "Aspect: ORIGINAL (16:9)");
|
||||||
else
|
else
|
||||||
sprintf (items[5].text, "Aspect: SCALED");
|
sprintf (items[5].text, "Aspect: SCALE");
|
||||||
|
|
||||||
sprintf (items[6].text, "Screen Position: (%s%02d,%s%02d)",
|
sprintf (items[6].text, "Screen Position: (%s%02d,%s%02d)",
|
||||||
(config.xshift < 0) ? "":"+", config.xshift,
|
(config.xshift < 0) ? "":"+", config.xshift,
|
||||||
@ -1104,20 +1121,49 @@ static void videomenu ()
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case 1: /*** tv mode ***/
|
case 1: /*** tv mode ***/
|
||||||
if (config.render == 2) break;
|
if (config.render != 2)
|
||||||
|
{
|
||||||
config.tv_mode = (config.tv_mode + 1) % 3;
|
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)
|
if (config.tv_mode == 0)
|
||||||
sprintf (items[1].text, "TV Mode: 60HZ");
|
sprintf (items[1].text, "TV Mode: 60HZ");
|
||||||
else if (config.tv_mode == 1)
|
else if (config.tv_mode == 1)
|
||||||
sprintf (items[1].text, "TV Mode: 50HZ");
|
sprintf (items[1].text, "TV Mode: 50HZ");
|
||||||
else
|
else
|
||||||
sprintf (items[1].text, "TV Mode: 50/60HZ");
|
sprintf (items[1].text, "TV Mode: 50/60HZ");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
GUI_WaitPrompt("Error","Progressive Mode is 60hz only !\n");
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 2: /*** bilinear filtering ***/
|
case 2: /*** bilinear filtering ***/
|
||||||
config.bilinear ^= 1;
|
config.bilinear ^= 1;
|
||||||
sprintf (items[2].text, "Bilinear Filter: %s",
|
sprintf (items[2].text, "Bilinear Filter: %s", config.bilinear ? " ON" : "OFF");
|
||||||
config.bilinear ? " ON" : "OFF");
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 3: /*** NTSC filter ***/
|
case 3: /*** NTSC filter ***/
|
||||||
@ -1134,8 +1180,7 @@ static void videomenu ()
|
|||||||
|
|
||||||
case 4: /*** overscan emulation ***/
|
case 4: /*** overscan emulation ***/
|
||||||
config.overscan ^= 1;
|
config.overscan ^= 1;
|
||||||
sprintf (items[4].text, "Overscan Color: %s",
|
sprintf (items[4].text, "Borders: %s", config.overscan ? "ON" : "OFF");
|
||||||
config.overscan ? "ORIGINAL" : "BLACK");
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 5: /*** aspect ratio ***/
|
case 5: /*** aspect ratio ***/
|
||||||
@ -1189,6 +1234,10 @@ static void videomenu ()
|
|||||||
(config.xshift < 0) ? "":"+", config.xshift,
|
(config.xshift < 0) ? "":"+", config.xshift,
|
||||||
(config.yshift < 0) ? "":"+", config.yshift);
|
(config.yshift < 0) ? "":"+", config.yshift);
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
GUI_WaitPrompt("Error","Please load a game first !\n");
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 7: /*** screen scaling ***/
|
case 7: /*** screen scaling ***/
|
||||||
@ -1213,6 +1262,10 @@ static void videomenu ()
|
|||||||
(config.xscale < 0) ? "":"+", config.xscale,
|
(config.xscale < 0) ? "":"+", config.xscale,
|
||||||
(config.yscale < 0) ? "":"+", config.yscale);
|
(config.yscale < 0) ? "":"+", config.yscale);
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
GUI_WaitPrompt("Error","Please load a game first !\n");
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case -1:
|
case -1:
|
||||||
@ -2402,8 +2455,8 @@ void MainMenu (void)
|
|||||||
GUI_DeleteMenu(m);
|
GUI_DeleteMenu(m);
|
||||||
gxClearScreen((GXColor)BLACK);
|
gxClearScreen((GXColor)BLACK);
|
||||||
gxSetScreen();
|
gxSetScreen();
|
||||||
|
audio_init(snd.sample_rate,snd.frame_rate);
|
||||||
system_init();
|
system_init();
|
||||||
audio_init(48000,vdp_pal?50.0:(1000000.0/16715.0));
|
|
||||||
system_reset();
|
system_reset();
|
||||||
memfile_autoload(config.sram_auto,-1);
|
memfile_autoload(config.sram_auto,-1);
|
||||||
quit = 1;
|
quit = 1;
|
||||||
|
@ -25,7 +25,7 @@
|
|||||||
#include "shared.h"
|
#include "shared.h"
|
||||||
|
|
||||||
/* DMA soundbuffers (required to be 32-bytes aligned)
|
/* 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:
|
To prevent audio clashes, we use double buffering technique:
|
||||||
one buffer is the active DMA buffer
|
one buffer is the active DMA buffer
|
||||||
the other one is the current work buffer (updated during frame emulation)
|
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 */
|
/* Current work soundbuffer */
|
||||||
u8 mixbuffer;
|
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 */
|
/* audio DMA status */
|
||||||
static u8 audioStarted = 0;
|
static u8 audioStarted = 0;
|
||||||
|
|
||||||
@ -98,38 +89,14 @@ void gx_audio_Shutdown(void)
|
|||||||
/***
|
/***
|
||||||
gx_audio_Update
|
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
|
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
|
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 */
|
/* set next DMA soundbuffer */
|
||||||
s16 *sb = (s16 *)(soundbuffer[mixbuffer]);
|
s16 *sb = (s16 *)(soundbuffer[mixbuffer]);
|
||||||
mixbuffer ^= 1;
|
mixbuffer ^= 1;
|
||||||
size = size << 2;
|
|
||||||
DCFlushRange((void *)sb, size);
|
DCFlushRange((void *)sb, size);
|
||||||
AUDIO_InitDMA((u32) sb, size);
|
AUDIO_InitDMA((u32) sb, size);
|
||||||
|
|
||||||
@ -140,7 +107,8 @@ void gx_audio_Update(void)
|
|||||||
{
|
{
|
||||||
audioStarted = 1;
|
audioStarted = 1;
|
||||||
AUDIO_StartDMA();
|
AUDIO_StartDMA();
|
||||||
if (frameticker > 1) frameticker = 1;
|
if (frameticker > 1)
|
||||||
|
frameticker = 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -156,29 +124,16 @@ void gx_audio_Start(void)
|
|||||||
PauseOgg(1);
|
PauseOgg(1);
|
||||||
StopOgg();
|
StopOgg();
|
||||||
ASND_Pause(1);
|
ASND_Pause(1);
|
||||||
AUDIO_StopDMA ();
|
ASND_End();
|
||||||
AUDIO_RegisterDMACallback(NULL);
|
|
||||||
audioStarted = 0;
|
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;
|
mixbuffer = 0;
|
||||||
delta = 0;
|
|
||||||
|
|
||||||
/* reset sound buffers */
|
/* reset sound buffers */
|
||||||
memset(soundbuffer, 0, 2 * 3840);
|
memset(soundbuffer, 0, 2 * 3840);
|
||||||
|
|
||||||
/* By default, use audio DMA to synchronize frame emulation */
|
/* By default, use audio DMA to synchronize frame emulation */
|
||||||
if (gc_pal | vdp_pal) AUDIO_RegisterDMACallback(ai_callback);
|
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/***
|
/***
|
||||||
|
@ -32,6 +32,6 @@ extern void gx_audio_Init(void);
|
|||||||
extern void gx_audio_Shutdown(void);
|
extern void gx_audio_Shutdown(void);
|
||||||
extern void gx_audio_Start(void);
|
extern void gx_audio_Start(void);
|
||||||
extern void gx_audio_Stop(void);
|
extern void gx_audio_Stop(void);
|
||||||
extern void gx_audio_Update(void);
|
extern void gx_audio_Update(int size);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -1283,9 +1283,11 @@ void gx_video_Start(void)
|
|||||||
|
|
||||||
/* VSYNC callbacks */
|
/* VSYNC callbacks */
|
||||||
/* in 60hz mode we use VSYNC to synchronize frame emulation */
|
/* 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_SetPostRetraceCallback(NULL);
|
||||||
VIDEO_Flush();
|
VIDEO_Flush();
|
||||||
|
VIDEO_WaitVSync();
|
||||||
|
|
||||||
/* interlaced/progressive mode */
|
/* interlaced/progressive mode */
|
||||||
if (config.render == 2)
|
if (config.render == 2)
|
||||||
|
@ -125,10 +125,20 @@ void reloadrom (int size, char *name)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
system_init (); /* Initialize System */
|
/* initialize audio back-end */
|
||||||
audio_init(48000,vdp_pal?50.0:(1000000.0/16715.0));
|
/* 60hz video mode requires synchronization with Video Interrupt. */
|
||||||
ClearGGCodes (); /* Clear Game Genie patches */
|
/* VSYNC period is 16715 us on Wii/Gamecube (approx. 802.32 samples per frame) */
|
||||||
system_reset (); /* System Power ON */
|
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();
|
DI_Init();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
int size;
|
||||||
|
|
||||||
/* initialize hardware */
|
/* initialize hardware */
|
||||||
gx_video_Init();
|
gx_video_Init();
|
||||||
@ -265,9 +276,6 @@ int main (int argc, char *argv[])
|
|||||||
/* skip frame */
|
/* skip frame */
|
||||||
frameticker-=2;
|
frameticker-=2;
|
||||||
system_frame (1);
|
system_frame (1);
|
||||||
|
|
||||||
/* update audio only */
|
|
||||||
gx_audio_Update();
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -277,11 +285,14 @@ int main (int argc, char *argv[])
|
|||||||
|
|
||||||
/* render frame */
|
/* render frame */
|
||||||
system_frame (0);
|
system_frame (0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* retrieve audio samples */
|
||||||
|
size = audio_update();
|
||||||
|
|
||||||
/* update video & audio */
|
/* update video & audio */
|
||||||
gx_video_Update();
|
gx_video_Update();
|
||||||
gx_audio_Update();
|
gx_audio_Update(size * 4);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
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
|
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
|
uint8 cycle2hc40[3420] =
|
||||||
WWW: http://cgfm2.emuviews.com
|
{
|
||||||
|
/* 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
|
/* 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,
|
||||||
Range 00-93, E9-FF 00-B6, E4-FF
|
0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5,
|
||||||
Display area 00-7F 00-9F
|
0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6,
|
||||||
V counter increment 84, 85 A4, A5
|
0xe5, 0xe5, 0xe5, 0xe5, 0xe5, 0xe5, 0xe5, 0xe5, 0xe5, 0xe5, 0xe5, 0xe5, 0xe5, 0xe5, 0xe5, 0xe5,
|
||||||
V-blanking in 86, 87 A7, A8
|
0xe6, 0xe6, 0xe6, 0xe6, 0xe6, 0xe6, 0xe6, 0xe6,
|
||||||
V-blanking out 86, 87 A7, A8
|
|
||||||
H-blanking in 93, E9 B2, E4
|
|
||||||
H-blanking out 06, 07 06, 07
|
|
||||||
|
|
||||||
Comma seperated values show the H counter value before an event occurs,
|
/* horizontal sync (32 pixels -> 313 Mcycles) */
|
||||||
and then the H counter value immediately after.
|
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
|
/* left blanking (32 pixels -> 259 Mcycles) */
|
||||||
off by one or two.
|
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.
|
/* remaining active display (304 pixels -> 2432 Mcycles) */
|
||||||
The H counter will never actually be set to the values 94-E8 or B7-E3.
|
0x0d, 0x0d, 0x0d, 0x0d,
|
||||||
Perhaps this is the horizontal retrace period.
|
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,
|
||||||
Interestingly enough, the timing values for the 32-cell display mode
|
0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x10, 0x10, 0x10, 0x10,
|
||||||
are identical to that of the SMS.
|
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,
|
||||||
It would appear that in 40-cell mode, the horizontal blanking period
|
0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x13, 0x13, 0x13, 0x13,
|
||||||
is shorter as the active display period takes more time.
|
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,
|
||||||
The V-blanking flag can also be forcibly set by disabling the display
|
0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x16, 0x16, 0x16, 0x16,
|
||||||
through bit 6 of register #1.
|
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,
|
||||||
H counter
|
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,
|
||||||
Now for some additional information on the horizontal aspects of the
|
0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1d, 0x1d, 0x1d, 0x1d,
|
||||||
display, taken from the TMS9918 manual and my tests on a NTSC Genesis.
|
0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1e, 0x1e, 0x1e, 0x1e,
|
||||||
Be warned that a real SMS may have different results.
|
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,
|
||||||
The H counter is 9 bits, and reading it returns the upper 8 bits. This is
|
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x21, 0x21, 0x21, 0x21,
|
||||||
because a scanline consists of 342 pixels, which couldn't be represented
|
0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x22, 0x22, 0x22, 0x22,
|
||||||
with an 8-bit counter. Each scanline is divided up as follows:
|
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,
|
||||||
Pixels H.Cnt Description
|
0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x25, 0x25, 0x25, 0x25,
|
||||||
256 : 00-7F : Active display
|
0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x26, 0x26, 0x26, 0x26,
|
||||||
15 : 80-87 : Right border
|
0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x27, 0x27, 0x27, 0x27,
|
||||||
8 : 87-8B : Right blanking
|
0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x28, 0x28, 0x28, 0x28,
|
||||||
26 : 8B-ED : Horizontal sync
|
0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x29, 0x29, 0x29, 0x29,
|
||||||
2 : ED-EE : Left blanking
|
0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x2a, 0x2a, 0x2a, 0x2a,
|
||||||
14 : EE-F5 : Color burst
|
0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2b, 0x2b, 0x2b, 0x2b,
|
||||||
8 : F5-F9 : Left blanking
|
0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2c, 0x2c, 0x2c, 0x2c,
|
||||||
13 : F9-FF : Left border
|
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,
|
||||||
Here's a description of what these areas look like:
|
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,
|
||||||
Active display - Where the display generated by the VDP goes.
|
0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x31, 0x31, 0x31, 0x31,
|
||||||
Right border - Filled with border color from VDP register $07.
|
0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x32, 0x32, 0x32, 0x32,
|
||||||
Right blanking - Filled with a light black color. (like display was blanked)
|
0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x33, 0x33, 0x33, 0x33,
|
||||||
Horizontal sync - Filled with a pure black color. (like display was turned off)
|
0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x34, 0x34, 0x34, 0x34,
|
||||||
Left blanking - Filled with the border color from VDP register $07.
|
0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x35, 0x35, 0x35, 0x35,
|
||||||
Color burst - Filled with a dark brown/orange color.
|
0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x36, 0x36, 0x36, 0x36,
|
||||||
Left blanking - Filled with a light black color. (like display was blanked)
|
0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x37, 0x37, 0x37, 0x37,
|
||||||
Left border - Filled with the border color from VDP register $07.
|
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,
|
||||||
uint8 cycle2hc32[488] = {
|
0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3c, 0x3c, 0x3c, 0x3c,
|
||||||
0x85, 0x85, 0x86, 0x86, 0x87, 0x87, 0x87, 0x88, 0x88, 0x88, 0x89, 0x89, 0x89, 0x8A, 0x8A, 0x8A,
|
0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3d, 0x3d, 0x3d, 0x3d,
|
||||||
0x8B, 0x8B, 0x8B, 0x8C, 0x8C, 0x8D, 0x8D, 0x8D, 0x8E, 0x8E, 0x8E, 0x8F, 0x8F, 0x8F, 0x90, 0x90,
|
0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3e, 0x3e, 0x3e, 0x3e,
|
||||||
0x90, 0x91, 0x91, 0x91, 0x92, 0x92, 0x92, 0x93, 0x93,
|
0x3e, 0x3e, 0x3e, 0x3e, 0x3e, 0x3e, 0x3e, 0x3e, 0x3e, 0x3e, 0x3e, 0x3e, 0x3f, 0x3f, 0x3f, 0x3f,
|
||||||
0xE9, 0xE9, 0xE9, 0xEA, 0xEA, 0xEA,
|
0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x40, 0x40, 0x40, 0x40,
|
||||||
0xEB, 0xEB, 0xEB, 0xEC, 0xEC, 0xEC, 0xED, 0xED, 0xED, 0xEE, 0xEE, 0xEE, 0xEF, 0xEF, 0xF0, 0xF0,
|
0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x41, 0x41, 0x41, 0x41,
|
||||||
0xF0, 0xF1, 0xF1, 0xF1, 0xF2, 0xF2, 0xF2, 0xF3, 0xF3, 0xF3, 0xF4, 0xF4, 0xF4, 0xF5, 0xF5, 0xF6,
|
0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x42, 0x42, 0x42, 0x42,
|
||||||
0xF6, 0xF6, 0xF7, 0xF7, 0xF7, 0xF8, 0xF8, 0xF8, 0xF9, 0xF9, 0xF9, 0xFA, 0xFA, 0xFA, 0xFB, 0xFB,
|
0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x43, 0x43, 0x43, 0x43,
|
||||||
0xFB, 0xFC, 0xFC, 0xFD, 0xFD, 0xFD, 0xFE, 0xFE, 0xFE, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x01,
|
0x43, 0x43, 0x43, 0x43, 0x43, 0x43, 0x43, 0x43, 0x43, 0x43, 0x43, 0x43, 0x44, 0x44, 0x44, 0x44,
|
||||||
0x01, 0x01, 0x02, 0x02, 0x02, 0x03, 0x03, 0x03, 0x04, 0x04, 0x04, 0x05, 0x05, 0x05, 0x06, 0x06,
|
0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x45, 0x45, 0x45, 0x45,
|
||||||
0x07, 0x07, 0x07, 0x08, 0x08, 0x08, 0x09, 0x09, 0x09, 0x0A, 0x0A, 0x0A, 0x0B, 0x0B, 0x0B, 0x0C,
|
0x45, 0x45, 0x45, 0x45, 0x45, 0x45, 0x45, 0x45, 0x45, 0x45, 0x45, 0x45, 0x46, 0x46, 0x46, 0x46,
|
||||||
0x0C, 0x0C, 0x0D, 0x0D, 0x0E, 0x0E, 0x0E, 0x0F, 0x0F, 0x0F, 0x10, 0x10, 0x10, 0x11, 0x11, 0x11,
|
0x46, 0x46, 0x46, 0x46, 0x46, 0x46, 0x46, 0x46, 0x46, 0x46, 0x46, 0x46, 0x47, 0x47, 0x47, 0x47,
|
||||||
0x12, 0x12, 0x12, 0x13, 0x13, 0x13, 0x14, 0x14, 0x15, 0x15, 0x15, 0x16, 0x16, 0x16, 0x17, 0x17,
|
0x47, 0x47, 0x47, 0x47, 0x47, 0x47, 0x47, 0x47, 0x47, 0x47, 0x47, 0x47, 0x48, 0x48, 0x48, 0x48,
|
||||||
0x17, 0x18, 0x18, 0x18, 0x19, 0x19, 0x19, 0x1A, 0x1A, 0x1B, 0x1B, 0x1B, 0x1C, 0x1C, 0x1C, 0x1D,
|
0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x49, 0x49, 0x49, 0x49,
|
||||||
0x1D, 0x1D, 0x1E, 0x1E, 0x1E, 0x1F, 0x1F, 0x1F, 0x20, 0x20, 0x20, 0x21, 0x21, 0x22, 0x22, 0x22,
|
0x49, 0x49, 0x49, 0x49, 0x49, 0x49, 0x49, 0x49, 0x49, 0x49, 0x49, 0x49, 0x4a, 0x4a, 0x4a, 0x4a,
|
||||||
0x23, 0x23, 0x23, 0x24, 0x24, 0x24, 0x25, 0x25, 0x25, 0x26, 0x26, 0x26, 0x27, 0x27, 0x27, 0x28,
|
0x4a, 0x4a, 0x4a, 0x4a, 0x4a, 0x4a, 0x4a, 0x4a, 0x4a, 0x4a, 0x4a, 0x4a, 0x4b, 0x4b, 0x4b, 0x4b,
|
||||||
0x28, 0x29, 0x29, 0x29, 0x2A, 0x2A, 0x2A, 0x2B, 0x2B, 0x2B, 0x2C, 0x2C, 0x2C, 0x2D, 0x2D, 0x2D,
|
0x4b, 0x4b, 0x4b, 0x4b, 0x4b, 0x4b, 0x4b, 0x4b, 0x4b, 0x4b, 0x4b, 0x4b, 0x4c, 0x4c, 0x4c, 0x4c,
|
||||||
0x2E, 0x2E, 0x2F, 0x2F, 0x2F, 0x30, 0x30, 0x30, 0x31, 0x31, 0x31, 0x32, 0x32, 0x32, 0x33, 0x33,
|
0x4c, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c, 0x4d, 0x4d, 0x4d, 0x4d,
|
||||||
0x33, 0x34, 0x34, 0x34, 0x35, 0x35, 0x36, 0x36, 0x36, 0x37, 0x37, 0x37, 0x38, 0x38, 0x38, 0x39,
|
0x4d, 0x4d, 0x4d, 0x4d, 0x4d, 0x4d, 0x4d, 0x4d, 0x4d, 0x4d, 0x4d, 0x4d, 0x4e, 0x4e, 0x4e, 0x4e,
|
||||||
0x39, 0x39, 0x3A, 0x3A, 0x3A, 0x3B, 0x3B, 0x3B, 0x3C, 0x3C, 0x3D, 0x3D, 0x3D, 0x3E, 0x3E, 0x3E,
|
0x4e, 0x4e, 0x4e, 0x4e, 0x4e, 0x4e, 0x4e, 0x4e, 0x4e, 0x4e, 0x4e, 0x4e, 0x4f, 0x4f, 0x4f, 0x4f,
|
||||||
0x3F, 0x3F, 0x3F, 0x40, 0x40, 0x40, 0x41, 0x41, 0x41, 0x42, 0x42, 0x42, 0x43, 0x43, 0x44, 0x44,
|
0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x50, 0x50, 0x50, 0x50,
|
||||||
0x44, 0x45, 0x45, 0x45, 0x46, 0x46, 0x46, 0x47, 0x47, 0x47, 0x48, 0x48, 0x48, 0x49, 0x49, 0x4A,
|
0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x51, 0x51, 0x51, 0x51,
|
||||||
0x4A, 0x4A, 0x4B, 0x4B, 0x4B, 0x4C, 0x4C, 0x4C, 0x4D, 0x4D, 0x4D, 0x4E, 0x4E, 0x4E, 0x4F, 0x4F,
|
0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x52, 0x52, 0x52, 0x52,
|
||||||
0x4F, 0x50, 0x50, 0x51, 0x51, 0x51, 0x52, 0x52, 0x52, 0x53, 0x53, 0x53, 0x54, 0x54, 0x54, 0x55,
|
0x52, 0x52, 0x52, 0x52, 0x52, 0x52, 0x52, 0x52, 0x52, 0x52, 0x52, 0x52, 0x53, 0x53, 0x53, 0x53,
|
||||||
0x55, 0x55, 0x56, 0x56, 0x56, 0x57, 0x57, 0x58, 0x58, 0x58, 0x59, 0x59, 0x59, 0x5A, 0x5A, 0x5A,
|
0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x54, 0x54, 0x54, 0x54,
|
||||||
0x5B, 0x5B, 0x5B, 0x5C, 0x5C, 0x5C, 0x5D, 0x5D, 0x5E, 0x5E, 0x5E, 0x5F, 0x5F, 0x5F, 0x60, 0x60,
|
0x54, 0x54, 0x54, 0x54, 0x54, 0x54, 0x54, 0x54, 0x54, 0x54, 0x54, 0x54, 0x55, 0x55, 0x55, 0x55,
|
||||||
0x60, 0x61, 0x61, 0x61, 0x62, 0x62, 0x62, 0x63, 0x63, 0x63, 0x64, 0x64, 0x65, 0x65, 0x65, 0x66,
|
0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x56, 0x56, 0x56, 0x56,
|
||||||
0x66, 0x66, 0x67, 0x67, 0x67, 0x68, 0x68, 0x68, 0x69, 0x69, 0x69, 0x6A, 0x6A, 0x6A, 0x6B, 0x6B,
|
0x56, 0x56, 0x56, 0x56, 0x56, 0x56, 0x56, 0x56, 0x56, 0x56, 0x56, 0x56, 0x57, 0x57, 0x57, 0x57,
|
||||||
0x6C, 0x6C, 0x6C, 0x6D, 0x6D, 0x6D, 0x6E, 0x6E, 0x6E, 0x6F, 0x6F, 0x6F, 0x70, 0x70, 0x70, 0x71,
|
0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x58, 0x58, 0x58, 0x58,
|
||||||
0x71, 0x72, 0x72, 0x72, 0x73, 0x73, 0x73, 0x74, 0x74, 0x74, 0x75, 0x75, 0x75, 0x76, 0x76, 0x76,
|
0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0x59, 0x59, 0x59, 0x59,
|
||||||
0x77, 0x77, 0x77, 0x78, 0x78, 0x79, 0x79, 0x79, 0x7A, 0x7A, 0x7A, 0x7B, 0x7B, 0x7B, 0x7C, 0x7C,
|
0x59, 0x59, 0x59, 0x59, 0x59, 0x59, 0x59, 0x59, 0x59, 0x59, 0x59, 0x59, 0x5a, 0x5a, 0x5a, 0x5a,
|
||||||
0x7C, 0x7D, 0x7D, 0x7D, 0x7E, 0x7E, 0x7E, 0x7F, 0x7F, 0x80, 0x80, 0x80, 0x81, 0x81, 0x81, 0x82,
|
0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5b, 0x5b, 0x5b, 0x5b,
|
||||||
0x82, 0x82, 0x83, 0x83, 0x83, 0x84, 0x84, 0x84, 0x85,
|
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] = {
|
uint8 cycle2hc32[3420] =
|
||||||
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,
|
/* end of active display (16 pixels -> 160 Mcycles) , HINT triggered ? , Vcounter jump */
|
||||||
0xB2, 0xB3, 0xB3, 0xB4, 0xB4, 0xB4, 0xB5, 0xB5, 0xB6, 0xB6,
|
0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85,
|
||||||
0xE4, 0xE4, 0xE4, 0xE5, 0xE5, 0xE6, 0xE6,
|
0x85, 0x85, 0x85, 0x85, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86,
|
||||||
0xE7, 0xE7, 0xE7, 0xE8, 0xE8, 0xE9, 0xE9, 0xEA, 0xEA, 0xEB, 0xEB, 0xEB, 0xEC, 0xEC, 0xED, 0xED,
|
0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87,
|
||||||
0xEE, 0xEE, 0xEE, 0xEF, 0xEF, 0xF0, 0xF0, 0xF1, 0xF1, 0xF1, 0xF2, 0xF2, 0xF3, 0xF3, 0xF4, 0xF4,
|
0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x88, 0x88, 0x88, 0x88,
|
||||||
0xF4, 0xF5, 0xF5, 0xF6, 0xF6, 0xF7, 0xF7, 0xF7, 0xF8, 0xF8, 0xF9, 0xF9, 0xFA, 0xFA, 0xFB, 0xFB,
|
0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88,
|
||||||
0xFB, 0xFC, 0xFC, 0xFD, 0xFD, 0xFE, 0xFE, 0xFE, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x01, 0x01, 0x02,
|
0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89,
|
||||||
0x02, 0x03, 0x03, 0x03, 0x04, 0x04, 0x05, 0x05, 0x06, 0x06, 0x06, 0x07, 0x07, 0x08, 0x08, 0x09,
|
0x89, 0x89, 0x89, 0x89, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a,
|
||||||
0x09, 0x09, 0x0A, 0x0A, 0x0B, 0x0B, 0x0C, 0x0C, 0x0C, 0x0D, 0x0D, 0x0E, 0x0E, 0x0F, 0x0F, 0x10,
|
0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b,
|
||||||
0x10, 0x10, 0x11, 0x11, 0x12, 0x12, 0x13, 0x13, 0x13, 0x14, 0x14, 0x15, 0x15, 0x16, 0x16, 0x16,
|
0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8c, 0x8c, 0x8c, 0x8c,
|
||||||
0x17, 0x17, 0x18, 0x18, 0x19, 0x19, 0x19, 0x1A, 0x1A, 0x1B, 0x1B, 0x1C, 0x1C, 0x1C, 0x1D, 0x1D,
|
0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c,
|
||||||
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,
|
/* right border (14 pixels -> 140 Mcycles) */
|
||||||
0x2C, 0x2C, 0x2D, 0x2D, 0x2D, 0x2E, 0x2E, 0x2F, 0x2F, 0x30, 0x30, 0x30, 0x31, 0x31, 0x32, 0x32,
|
0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d,
|
||||||
0x33, 0x33, 0x33, 0x34, 0x34, 0x35, 0x35, 0x36, 0x36, 0x36, 0x37, 0x37, 0x38, 0x38, 0x39, 0x39,
|
0x8d, 0x8d, 0x8d, 0x8d, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e,
|
||||||
0x39, 0x3A, 0x3A, 0x3B, 0x3B, 0x3C, 0x3C, 0x3D, 0x3D, 0x3D, 0x3E, 0x3E, 0x3F, 0x3F, 0x40, 0x40,
|
0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f,
|
||||||
0x40, 0x41, 0x41, 0x42, 0x42, 0x43, 0x43, 0x43, 0x44, 0x44, 0x45, 0x45, 0x46, 0x46, 0x46, 0x47,
|
0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x90, 0x90, 0x90, 0x90,
|
||||||
0x47, 0x48, 0x48, 0x49, 0x49, 0x4A, 0x4A, 0x4A, 0x4B, 0x4B, 0x4C, 0x4C, 0x4D, 0x4D, 0x4D, 0x4E,
|
0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90,
|
||||||
0x4E, 0x4F, 0x4F, 0x50, 0x50, 0x50, 0x51, 0x51, 0x52, 0x52, 0x53, 0x53, 0x53, 0x54, 0x54, 0x55,
|
0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91,
|
||||||
0x55, 0x56, 0x56, 0x56, 0x57, 0x57, 0x58, 0x58, 0x59, 0x59, 0x5A, 0x5A, 0x5A, 0x5B, 0x5B, 0x5C,
|
0x91, 0x91, 0x91, 0x91, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92,
|
||||||
0x5C, 0x5D, 0x5D, 0x5D, 0x5E, 0x5E, 0x5F, 0x5F, 0x60, 0x60, 0x60, 0x61, 0x61, 0x62, 0x62, 0x63,
|
0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93,
|
||||||
0x63, 0x63, 0x64, 0x64, 0x65, 0x65, 0x66, 0x66, 0x67, 0x67, 0x67, 0x68, 0x68, 0x69, 0x69, 0x6A,
|
0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93,
|
||||||
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,
|
/* right blanking (9 pixels -> 90 Mcycles) , VDP status HBLANK flag set */
|
||||||
0x78, 0x78, 0x79, 0x79, 0x7A, 0x7A, 0x7A, 0x7B, 0x7B, 0x7C, 0x7C, 0x7D, 0x7D, 0x7D, 0x7E, 0x7E,
|
0xe9, 0xe9, 0xe9, 0xe9,
|
||||||
0x7F, 0x7F, 0x80, 0x80, 0x80, 0x81, 0x81, 0x82, 0x82, 0x83, 0x83, 0x84, 0x84, 0x84, 0x85, 0x85,
|
0xe9, 0xe9, 0xe9, 0xe9, 0xe9, 0xe9, 0xe9, 0xe9, 0xe9, 0xe9, 0xe9, 0xe9, 0xe9, 0xe9, 0xe9, 0xe9,
|
||||||
0x86, 0x86, 0x87, 0x87, 0x87, 0x88, 0x88, 0x89, 0x89, 0x8A, 0x8A, 0x8A, 0x8B, 0x8B, 0x8C, 0x8C,
|
0xea, 0xea, 0xea, 0xea, 0xea, 0xea, 0xea, 0xea, 0xea, 0xea, 0xea, 0xea, 0xea, 0xea, 0xea, 0xea,
|
||||||
0x8D, 0x8D, 0x8D, 0x8E, 0x8E, 0x8F, 0x8F, 0x90, 0x90, 0x90, 0x91, 0x91, 0x92, 0x92, 0x93, 0x93,
|
0xea, 0xea, 0xea, 0xea, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb,
|
||||||
0x94, 0x94, 0x94, 0x95, 0x95, 0x96, 0x96, 0x97, 0x97, 0x97, 0x98, 0x98, 0x99, 0x99, 0x9A, 0x9A,
|
0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xec, 0xec, 0xec, 0xec, 0xec, 0xec, 0xec, 0xec,
|
||||||
0x9A, 0x9B, 0x9B, 0x9C, 0x9C, 0x9D, 0x9D, 0x9D, 0x9E, 0x9E, 0x9F, 0x9F, 0xA0, 0xA0, 0xA1, 0xA1,
|
0xec, 0xec, 0xec, 0xec, 0xec, 0xec, 0xec, 0xec, 0xec, 0xec, 0xec, 0xec, 0xed, 0xed, 0xed, 0xed,
|
||||||
0xA1, 0xA2, 0xA2, 0xA3, 0xA3, 0xA4, 0xA4,
|
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;
|
uint8 *vctab;
|
||||||
|
@ -382,10 +382,27 @@ void set_region ()
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Force region setting */
|
/* Force region setting */
|
||||||
if (config.region_detect == 1) region_code = REGION_USA;
|
if (config.region_detect == 1)
|
||||||
else if (config.region_detect == 2) region_code = REGION_EUROPE;
|
region_code = REGION_USA;
|
||||||
else if (config.region_detect == 3) region_code = REGION_JAPAN_NTSC;
|
else if (config.region_detect == 2)
|
||||||
else if (config.region_detect == 4) region_code = REGION_JAPAN_PAL;
|
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 */
|
/* execute num_cycles worth of instructions. returns number of cycles used */
|
||||||
//int m68k_execute(int num_cycles);
|
//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
|
/* These functions let you read/write/modify the number of cycles left to run
|
||||||
* while m68k_execute() is running.
|
* while m68k_execute() is running.
|
||||||
* These are useful if the 68k accesses a memory-mapped port on another device
|
* These are useful if the 68k accesses a memory-mapped port on another device
|
||||||
* that requires immediate processing by another CPU.
|
* that requires immediate processing by another CPU.
|
||||||
*/
|
*/
|
||||||
int m68k_cycles_run(void); /* Number of cycles run so far */
|
//int m68k_cycles_run(void); /* Number of cycles run so far */
|
||||||
int m68k_cycles_remaining(void); /* Number of cycles left */
|
//int m68k_cycles_remaining(void); /* Number of cycles left */
|
||||||
void m68k_modify_timeslice(int cycles); /* Modify cycles left */
|
//void m68k_modify_timeslice(int cycles); /* Modify cycles left */
|
||||||
void m68k_end_timeslice(void); /* End timeslice now */
|
//void m68k_end_timeslice(void); /* End timeslice now */
|
||||||
|
|
||||||
/* Set the IPL0-IPL2 pins on the CPU (IRQ).
|
/* Set the IPL0-IPL2 pins on the CPU (IRQ).
|
||||||
* A transition from < 7 to 7 will cause a non-maskable interrupt (NMI).
|
* A transition from < 7 to 7 will cause a non-maskable interrupt (NMI).
|
||||||
* Setting IRQ to 0 will clear an interrupt request.
|
* 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. */
|
/* Halt the CPU as if you pulsed the HALT pin. */
|
||||||
|
@ -43,8 +43,8 @@ extern void m68040_fpu_op1(void);
|
|||||||
/* ================================= DATA ================================= */
|
/* ================================= DATA ================================= */
|
||||||
/* ======================================================================== */
|
/* ======================================================================== */
|
||||||
|
|
||||||
int m68ki_initial_cycles;
|
//int m68ki_initial_cycles;
|
||||||
int m68ki_remaining_cycles = 0; /* Number of clocks remaining */
|
//int m68ki_remaining_cycles = 0; /* Number of clocks remaining */
|
||||||
uint m68ki_tracing = 0;
|
uint m68ki_tracing = 0;
|
||||||
uint m68ki_address_space;
|
uint m68ki_address_space;
|
||||||
|
|
||||||
@ -777,10 +777,11 @@ void m68k_set_cpu_type(unsigned int cpu_type)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Execute a single instruction */
|
/* 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 our pool of clock cycles available */
|
||||||
SET_CYCLES(0);
|
//SET_CYCLES(0);
|
||||||
|
|
||||||
/* Set tracing accodring to T1. (T0 is done inside instruction) */
|
/* Set tracing accodring to T1. (T0 is done inside instruction) */
|
||||||
m68ki_trace_t1(); /* auto-disable (see m68kcpu.h) */
|
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) */
|
m68ki_exception_if_trace(); /* auto-disable (see m68kcpu.h) */
|
||||||
|
|
||||||
/* return how many clocks we used */
|
/* 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 */
|
/* 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
|
/* KS: Modified so that IPL* bits match with mask positions in the SR
|
||||||
* and cleaned out remenants of the interrupt controller.
|
* 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;
|
uint old_level = CPU_INT_LEVEL;
|
||||||
CPU_INT_LEVEL = int_level << 8;
|
CPU_INT_LEVEL = int_level << 8;
|
||||||
@ -830,50 +830,50 @@ extern void error(char *format, ...);
|
|||||||
#endif
|
#endif
|
||||||
extern uint8 irq_status;
|
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 */
|
/* Return point if we had an address error */
|
||||||
m68ki_set_address_error_trap(); /* auto-disable (see m68kcpu.h) */
|
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 */
|
/* check interrupt updates */
|
||||||
if (irq_status & 0x10)
|
if (irq_status & 0x10)
|
||||||
{
|
{
|
||||||
irq_status &= ~0x10;
|
irq_status &= ~0x10;
|
||||||
|
int_level = irq_status & 6;
|
||||||
temp = irq_status & 6;
|
|
||||||
|
|
||||||
/* hardware latency */
|
/* hardware latency */
|
||||||
if (irq_status & 0x40)
|
if (irq_status & 0x40)
|
||||||
count_m68k += m68k_execute();
|
m68k_execute();
|
||||||
|
|
||||||
#ifdef LOGVDP
|
#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
|
#endif
|
||||||
/* interrupt level */
|
/* update IRQ level */
|
||||||
m68k_set_irq(temp);
|
CPU_INT_LEVEL = int_level << 8;
|
||||||
}
|
m68ki_check_interrupts();
|
||||||
|
|
||||||
/* Make sure we're not stopped */
|
if (mcycles_68k >= cycles)
|
||||||
if(CPU_STOPPED)
|
|
||||||
{
|
|
||||||
count_m68k = cyc;
|
|
||||||
REG_PPC = REG_PC;
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* execute a single instruction */
|
/* 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)
|
int m68k_cycles_run(void)
|
||||||
{
|
{
|
||||||
return m68ki_initial_cycles - GET_CYCLES();
|
return m68ki_initial_cycles - GET_CYCLES();
|
||||||
@ -883,20 +883,22 @@ int m68k_cycles_remaining(void)
|
|||||||
{
|
{
|
||||||
return GET_CYCLES();
|
return GET_CYCLES();
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
/* Change the timeslice */
|
/* Change the timeslice */
|
||||||
|
/*
|
||||||
void m68k_modify_timeslice(int cycles)
|
void m68k_modify_timeslice(int cycles)
|
||||||
{
|
{
|
||||||
m68ki_initial_cycles += cycles;
|
m68ki_initial_cycles += cycles;
|
||||||
ADD_CYCLES(cycles);
|
ADD_CYCLES(cycles);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void m68k_end_timeslice(void)
|
void m68k_end_timeslice(void)
|
||||||
{
|
{
|
||||||
m68ki_initial_cycles = GET_CYCLES();
|
m68ki_initial_cycles = GET_CYCLES();
|
||||||
SET_CYCLES(0);
|
SET_CYCLES(0);
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
void m68k_init(void)
|
void m68k_init(void)
|
||||||
{
|
{
|
||||||
@ -925,7 +927,7 @@ void m68k_pulse_reset(void)
|
|||||||
{
|
{
|
||||||
/* Clear all stop levels and eat up all remaining cycles */
|
/* Clear all stop levels and eat up all remaining cycles */
|
||||||
CPU_STOPPED = 0;
|
CPU_STOPPED = 0;
|
||||||
SET_CYCLES(0);
|
//SET_CYCLES(0);
|
||||||
|
|
||||||
CPU_RUN_MODE = RUN_MODE_BERR_AERR_RESET;
|
CPU_RUN_MODE = RUN_MODE_BERR_AERR_RESET;
|
||||||
|
|
||||||
@ -953,6 +955,8 @@ void m68k_pulse_reset(void)
|
|||||||
m68ki_jump(REG_PC);
|
m68ki_jump(REG_PC);
|
||||||
|
|
||||||
CPU_RUN_MODE = RUN_MODE_NORMAL;
|
CPU_RUN_MODE = RUN_MODE_NORMAL;
|
||||||
|
|
||||||
|
USE_CYCLES(CYC_EXCEPTION[EXCEPTION_RESET]);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Pulse the HALT line on the CPU */
|
/* Pulse the HALT line on the CPU */
|
||||||
|
@ -33,8 +33,6 @@
|
|||||||
#include <setjmp.h>
|
#include <setjmp.h>
|
||||||
#endif /* M68K_EMULATE_ADDRESS_ERROR */
|
#endif /* M68K_EMULATE_ADDRESS_ERROR */
|
||||||
|
|
||||||
extern unsigned int count_m68k;
|
|
||||||
|
|
||||||
/* ======================================================================== */
|
/* ======================================================================== */
|
||||||
/* ==================== ARCHITECTURE-DEPENDANT DEFINES ==================== */
|
/* ==================== ARCHITECTURE-DEPENDANT DEFINES ==================== */
|
||||||
/* ======================================================================== */
|
/* ======================================================================== */
|
||||||
@ -562,10 +560,6 @@ extern unsigned int count_m68k;
|
|||||||
if(setjmp(m68ki_aerr_trap) != 0) \
|
if(setjmp(m68ki_aerr_trap) != 0) \
|
||||||
{ \
|
{ \
|
||||||
m68ki_exception_address_error(); \
|
m68ki_exception_address_error(); \
|
||||||
if(CPU_STOPPED) \
|
|
||||||
{ \
|
|
||||||
SET_CYCLES(0); \
|
|
||||||
} \
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#define m68ki_check_address_error(ADDR, WRITE_MODE, FC) \
|
#define m68ki_check_address_error(ADDR, WRITE_MODE, FC) \
|
||||||
@ -799,12 +793,15 @@ extern unsigned int count_m68k;
|
|||||||
|
|
||||||
/* ---------------------------- Cycle Counting ---------------------------- */
|
/* ---------------------------- Cycle Counting ---------------------------- */
|
||||||
|
|
||||||
|
/*
|
||||||
#define ADD_CYCLES(A) m68ki_remaining_cycles += (A)
|
#define ADD_CYCLES(A) m68ki_remaining_cycles += (A)
|
||||||
#define USE_CYCLES(A) m68ki_remaining_cycles -= (A)
|
#define USE_CYCLES(A) m68ki_remaining_cycles -= (A)
|
||||||
#define SET_CYCLES(A) m68ki_remaining_cycles = A
|
#define SET_CYCLES(A) m68ki_remaining_cycles = A
|
||||||
#define GET_CYCLES() m68ki_remaining_cycles
|
#define GET_CYCLES() m68ki_remaining_cycles
|
||||||
#define USE_ALL_CYCLES() m68ki_remaining_cycles = 0
|
#define USE_ALL_CYCLES() m68ki_remaining_cycles = 0
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define USE_CYCLES(A) mcycles_68k += (7 * (A))
|
||||||
|
|
||||||
|
|
||||||
/* ----------------------------- Read / Write ----------------------------- */
|
/* ----------------------------- Read / Write ----------------------------- */
|
||||||
@ -917,9 +914,10 @@ typedef struct
|
|||||||
|
|
||||||
} m68ki_cpu_core;
|
} m68ki_cpu_core;
|
||||||
|
|
||||||
|
extern unsigned int mcycles_68k;
|
||||||
|
|
||||||
extern m68ki_cpu_core m68ki_cpu;
|
extern m68ki_cpu_core m68ki_cpu;
|
||||||
extern sint m68ki_remaining_cycles;
|
//extern sint m68ki_remaining_cycles;
|
||||||
extern uint m68ki_tracing;
|
extern uint m68ki_tracing;
|
||||||
extern const uint8 m68ki_shift_8_table[];
|
extern const uint8 m68ki_shift_8_table[];
|
||||||
extern const uint16 m68ki_shift_16_table[];
|
extern const uint16 m68ki_shift_16_table[];
|
||||||
@ -2042,16 +2040,10 @@ INLINE void m68ki_exception_interrupt(uint int_level)
|
|||||||
|
|
||||||
m68ki_jump(new_pc);
|
m68ki_jump(new_pc);
|
||||||
|
|
||||||
/* Defer cycle counting until later */
|
/* Update cycle count now */
|
||||||
count_m68k += CYC_EXCEPTION[vector];
|
USE_CYCLES(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 */
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* ASG: Check for interrupts */
|
/* ASG: Check for interrupts */
|
||||||
INLINE void m68ki_check_interrupts(void)
|
INLINE void m68ki_check_interrupts(void)
|
||||||
{
|
{
|
||||||
|
@ -31065,7 +31065,7 @@ static void m68k_op_stop(void)
|
|||||||
m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */
|
m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */
|
||||||
CPU_STOPPED |= STOP_LEVEL_STOP;
|
CPU_STOPPED |= STOP_LEVEL_STOP;
|
||||||
m68ki_set_sr(new_sr);
|
m68ki_set_sr(new_sr);
|
||||||
m68ki_remaining_cycles = 0;
|
//m68ki_remaining_cycles = 0;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
m68ki_exception_privilege_violation();
|
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));
|
error ("Lockup %08X = %02X (%08X)\n", address, data, m68k_get_reg (NULL, M68K_REG_PC));
|
||||||
#endif
|
#endif
|
||||||
gen_running = config.force_dtack;
|
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)
|
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));
|
error ("Lockup %08X = %04X (%08X)\n", address, data, m68k_get_reg (NULL, M68K_REG_PC));
|
||||||
#endif
|
#endif
|
||||||
gen_running = config.force_dtack;
|
gen_running = config.force_dtack;
|
||||||
if (!gen_running) m68k_end_timeslice ();
|
if (!gen_running)
|
||||||
|
m68k_pulse_halt ();
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32 m68k_lockup_r_8 (uint32 address)
|
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));
|
error ("Lockup %08X.b (%08X)\n", address, m68k_get_reg (NULL, M68K_REG_PC));
|
||||||
#endif
|
#endif
|
||||||
gen_running = config.force_dtack;
|
gen_running = config.force_dtack;
|
||||||
if (!gen_running) m68k_end_timeslice ();
|
if (!gen_running)
|
||||||
|
m68k_pulse_halt ();
|
||||||
return -1;
|
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));
|
error ("Lockup %08X.w (%08X)\n", address, m68k_get_reg (NULL, M68K_REG_PC));
|
||||||
#endif
|
#endif
|
||||||
gen_running = config.force_dtack;
|
gen_running = config.force_dtack;
|
||||||
if (!gen_running) m68k_end_timeslice ();
|
if (!gen_running)
|
||||||
|
m68k_pulse_halt ();
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -111,28 +115,32 @@ static int pico_page[7] = {0x00,0x01,0x03,0x07,0x0F,0x1F,0x3F};
|
|||||||
|
|
||||||
uint32 eeprom_read_byte(uint32 address)
|
uint32 eeprom_read_byte(uint32 address)
|
||||||
{
|
{
|
||||||
if (address == eeprom.type.sda_out_adr) return eeprom_read(address, 0);
|
if (address == eeprom.type.sda_out_adr)
|
||||||
else return READ_BYTE(cart.rom, address);
|
return eeprom_read(address, 0);
|
||||||
|
return READ_BYTE(cart.rom, address);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32 eeprom_read_word(uint32 address)
|
uint32 eeprom_read_word(uint32 address)
|
||||||
{
|
{
|
||||||
if (address == (eeprom.type.sda_out_adr & 0xfffffe)) return eeprom_read(address, 1);
|
if (address == (eeprom.type.sda_out_adr & 0xfffffe))
|
||||||
else return *(uint16 *)(cart.rom + address);
|
return eeprom_read(address, 1);
|
||||||
|
return *(uint16 *)(cart.rom + address);
|
||||||
}
|
}
|
||||||
|
|
||||||
void eeprom_write_byte(uint32 address, uint32 data)
|
void eeprom_write_byte(uint32 address, uint32 data)
|
||||||
{
|
{
|
||||||
if ((address == eeprom.type.sda_in_adr) || (address == eeprom.type.scl_adr))
|
if ((address == eeprom.type.sda_in_adr) || (address == eeprom.type.scl_adr))
|
||||||
eeprom_write(address, data, 0);
|
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)
|
void eeprom_write_word(uint32 address, uint32 data)
|
||||||
{
|
{
|
||||||
if ((address == (eeprom.type.sda_in_adr&0xfffffe)) || (address == (eeprom.type.scl_adr&0xfffffe)))
|
if ((address == (eeprom.type.sda_in_adr&0xfffffe)) || (address == (eeprom.type.scl_adr&0xfffffe)))
|
||||||
eeprom_write(address, data, 1);
|
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)
|
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)
|
switch ((address >> 13) & 3)
|
||||||
{
|
{
|
||||||
case 2: /* YM2612 */
|
case 2: /* YM2612 */
|
||||||
return fm_read(0, address & 3);
|
return fm_read(mcycles_68k, address & 3);
|
||||||
|
|
||||||
case 3: /* MISC */
|
case 3: /* MISC */
|
||||||
if ((address & 0xff00) == 0x7f00) return m68k_lockup_r_8(address); /* VDP */
|
if ((address & 0xff00) == 0x7f00)
|
||||||
else return (m68k_read_bus_8(address) | 0xff);
|
return m68k_lockup_r_8(address); /* VDP */
|
||||||
|
return (m68k_read_bus_8(address) | 0xff);
|
||||||
|
|
||||||
default: /* ZRAM */
|
default: /* ZRAM */
|
||||||
return zram[address & 0x1fff];
|
return zram[address & 0x1fff];
|
||||||
@ -158,19 +169,22 @@ uint32 z80_read_byte(uint32 address)
|
|||||||
|
|
||||||
uint32 z80_read_word(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)
|
switch ((address >> 13) & 3)
|
||||||
{
|
{
|
||||||
case 2: /* YM2612 */
|
case 2: /* YM2612 */
|
||||||
{
|
{
|
||||||
int temp = fm_read(0, address & 3);
|
int temp = fm_read(mcycles_68k, address & 3);
|
||||||
return (temp << 8 | temp);
|
return (temp << 8 | temp);
|
||||||
}
|
}
|
||||||
|
|
||||||
case 3: /* MISC */
|
case 3: /* MISC */
|
||||||
if ((address & 0xff00) == 0x7f00) return m68k_lockup_r_16(address); /* VDP */
|
if ((address & 0xff00) == 0x7f00)
|
||||||
else return (m68k_read_bus_16(address) | 0xffff);
|
return m68k_lockup_r_16(address); /* VDP */
|
||||||
|
return (m68k_read_bus_16(address) | 0xffff);
|
||||||
|
|
||||||
default: /* ZRAM */
|
default: /* ZRAM */
|
||||||
{
|
{
|
||||||
@ -182,7 +196,8 @@ uint32 z80_read_word(uint32 address)
|
|||||||
|
|
||||||
void z80_write_byte(uint32 address, uint32 data)
|
void z80_write_byte(uint32 address, uint32 data)
|
||||||
{
|
{
|
||||||
if (zbusack)
|
/* Z80 bus is available ? */
|
||||||
|
if (zstate ^ 3)
|
||||||
{
|
{
|
||||||
m68k_unused_8_w(address, data);
|
m68k_unused_8_w(address, data);
|
||||||
return;
|
return;
|
||||||
@ -191,7 +206,7 @@ void z80_write_byte(uint32 address, uint32 data)
|
|||||||
switch ((address >> 13) & 3)
|
switch ((address >> 13) & 3)
|
||||||
{
|
{
|
||||||
case 2: /* YM2612 */
|
case 2: /* YM2612 */
|
||||||
fm_write(0, address & 3, data);
|
fm_write(mcycles_68k, address & 3, data);
|
||||||
return;
|
return;
|
||||||
|
|
||||||
case 3:
|
case 3:
|
||||||
@ -212,15 +227,15 @@ void z80_write_byte(uint32 address, uint32 data)
|
|||||||
|
|
||||||
default: /* ZRAM */
|
default: /* ZRAM */
|
||||||
zram[address & 0x1fff] = data;
|
zram[address & 0x1fff] = data;
|
||||||
count_m68k++; /* Z80 bus latency (Pacman 2: New Adventures) */
|
mcycles_68k+=8; /* Z80 bus latency (Pacman 2: New Adventures) */
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void z80_write_word(uint32 address, uint32 data)
|
void z80_write_word(uint32 address, uint32 data)
|
||||||
{
|
{
|
||||||
/* Z80 still hold the bus ? */
|
/* Z80 bus is available ? */
|
||||||
if (zbusack)
|
if (zstate ^ 3)
|
||||||
{
|
{
|
||||||
m68k_unused_16_w(address, data);
|
m68k_unused_16_w(address, data);
|
||||||
return;
|
return;
|
||||||
@ -229,7 +244,7 @@ void z80_write_word(uint32 address, uint32 data)
|
|||||||
switch ((address >> 13) & 3)
|
switch ((address >> 13) & 3)
|
||||||
{
|
{
|
||||||
case 2: /* YM2612 */
|
case 2: /* YM2612 */
|
||||||
fm_write (0, address & 3, data >> 8);
|
fm_write (mcycles_68k, address & 3, data >> 8);
|
||||||
return;
|
return;
|
||||||
|
|
||||||
case 3:
|
case 3:
|
||||||
@ -262,17 +277,21 @@ uint32 ctrl_io_read_byte(uint32 address)
|
|||||||
switch ((address >> 8) & 0xff)
|
switch ((address >> 8) & 0xff)
|
||||||
{
|
{
|
||||||
case 0x00: /* I/O chip */
|
case 0x00: /* I/O chip */
|
||||||
if (address & 0xe0) return m68k_read_bus_8(address);
|
if (address & 0xe0)
|
||||||
else return (io_read((address >> 1) & 0x0f));
|
return m68k_read_bus_8(address);
|
||||||
|
return (io_read((address >> 1) & 0x0f));
|
||||||
|
|
||||||
case 0x11: /* BUSACK */
|
case 0x11: /* BUSACK */
|
||||||
if (address & 1) return m68k_read_bus_8(address);
|
if (address & 1)
|
||||||
else return ((m68k_read_pcrelative_8(REG_PC) & 0xfe) | zbusack);
|
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 */
|
case 0x30: /* TIME */
|
||||||
if (cart.hw.time_r)
|
if (cart.hw.time_r)
|
||||||
return ((address & 1) ? (cart.hw.time_r(address) & 0xff) : (cart.hw.time_r(address) >> 8));
|
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 0x10: /* MEMORY MODE */
|
||||||
case 0x12: /* RESET */
|
case 0x12: /* RESET */
|
||||||
@ -294,23 +313,28 @@ uint32 ctrl_io_read_word(uint32 address)
|
|||||||
{
|
{
|
||||||
case 0x00: /* I/O chip */
|
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);
|
int temp = io_read((address >> 1) & 0x0f);
|
||||||
return (temp << 8 | temp);
|
return (temp << 8 | temp);
|
||||||
}
|
}
|
||||||
|
|
||||||
case 0x11: /* BUSACK */
|
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 */
|
case 0x30: /* TIME */
|
||||||
if (cart.hw.time_r) return cart.hw.time_r(address);
|
if (cart.hw.time_r)
|
||||||
else return m68k_read_bus_16(address);
|
return cart.hw.time_r(address);
|
||||||
|
return m68k_read_bus_16(address);
|
||||||
|
|
||||||
case 0x50: /* SVP */
|
case 0x50: /* SVP */
|
||||||
if (svp)
|
if (svp)
|
||||||
{
|
{
|
||||||
if ((address & 0xfd) == 0) return svp->ssp1601.gr[SSP_XST].h;
|
if ((address & 0xfd) == 0)
|
||||||
else if ((address & 0xff) == 4)
|
return svp->ssp1601.gr[SSP_XST].h;
|
||||||
|
if ((address & 0xff) == 4)
|
||||||
{
|
{
|
||||||
uint32 temp = svp->ssp1601.gr[SSP_PM0].h;
|
uint32 temp = svp->ssp1601.gr[SSP_PM0].h;
|
||||||
svp->ssp1601.gr[SSP_PM0].h &= ~1;
|
svp->ssp1601.gr[SSP_PM0].h &= ~1;
|
||||||
@ -337,18 +361,24 @@ void ctrl_io_write_byte(uint32 address, uint32 data)
|
|||||||
switch ((address >> 8) & 0xff)
|
switch ((address >> 8) & 0xff)
|
||||||
{
|
{
|
||||||
case 0x00: /* I/O chip */
|
case 0x00: /* I/O chip */
|
||||||
if ((address & 0xe1) == 0x01) io_write((address >> 1) & 0x0f, data); /* get /LWR only */
|
if ((address & 0xe1) == 0x01)
|
||||||
else m68k_unused_8_w(address, data);
|
io_write((address >> 1) & 0x0f, data); /* get /LWR only */
|
||||||
|
else
|
||||||
|
m68k_unused_8_w(address, data);
|
||||||
return;
|
return;
|
||||||
|
|
||||||
case 0x11: /* BUSREQ */
|
case 0x11: /* BUSREQ */
|
||||||
if (address & 1) m68k_unused_8_w(address, data);
|
if (address & 1)
|
||||||
else gen_busreq_w(data & 1);
|
m68k_unused_8_w(address, data);
|
||||||
|
else
|
||||||
|
gen_busreq_w(data & 1);
|
||||||
return;
|
return;
|
||||||
|
|
||||||
case 0x12: /* RESET */
|
case 0x12: /* RESET */
|
||||||
if (address & 1) m68k_unused_8_w(address, data);
|
if (address & 1)
|
||||||
else gen_reset_w(data & 1);
|
m68k_unused_8_w(address, data);
|
||||||
|
else
|
||||||
|
gen_reset_w(data & 1);
|
||||||
return;
|
return;
|
||||||
|
|
||||||
case 0x30: /* TIME */
|
case 0x30: /* TIME */
|
||||||
@ -368,7 +398,10 @@ void ctrl_io_write_byte(uint32 address, uint32 data)
|
|||||||
memset(cart.rom, 0xff, cart.romsize);
|
memset(cart.rom, 0xff, cart.romsize);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else m68k_unused_8_w (address, data);
|
else
|
||||||
|
{
|
||||||
|
m68k_unused_8_w (address, data);
|
||||||
|
}
|
||||||
return;
|
return;
|
||||||
|
|
||||||
case 0x10: /* MEMORY MODE */
|
case 0x10: /* MEMORY MODE */
|
||||||
@ -390,8 +423,10 @@ void ctrl_io_write_word(uint32 address, uint32 data)
|
|||||||
switch ((address >> 8) & 0xff)
|
switch ((address >> 8) & 0xff)
|
||||||
{
|
{
|
||||||
case 0x00: /* I/O chip */
|
case 0x00: /* I/O chip */
|
||||||
if (address & 0xe0) m68k_unused_16_w (address, data);
|
if (address & 0xe0)
|
||||||
else io_write ((address >> 1) & 0x0f, data & 0xff);
|
m68k_unused_16_w (address, data);
|
||||||
|
else
|
||||||
|
io_write ((address >> 1) & 0x0f, data & 0xff);
|
||||||
return;
|
return;
|
||||||
|
|
||||||
case 0x11: /* BUSREQ */
|
case 0x11: /* BUSREQ */
|
||||||
@ -405,7 +440,10 @@ void ctrl_io_write_word(uint32 address, uint32 data)
|
|||||||
case 0x50: /* SVP REGISTERS */
|
case 0x50: /* SVP REGISTERS */
|
||||||
if (svp)
|
if (svp)
|
||||||
{
|
{
|
||||||
if (address & 0xfd) m68k_unused_16_w(address, data);
|
if (address & 0xfd)
|
||||||
|
{
|
||||||
|
m68k_unused_16_w(address, data);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* just guessing here (Notaz) */
|
/* just guessing here (Notaz) */
|
||||||
@ -414,7 +452,10 @@ void ctrl_io_write_word(uint32 address, uint32 data)
|
|||||||
svp->ssp1601.emu_status &= ~SSP_WAIT_PM0;
|
svp->ssp1601.emu_status &= ~SSP_WAIT_PM0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else m68k_unused_16_w (address, data);
|
else
|
||||||
|
{
|
||||||
|
m68k_unused_16_w (address, data);
|
||||||
|
}
|
||||||
return;
|
return;
|
||||||
|
|
||||||
case 0x30: /* TIME */
|
case 0x30: /* TIME */
|
||||||
@ -523,8 +564,10 @@ void vdp_write_byte(uint32 address, uint32 data)
|
|||||||
|
|
||||||
case 0x10: /* PSG */
|
case 0x10: /* PSG */
|
||||||
case 0x14:
|
case 0x14:
|
||||||
if (address & 1) psg_write(0, data);
|
if (address & 1)
|
||||||
else m68k_unused_8_w(address, data);
|
psg_write(mcycles_68k, data);
|
||||||
|
else
|
||||||
|
m68k_unused_8_w(address, data);
|
||||||
return;
|
return;
|
||||||
|
|
||||||
case 0x18: /* Unused */
|
case 0x18: /* Unused */
|
||||||
@ -555,7 +598,7 @@ void vdp_write_word(uint32 address, uint32 data)
|
|||||||
|
|
||||||
case 0x10: /* PSG */
|
case 0x10: /* PSG */
|
||||||
case 0x14:
|
case 0x14:
|
||||||
psg_write(0, data & 0xff);
|
psg_write(mcycles_68k, data & 0xff);
|
||||||
return;
|
return;
|
||||||
|
|
||||||
case 0x18: /* Unused */
|
case 0x18: /* Unused */
|
||||||
|
@ -65,17 +65,19 @@ uint32 zbank_read_ctrl_io(uint32 address)
|
|||||||
switch ((address >> 8) & 0xff)
|
switch ((address >> 8) & 0xff)
|
||||||
{
|
{
|
||||||
case 0x00: /* I/O chip */
|
case 0x00: /* I/O chip */
|
||||||
if (address & 0xe0) return zbank_unused_r(address);
|
if (address & 0xe0)
|
||||||
else return (io_read((address >> 1) & 0x0f));
|
return zbank_unused_r(address);
|
||||||
|
return (io_read((address >> 1) & 0x0f));
|
||||||
|
|
||||||
case 0x11: /* BUSACK */
|
case 0x11: /* BUSACK */
|
||||||
if (address & 1) return zbank_unused_r(address);
|
if (address & 1)
|
||||||
else return (0xfe | zbusack);
|
return zbank_unused_r(address);
|
||||||
|
return 0xff;
|
||||||
|
|
||||||
case 0x30: /* TIME */
|
case 0x30: /* TIME */
|
||||||
if (cart.hw.time_r)
|
if (cart.hw.time_r)
|
||||||
return ((address & 1) ? (cart.hw.time_r(address) & 0xff) : (cart.hw.time_r(address) >> 8));
|
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 0x10: /* MEMORY MODE */
|
||||||
case 0x12: /* RESET */
|
case 0x12: /* RESET */
|
||||||
@ -96,18 +98,24 @@ void zbank_write_ctrl_io(uint32 address, uint32 data)
|
|||||||
switch ((address >> 8) & 0xff)
|
switch ((address >> 8) & 0xff)
|
||||||
{
|
{
|
||||||
case 0x00: /* I/O chip */
|
case 0x00: /* I/O chip */
|
||||||
if ((address & 0xe1) == 0x01) io_write((address >> 1) & 0x0f, data); /* get /LWR only */
|
if ((address & 0xe1) == 0x01)
|
||||||
else zbank_unused_w(address, data);
|
io_write((address >> 1) & 0x0f, data); /* get /LWR only */
|
||||||
|
else
|
||||||
|
zbank_unused_w(address, data);
|
||||||
return;
|
return;
|
||||||
|
|
||||||
case 0x11: /* BUSREQ */
|
case 0x11: /* BUSREQ */
|
||||||
if (address & 1) zbank_unused_w(address, data);
|
if (address & 1)
|
||||||
else gen_busreq_w(data & 1);
|
zbank_unused_w(address, data);
|
||||||
|
else
|
||||||
|
gen_busreq_w(data & 1);
|
||||||
return;
|
return;
|
||||||
|
|
||||||
case 0x12: /* RESET */
|
case 0x12: /* RESET */
|
||||||
if (address & 1) zbank_unused_w(address, data);
|
if (address & 1)
|
||||||
else gen_reset_w(data & 1);
|
zbank_unused_w(address, data);
|
||||||
|
else
|
||||||
|
gen_reset_w(data & 1);
|
||||||
return;
|
return;
|
||||||
|
|
||||||
case 0x30: /* TIME */
|
case 0x30: /* TIME */
|
||||||
@ -127,7 +135,10 @@ void zbank_write_ctrl_io(uint32 address, uint32 data)
|
|||||||
memset(cart.rom, 0xff, cart.romsize);
|
memset(cart.rom, 0xff, cart.romsize);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else zbank_unused_w (address, data);
|
else
|
||||||
|
{
|
||||||
|
zbank_unused_w (address, data);
|
||||||
|
}
|
||||||
return;
|
return;
|
||||||
|
|
||||||
case 0x10: /* MEMORY MODE */
|
case 0x10: /* MEMORY MODE */
|
||||||
@ -195,8 +206,10 @@ void zbank_write_vdp(uint32 address, uint32 data)
|
|||||||
|
|
||||||
case 0x10: /* PSG */
|
case 0x10: /* PSG */
|
||||||
case 0x14:
|
case 0x14:
|
||||||
if (address & 1) psg_write(1, data);
|
if (address & 1)
|
||||||
else zbank_unused_w(address, data);
|
psg_write(mcycles_z80, data);
|
||||||
|
else
|
||||||
|
zbank_unused_w(address, data);
|
||||||
return;
|
return;
|
||||||
|
|
||||||
case 0x18: /* Unused */
|
case 0x18: /* Unused */
|
||||||
|
@ -109,8 +109,10 @@ static inline void z80_vdp_w(unsigned int address, unsigned int data)
|
|||||||
|
|
||||||
case 0x10: /* PSG */
|
case 0x10: /* PSG */
|
||||||
case 0x14:
|
case 0x14:
|
||||||
if (address & 1) psg_write(1, data);
|
if (address & 1)
|
||||||
else z80_unused_w(address, data);
|
psg_write(mcycles_z80, data);
|
||||||
|
else
|
||||||
|
z80_unused_w(address, data);
|
||||||
return;
|
return;
|
||||||
|
|
||||||
case 0x18: /* Unused */
|
case 0x18: /* Unused */
|
||||||
@ -139,18 +141,20 @@ unsigned int cpu_readmem16(unsigned int address)
|
|||||||
return zram[address & 0x1fff];
|
return zram[address & 0x1fff];
|
||||||
|
|
||||||
case 2: /* YM2612 */
|
case 2: /* YM2612 */
|
||||||
return fm_read(1, address & 3);
|
return fm_read(mcycles_68k, address & 3);
|
||||||
|
|
||||||
case 3: /* VDP */
|
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);
|
return z80_unused_r(address);
|
||||||
|
|
||||||
default: /* V-bus bank */
|
default: /* V-bus bank */
|
||||||
{
|
{
|
||||||
address = zbank | (address & 0x7fff);
|
address = zbank | (address & 0x7fff);
|
||||||
int slot = address >> 16;
|
int slot = address >> 16;
|
||||||
if (zbank_memory_map[slot].read) return (*zbank_memory_map[slot].read)(address);
|
if (zbank_memory_map[slot].read)
|
||||||
else return READ_BYTE(m68k_memory_map[slot].base, address&0xffff);
|
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;
|
return;
|
||||||
|
|
||||||
case 2: /* YM2612 */
|
case 2: /* YM2612 */
|
||||||
fm_write(1, address & 3, data);
|
fm_write(mcycles_z80, address & 3, data);
|
||||||
return;
|
return;
|
||||||
|
|
||||||
case 3: /* Bank register and VDP */
|
case 3: /* Bank register and VDP */
|
||||||
@ -190,8 +194,10 @@ void cpu_writemem16(unsigned int address, unsigned int data)
|
|||||||
{
|
{
|
||||||
address = zbank | (address & 0x7fff);
|
address = zbank | (address & 0x7fff);
|
||||||
int slot = address >> 16;
|
int slot = address >> 16;
|
||||||
if (zbank_memory_map[slot].write) (*zbank_memory_map[slot].write)(address, data);
|
if (zbank_memory_map[slot].write)
|
||||||
else WRITE_BYTE(m68k_memory_map[slot].base, address&0xffff, data);
|
(*zbank_memory_map[slot].write)(address, data);
|
||||||
|
else
|
||||||
|
WRITE_BYTE(m68k_memory_map[slot].base, address&0xffff, data);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -307,17 +307,20 @@ static __inline__ void WRITE_LONG(void *address, uint32 data)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**************************************************/
|
/************************************************/
|
||||||
/* Pixel creation macros */
|
/* Pixel creation macros */
|
||||||
/* Input is four bits each (R,G,B), 12 bits total */
|
/* each R,G,B color channel is 4-bits with a */
|
||||||
/* Color range depends on the S/TE mode: */
|
/* total of 15 different intensity levels. */
|
||||||
/* */
|
/* */
|
||||||
/* normal mode : xxx0 (0-14) */
|
/* Color intensity depends on the S/TE mode: */
|
||||||
/* shadow mode : 0xxx (0-7) */
|
/* */
|
||||||
/* highlight mode: 1xxx - 1 (7-14) */
|
/* normal : xxx0 (0-14) */
|
||||||
|
/* shadow : 0xxx (0-7) */
|
||||||
|
/* highlight: 1xxx - 1 (7-14) */
|
||||||
/* */
|
/* */
|
||||||
/* with xxx0 = original 4-bits CRAM value */
|
/* with xxx0 = original 4-bits CRAM value */
|
||||||
/**************************************************/
|
/* */
|
||||||
|
/************************************************/
|
||||||
#ifndef NGC
|
#ifndef NGC
|
||||||
|
|
||||||
/* 8:8:8 RGB */
|
/* 8:8:8 RGB */
|
||||||
@ -330,7 +333,8 @@ static __inline__ void WRITE_LONG(void *address, uint32 data)
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* 5:6:5 RGB */
|
/* 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 */
|
/* Clip data */
|
||||||
static clip_t clip[2];
|
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 */
|
static uint8 obj_buf[0x200]; /* Object layer line buffer */
|
||||||
|
|
||||||
/* Sprite line buffer data */
|
/* Sprite line buffer data */
|
||||||
static uint32 object_index_count;
|
uint32 object_index_count;
|
||||||
|
|
||||||
/*--------------------------------------------------------------------------*/
|
/*--------------------------------------------------------------------------*/
|
||||||
/* Look-up table functions (handles priority between layers pixels) */
|
/* 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;
|
xpos = object_info[count].xpos & 0x1ff;
|
||||||
|
|
||||||
/* sprite masking (ignore the 1st sprite) */
|
/* sprite masking (requires at least one sprite with xpos > 0) */
|
||||||
if (xpos) spr_over = 1;
|
if (xpos)
|
||||||
|
spr_over = 1;
|
||||||
else if (spr_over)
|
else if (spr_over)
|
||||||
{
|
{
|
||||||
spr_over = 0;
|
spr_over = 0;
|
||||||
@ -1517,7 +1522,7 @@ static void render_obj(uint32 line, uint8 *buf, uint8 *table)
|
|||||||
width = sizetab[(size >> 2) & 3];
|
width = sizetab[(size >> 2) & 3];
|
||||||
|
|
||||||
/* update pixel count (off-screen sprites included) */
|
/* update pixel count (off-screen sprites included) */
|
||||||
pixelcount += xpos ? width : (width * 2);
|
pixelcount += width;
|
||||||
|
|
||||||
if(((xpos + width) >= left) && (xpos < right) && !mask)
|
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;
|
xpos = object_info[count].xpos & 0x1ff;
|
||||||
|
|
||||||
/* sprite masking (ignore the 1st sprite) */
|
/* sprite masking (requires at least one sprite with xpos > 0) */
|
||||||
if (xpos) spr_over = 1;
|
if (xpos)
|
||||||
|
spr_over = 1;
|
||||||
else if(spr_over)
|
else if(spr_over)
|
||||||
{
|
{
|
||||||
spr_over = 0;
|
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];
|
width = sizetab[(size >> 2) & 3];
|
||||||
|
|
||||||
/* update pixel count (off-screen sprites included) */
|
/* update pixel count (off-screen sprites included) */
|
||||||
pixelcount += xpos ? width : (width * 2);
|
pixelcount += width;
|
||||||
|
|
||||||
if(((xpos + width) >= left) && (xpos < right) && !mask)
|
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 */
|
/* number of tiles to draw */
|
||||||
/* adjusted for sprite limit */
|
/* 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;
|
width >>= 3;
|
||||||
|
|
||||||
for(column = 0; column < width; column += 1, lb+=8)
|
for(column = 0; column < width; column += 1, lb+=8)
|
||||||
{
|
{
|
||||||
index = (name + s[column]) & 0x3ff;
|
index = (name + s[column]) & 0x3ff;
|
||||||
offs = index << 7 | attr_mask << 6 | v_line;
|
offs = index << 7 | attr_mask << 6 | v_line;
|
||||||
if(attr & 0x1000) offs ^= 0x40;
|
if(attr & 0x1000)
|
||||||
|
offs ^= 0x40;
|
||||||
src = &bg_pattern_cache[offs];
|
src = &bg_pattern_cache[offs];
|
||||||
DRAW_SPRITE_TILE;
|
DRAW_SPRITE_TILE;
|
||||||
}
|
}
|
||||||
@ -1662,9 +1670,11 @@ void render_init(void)
|
|||||||
int bx, ax, i;
|
int bx, ax, i;
|
||||||
|
|
||||||
/* Allocate and align pixel look-up tables */
|
/* 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));
|
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 */
|
/* Make pixel look-up table data */
|
||||||
for (bx = 0; bx < 0x100; bx += 1)
|
for (bx = 0; bx < 0x100; bx += 1)
|
||||||
@ -1722,7 +1732,8 @@ void render_reset(void)
|
|||||||
|
|
||||||
void render_shutdown(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;
|
uint32 x_offset = bitmap.viewport.x;
|
||||||
|
|
||||||
/* display OFF */
|
/* display OFF */
|
||||||
if (reg[0] & 0x01) return;
|
if (reg[0] & 0x01)
|
||||||
|
return;
|
||||||
|
|
||||||
/* background color (blanked display or vertical borders) */
|
/* background color (blanked display or vertical borders) */
|
||||||
if (!(reg[1] & 0x40) || overscan)
|
if (!(reg[1] & 0x40) || overscan)
|
||||||
@ -1761,28 +1773,32 @@ void render_line(uint32 line, uint32 overscan)
|
|||||||
uint32 odd = odd_frame;
|
uint32 odd = odd_frame;
|
||||||
|
|
||||||
/* render BG layers */
|
/* render BG layers */
|
||||||
if(reg[11] & 4) render_bg_im2_vs(line, width, odd);
|
if(reg[11] & 4)
|
||||||
else render_bg_im2(line, width, odd);
|
render_bg_im2_vs(line, width, odd);
|
||||||
|
else
|
||||||
|
render_bg_im2(line, width, odd);
|
||||||
|
|
||||||
if (reg[12] & 8)
|
if (reg[12] & 8)
|
||||||
{
|
{
|
||||||
/* Shadow & Highlight */
|
/* Shadow & Highlight */
|
||||||
merge(&nta_buf[0x20], &ntb_buf[0x20], &bg_buf[0x20], lut[2], width);
|
merge(&nta_buf[0x20], &ntb_buf[0x20], &bg_buf[0x20], lut[2], width);
|
||||||
memset(&obj_buf[0x20], 0, 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);
|
merge(&obj_buf[0x20], &bg_buf[0x20], &lb[0x20], lut[4], width);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
merge(&nta_buf[0x20], &ntb_buf[0x20], &lb[0x20], lut[0], width);
|
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
|
else
|
||||||
{
|
{
|
||||||
/* render BG layers */
|
/* render BG layers */
|
||||||
if(reg[11] & 4) render_bg_vs(line, width);
|
if(reg[11] & 4)
|
||||||
else render_bg(line, width);
|
render_bg_vs(line, width);
|
||||||
|
else
|
||||||
|
render_bg(line, width);
|
||||||
|
|
||||||
if(reg[12] & 8)
|
if(reg[12] & 8)
|
||||||
{
|
{
|
||||||
@ -1818,13 +1834,16 @@ void remap_buffer(uint32 line, uint32 width)
|
|||||||
line = (line + bitmap.viewport.y) % lines_per_frame;
|
line = (line + bitmap.viewport.y) % lines_per_frame;
|
||||||
|
|
||||||
/* double resolution mode */
|
/* double resolution mode */
|
||||||
if (config.render && interlaced) line = (line * 2) + odd_frame;
|
if (config.render && interlaced)
|
||||||
|
line = (line * 2) + odd_frame;
|
||||||
|
|
||||||
/* NTSC Filter */
|
/* NTSC Filter */
|
||||||
if (config.ntsc)
|
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);
|
if (reg[12]&1)
|
||||||
else sms_ntsc_blit(&sms_ntsc, ( SMS_NTSC_IN_T const * )pixel_16, tmp_buf+0x20-bitmap.viewport.x, width, line);
|
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;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1928,7 +1947,8 @@ void parse_satb(uint32 line)
|
|||||||
/* sprite limit (max. 16 or 20 sprites displayed per line) */
|
/* sprite limit (max. 16 or 20 sprites displayed per line) */
|
||||||
if(object_index_count == limit)
|
if(object_index_count == limit)
|
||||||
{
|
{
|
||||||
if(vint_pending == 0) status |= 0x40;
|
if(vint_pending == 0)
|
||||||
|
status |= 0x40;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -24,6 +24,9 @@
|
|||||||
#ifndef _RENDER_H_
|
#ifndef _RENDER_H_
|
||||||
#define _RENDER_H_
|
#define _RENDER_H_
|
||||||
|
|
||||||
|
/* Global variables */
|
||||||
|
extern uint32 object_index_count;
|
||||||
|
|
||||||
/* Function prototypes */
|
/* Function prototypes */
|
||||||
extern void render_init(void);
|
extern void render_init(void);
|
||||||
extern void render_reset(void);
|
extern void render_reset(void);
|
||||||
|
@ -104,7 +104,7 @@ void Fir_Resampler_clear()
|
|||||||
if ( buffer_size )
|
if ( buffer_size )
|
||||||
{
|
{
|
||||||
write_pos = &buffer [WRITE_OFFSET];
|
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;
|
pos = 0.0;
|
||||||
input_per_cycle = 0;
|
input_per_cycle = 0;
|
||||||
|
|
||||||
|
memset(impulses, 0, MAX_RES*WIDTH*sizeof(sample_t));
|
||||||
|
|
||||||
for ( i = 0; i < res; i++ )
|
for ( i = 0; i < res; i++ )
|
||||||
{
|
{
|
||||||
gen_sinc( ROLLOFF, (int) (WIDTH * filter + 1) & ~1, pos, filter,
|
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 ) );
|
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_ = out;
|
||||||
sample_t* out_r = out[1];
|
|
||||||
sample_t* in = buffer;
|
sample_t* in = buffer;
|
||||||
sample_t* end_pos = write_pos;
|
sample_t* end_pos = write_pos;
|
||||||
unsigned long skip = skip_bits >> imp_phase;
|
unsigned long skip = skip_bits >> imp_phase;
|
||||||
@ -258,8 +259,8 @@ int Fir_Resampler_read( sample_t** out, long count )
|
|||||||
remain = res;
|
remain = res;
|
||||||
}
|
}
|
||||||
|
|
||||||
*out_l++ = (sample_t) l;
|
*out++ = (sample_t) l;
|
||||||
*out_r++ = (sample_t) r;
|
*out++ = (sample_t) r;
|
||||||
}
|
}
|
||||||
while ( in <= end_pos );
|
while ( in <= end_pos );
|
||||||
}
|
}
|
||||||
@ -270,7 +271,7 @@ int Fir_Resampler_read( sample_t** out, long count )
|
|||||||
write_pos = &buffer [left];
|
write_pos = &buffer [left];
|
||||||
memmove( buffer, in, left * sizeof *in );
|
memmove( buffer, in, left * sizeof *in );
|
||||||
|
|
||||||
return out_l - out[0];
|
return out - out_;
|
||||||
}
|
}
|
||||||
|
|
||||||
int Fir_Resampler_input_needed( long output_count )
|
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_written( void );
|
||||||
extern int Fir_Resampler_avail( void );
|
extern int Fir_Resampler_avail( void );
|
||||||
extern void Fir_Resampler_write( long count );
|
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_input_needed( long output_count );
|
||||||
extern int Fir_Resampler_skip_input( long count );
|
extern int Fir_Resampler_skip_input( long count );
|
||||||
|
|
||||||
|
@ -109,10 +109,10 @@ static const int PSGVolumeValues[2][16] = {
|
|||||||
|
|
||||||
static SN76489_Context SN76489;
|
static SN76489_Context SN76489;
|
||||||
|
|
||||||
void SN76489_Init(int PSGClockValue, int SamplingRate)
|
void SN76489_Init(float PSGClockValue, int SamplingRate)
|
||||||
{
|
{
|
||||||
SN76489_Context *p = &SN76489;
|
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_Config(MUTE_ALLON, VOL_FULL, FB_SEGAVDP, SRW_SEGAVDP, config.psgBoostNoise);
|
||||||
SN76489_Reset();
|
SN76489_Reset();
|
||||||
}
|
}
|
||||||
|
@ -16,7 +16,7 @@
|
|||||||
#define _SN76489_H_
|
#define _SN76489_H_
|
||||||
|
|
||||||
/* Function prototypes */
|
/* 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_Reset(void);
|
||||||
extern void SN76489_Shutdown(void);
|
extern void SN76489_Shutdown(void);
|
||||||
extern void SN76489_SetContext(uint8 *data);
|
extern void SN76489_SetContext(uint8 *data);
|
||||||
|
@ -24,105 +24,229 @@
|
|||||||
#include "shared.h"
|
#include "shared.h"
|
||||||
#include "Fir_Resampler.h"
|
#include "Fir_Resampler.h"
|
||||||
|
|
||||||
/* cycle-accurate samples */
|
/* Cycle-accurate samples */
|
||||||
static int m68cycles_per_sample[2];
|
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 */
|
/* Run FM chip for required M-cycles */
|
||||||
static inline int fm_sample_cnt(uint8 z80)
|
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);
|
/* convert to 21.11 fixed point */
|
||||||
else return ((count_m68k / m68cycles_per_sample[0]) - snd.fm.pos);
|
cycles <<= 11;
|
||||||
}
|
|
||||||
|
|
||||||
static inline int psg_sample_cnt(uint8 z80)
|
if (cycles > fm_cycles_count)
|
||||||
{
|
|
||||||
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)
|
|
||||||
{
|
{
|
||||||
YM2612Update(cnt);
|
/* period to run */
|
||||||
snd.fm.pos += cnt;
|
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 */
|
/* Run PSG chip for required M-cycles */
|
||||||
static inline void psg_update(int cnt)
|
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;
|
snd.psg.pos += cnt;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* initialize sound chips emulation */
|
/* Initialize sound chips emulation */
|
||||||
void sound_init(int rate, double fps)
|
void sound_init(void)
|
||||||
{
|
{
|
||||||
double vclk = (vdp_pal ? (double)CLOCK_PAL : (double)CLOCK_NTSC) / 7.0; /* 68000 and YM2612 clock */
|
/* Number of M-cycles executed per second. */
|
||||||
double zclk = (vdp_pal ? (double)CLOCK_PAL : (double)CLOCK_NTSC) / 15.0; /* Z80 and SN76489 clock */
|
/* */
|
||||||
|
/* 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 */
|
/* For better accuracy, sound chips run in synchronization with 68k and Z80 cpus */
|
||||||
m68cycles_per_sample[0] = (int)(((double)m68cycles_per_line * (double)lines_per_frame * fps/ (double)rate) + 0.5);
|
/* These values give the exact number of M-cycles between 2 rendered samples. */
|
||||||
m68cycles_per_sample[1] = m68cycles_per_sample[0];
|
/* 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)
|
if (config.hq_fm)
|
||||||
{
|
{
|
||||||
/* "real" ratio is (vclk/144.0)/(rate) but since we need perfect synchronization between video & audio
|
fm_cycles_ratio = 144 * 7 * (1 << 11);
|
||||||
on the target system, we are not exactly running at the real genesis framerate but the target
|
Fir_Resampler_time_ratio(mclk / (double)snd.sample_rate / (144.0 * 7.0));
|
||||||
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;
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* initialize sound chips */
|
#ifdef LOG_SOUND
|
||||||
SN76489_Init((int)zclk,rate);
|
error("%d mcycles per PSG samples\n", psg_cycles_ratio);
|
||||||
YM2612Init((int)vclk,rate);
|
error("%d mcycles per FM samples\n", fm_cycles_ratio);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void sound_update(int fm_len, int psg_len)
|
/* Reset sound chips emulation */
|
||||||
|
void sound_reset(void)
|
||||||
{
|
{
|
||||||
/* update last samples (if needed) */
|
YM2612ResetChip();
|
||||||
fm_update(fm_len - snd.fm.pos);
|
SN76489_Reset();
|
||||||
psg_update(psg_len - snd.psg.pos);
|
fm_cycles_count = 0;
|
||||||
|
psg_cycles_count = 0;
|
||||||
/* reset samples count */
|
|
||||||
snd.fm.pos = 0;
|
|
||||||
snd.psg.pos = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* reset FM chip */
|
/* 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)
|
void fm_reset(void)
|
||||||
{
|
{
|
||||||
fm_update(fm_sample_cnt(0));
|
fm_update(mcycles_68k);
|
||||||
YM2612ResetChip();
|
YM2612ResetChip();
|
||||||
}
|
}
|
||||||
|
|
||||||
/* write FM chip */
|
/* Write FM chip */
|
||||||
void fm_write(unsigned int cpu, unsigned int address, unsigned int data)
|
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);
|
YM2612Write(address, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* read FM status */
|
/* Read FM status */
|
||||||
unsigned int fm_read(unsigned int cpu, unsigned int address)
|
unsigned int fm_read(unsigned int cycles, unsigned int address)
|
||||||
{
|
{
|
||||||
fm_update(fm_sample_cnt(cpu));
|
fm_update(cycles);
|
||||||
return YM2612Read();
|
return YM2612Read();
|
||||||
}
|
}
|
||||||
|
|
||||||
/* write PSG chip */
|
/* Write PSG chip */
|
||||||
void psg_write(unsigned int cpu, unsigned int data)
|
void psg_write(unsigned int cycles, unsigned int data)
|
||||||
{
|
{
|
||||||
psg_update(psg_sample_cnt(cpu));
|
psg_update(cycles);
|
||||||
SN76489_Write(data);
|
SN76489_Write(data);
|
||||||
}
|
}
|
||||||
|
@ -25,11 +25,12 @@
|
|||||||
#define _SOUND_H_
|
#define _SOUND_H_
|
||||||
|
|
||||||
/* Function prototypes */
|
/* Function prototypes */
|
||||||
extern void sound_init(int rate, double fps);
|
extern void sound_init(void);
|
||||||
extern void sound_update(int fm_len, int psg_len);
|
extern void sound_reset(void);
|
||||||
|
extern int sound_update(unsigned int cycles);
|
||||||
extern void fm_reset(void);
|
extern void fm_reset(void);
|
||||||
extern void fm_write(unsigned int cpu, unsigned int address, unsigned int data);
|
extern void fm_write(unsigned int cycles, unsigned int address, unsigned int data);
|
||||||
extern unsigned int fm_read(unsigned int cpu, unsigned int address);
|
extern unsigned int fm_read(unsigned int cycles, unsigned int address);
|
||||||
extern void psg_write(unsigned int cpu, unsigned int data);
|
extern void psg_write(unsigned int cycles, unsigned int data);
|
||||||
|
|
||||||
#endif /* _SOUND_H_ */
|
#endif /* _SOUND_H_ */
|
||||||
|
@ -554,7 +554,7 @@ typedef struct
|
|||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
UINT32 clock; /* master clock (Hz) */
|
float clock; /* master clock (Hz) */
|
||||||
UINT32 rate; /* sampling rate (Hz) */
|
UINT32 rate; /* sampling rate (Hz) */
|
||||||
UINT16 address; /* address register */
|
UINT16 address; /* address register */
|
||||||
UINT8 status; /* status flag */
|
UINT8 status; /* status flag */
|
||||||
@ -1775,7 +1775,7 @@ static void init_timetables(double freqbase)
|
|||||||
static void OPNSetPres(int pres)
|
static void OPNSetPres(int pres)
|
||||||
{
|
{
|
||||||
/* frequency base (ratio between FM original samplerate & desired output samplerate)*/
|
/* 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) */
|
/* YM2612 running at original frequency (~53267 Hz) */
|
||||||
if (config.hq_fm) freqbase = 1.0;
|
if (config.hq_fm) freqbase = 1.0;
|
||||||
@ -1913,7 +1913,7 @@ static void init_tables(void)
|
|||||||
|
|
||||||
|
|
||||||
/* initialize ym2612 emulator(s) */
|
/* initialize ym2612 emulator(s) */
|
||||||
int YM2612Init(int clock, int rate)
|
int YM2612Init(float clock, int rate)
|
||||||
{
|
{
|
||||||
memset(&ym2612,0,sizeof(YM2612));
|
memset(&ym2612,0,sizeof(YM2612));
|
||||||
init_tables();
|
init_tables();
|
||||||
@ -2017,24 +2017,10 @@ unsigned int YM2612Read(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Generate 16 bits samples for ym2612 */
|
/* Generate 16 bits samples for ym2612 */
|
||||||
void YM2612Update(int length)
|
void YM2612Update(short int *buffer, int length)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
int lt,rt;
|
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 PG increments and EG rates if required */
|
||||||
refresh_fc_eg_chan(&ym2612.CH[0]);
|
refresh_fc_eg_chan(&ym2612.CH[0]);
|
||||||
@ -2139,16 +2125,8 @@ void YM2612Update(int length)
|
|||||||
// Limit(rt,MAXOUT,MINOUT);
|
// Limit(rt,MAXOUT,MINOUT);
|
||||||
|
|
||||||
/* buffering */
|
/* buffering */
|
||||||
if (bufFIR)
|
*buffer++ = lt;
|
||||||
{
|
*buffer++ = rt;
|
||||||
*bufFIR++ = lt;
|
|
||||||
*bufFIR++ = rt;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
*bufL++ = lt;
|
|
||||||
*bufR++ = rt;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* CSM mode: if CSM Key ON has occured, CSM Key OFF need to be sent */
|
/* 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) */
|
/* 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)
|
void YM2612Restore(unsigned char *buffer)
|
||||||
{
|
{
|
||||||
/* save current timings */
|
/* save current timings */
|
||||||
int clock = ym2612.OPN.ST.clock;
|
float clock = ym2612.OPN.ST.clock;
|
||||||
int rate = ym2612.OPN.ST.rate;
|
int rate = ym2612.OPN.ST.rate;
|
||||||
|
|
||||||
/* restore internal state */
|
/* restore internal state */
|
||||||
|
@ -19,9 +19,9 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
extern int YM2612Init(int baseclock, int rate);
|
extern int YM2612Init(float clock, int rate);
|
||||||
extern int YM2612ResetChip(void);
|
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 void YM2612Write(unsigned int a, unsigned int v);
|
||||||
extern unsigned int YM2612Read(void);
|
extern unsigned int YM2612Read(void);
|
||||||
extern unsigned char *YM2612GetContextPtr(void);
|
extern unsigned char *YM2612GetContextPtr(void);
|
||||||
|
@ -59,10 +59,8 @@ int state_load(unsigned char *buffer)
|
|||||||
// GENESIS
|
// GENESIS
|
||||||
load_param(work_ram, sizeof(work_ram));
|
load_param(work_ram, sizeof(work_ram));
|
||||||
load_param(zram, sizeof(zram));
|
load_param(zram, sizeof(zram));
|
||||||
load_param(&zbusreq, sizeof(zbusreq));
|
load_param(&zstate, sizeof(zstate));
|
||||||
load_param(&zreset, sizeof(zreset));
|
|
||||||
load_param(&zbank, sizeof(zbank));
|
load_param(&zbank, sizeof(zbank));
|
||||||
zbusack = 1 ^(zbusreq & zreset);
|
|
||||||
|
|
||||||
// IO
|
// IO
|
||||||
load_param(io_reg, sizeof(io_reg));
|
load_param(io_reg, sizeof(io_reg));
|
||||||
@ -134,8 +132,7 @@ int state_save(unsigned char *buffer)
|
|||||||
// GENESIS
|
// GENESIS
|
||||||
save_param(work_ram, sizeof(work_ram));
|
save_param(work_ram, sizeof(work_ram));
|
||||||
save_param(zram, sizeof(zram));
|
save_param(zram, sizeof(zram));
|
||||||
save_param(&zbusreq, sizeof(zbusreq));
|
save_param(&zstate, sizeof(zstate));
|
||||||
save_param(&zreset, sizeof(zreset));
|
|
||||||
save_param(&zbank, sizeof(zbank));
|
save_param(&zbank, sizeof(zbank));
|
||||||
|
|
||||||
// IO
|
// IO
|
||||||
|
273
source/system.c
273
source/system.c
@ -30,12 +30,10 @@
|
|||||||
/* Global variables */
|
/* Global variables */
|
||||||
t_bitmap bitmap;
|
t_bitmap bitmap;
|
||||||
t_snd snd;
|
t_snd snd;
|
||||||
uint32 count_m68k;
|
uint32 mcycles_vdp;
|
||||||
uint32 line_m68k;
|
uint32 mcycles_z80;
|
||||||
uint32 hint_m68k;
|
uint32 mcycles_68k;
|
||||||
uint32 count_z80;
|
uint32 hint_68k;
|
||||||
uint32 line_z80;
|
|
||||||
int32 current_z80;
|
|
||||||
uint8 system_hw;
|
uint8 system_hw;
|
||||||
|
|
||||||
/****************************************************************
|
/****************************************************************
|
||||||
@ -56,7 +54,7 @@ void audio_set_equalizer(void)
|
|||||||
****************************************************************/
|
****************************************************************/
|
||||||
static int llp,rrp;
|
static int llp,rrp;
|
||||||
|
|
||||||
void audio_update (int size)
|
int audio_update (void)
|
||||||
{
|
{
|
||||||
int i, l, r;
|
int i, l, r;
|
||||||
int ll = llp;
|
int ll = llp;
|
||||||
@ -68,26 +66,45 @@ void audio_update (int size)
|
|||||||
uint32 factora = (config.lp_range << 16) / 100;
|
uint32 factora = (config.lp_range << 16) / 100;
|
||||||
uint32 factorb = 0x10000 - factora;
|
uint32 factorb = 0x10000 - factora;
|
||||||
|
|
||||||
int16 *fm[2] = {snd.fm.buffer[0],snd.fm.buffer[1]};
|
int16 *fm = snd.fm.buffer;
|
||||||
int16 *psg = snd.psg.buffer;
|
int16 *psg = snd.psg.buffer;
|
||||||
|
|
||||||
#ifdef NGC
|
#ifdef NGC
|
||||||
int16 *sb = (int16 *) soundbuffer[mixbuffer];
|
int16 *sb = (int16 *) soundbuffer[mixbuffer];
|
||||||
#endif
|
#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)
|
if (config.hq_fm)
|
||||||
{
|
{
|
||||||
int len = Fir_Resampler_input_needed(size << 1);
|
/* resample into FM output buffer */
|
||||||
sound_update(len >> 1,size);
|
|
||||||
Fir_Resampler_write(len);
|
|
||||||
Fir_Resampler_read(fm,size);
|
Fir_Resampler_read(fm,size);
|
||||||
|
|
||||||
|
#ifdef LOG_SOUND
|
||||||
|
error("%d FM samples remaining\n",Fir_Resampler_written() >> 1);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
else
|
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 */
|
/* mix samples */
|
||||||
for (i = 0; i < size; i ++)
|
for (i = 0; i < size; i ++)
|
||||||
{
|
{
|
||||||
@ -95,8 +112,8 @@ void audio_update (int size)
|
|||||||
l = r = ((*psg++) * psg_preamp)/100;
|
l = r = ((*psg++) * psg_preamp)/100;
|
||||||
|
|
||||||
/* FM samples (stereo) */
|
/* FM samples (stereo) */
|
||||||
l += (*fm[0]++ * fm_preamp)/100;
|
l += (*fm++ * fm_preamp)/100;
|
||||||
r += (*fm[1]++ * fm_preamp)/100;
|
r += (*fm++ * fm_preamp)/100;
|
||||||
|
|
||||||
/* filtering */
|
/* filtering */
|
||||||
if (filter & 1)
|
if (filter & 1)
|
||||||
@ -130,15 +147,25 @@ void audio_update (int size)
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
/* save delayed samples */
|
/* save delayed samples for next frame */
|
||||||
llp = ll;
|
llp = ll;
|
||||||
rrp = rr;
|
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
|
* AUDIO System initialization
|
||||||
****************************************************************/
|
****************************************************************/
|
||||||
int audio_init (int rate, double fps)
|
int audio_init (int samplerate, float framerate)
|
||||||
{
|
{
|
||||||
/* Shutdown first */
|
/* Shutdown first */
|
||||||
audio_shutdown();
|
audio_shutdown();
|
||||||
@ -146,61 +173,91 @@ int audio_init (int rate, double fps)
|
|||||||
/* Clear the sound data context */
|
/* Clear the sound data context */
|
||||||
memset(&snd, 0, sizeof (snd));
|
memset(&snd, 0, sizeof (snd));
|
||||||
|
|
||||||
/* Make sure the requested sample rate is valid */
|
/* Default settings */
|
||||||
if (!rate || ((rate < 8000) | (rate > 48000))) return (-1);
|
snd.sample_rate = samplerate;
|
||||||
snd.sample_rate = rate;
|
snd.frame_rate = framerate;
|
||||||
|
|
||||||
|
/* Calculate the sound buffer size (for one frame) */
|
||||||
|
snd.buffer_size = (int)(samplerate / framerate) + 32;
|
||||||
|
|
||||||
#ifndef NGC
|
#ifndef NGC
|
||||||
/* Calculate the sound buffer size (for one frame) */
|
|
||||||
snd.buffer_size = (rate / vdp_rate);
|
|
||||||
|
|
||||||
/* Output buffers */
|
/* Output buffers */
|
||||||
snd.buffer[0] = (int16 *) malloc(SND_SIZE);
|
snd.buffer[0] = (int16 *) malloc(SND_SIZE);
|
||||||
snd.buffer[1] = (int16 *) malloc(SND_SIZE);
|
snd.buffer[1] = (int16 *) malloc(SND_SIZE);
|
||||||
if (!snd.buffer[0] || !snd.buffer[1]) return (-1);
|
if (!snd.buffer[0] || !snd.buffer[1])
|
||||||
#else
|
return (-1);
|
||||||
/* Calculate the sound buffer size (for one frame) */
|
|
||||||
snd.buffer_size = (rate / vdp_rate) + 32;
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* SN76489 stream buffers */
|
/* SN76489 stream buffers */
|
||||||
snd.psg.buffer = (int16 *)malloc (SND_SIZE);
|
snd.psg.buffer = (int16 *) malloc(SND_SIZE);
|
||||||
if (!snd.psg.buffer) return (-1);
|
if (!snd.psg.buffer)
|
||||||
|
return (-1);
|
||||||
|
|
||||||
/* YM2612 stream buffers */
|
/* YM2612 stream buffers */
|
||||||
snd.fm.buffer[0] = (int16 *)malloc (SND_SIZE);
|
snd.fm.buffer = (int16 *) malloc(SND_SIZE * 2);
|
||||||
snd.fm.buffer[1] = (int16 *)malloc (SND_SIZE);
|
if (!snd.fm.buffer)
|
||||||
if (!snd.fm.buffer[0] || !snd.fm.buffer[1]) return (-1);
|
return (-1);
|
||||||
|
|
||||||
/* Resampling buffer */
|
/* Resampling buffer */
|
||||||
if (config.hq_fm)
|
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 */
|
/* Set audio enable flag */
|
||||||
snd.enabled = 1;
|
snd.enabled = 1;
|
||||||
|
|
||||||
/* Initialize Sound Chips emulation */
|
/* Reset audio */
|
||||||
sound_init(rate,fps);
|
audio_reset();
|
||||||
|
|
||||||
return (0);
|
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
|
* AUDIO System shutdown
|
||||||
****************************************************************/
|
****************************************************************/
|
||||||
void audio_shutdown(void)
|
void audio_shutdown(void)
|
||||||
{
|
{
|
||||||
/* Sound buffers */
|
/* Sound buffers */
|
||||||
if (snd.buffer[0]) free(snd.buffer[0]);
|
#ifndef NGC
|
||||||
if (snd.buffer[1]) free(snd.buffer[1]);
|
if (snd.buffer[0])
|
||||||
if (snd.fm.buffer[0]) free(snd.fm.buffer[0]);
|
free(snd.buffer[0]);
|
||||||
if (snd.fm.buffer[1]) free(snd.fm.buffer[1]);
|
if (snd.buffer[1])
|
||||||
if (snd.psg.buffer) free(snd.psg.buffer);
|
free(snd.buffer[1]);
|
||||||
|
#endif
|
||||||
|
if (snd.fm.buffer)
|
||||||
|
free(snd.fm.buffer);
|
||||||
|
if (snd.psg.buffer)
|
||||||
|
free(snd.psg.buffer);
|
||||||
|
|
||||||
/* Resampling buffer */
|
/* Resampling buffer */
|
||||||
Fir_Resampler_shutdown();
|
Fir_Resampler_shutdown();
|
||||||
@ -219,6 +276,9 @@ void system_init (void)
|
|||||||
|
|
||||||
/* Cartridge hardware */
|
/* Cartridge hardware */
|
||||||
cart_hw_init();
|
cart_hw_init();
|
||||||
|
|
||||||
|
/* Sound Chips hardware */
|
||||||
|
sound_init();
|
||||||
}
|
}
|
||||||
|
|
||||||
/****************************************************************
|
/****************************************************************
|
||||||
@ -231,17 +291,15 @@ void system_reset (void)
|
|||||||
|
|
||||||
/* Genesis hardware */
|
/* Genesis hardware */
|
||||||
gen_reset(1);
|
gen_reset(1);
|
||||||
SN76489_Reset();
|
|
||||||
io_reset();
|
io_reset();
|
||||||
vdp_reset();
|
vdp_reset();
|
||||||
render_reset();
|
render_reset();
|
||||||
|
|
||||||
/* Clear Sound Buffers */
|
/* Sound chips */
|
||||||
if (snd.psg.buffer) memset (snd.psg.buffer, 0, SND_SIZE);
|
sound_reset();
|
||||||
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);
|
/* Audio System */
|
||||||
Fir_Resampler_clear();
|
audio_reset();
|
||||||
llp = rrp = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/****************************************************************
|
/****************************************************************
|
||||||
@ -265,15 +323,6 @@ int system_frame (int do_skip)
|
|||||||
return 0;
|
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 */
|
/* update display settings */
|
||||||
int line;
|
int line;
|
||||||
int reset = resetline;
|
int reset = resetline;
|
||||||
@ -291,17 +340,21 @@ int system_frame (int do_skip)
|
|||||||
odd_frame ^= 1;
|
odd_frame ^= 1;
|
||||||
|
|
||||||
/* clear VBLANK and DMA flags */
|
/* clear VBLANK and DMA flags */
|
||||||
status &= 0xFFF5;
|
status &= 0xFFE5;
|
||||||
|
|
||||||
/* even/odd field flag (interlaced modes only) */
|
/* even/odd field flag (interlaced modes only) */
|
||||||
if (odd_frame && interlaced) status |= 0x0010;
|
if (odd_frame && interlaced)
|
||||||
else status &= 0xFFEF;
|
status |= 0x0010;
|
||||||
|
|
||||||
/* reload HCounter */
|
/* reload HCounter */
|
||||||
int h_counter = reg[10];
|
int h_counter = reg[10];
|
||||||
|
|
||||||
/* parse sprites for line 0 (done on last line) */
|
/* reset VDP FIFO */
|
||||||
parse_satb (0x80);
|
fifo_write_cnt = 0;
|
||||||
|
fifo_lastwrite = 0;
|
||||||
|
|
||||||
|
/* reset line cycle count */
|
||||||
|
mcycles_vdp = 0;
|
||||||
|
|
||||||
/* process scanlines */
|
/* process scanlines */
|
||||||
for (line = 0; line < lines_per_frame; line ++)
|
for (line = 0; line < lines_per_frame; line ++)
|
||||||
@ -312,14 +365,10 @@ int system_frame (int do_skip)
|
|||||||
/* update 6-Buttons or Menacer */
|
/* update 6-Buttons or Menacer */
|
||||||
input_update();
|
input_update();
|
||||||
|
|
||||||
/* update CPU cycle counters */
|
/* 68k line cycle count */
|
||||||
hint_m68k = count_m68k;
|
hint_68k = mcycles_68k;
|
||||||
line_m68k = aim_m68k;
|
|
||||||
line_z80 = aim_z80;
|
|
||||||
aim_z80 += z80cycles_per_line;
|
|
||||||
aim_m68k += m68cycles_per_line;
|
|
||||||
|
|
||||||
/* Soft Reset ? */
|
/* Soft Reset line */
|
||||||
if (line == reset)
|
if (line == reset)
|
||||||
{
|
{
|
||||||
/* Pro Action Replay (switch at "Trainer" position) */
|
/* Pro Action Replay (switch at "Trainer" position) */
|
||||||
@ -329,6 +378,10 @@ int system_frame (int do_skip)
|
|||||||
gen_reset(0);
|
gen_reset(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* update VDP DMA */
|
||||||
|
if (dma_length)
|
||||||
|
vdp_update_dma();
|
||||||
|
|
||||||
/* active display */
|
/* active display */
|
||||||
if (line <= vdp_height)
|
if (line <= vdp_height)
|
||||||
{
|
{
|
||||||
@ -337,27 +390,16 @@ int system_frame (int do_skip)
|
|||||||
{
|
{
|
||||||
h_counter = reg[10];
|
h_counter = reg[10];
|
||||||
hint_pending = 1;
|
hint_pending = 1;
|
||||||
if (reg[0] & 0x10) irq_status = (irq_status & ~0x40) | 0x14;
|
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 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 */
|
/* vertical retrace */
|
||||||
if (line == vdp_height)
|
if (line == vdp_height)
|
||||||
{
|
{
|
||||||
/* render overscan */
|
/* 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) */
|
/* update inputs (doing this here fix Warriors of Eternal Sun) */
|
||||||
osd_input_Update();
|
osd_input_Update();
|
||||||
@ -369,37 +411,36 @@ int system_frame (int do_skip)
|
|||||||
zirq = 1;
|
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) */
|
/* delay between VINT flag & V Interrupt (Ex-Mutants, Tyrant) */
|
||||||
m68k_run(line_m68k + 84);
|
m68k_run(mcycles_vdp + 588);
|
||||||
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 */
|
|
||||||
status |= 0x80;
|
status |= 0x80;
|
||||||
|
|
||||||
/* 36 cycles latency after VINT occurence flag (Ex-Mutants, Tyrant) */
|
/* delay between VBLANK flag & V Interrupt (Dracula, OutRunners, VR Troopers) */
|
||||||
m68k_run(line_m68k + 113);
|
m68k_run(mcycles_vdp + 788);
|
||||||
|
if (zstate == 1)
|
||||||
|
z80_run(mcycles_vdp + 788);
|
||||||
|
else
|
||||||
|
mcycles_z80 = mcycles_vdp + 788;
|
||||||
|
|
||||||
|
/* V Interrupt */
|
||||||
vint_pending = 1;
|
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)
|
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);
|
render_line(line, 0);
|
||||||
if (line < (vdp_height-1)) parse_satb(0x81 + line);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* update DMA timings */
|
|
||||||
if (dma_length) vdp_update_dma();
|
|
||||||
|
|
||||||
/* render overscan */
|
/* 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 */
|
/* clear any pending Z80 interrupt */
|
||||||
if (zirq)
|
if (zirq)
|
||||||
@ -410,17 +451,23 @@ int system_frame (int do_skip)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* process line */
|
/* process line */
|
||||||
m68k_run(aim_m68k);
|
m68k_run(mcycles_vdp + MCYCLES_PER_LINE);
|
||||||
if (zreset == 1 && zbusreq == 0)
|
if (zstate == 1)
|
||||||
{
|
z80_run(mcycles_vdp + MCYCLES_PER_LINE);
|
||||||
current_z80 = aim_z80 - count_z80;
|
else
|
||||||
if (current_z80 > 0) count_z80 += z80_execute(current_z80);
|
mcycles_z80 = mcycles_vdp + MCYCLES_PER_LINE;
|
||||||
}
|
|
||||||
else count_z80 = aim_z80;
|
|
||||||
|
|
||||||
/* SVP chip */
|
/* 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;
|
return gen_running;
|
||||||
}
|
}
|
||||||
|
@ -28,12 +28,7 @@
|
|||||||
#define SYSTEM_MEGADRIVE 1
|
#define SYSTEM_MEGADRIVE 1
|
||||||
#define SYSTEM_PICO 2
|
#define SYSTEM_PICO 2
|
||||||
|
|
||||||
/* CPU cycles increments */
|
#define MCYCLES_PER_LINE 3420
|
||||||
#define z80cycles_per_line 228
|
|
||||||
#define m68cycles_per_line 488
|
|
||||||
|
|
||||||
#define CLOCK_NTSC 53693175
|
|
||||||
#define CLOCK_PAL 53203424
|
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
@ -59,18 +54,19 @@ typedef struct
|
|||||||
|
|
||||||
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 enabled; /* 1= sound emulation is enabled */
|
||||||
int buffer_size; /* Size of sound buffer (in bytes) */
|
int buffer_size; /* Size of sound buffer (in bytes) */
|
||||||
int16 *buffer[2]; /* Signed 16-bit stereo sound data */
|
int16 *buffer[2]; /* Signed 16-bit stereo sound data */
|
||||||
struct
|
struct
|
||||||
{
|
{
|
||||||
int pos;
|
int16 *pos;
|
||||||
int16 *buffer[2];
|
int16 *buffer;
|
||||||
} fm;
|
} fm;
|
||||||
struct
|
struct
|
||||||
{
|
{
|
||||||
int pos;
|
int16 *pos;
|
||||||
int16 *buffer;
|
int16 *buffer;
|
||||||
} psg;
|
} psg;
|
||||||
} t_snd;
|
} t_snd;
|
||||||
@ -78,18 +74,17 @@ typedef struct
|
|||||||
/* Global variables */
|
/* Global variables */
|
||||||
extern t_bitmap bitmap;
|
extern t_bitmap bitmap;
|
||||||
extern t_snd snd;
|
extern t_snd snd;
|
||||||
extern uint32 count_m68k;
|
extern uint32 mcycles_vdp;
|
||||||
extern uint32 line_m68k;
|
extern uint32 mcycles_z80;
|
||||||
extern uint32 hint_m68k;
|
extern uint32 mcycles_68k;
|
||||||
extern uint32 count_z80;
|
extern uint32 hint_68k;
|
||||||
extern uint32 line_z80;
|
|
||||||
extern int32 current_z80;
|
|
||||||
extern uint8 system_hw;
|
extern uint8 system_hw;
|
||||||
|
|
||||||
/* Function prototypes */
|
/* 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_shutdown (void);
|
||||||
extern void audio_update (int len);
|
extern int audio_update (void);
|
||||||
extern void audio_set_equalizer(void);
|
extern void audio_set_equalizer(void);
|
||||||
extern void system_init (void);
|
extern void system_init (void);
|
||||||
extern void system_reset (void);
|
extern void system_reset (void);
|
||||||
|
@ -103,7 +103,7 @@ int main (int argc, char *argv[])
|
|||||||
|
|
||||||
/* initialize emulation */
|
/* initialize emulation */
|
||||||
system_init();
|
system_init();
|
||||||
audio_init(option.sndrate);
|
audio_init(option.sndrate, vdp_pal ? 50 : 60);
|
||||||
|
|
||||||
f = fopen("./game.srm", "rb");
|
f = fopen("./game.srm", "rb");
|
||||||
if (f!=NULL)
|
if (f!=NULL)
|
||||||
@ -132,8 +132,9 @@ int main (int argc, char *argv[])
|
|||||||
system_frame(1);
|
system_frame(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
audio_update(snd.buffer_size);
|
audio_update();
|
||||||
if(option.sound) dos_update_audio();
|
if(option.sound)
|
||||||
|
dos_update_audio();
|
||||||
}
|
}
|
||||||
|
|
||||||
f = fopen("./game.srm", "wb");
|
f = fopen("./game.srm", "wb");
|
||||||
@ -366,11 +367,19 @@ void dos_update_input(void)
|
|||||||
{
|
{
|
||||||
vdp_pal ^= 1;
|
vdp_pal ^= 1;
|
||||||
|
|
||||||
/* reinitialize timings */
|
/* save YM2612 context */
|
||||||
system_init ();
|
unsigned char *temp = memalign(32,YM2612GetContextSize());
|
||||||
unsigned char *temp = malloc(YM2612GetContextSize());
|
if (temp)
|
||||||
if (temp) memcpy(temp, YM2612GetContextPtr(), YM2612GetContextSize());
|
memcpy(temp, YM2612GetContextPtr(), YM2612GetContextSize());
|
||||||
audio_init(48000);
|
|
||||||
|
/* reinitialize all timings */
|
||||||
|
audio_init(snd.sample_rate, framerate);
|
||||||
|
system_init();
|
||||||
|
|
||||||
|
/* restore SRAM */
|
||||||
|
memfile_autoload(config.sram_auto,-1);
|
||||||
|
|
||||||
|
/* restore YM2612 context */
|
||||||
if (temp)
|
if (temp)
|
||||||
{
|
{
|
||||||
YM2612Restore(temp);
|
YM2612Restore(temp);
|
||||||
@ -378,7 +387,7 @@ void dos_update_input(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* reinitialize HVC tables */
|
/* 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;
|
hctab = (reg[12] & 1) ? cycle2hc40 : cycle2hc32;
|
||||||
|
|
||||||
/* reinitialize overscan area */
|
/* reinitialize overscan area */
|
||||||
|
@ -12,7 +12,7 @@ NAME = gen_sdl.exe
|
|||||||
|
|
||||||
CC = gcc
|
CC = gcc
|
||||||
CFLAGS = `sdl-config --cflags` -O6 -march=i686 -fomit-frame-pointer
|
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
|
INCLUDES = -I. -I.. -I../z80 -I../m68k -I../sound -I../cart_hw -I../cart_hw/svp -I../ntsc
|
||||||
LIBS = `sdl-config --libs` -lz -lm
|
LIBS = `sdl-config --libs` -lz -lm
|
||||||
|
|
||||||
|
@ -304,11 +304,19 @@ static int sdl_control_update(SDLKey keystate)
|
|||||||
{
|
{
|
||||||
vdp_pal ^= 1;
|
vdp_pal ^= 1;
|
||||||
|
|
||||||
/* reinitialize timings */
|
/* save YM2612 context */
|
||||||
system_init ();
|
unsigned char *temp = memalign(32,YM2612GetContextSize());
|
||||||
unsigned char *temp = malloc(YM2612GetContextSize());
|
if (temp)
|
||||||
if (temp) memcpy(temp, YM2612GetContextPtr(), YM2612GetContextSize());
|
memcpy(temp, YM2612GetContextPtr(), YM2612GetContextSize());
|
||||||
audio_init(SOUND_FREQUENCY);
|
|
||||||
|
/* reinitialize all timings */
|
||||||
|
audio_init(snd.sample_rate, framerate);
|
||||||
|
system_init();
|
||||||
|
|
||||||
|
/* restore SRAM */
|
||||||
|
memfile_autoload(config.sram_auto,-1);
|
||||||
|
|
||||||
|
/* restore YM2612 context */
|
||||||
if (temp)
|
if (temp)
|
||||||
{
|
{
|
||||||
YM2612Restore(temp);
|
YM2612Restore(temp);
|
||||||
@ -316,7 +324,7 @@ static int sdl_control_update(SDLKey keystate)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* reinitialize HVC tables */
|
/* 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;
|
hctab = (reg[12] & 1) ? cycle2hc40 : cycle2hc32;
|
||||||
|
|
||||||
/* reinitialize overscan area */
|
/* reinitialize overscan area */
|
||||||
@ -528,8 +536,8 @@ int main (int argc, char **argv)
|
|||||||
SDL_UnlockSurface(sdl_video.surf_bitmap);
|
SDL_UnlockSurface(sdl_video.surf_bitmap);
|
||||||
|
|
||||||
/* initialize emulation */
|
/* initialize emulation */
|
||||||
|
audio_init(SOUND_FREQUENCY, vdp_pal ? 50 : 60);
|
||||||
system_init();
|
system_init();
|
||||||
audio_init(SOUND_FREQUENCY);
|
|
||||||
|
|
||||||
/* load SRAM */
|
/* load SRAM */
|
||||||
f = fopen("./game.srm", "rb");
|
f = fopen("./game.srm", "rb");
|
||||||
@ -545,8 +553,9 @@ int main (int argc, char **argv)
|
|||||||
if(use_sound)
|
if(use_sound)
|
||||||
SDL_PauseAudio(0);
|
SDL_PauseAudio(0);
|
||||||
|
|
||||||
|
/* 3 frames = 50 ms (60hz) or 60 ms (50hz) */
|
||||||
if(sdl_sync.sem_sync)
|
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 */
|
/* emulation loop */
|
||||||
while(running)
|
while(running)
|
||||||
|
186
source/vdp.c
186
source/vdp.c
@ -72,12 +72,10 @@ uint16 v_counter; /* VDP scanline counter */
|
|||||||
uint32 dma_length; /* Current DMA remaining bytes */
|
uint32 dma_length; /* Current DMA remaining bytes */
|
||||||
int32 fifo_write_cnt; /* VDP writes fifo count */
|
int32 fifo_write_cnt; /* VDP writes fifo count */
|
||||||
uint32 fifo_lastwrite; /* last VDP write cycle */
|
uint32 fifo_lastwrite; /* last VDP write cycle */
|
||||||
uint8 fifo_latency; /* VDP write cycles latency */
|
|
||||||
uint8 odd_frame; /* 1: odd field, 0: even field */
|
uint8 odd_frame; /* 1: odd field, 0: even field */
|
||||||
uint8 im2_flag; /* 1= Interlace mode 2 is being used */
|
uint8 im2_flag; /* 1= Interlace mode 2 is being used */
|
||||||
uint8 interlaced; /* 1: Interlaced mode 1 or 2 */
|
uint8 interlaced; /* 1: Interlaced mode 1 or 2 */
|
||||||
uint8 vdp_pal; /* 1: PAL , 0: NTSC (default) */
|
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 */
|
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_base_mask; /* Base bits of SAT */
|
||||||
static uint16 sat_addr_mask; /* Index bits of SAT */
|
static uint16 sat_addr_mask; /* Index bits of SAT */
|
||||||
static uint32 dma_endCycles; /* 68k cycles to DMA end */
|
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
|
/* DMA Timings
|
||||||
|
|
||||||
@ -141,21 +140,10 @@ static inline void dma_fill(unsigned int data);
|
|||||||
void vdp_init(void)
|
void vdp_init(void)
|
||||||
{
|
{
|
||||||
/* PAL/NTSC timings */
|
/* PAL/NTSC timings */
|
||||||
switch (region_code)
|
if (vdp_pal)
|
||||||
{
|
|
||||||
case REGION_EUROPE:
|
|
||||||
case REGION_JAPAN_PAL:
|
|
||||||
vdp_pal = 1;
|
|
||||||
vdp_rate = 50;
|
|
||||||
lines_per_frame = 313;
|
lines_per_frame = 313;
|
||||||
break;
|
else
|
||||||
|
|
||||||
default:
|
|
||||||
vdp_pal = 0;
|
|
||||||
vdp_rate = 60;
|
|
||||||
lines_per_frame = 262;
|
lines_per_frame = 262;
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void vdp_reset(void)
|
void vdp_reset(void)
|
||||||
@ -233,8 +221,8 @@ void vdp_reset(void)
|
|||||||
reg_w(15, 0x02); /* auto increment */
|
reg_w(15, 0x02); /* auto increment */
|
||||||
}
|
}
|
||||||
|
|
||||||
/* default latency */
|
/* default FIFO timing */
|
||||||
fifo_latency = 27;
|
fifo_latency = 192;
|
||||||
}
|
}
|
||||||
|
|
||||||
void vdp_shutdown(void)
|
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.y = config.overscan ? (((reg[1] & 8) ? 0 : 8) + (vdp_pal ? 24 : 0)) : 0;
|
||||||
bitmap.viewport.changed = 1;
|
bitmap.viewport.changed = 1;
|
||||||
|
|
||||||
/* restore VDP timings */
|
/* restore FIFO timings */
|
||||||
fifo_latency = (reg[12] & 1) ? 27 : 30;
|
fifo_latency = (reg[12] & 1) ? 192 : 210;
|
||||||
if ((code & 0x0F) == 0x01) fifo_latency = fifo_latency * 2;
|
if ((code & 0x0F) == 0x01)
|
||||||
|
fifo_latency = fifo_latency * 2;
|
||||||
|
|
||||||
/* remake cache */
|
/* remake cache */
|
||||||
for (i=0;i<0x800;i++)
|
for (i=0;i<0x800;i++)
|
||||||
@ -295,21 +284,21 @@ void vdp_update_dma()
|
|||||||
int rate = dma_rates[index];
|
int rate = dma_rates[index];
|
||||||
|
|
||||||
/* 68k cycles left */
|
/* 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;
|
if (left_cycles < 0) left_cycles = 0;
|
||||||
|
|
||||||
/* DMA bytes left */
|
/* DMA bytes left */
|
||||||
int dma_bytes = (left_cycles * rate) / m68cycles_per_line;
|
int dma_bytes = (left_cycles * rate) / MCYCLES_PER_LINE;
|
||||||
|
|
||||||
#ifdef LOGVDP
|
#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
|
#endif
|
||||||
|
|
||||||
/* determinate DMA length in CPU cycles */
|
/* determinate DMA length in CPU cycles */
|
||||||
if (dma_length < dma_bytes)
|
if (dma_length < dma_bytes)
|
||||||
{
|
{
|
||||||
/* DMA will be finished during this line */
|
/* 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;
|
dma_length = 0;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -324,7 +313,7 @@ void vdp_update_dma()
|
|||||||
{
|
{
|
||||||
/* 68K COPY to V-RAM */
|
/* 68K COPY to V-RAM */
|
||||||
/* 68K is frozen during DMA operation */
|
/* 68K is frozen during DMA operation */
|
||||||
count_m68k += dma_cycles;
|
mcycles_68k += dma_cycles;
|
||||||
|
|
||||||
#ifdef LOGVDP
|
#ifdef LOGVDP
|
||||||
error("-->CPU frozen for %d cycles\n", dma_cycles);
|
error("-->CPU frozen for %d cycles\n", dma_cycles);
|
||||||
@ -334,7 +323,7 @@ void vdp_update_dma()
|
|||||||
{
|
{
|
||||||
/* VRAM Fill or VRAM Copy */
|
/* VRAM Fill or VRAM Copy */
|
||||||
/* set DMA end cyles count */
|
/* set DMA end cyles count */
|
||||||
dma_endCycles = count_m68k + dma_cycles;
|
dma_endCycles = mcycles_68k + dma_cycles;
|
||||||
|
|
||||||
#ifdef LOGVDP
|
#ifdef LOGVDP
|
||||||
error("-->DMA ends in %d cycles\n", dma_cycles);
|
error("-->DMA ends in %d cycles\n", dma_cycles);
|
||||||
@ -348,7 +337,6 @@ void vdp_update_dma()
|
|||||||
/*--------------------------------------------------------------------------*/
|
/*--------------------------------------------------------------------------*/
|
||||||
/* VDP Ports handler */
|
/* VDP Ports handler */
|
||||||
/*--------------------------------------------------------------------------*/
|
/*--------------------------------------------------------------------------*/
|
||||||
|
|
||||||
void vdp_ctrl_w(unsigned int data)
|
void vdp_ctrl_w(unsigned int data)
|
||||||
{
|
{
|
||||||
if (pending == 0)
|
if (pending == 0)
|
||||||
@ -398,18 +386,23 @@ void vdp_ctrl_w(unsigned int data)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* FIFO emulation:
|
/*
|
||||||
---------------
|
FIFO emulation (Chaos Engine/Soldier of Fortune, Double Clutch)
|
||||||
HDISP is 256*10/7 = approx. 366 cycles (same for both modes)
|
---------------------------------------------------------------
|
||||||
this gives:
|
|
||||||
H32: 16 accesses --> 366/16 = 23 cycles per access
|
HDISP is 2560 mcycles (same in both modes)
|
||||||
H40: 20 accesses --> 366/20 = 18 cycles per access
|
|
||||||
|
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)
|
if ((code & 0x0F) == 0x01)
|
||||||
fifo_latency = fifo_latency * 2;
|
fifo_latency = fifo_latency * 2;
|
||||||
}
|
}
|
||||||
@ -442,7 +435,7 @@ unsigned int vdp_ctrl_r(void)
|
|||||||
else status ^= 0x200;
|
else status ^= 0x200;
|
||||||
|
|
||||||
/* update DMA Busy flag */
|
/* update DMA Busy flag */
|
||||||
if ((status & 2) && !dma_length && (count_m68k >= dma_endCycles))
|
if ((status & 2) && !dma_length && (mcycles_68k >= dma_endCycles))
|
||||||
status &= 0xFFFD;
|
status &= 0xFFFD;
|
||||||
|
|
||||||
unsigned int temp = status;
|
unsigned int temp = status;
|
||||||
@ -452,7 +445,7 @@ unsigned int vdp_ctrl_r(void)
|
|||||||
temp |= 0x08;
|
temp |= 0x08;
|
||||||
|
|
||||||
/* HBLANK flag (Sonic 3 and Sonic 2 "VS Modes", Lemmings 2, Mega Turrican) */
|
/* 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;
|
temp |= 0x04;
|
||||||
|
|
||||||
/* clear pending flag */
|
/* clear pending flag */
|
||||||
@ -462,21 +455,21 @@ unsigned int vdp_ctrl_r(void)
|
|||||||
status &= 0xFF9F;
|
status &= 0xFF9F;
|
||||||
|
|
||||||
#ifdef LOGVDP
|
#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
|
#endif
|
||||||
return (temp);
|
return (temp);
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned int vdp_hvc_r(void)
|
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];
|
uint8 vc = vctab[v_counter];
|
||||||
|
|
||||||
/* interlace mode 2 */
|
/* interlace mode 2 */
|
||||||
if (im2_flag) vc = (vc << 1) | ((vc >> 7) & 1);
|
if (im2_flag) vc = (vc << 1) | ((vc >> 7) & 1);
|
||||||
|
|
||||||
#ifdef LOGVDP
|
#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
|
#endif
|
||||||
return ((vc << 8) | hc);
|
return ((vc << 8) | hc);
|
||||||
}
|
}
|
||||||
@ -506,13 +499,13 @@ void vdp_data_w(unsigned int data)
|
|||||||
if (fifo_write_cnt == 0)
|
if (fifo_write_cnt == 0)
|
||||||
{
|
{
|
||||||
/* reset cycle counter */
|
/* reset cycle counter */
|
||||||
fifo_lastwrite = count_m68k;
|
fifo_lastwrite = mcycles_68k;
|
||||||
|
|
||||||
/* FIFO is not empty anymore */
|
/* FIFO is not empty anymore */
|
||||||
status &= 0xFDFF;
|
status &= 0xFDFF;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* increase write counter */
|
/* increase FIFO word count */
|
||||||
fifo_write_cnt ++;
|
fifo_write_cnt ++;
|
||||||
|
|
||||||
/* is FIFO full ? */
|
/* is FIFO full ? */
|
||||||
@ -522,7 +515,7 @@ void vdp_data_w(unsigned int data)
|
|||||||
|
|
||||||
/* VDP latency (Chaos Engine, Soldiers of Fortune, Double Clutch) */
|
/* VDP latency (Chaos Engine, Soldiers of Fortune, Double Clutch) */
|
||||||
if (fifo_write_cnt > 4)
|
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 */
|
case 0x00: /* VRAM */
|
||||||
temp = *(uint16 *) & vram[(addr & 0xFFFE)];
|
temp = *(uint16 *) & vram[(addr & 0xFFFE)];
|
||||||
#ifdef LOGVDP
|
#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
|
#endif
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -550,14 +543,14 @@ unsigned int vdp_data_r(void)
|
|||||||
temp = *(uint16 *) & cram[(addr & 0x7E)];
|
temp = *(uint16 *) & cram[(addr & 0x7E)];
|
||||||
temp = UNPACK_CRAM (temp);
|
temp = UNPACK_CRAM (temp);
|
||||||
#ifdef LOGVDP
|
#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
|
#endif
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0x04: /* VSRAM */
|
case 0x04: /* VSRAM */
|
||||||
temp = *(uint16 *) & vsram[(addr & 0x7E)];
|
temp = *(uint16 *) & vsram[(addr & 0x7E)];
|
||||||
#ifdef LOGVDP
|
#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
|
#endif
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -576,7 +569,7 @@ unsigned int vdp_data_r(void)
|
|||||||
int vdp_int_ack_callback(int int_level)
|
int vdp_int_ack_callback(int int_level)
|
||||||
{
|
{
|
||||||
#ifdef LOGVDP
|
#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
|
#endif
|
||||||
|
|
||||||
/* VINT triggered ? */
|
/* VINT triggered ? */
|
||||||
@ -597,11 +590,13 @@ int vdp_int_ack_callback(int int_level)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* update IRQ status */
|
/* update IRQ status */
|
||||||
irq_status = 0x10;
|
irq_status = 0;
|
||||||
if (vint_pending && (reg[1] & 0x20))
|
if (vint_pending && (reg[1] & 0x20))
|
||||||
irq_status |= 6;
|
irq_status |= 0x16;
|
||||||
else if (hint_pending && (reg[0] & 0x10))
|
else if (hint_pending && (reg[0] & 0x10))
|
||||||
irq_status |= 4;
|
irq_status |= 0x14;
|
||||||
|
else
|
||||||
|
m68k_set_irq(0);
|
||||||
|
|
||||||
return M68K_INT_ACK_AUTOVECTOR;
|
return M68K_INT_ACK_AUTOVECTOR;
|
||||||
}
|
}
|
||||||
@ -614,14 +609,15 @@ static inline void fifo_update()
|
|||||||
if (fifo_write_cnt > 0)
|
if (fifo_write_cnt > 0)
|
||||||
{
|
{
|
||||||
/* update FIFO reads */
|
/* 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)
|
if (fifo_read > 0)
|
||||||
{
|
{
|
||||||
fifo_write_cnt -= fifo_read;
|
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 */
|
/* 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 */
|
case 0x01: /* VRAM */
|
||||||
|
|
||||||
#ifdef LOGVDP
|
#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
|
#endif
|
||||||
|
|
||||||
/* Byte-swap data if A0 is set */
|
/* Byte-swap data if A0 is set */
|
||||||
@ -663,7 +659,7 @@ static inline void data_w(unsigned int data)
|
|||||||
case 0x03: /* CRAM */
|
case 0x03: /* CRAM */
|
||||||
{
|
{
|
||||||
#ifdef LOGVDP
|
#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
|
#endif
|
||||||
uint16 *p = (uint16 *) &cram[(addr & 0x7E)];
|
uint16 *p = (uint16 *) &cram[(addr & 0x7E)];
|
||||||
data = PACK_CRAM (data & 0x0EEE);
|
data = PACK_CRAM (data & 0x0EEE);
|
||||||
@ -681,10 +677,10 @@ static inline void data_w(unsigned int data)
|
|||||||
if (border == index)
|
if (border == index)
|
||||||
color_update (0x00, *p);
|
color_update (0x00, *p);
|
||||||
|
|
||||||
/* CRAM modified during HBLANK */
|
/* CRAM modified during HBLANK (Striker, Zero the Kamikaze, etc) */
|
||||||
if (!(status & 8) && (reg[1]&0x40) && (count_m68k <= (line_m68k + 84)))
|
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);
|
remap_buffer(v_counter,bitmap.viewport.w + 2*bitmap.viewport.x);
|
||||||
#ifdef LOGVDP
|
#ifdef LOGVDP
|
||||||
error("Line remapped\n");
|
error("Line remapped\n");
|
||||||
@ -699,7 +695,7 @@ static inline void data_w(unsigned int data)
|
|||||||
|
|
||||||
case 0x05: /* VSRAM */
|
case 0x05: /* VSRAM */
|
||||||
#ifdef LOGVDP
|
#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
|
#endif
|
||||||
*(uint16 *) &vsram[(addr & 0x7E)] = data;
|
*(uint16 *) &vsram[(addr & 0x7E)] = data;
|
||||||
break;
|
break;
|
||||||
@ -716,14 +712,15 @@ static inline void data_w(unsigned int data)
|
|||||||
static inline void reg_w(unsigned int r, unsigned int d)
|
static inline void reg_w(unsigned int r, unsigned int d)
|
||||||
{
|
{
|
||||||
#ifdef LOGVDP
|
#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
|
#endif
|
||||||
|
|
||||||
/* See if Mode 4 (SMS mode) is enabled
|
/* 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
|
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)
|
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)
|
switch(r)
|
||||||
{
|
{
|
||||||
@ -734,8 +731,10 @@ static inline void reg_w(unsigned int r, unsigned int d)
|
|||||||
{
|
{
|
||||||
/* update IRQ status */
|
/* update IRQ status */
|
||||||
irq_status = 0x50;
|
irq_status = 0x50;
|
||||||
if (vint_pending && (reg[1] & 0x20)) irq_status |= 0x26;
|
if (vint_pending && (reg[1] & 0x20))
|
||||||
else if (d & 0x10) irq_status |= 4;
|
irq_status |= 0x26;
|
||||||
|
else if (d & 0x10)
|
||||||
|
irq_status |= 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Palette bit */
|
/* Palette bit */
|
||||||
@ -759,8 +758,10 @@ static inline void reg_w(unsigned int r, unsigned int d)
|
|||||||
{
|
{
|
||||||
/* update IRQ status */
|
/* update IRQ status */
|
||||||
irq_status = 0x50;
|
irq_status = 0x50;
|
||||||
if (d & 0x20) irq_status |= 0x26;
|
if (d & 0x20)
|
||||||
else if (hint_pending && (reg[0] & 0x10)) irq_status |= 4;
|
irq_status |= 0x26;
|
||||||
|
else if (hint_pending && (reg[0] & 0x10))
|
||||||
|
irq_status |= 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* See if the viewport height has actually been changed */
|
/* 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;
|
if (config.overscan) bitmap.viewport.y = ((vdp_pal ? 288 : 240) - bitmap.viewport.h) / 2;
|
||||||
|
|
||||||
/* update VC table */
|
/* 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 (((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;
|
reg[1] = d;
|
||||||
render_line(v_counter, 0);
|
|
||||||
#ifdef LOGVDP
|
#ifdef LOGVDP
|
||||||
error("Line redrawn\n");
|
error("Line redrawn (%d sprites) \n",object_index_count);
|
||||||
#endif
|
#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
|
#ifdef LOGVDP
|
||||||
else
|
else
|
||||||
@ -837,10 +845,10 @@ static inline void reg_w(unsigned int r, unsigned int d)
|
|||||||
border = d;
|
border = d;
|
||||||
color_update(0x00, *(uint16 *)&cram[(border << 1)]);
|
color_update(0x00, *(uint16 *)&cram[(border << 1)]);
|
||||||
|
|
||||||
/* background color modified during Horizontal Blanking */
|
/* Background color modified during Horizontal Blanking (Road Rash 1,2,3)*/
|
||||||
if (!(status & 8) && (count_m68k <= (line_m68k + 84)))
|
if (!(status & 8) && (mcycles_68k <= (mcycles_vdp + 860)))
|
||||||
{
|
{
|
||||||
/* remap entire line (see Road Rash I,II,III) */
|
/* remap colors */
|
||||||
reg[7] = d;
|
reg[7] = d;
|
||||||
remap_buffer(v_counter,bitmap.viewport.w + 2*bitmap.viewport.x);
|
remap_buffer(v_counter,bitmap.viewport.w + 2*bitmap.viewport.x);
|
||||||
#ifdef LOGVDP
|
#ifdef LOGVDP
|
||||||
@ -994,7 +1002,8 @@ static inline void dma_vbus (void)
|
|||||||
{
|
{
|
||||||
/* Return $FFFF only when the Z80 isn't hogging the Z-bus.
|
/* Return $FFFF only when the Z80 isn't hogging the Z-bus.
|
||||||
(e.g. Z80 isn't reset and 68000 has the 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
|
/* 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.
|
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 */
|
/* All remaining locations access work RAM */
|
||||||
else temp = *(uint16 *)(work_ram + (source & 0xffff));
|
else
|
||||||
|
temp = *(uint16 *)(work_ram + (source & 0xffff));
|
||||||
|
|
||||||
source += 2;
|
source += 2;
|
||||||
source = ((base & 0xFE0000) | (source & 0x1FFFF));
|
source = ((base & 0xFE0000) | (source & 0x1FFFF));
|
||||||
@ -1059,12 +1069,12 @@ static inline void dma_fill(unsigned int data)
|
|||||||
/* write MSB */
|
/* write MSB */
|
||||||
data = (data >> 8) & 0xff;
|
data = (data >> 8) & 0xff;
|
||||||
|
|
||||||
/* detect internal SAT modification */
|
/* intercept SAT writes */
|
||||||
if ((addr & sat_base_mask) == satb)
|
if ((addr & sat_base_mask) == satb)
|
||||||
{
|
{
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
/* update internal SAT (fix Battletech) */
|
/* update internal SAT copy */
|
||||||
WRITE_BYTE(sat, (addr & sat_addr_mask)^1, data);
|
WRITE_BYTE(sat, (addr & sat_addr_mask)^1, data);
|
||||||
WRITE_BYTE(vram, addr^1, data);
|
WRITE_BYTE(vram, addr^1, data);
|
||||||
MARK_BG_DIRTY (addr);
|
MARK_BG_DIRTY (addr);
|
||||||
|
@ -59,12 +59,10 @@ extern uint16 v_counter;
|
|||||||
extern uint32 dma_length;
|
extern uint32 dma_length;
|
||||||
extern int32 fifo_write_cnt;
|
extern int32 fifo_write_cnt;
|
||||||
extern uint32 fifo_lastwrite;
|
extern uint32 fifo_lastwrite;
|
||||||
extern uint8 fifo_latency;
|
|
||||||
extern uint8 im2_flag;
|
extern uint8 im2_flag;
|
||||||
extern uint8 interlaced;
|
extern uint8 interlaced;
|
||||||
extern uint8 odd_frame;
|
extern uint8 odd_frame;
|
||||||
extern uint8 vdp_pal;
|
extern uint8 vdp_pal;
|
||||||
extern uint8 vdp_rate;
|
|
||||||
extern uint16 lines_per_frame;
|
extern uint16 lines_per_frame;
|
||||||
|
|
||||||
extern uint8 *vctab;
|
extern uint8 *vctab;
|
||||||
@ -72,8 +70,8 @@ extern uint8 *hctab;
|
|||||||
extern uint8 vc_ntsc_224[262];
|
extern uint8 vc_ntsc_224[262];
|
||||||
extern uint8 vc_pal_224[313];
|
extern uint8 vc_pal_224[313];
|
||||||
extern uint8 vc_pal_240[313];
|
extern uint8 vc_pal_240[313];
|
||||||
extern uint8 cycle2hc32[488];
|
extern uint8 cycle2hc32[3420];
|
||||||
extern uint8 cycle2hc40[488];
|
extern uint8 cycle2hc40[3420];
|
||||||
|
|
||||||
/* Function prototypes */
|
/* Function prototypes */
|
||||||
extern void vdp_init(void);
|
extern void vdp_init(void);
|
||||||
|
@ -202,7 +202,8 @@
|
|||||||
#define IFF2 Z80.iff2
|
#define IFF2 Z80.iff2
|
||||||
#define HALT Z80.halt
|
#define HALT Z80.halt
|
||||||
|
|
||||||
int z80_ICount;
|
extern unsigned int mcycles_z80;
|
||||||
|
|
||||||
Z80_Regs Z80;
|
Z80_Regs Z80;
|
||||||
static UINT32 EA;
|
static UINT32 EA;
|
||||||
|
|
||||||
@ -466,7 +467,7 @@ INLINE void BURNODD(int cycles, int opcodes, int cyclesum)
|
|||||||
if( cycles > 0 )
|
if( cycles > 0 )
|
||||||
{
|
{
|
||||||
R += (cycles / cyclesum) * opcodes;
|
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
|
* 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
|
* execute an opcode
|
||||||
@ -3224,7 +3225,7 @@ static void take_interrupt(void)
|
|||||||
RM16( irq_vector, &Z80.pc );
|
RM16( irq_vector, &Z80.pc );
|
||||||
LOG(("Z80 #%d IM2 [$%04x] = $%04x\n",cpu_getactivecpu() , irq_vector, PCD));
|
LOG(("Z80 #%d IM2 [$%04x] = $%04x\n",cpu_getactivecpu() , irq_vector, PCD));
|
||||||
/* CALL $xxxx + 'interrupt latency' cycles */
|
/* 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
|
else
|
||||||
/* Interrupt mode 1. RST 38h */
|
/* Interrupt mode 1. RST 38h */
|
||||||
@ -3234,7 +3235,7 @@ static void take_interrupt(void)
|
|||||||
PUSH( pc );
|
PUSH( pc );
|
||||||
PCD = 0x0038;
|
PCD = 0x0038;
|
||||||
/* RST $38 + 'interrupt latency' cycles */
|
/* 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
|
else
|
||||||
{
|
{
|
||||||
@ -3248,18 +3249,18 @@ static void take_interrupt(void)
|
|||||||
PUSH( pc );
|
PUSH( pc );
|
||||||
PCD = irq_vector & 0xffff;
|
PCD = irq_vector & 0xffff;
|
||||||
/* CALL $xxxx + 'interrupt latency' cycles */
|
/* 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;
|
break;
|
||||||
case 0xc30000: /* jump */
|
case 0xc30000: /* jump */
|
||||||
PCD = irq_vector & 0xffff;
|
PCD = irq_vector & 0xffff;
|
||||||
/* JP $xxxx + 2 cycles */
|
/* 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;
|
break;
|
||||||
default: /* rst (or other opcodes?) */
|
default: /* rst (or other opcodes?) */
|
||||||
PUSH( pc );
|
PUSH( pc );
|
||||||
PCD = irq_vector & 0x0038;
|
PCD = irq_vector & 0x0038;
|
||||||
/* RST $xx + 2 cycles */
|
/* 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;
|
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 */
|
/* 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 */
|
/* via timers, and can't be dynamically enabled, so it is safe */
|
||||||
/* to just check here */
|
/* to just check here */
|
||||||
@ -3422,25 +3421,23 @@ int z80_execute(int cycles)
|
|||||||
PUSH( pc );
|
PUSH( pc );
|
||||||
PCD = 0x0066;
|
PCD = 0x0066;
|
||||||
WZ=PCD;
|
WZ=PCD;
|
||||||
z80_ICount -= 11;
|
mcycles_z80 += 11*15;
|
||||||
Z80.nmi_pending = FALSE;
|
Z80.nmi_pending = FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
while( z80_ICount > 0 )
|
while( mcycles_z80 < cycles )
|
||||||
{
|
{
|
||||||
/* check for IRQs before each instruction */
|
/* check for IRQs before each instruction */
|
||||||
if (Z80.irq_state != CLEAR_LINE && IFF1 && !Z80.after_ei)
|
if (Z80.irq_state != CLEAR_LINE && IFF1 && !Z80.after_ei)
|
||||||
take_interrupt();
|
take_interrupt();
|
||||||
Z80.after_ei = FALSE;
|
Z80.after_ei = FALSE;
|
||||||
|
|
||||||
if (z80_ICount > 0)
|
if (mcycles_z80 < cycles)
|
||||||
{
|
{
|
||||||
R++;
|
R++;
|
||||||
EXEC_INLINE(op,ROP());
|
EXEC_INLINE(op,ROP());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return cycles - z80_ICount;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
@ -3453,7 +3450,7 @@ void z80_burn(int cycles)
|
|||||||
/* NOP takes 4 cycles per instruction */
|
/* NOP takes 4 cycles per instruction */
|
||||||
int n = (cycles + 3) / 4;
|
int n = (cycles + 3) / 4;
|
||||||
R += n;
|
R += n;
|
||||||
z80_ICount -= 4 * n;
|
mcycles_z80 += 4 * n * 15;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -40,13 +40,12 @@ typedef struct
|
|||||||
} Z80_Regs;
|
} Z80_Regs;
|
||||||
|
|
||||||
|
|
||||||
extern int z80_ICount;
|
|
||||||
extern Z80_Regs Z80;
|
extern Z80_Regs Z80;
|
||||||
|
|
||||||
void z80_init(int index, int clock, const void *config, int (*irqcallback)(int));
|
void z80_init(int index, int clock, const void *config, int (*irqcallback)(int));
|
||||||
void z80_reset (void);
|
void z80_reset (void);
|
||||||
void z80_exit (void);
|
void z80_exit (void);
|
||||||
int z80_execute(int cycles);
|
void z80_run(int cycles);
|
||||||
void z80_burn(int cycles);
|
void z80_burn(int cycles);
|
||||||
void z80_get_context (void *dst);
|
void z80_get_context (void *dst);
|
||||||
void z80_set_context (void *src);
|
void z80_set_context (void *src);
|
||||||
|
Loading…
Reference in New Issue
Block a user