huge update

This commit is contained in:
ekeeke31 2008-12-04 19:32:22 +00:00
parent 1a730e7183
commit 0165ac387f
36 changed files with 2160 additions and 2463 deletions

View File

@ -12,7 +12,7 @@ CURRENT:
.modified SSG-EG Decay End Level: fix some sound effects (ChainSaw, Zap...) in "Beavis & Butthead" .modified SSG-EG Decay End Level: fix some sound effects (ChainSaw, Zap...) in "Beavis & Butthead"
.improved Detune overflow accuracy: fix very high frequency sounds in many games .improved Detune overflow accuracy: fix very high frequency sounds in many games
.fixed registers 0x20-0x26 Reset state: fix intro music in "B.O.B" .fixed registers 0x20-0x26 Reset state: fix intro music in "B.O.B"
.reverted incorrect fix with KEY ON: fix "Flamethrower" sound effect in "Alien 3" and many other games .reverted incorrect fix with KEY ON: fix "Flamethrower" sound effect in "Alien 3" and many others
- adjusted HCounter values: fixes line flickering in "Sonic 3D" bonus stage - adjusted HCounter values: fixes line flickering in "Sonic 3D" bonus stage
- adjusted VINT timing: fixes hang-up in "V.R Troopers" - adjusted VINT timing: fixes hang-up in "V.R Troopers"
@ -20,6 +20,7 @@ CURRENT:
- fixed broken Z80 access to WRAM: fixes hang-up in "Mamono Hunter Youko" - fixed broken Z80 access to WRAM: fixes hang-up in "Mamono Hunter Youko"
- modified JCART emulation: fixes corrupted tracks logo in "Micro Machines 2" - modified JCART emulation: fixes corrupted tracks logo in "Micro Machines 2"
- added Blargg's NTSC Filters support (NTSC video artifacts emulation) - added Blargg's NTSC Filters support (NTSC video artifacts emulation)
- improved emulation speed: highly optimized VDP rendering engine, 68k memory handlers, cpu execution & interrupts
[NGC/Wii] [NGC/Wii]
@ -27,10 +28,9 @@ CURRENT:
- remove slowest libsamplerate settings under "HQ YM2612" option, only keeps SRC_LINEAR (faster) and SRC_SINC_FAST (better) - remove slowest libsamplerate settings under "HQ YM2612" option, only keeps SRC_LINEAR (faster) and SRC_SINC_FAST (better)
- implemented fast scrolling in menu using Wiimote D-PAD - implemented fast scrolling in menu using Wiimote D-PAD
- added an option to enable/disable bilinear filtering - added an option to enable/disable bilinear filtering
- rewrote video renderer: improved horizontal scaling (VI+GX), faster rendering (direct texture mapping)... - rewrote video engine: improved horizontal scaling (VI+GX), improved rendering speed (direct texture mapping)
- removed embedded font, (re)enabled IPL font support: now should works for Qoob users too (thanks to emukiddid) - removed embedded font, (re)enabled IPL font support: now should works for Qoob users too (thanks to emukiddid)
- fixed "Reset" button behavior, now acts more like Genesis Reset button ;-) - fixed "Reset" button behavior, now acts more like Genesis Reset button ;-)
- added SDCARD read-ahead cache support (svpe's libogc patches)
- minor bugfixes and menu tweaks - minor bugfixes and menu tweaks
@ -40,8 +40,9 @@ CURRENT:
[Wii only] [Wii only]
- added "Power" button support, including shutdown from the wiimote (libogc CVS) - added "Power" button support
- added SDHC support (libogc CVS) - improved SDCARD access speed (svpe's "read-ahead" patch)
- compiled with libogc CVS: SDHC support, Wiimote shutdown button support

View File

@ -1,13 +1,14 @@
/**************************************************************************** /****************************************************************************
* Genesis Plus 1.2a * Genesis Plus 1.2a
* Cartridge Hardware support * Cartridge Hardware support
* *
* code by Eke-Eke, GC/Wii port * code by Eke-Eke, GC/Wii port
* *
* Lots of protection mechanism have been discovered by Haze * Most cartridge protections documented by Haze
* (http://haze.mameworld.info/) * (http://haze.mameworld.info/)
* *
* Realtec mapper has been figured out by TascoDeluxe * Realtec mapper documented by TascoDeluxe
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
@ -30,14 +31,14 @@
#define CART_CNT 26 #define CART_CNT 26
/* Function prototypes */ /* Function prototypes */
void default_time_w(unsigned int address, unsigned int value); void default_time_w(uint32 address, uint32 data);
void special_mapper_w(unsigned int address, unsigned int value); void special_mapper_w(uint32 address, uint32 data);
void realtec_mapper_w(unsigned int address, unsigned int value); void realtec_mapper_w(uint32 address, uint32 data);
void seganet_mapper_w(unsigned int address, unsigned int value); void seganet_mapper_w(uint32 address, uint32 data);
unsigned int radica_mapper_r(unsigned int address); uint32 radica_mapper_r(uint32 address);
void default_regs_w(unsigned int address, unsigned int value); void default_regs_w(uint32 address, uint32 data);
unsigned int default_regs_r(unsigned int address); uint32 default_regs_r(uint32 address);
void special_regs_w(unsigned int address, unsigned int value); void special_regs_w(uint32 address, uint32 data);
/* Cart database entry */ /* Cart database entry */
typedef struct typedef struct
@ -56,64 +57,65 @@ typedef struct
T_CART_ENTRY rom_database[CART_CNT] = T_CART_ENTRY rom_database[CART_CNT] =
{ {
/* Game no Kanzume Otokuyou */ /* Game no Kanzume Otokuyou */
{0x0000,0xf9d1,0,0,{{0,0,0,0},{0,0,0,0},{0,0,0,0},0,0,seganet_mapper_w,0,0}}, {0x0000,0xf9d1,0,0,{{0,0,0,0},{0,0,0,0},{0,0,0,0},0,0,0,seganet_mapper_w,0,0}},
/* RADICA (Volume 1) (not byteswapped) */ /* RADICA (Volume 1) (not byteswapped) */
{0x0000,0x2326,0,0,{{0,0,0,0},{0,0,0,0},{0,0,0,0},0,radica_mapper_r,0,0,0}}, {0x0000,0x2326,0,0,{{0,0,0,0},{0,0,0,0},{0,0,0,0},0,1,radica_mapper_r,0,0,0}},
/* RADICA (Volume 2) */ /* RADICA (Volume 2) */
{0x4f10,0x0836,0,0,{{0,0,0,0},{0,0,0,0},{0,0,0,0},0,radica_mapper_r,0,0,0}}, {0x4f10,0x0836,0,0,{{0,0,0,0},{0,0,0,0},{0,0,0,0},0,1,radica_mapper_r,0,0,0}},
/* RADICA (Volume 1) */ /* RADICA (Volume 1) */
{0xf424,0x9f82,0,0,{{0,0,0,0},{0,0,0,0},{0,0,0,0},0,radica_mapper_r,0,0,0}}, {0xf424,0x9f82,0,0,{{0,0,0,0},{0,0,0,0},{0,0,0,0},0,1,radica_mapper_r,0,0,0}},
/* Funny World & Balloon Boy */ /* Funny World & Balloon Boy */
{0x0000,0x06ab,8,8,{{0,0,0,0},{0,0,0,0},{0,0,0,0},1,0,0,0,realtec_mapper_w}}, {0x0000,0x06ab,0x40,0x40,{{0,0,0,0},{0,0,0,0},{0,0,0,0},1,1,0,0,0,realtec_mapper_w}},
/* Whac-a-Critter */ /* Whac-a-Critter */
{0xffff,0xf863,8,8,{{0,0,0,0},{0,0,0,0},{0,0,0,0},1,0,0,0,realtec_mapper_w}}, {0xffff,0xf863,0x40,0x40,{{0,0,0,0},{0,0,0,0},{0,0,0,0},1,1,0,0,0,realtec_mapper_w}},
/* Earth Defense */ /* Earth Defense */
{0xffff,0x44fb,8,8,{{0,0,0,0},{0,0,0,0},{0,0,0,0},1,0,0,0,realtec_mapper_w}}, {0xffff,0x44fb,0x40,0x40,{{0,0,0,0},{0,0,0,0},{0,0,0,0},1,1,0,0,0,realtec_mapper_w}},
/* Super Mario 2 1998 */ /* Super Mario 2 1998 */
{0xffff,0x0474,0,0,{{0x0a,0,0,0},{0xffffff,0,0,0},{0xa13000,0,0,0},0,default_regs_r,0,0,0}}, {0xffff,0x0474,0,0,{{0x0a,0,0,0},{0xffffff,0,0,0},{0xa13000,0,0,0},0,0,default_regs_r,0,0,0}},
/* Super Mario 2 1998 */ /* Super Mario 2 1998 */
{0x2020,0xb4eb,0,0,{{0x1c,0,0,0},{0xffffff,0,0,0},{0xa13000,0,0,0},0,default_regs_r,0,0,0}}, {0x2020,0xb4eb,0,0,{{0x1c,0,0,0},{0xffffff,0,0,0},{0xa13000,0,0,0},0,0,default_regs_r,0,0,0}},
/* Supper Bubble Bobble */ /* Supper Bubble Bobble */
{0x0000,0x16cd,8,8,{{0x55,0x0f,0,0},{0xffffff,0xffffff,0,0},{0x400000,0x400002,0,0},0,0,0,default_regs_r,0}}, {0x0000,0x16cd,0x40,0x40,{{0x55,0x0f,0,0},{0xffffff,0xffffff,0,0},{0x400000,0x400002,0,0},0,0,0,0,default_regs_r,0}},
/* Mahjong Lover */ /* Mahjong Lover */
{0x0000,0x7037,8,8,{{0x90,0xd3,0,0},{0xffffff,0xffffff,0,0},{0x400000,0x401000,0,0},0,0,0,default_regs_r,0}}, {0x0000,0x7037,0x40,0x40,{{0x90,0xd3,0,0},{0xffffff,0xffffff,0,0},{0x400000,0x401000,0,0},0,0,0,0,default_regs_r,0}},
/* Lion King 2 */ /* Lion King 2 */
{0xffff,0x1d9b,8,8,{{0,0,0,0},{0xfffffd,0xfffffd,0,0},{0x400000,0x400004,0,0},0,0,0,default_regs_r,default_regs_w}}, {0xffff,0x1d9b,0x40,0x40,{{0,0,0,0},{0xfffffd,0xfffffd,0,0},{0x400000,0x400004,0,0},0,0,0,0,default_regs_r,default_regs_w}},
/* Squirell King */ /* Squirell King */
{0x0000,0x8ec8,8,8,{{0,0,0,0},{0xfffffd,0xfffffd,0,0},{0x400000,0x400004,0,0},0,0,0,default_regs_r,default_regs_w}}, {0x0000,0x8ec8,0x40,0x40,{{0,0,0,0},{0xfffffd,0xfffffd,0,0},{0x400000,0x400004,0,0},0,0,0,0,default_regs_r,default_regs_w}},
/* Rockman X3 */ /* Rockman X3 */
{0x0000,0x9d0e,8,8,{{0x0c,0x88,0,0},{0xffffff,0xffffff,0,0},{0xa13000,0x400004,0,0},0,default_regs_r,0,default_regs_r,0}}, {0x0000,0x9d0e,0x40,0x40,{{0x0c,0x88,0,0},{0xffffff,0xffffff,0,0},{0xa13000,0x400004,0,0},0,0,default_regs_r,0,default_regs_r,0}},
/* A Bug's Life */ /* A Bug's Life */
{0x7f7f,0x2aad,0,0,{{0x28,0x1f,0x01,0},{0xffffff,0xffffff,0xffffff,0},{0xa13000,0xa13002,0xa1303e,0},0,default_regs_r,0,0,0}}, {0x7f7f,0x2aad,0,0,{{0x28,0x1f,0x01,0},{0xffffff,0xffffff,0xffffff,0},{0xa13000,0xa13002,0xa1303e,0},0,0,default_regs_r,0,0,0}},
/* King of Fighter 99 */ /* King of Fighter 99 */
{0x0000,0x21e,0,0,{{0x00,0x01,0x1f,0},{0xffffff,0xffffff,0xffffff,0},{0xa13000,0xa13002,0xa1303e,0},0,default_regs_r,0,0,0}}, {0x0000,0x21e,0,0,{{0x00,0x01,0x1f,0},{0xffffff,0xffffff,0xffffff,0},{0xa13000,0xa13002,0xa1303e,0},0,0,default_regs_r,0,0,0}},
/* Pocket Monster */ /* Pocket Monster */
{0xd6fc,0x1eb1,0,0,{{0x00,0x01,0x1f,0},{0xffffff,0xffffff,0xffffff,0},{0xa13000,0xa13002,0xa1303e,0},0,default_regs_r,0,0,0}}, {0xd6fc,0x1eb1,0,0,{{0x00,0x01,0x1f,0},{0xffffff,0xffffff,0xffffff,0},{0xa13000,0xa13002,0xa1303e,0},0,0,default_regs_r,0,0,0}},
/* Lion King 3 */ /* Lion King 3 */
{0x0000,0x507c,12,15,{{0,0,0,0},{0xf0000e,0xf0000e,0xf0000e,0},{0x600000,0x600002,0x600004,0},0,0,0,default_regs_r,special_regs_w}}, {0x0000,0x507c,0x60,0x7f,{{0,0,0,0},{0xf0000e,0xf0000e,0xf0000e,0},{0x600000,0x600002,0x600004,0},0,1,0,0,default_regs_r,special_regs_w}},
/* Super King Kong 99 */ /* Super King Kong 99 */
{0x0000,0x7d6e,12,15,{{0,0,0,0},{0xf0000e,0xf0000e,0xf0000e,0},{0x600000,0x600002,0x600004,0},0,0,0,default_regs_r,special_regs_w}}, {0x0000,0x7d6e,0x60,0x7f,{{0,0,0,0},{0xf0000e,0xf0000e,0xf0000e,0},{0x600000,0x600002,0x600004,0},0,1,0,0,default_regs_r,special_regs_w}},
/* Pokemon Stadium */ /* Pokemon Stadium */
{0x0000,0x843c,14,15,{{0,0,0,0},{0,0,0,0},{0,0,0,0},0,0,0,0,special_regs_w}}, {0x0000,0x843c,0x70,0x7f,{{0,0,0,0},{0,0,0,0},{0,0,0,0},0,1,0,0,0,special_regs_w}},
/* Elf Wor */ /* Elf Wor */
{0x0080,0x3dba,8,8,{{0x55,0x0f,0xc9,0x18},{0xffffff,0xffffff,0xffffff,0xffffff},{0x400000,0x400002,0x400004,0x400006},0,0,0,default_regs_r,0}}, {0x0080,0x3dba,0x40,0x40,{{0x55,0x0f,0xc9,0x18},{0xffffff,0xffffff,0xffffff,0xffffff},{0x400000,0x400002,0x400004,0x400006},0,0,0,0,default_regs_r,0}},
/* Huan Le Tao Qi Shu - Smart Mouse */ /* Huan Le Tao Qi Shu - Smart Mouse */
{0x0000,0x1a28,8,8,{{0x55,0x0f,0xaa,0xf0},{0xffffff,0xffffff,0xffffff,0xffffff},{0x400000,0x400002,0x400004,0x400006},0,0,0,default_regs_r,0}}, {0x0000,0x1a28,0x40,0x40,{{0x55,0x0f,0xaa,0xf0},{0xffffff,0xffffff,0xffffff,0xffffff},{0x400000,0x400002,0x400004,0x400006},0,0,0,0,default_regs_r,0}},
/* Ya-Se Chuanshuo */ /* Ya-Se Chuanshuo */
{0xffff,0xd472,8,8,{{0x63,0x98,0xc9,0x18},{0xffffff,0xffffff,0xffffff,0xffffff},{0x400000,0x400002,0x400004,0x400006},0,0,0,default_regs_r,0}}, {0xffff,0xd472,0x40,0x40,{{0x63,0x98,0xc9,0x18},{0xffffff,0xffffff,0xffffff,0xffffff},{0x400000,0x400002,0x400004,0x400006},0,0,0,0,default_regs_r,0}},
/* Soul Blade */ /* Soul Blade */
{0x0000,0x0c5b,8,8,{{0x00,0x98,0xc9,0xF0},{0xffffff,0xffffff,0xffffff,0xffffff},{0x400000,0x400002,0x400004,0x400006},0,0,0,default_regs_r,0}}, {0x0000,0x0c5b,0x40,0x40,{{0x00,0x98,0xc9,0xF0},{0xffffff,0xffffff,0xffffff,0xffffff},{0x400000,0x400002,0x400004,0x400006},0,0,0,0,default_regs_r,0}},
/* King of Fighter 98 */ /* King of Fighter 98 */
{0x0000,0xd0a0,9,9,{{0xaa,0xa0,0xf0,0xa0},{0xfc0000,0xffffff,0xffffff,0xffffff},{0x480000,0x4c82c0,0x4cdda0,0x4f8820},0,0,0,default_regs_r,0}}, {0x0000,0xd0a0,0x48,0x4f,{{0xaa,0xa0,0xf0,0xa0},{0xfc0000,0xffffff,0xffffff,0xffffff},{0x480000,0x4c82c0,0x4cdda0,0x4f8820},0,0,0,0,default_regs_r,0}},
/* Lian Huan Pao - Barver Battle Saga */ /* Lian Huan Pao - Barver Battle Saga */
{0x30b9,0x1c2a,8,8,{{0,0,0,0},{0,0,0,0},{0,0,0,0},0,0,0,default_regs_r,0}} {0x30b9,0x1c2a,0x40,0x40,{{0,0,0,0},{0,0,0,0},{0,0,0,0},0,0,0,0,default_regs_r,0}}
}; };
/* current cart hardware */ /* previous inputs */
T_CART_HW cart_hw; static int old_system[2] = {-1,-1};
uint8 j_cart;
int old_system[2] = {-1,-1}; /* temporary memory chunk */
uint8 mem_chunk[0x10000];
/************************************************************ /************************************************************
Cart Hardware initialization Cart Hardware initialization
@ -122,16 +124,27 @@ int old_system[2] = {-1,-1};
/* hardware that need to be reseted on power on */ /* hardware that need to be reseted on power on */
void cart_hw_reset() void cart_hw_reset()
{ {
int i;
/* reset bankshifting */
if (cart_hw.bankshift)
{
for (i=0x00; i<0x40; i++)
m68k_memory_map[i].base = cart_rom + (i<<16);
}
/* Realtec mapper */ /* Realtec mapper */
if (cart_hw.realtec & 1) if (cart_hw.realtec & 1)
{ {
int i;
/* enable BOOTROM */ /* enable BOOTROM */
for (i=0; i<8; i++) m68k_readmap_16[i] = REALTEC_ROM; for (i=0; i<0x40; i++) m68k_memory_map[i].base = mem_chunk;
for (i=0; i<8; i++) memcpy(mem_chunk + i*0x2000, cart_rom + 0x7e000, 0x2000);
cart_hw.realtec |= 2; cart_hw.realtec |= 2;
} }
/* save default cartridge slot mapping */
default_rom = m68k_memory_map[0].base;
/* SVP chip */ /* SVP chip */
if (svp) svp_reset(); if (svp) svp_reset();
} }
@ -142,22 +155,29 @@ void cart_hw_init()
int i; int i;
/********************************************** /**********************************************
DEFAULT CART MAPPING DEFAULT CARTRIDGE MAPPING
***********************************************/ ***********************************************/
for (i=0; i<8; i++) for (i=0; i<0x40; i++)
{ {
m68k_readmap_8[i] = ROM; /* cartridge ROM */
m68k_readmap_16[i] = ROM; m68k_memory_map[i].base = cart_rom + (i<<16);
m68k_writemap_8[i] = UNUSED; m68k_memory_map[i].read8 = NULL;
m68k_writemap_16[i] = UNUSED; m68k_memory_map[i].read16 = NULL;
m68k_memory_map[i].write8 = m68k_unused_8_w;
m68k_memory_map[i].write16 = m68k_unused_16_w;
zbank_memory_map[i].read = NULL;
zbank_memory_map[i].write = zbank_unused_w;
} }
for (i=8; i<16; i++) for (i=0x40; i<0x80; i++)
{ {
m68k_readmap_8[i] = UNUSED; /* unused area */
m68k_readmap_16[i] = UNUSED; m68k_memory_map[i].read8 = m68k_read_bus_8;
m68k_writemap_8[i] = UNUSED; m68k_memory_map[i].read16 = m68k_read_bus_16;
m68k_writemap_16[i] = UNUSED; m68k_memory_map[i].write8 = m68k_unused_8_w;
m68k_memory_map[i].write16 = m68k_unused_16_w;
zbank_memory_map[i].read = zbank_unused_r;
zbank_memory_map[i].write = zbank_unused_w;
} }
/* restore previous setting */ /* restore previous setting */
@ -174,25 +194,29 @@ void cart_hw_init()
if (sram.custom) if (sram.custom)
{ {
/* serial EEPROM */ /* serial EEPROM */
m68k_readmap_8[eeprom.type.sda_out_adr >> 19] = EEPROM; m68k_memory_map[eeprom.type.sda_out_adr >> 16].read8 = eeprom_read_byte;
m68k_readmap_16[eeprom.type.sda_out_adr >> 19] = EEPROM; m68k_memory_map[eeprom.type.sda_out_adr >> 16].read16 = eeprom_read_word;
m68k_writemap_8[eeprom.type.sda_in_adr >> 19] = EEPROM; m68k_memory_map[eeprom.type.sda_in_adr >> 16].read8 = eeprom_read_byte;
m68k_writemap_16[eeprom.type.sda_in_adr >> 19] = EEPROM; m68k_memory_map[eeprom.type.sda_in_adr >> 16].read16 = eeprom_read_word;
m68k_writemap_8[eeprom.type.scl_adr >> 19] = EEPROM; m68k_memory_map[eeprom.type.scl_adr >> 16].write8 = eeprom_write_byte;
m68k_writemap_16[eeprom.type.scl_adr >> 19] = EEPROM; m68k_memory_map[eeprom.type.scl_adr >> 16].write16 = eeprom_write_word;
zbank_memory_map[eeprom.type.sda_out_adr >> 16].read = eeprom_read_byte;
zbank_memory_map[eeprom.type.sda_in_adr >> 16].read = eeprom_read_byte;
zbank_memory_map[eeprom.type.scl_adr >> 16].write = eeprom_write_byte;
} }
else else
{ {
/* 64KB SRAM */ /* Static RAM (64k max.) */
m68k_readmap_8[sram.start >> 19] = SRAM; m68k_memory_map[sram.start >> 16].base = sram.sram;
m68k_readmap_16[sram.start >> 19] = SRAM; m68k_memory_map[sram.start >> 16].read8 = NULL;
if (sram.write) m68k_memory_map[sram.start >> 16].read16 = NULL;
{ m68k_memory_map[sram.start >> 16].write8 = NULL;
m68k_writemap_8[sram.start >> 19] = SRAM; m68k_memory_map[sram.start >> 16].write16 = NULL;
m68k_writemap_16[sram.start >> 19] = SRAM; zbank_memory_map[sram.start >> 16].read = NULL;
} zbank_memory_map[sram.start >> 16].write = NULL;
} }
} }
/********************************************** /**********************************************
SVP CHIP SVP CHIP
***********************************************/ ***********************************************/
@ -200,12 +224,20 @@ void cart_hw_init()
if (strstr(rominfo.international,"Virtua Racing") != NULL) if (strstr(rominfo.international,"Virtua Racing") != NULL)
{ {
svp_init(); svp_init();
m68k_readmap_16[6] = SVP_DRAM;
m68k_writemap_16[6] = SVP_DRAM; m68k_memory_map[0x30].base = svp->dram;
m68k_readmap_16[7] = SVP_CELL; m68k_memory_map[0x30].read16 = NULL;
m68k_writemap_16[7] = SVP_CELL; m68k_memory_map[0x30].write16 = svp_write_dram;
m68k_memory_map[0x31].base = svp->dram + 0x10000;
m68k_memory_map[0x31].read16 = NULL;
m68k_memory_map[0x31].write16 = svp_write_dram;
m68k_memory_map[0x39].read16 = svp_read_cell_1;
m68k_memory_map[0x3a].read16 = svp_read_cell_2;
} }
/* default GUN settings */ /* default GUN settings */
input.x_offset = 0x00; input.x_offset = 0x00;
input.y_offset = 0x00; input.y_offset = 0x00;
@ -289,8 +321,10 @@ void cart_hw_init()
if (genromsize <= 0x380000) /* just to be sure (checksum might not be enough) */ if (genromsize <= 0x380000) /* just to be sure (checksum might not be enough) */
{ {
j_cart = 1; j_cart = 1;
m68k_readmap_16[7] = J_CART; m68k_memory_map[0x38].read16 = jcart_read;
m68k_writemap_16[7] = J_CART; m68k_memory_map[0x38].write16 = jcart_write;
m68k_memory_map[0x3f].read16 = jcart_read;
m68k_memory_map[0x3f].write16 = jcart_write;
/* save current setting */ /* save current setting */
if (old_system[0] == -1) old_system[0] = input.system[0]; if (old_system[0] == -1) old_system[0] = input.system[0];
@ -302,27 +336,6 @@ void cart_hw_init()
} }
} }
/**********************************************
ULTIMATE MK3 HACK
***********************************************/
if (genromsize > 0x600000)
{
for (i=8; i<20; i++)
{
m68k_readmap_8[i] = UMK3_HACK;
m68k_readmap_16[i] = UMK3_HACK;
}
#if M68K_EMULATE_ADDRESS_ERROR
/* this game does not work properly on real hardware */
emulate_address_error = 0;
#endif
}
#if M68K_EMULATE_ADDRESS_ERROR
/* default behavior */
else emulate_address_error = 1;
#endif
/********************************************** /**********************************************
Mappers & HW registers Mappers & HW registers
***********************************************/ ***********************************************/
@ -345,13 +358,53 @@ void cart_hw_init()
int j = rom_database[i].bank_start; int j = rom_database[i].bank_start;
while (j <= rom_database[i].bank_end) while (j <= rom_database[i].bank_end)
{ {
if (cart_hw.regs_r) m68k_readmap_8[j] = CART_HW; if (cart_hw.regs_r)
if (cart_hw.regs_w) m68k_writemap_8[j] = CART_HW; {
m68k_memory_map[j].read8 = cart_hw.regs_r;
m68k_memory_map[j].read16 = cart_hw.regs_r;
zbank_memory_map[j].read = cart_hw.regs_r;
}
if (cart_hw.regs_w)
{
m68k_memory_map[j].write8 = cart_hw.regs_w;
m68k_memory_map[j].write16 = cart_hw.regs_w;
zbank_memory_map[j].write = cart_hw.regs_w;
}
j++; j++;
} }
/* leave loop */
i = CART_CNT + 1; i = CART_CNT + 1;
} }
} }
#if M68K_EMULATE_ADDRESS_ERROR
/* default behavior */
emulate_address_error = 1;
#endif
/* detect ROM files larger than 4MB */
if (genromsize > 0x800000)
{
/* Ultimate MK3 (hack) */
for (i=0x40; i<0xA0; i++)
{
m68k_memory_map[i].base = cart_rom + (i<<16);
m68k_memory_map[i].read8 = NULL;
m68k_memory_map[i].read16 = NULL;
zbank_memory_map[i].read = NULL;
}
#if M68K_EMULATE_ADDRESS_ERROR
/* this game does not work properly on real hardware */
emulate_address_error = 0;
#endif
}
else if (genromsize > 0x400000)
{
/* assume SSF2 mapper */
cart_hw.bankshift = 1;
}
} }
/************************************************************ /************************************************************
@ -360,190 +413,167 @@ void cart_hw_init()
/* /*
"official" ROM/RAM switch "official" ROM/RAM switch
*/ */
static inline void sega_mapper_w(unsigned int address, unsigned int value) static inline void sega_mapper_w(uint32 address, uint32 data)
{ {
uint8 bank = (address >> 1) & 7; uint32 i,slot = (address >> 1) & 7;
uint8 *src;
switch (bank) switch (slot)
{ {
case 0: case 0:
/* ROM/SRAM switch (Phantasy Star IV, Story of Thor/Beyond Oasis, Sonic 3 & Knuckles) */
if (data & 1)
{ {
/* ROM/RAM switch (Phantasy Star IV, Story of Thor/Beyond Oasis, Sonic 3 & Knuckles) */ /* SRAM enabled */
if (value & 1) m68k_memory_map[0x20].base = sram.sram;
{
/* SRAM is mapped above 200000h */
m68k_readmap_8[4] = SRAM;
m68k_readmap_16[4] = SRAM;
if (value & 2) if (data & 2)
{ {
/* SRAM write protected */ /* SRAM write disabled */
m68k_writemap_8[4] = UNUSED; m68k_memory_map[0x20].write8 = m68k_unused_8_w;
m68k_writemap_16[4] = UNUSED; m68k_memory_map[0x20].write16 = m68k_unused_16_w;
zbank_memory_map[0x20].write = zbank_unused_w;
} }
else else
{ {
/* SRAM write enabled */ /* SRAM write enabled */
m68k_writemap_8[4] = SRAM; m68k_memory_map[0x20].write8 = NULL;
m68k_writemap_16[4] = SRAM; m68k_memory_map[0x20].write16 = NULL;
zbank_memory_map[0x20].write = NULL;
} }
} }
else else
{ {
/* ROM is mapped above 200000h */ /* ROM enabled */
m68k_readmap_8[4] = ROM; m68k_memory_map[0x20].base = cart_rom + 0x200000;
m68k_readmap_16[4] = ROM;
m68k_writemap_8[4] = UNUSED;
m68k_writemap_16[4] = UNUSED;
} }
break; break;
}
default: default:
/* ROM Bankswitch (Super Street Fighter 2) /* ROM Bankswitch (Super Street Fighter 2)
documented by Bart Trzynadlowski (http://www.trzy.org/files/ssf2.txt) documented by Bart Trzynadlowski (http://www.trzy.org/files/ssf2.txt)
*/ */
rom_readmap[bank] = &cart_rom[value << 19]; slot = slot << 3; /* 8 x 512k banks */
src = cart_rom + (data << 19);
for (i=0; i<8; i++) m68k_memory_map[slot++].base = src + (i<<16);
break; break;
} }
} }
/* /*
custom ROM Bankswitch used by pirate "Multi-in-1" carts custom ROM Bankswitch used by pirate "Multi-in-1" carts
(documented by Haze)
*/ */
static inline void multi_mapper_w(unsigned int address, unsigned int value) static inline void multi_mapper_w(uint32 address, uint32 data)
{ {
int i; int i;
uint32 bank_addr = (address & 0x3F) << 16;
/* those games are generally not bigger than 1MB but it's safer to update all 512K banks */ cart_hw.bankshift = 1;
for (i=0; i<8; i++)
/* 64 x 64k banks */
for (i=0; i<64; i++)
{ {
if (bank_addr >= genromsize) return; m68k_memory_map[i].base = &cart_rom[((address++) & 0x3f) << 16];
rom_readmap[i] = &cart_rom[bank_addr];
bank_addr += 0x80000;
} }
} }
/* /*
Special ROM Bankswitch used for copy protection Special ROM Bankswitch used for copy protection
Used by unlicensed cartridges (Lion King III, Super King Kong 99) Used by unlicensed cartridges (Lion King III, Super King Kong 99)
(documented by Haze)
*/ */
void special_mapper_w(unsigned int address, unsigned int value) void special_mapper_w(uint32 address, uint32 data)
{ {
rom_readmap[0] = &cart_rom[value << 15]; /* 1 x 32k bank */
m68k_memory_map[0].base = mem_chunk;
memcpy(mem_chunk,&cart_rom[(data & 0x7f) << 15],0x8000);
memcpy(mem_chunk+0x8000,cart_rom + 0x8000,0x8000);
} }
/* /*
Realtec ROM Bankswitch (Earth Defend, Balloon Boy & Funny World, Whac-A-Critter) Realtec ROM Bankswitch (Earth Defend, Balloon Boy & Funny World, Whac-A-Critter)
(documented by TascoDeluxe)
*/ */
void realtec_mapper_w(unsigned int address, unsigned int value) void realtec_mapper_w(uint32 address, uint32 data)
{
uint32 base_addr;
if (cart_hw.realtec & 2)
{ {
int i; int i;
cart_hw.realtec &= ~2; uint32 base;
/* disable Realtec BOOTROM */
for (i=0; i<8; i++)
{
m68k_readmap_8[i] = ROM;
m68k_readmap_16[i] = ROM;
}
}
/* 32 x 128k banks */
switch (address) switch (address)
{ {
case 0x404000: /* three lower bits of ROM base address */ case 0x404000: /* three lower bits of ROM base address */
cart_hw.regs[0] = value; cart_hw.regs[0] = data & 7;
base_addr = (value | ((cart_hw.regs[1] & 6) << 2)) << 17; base = ((data & 7) | (cart_hw.regs[1] << 2));
rom_readmap[0] = &cart_rom[base_addr]; for (i=0; i<=cart_hw.regs[2]; i++)
{
m68k_memory_map[i*2].base = &cart_rom[((base + i)*2 & 0x3f) << 16];
m68k_memory_map[i*2+1].base = &cart_rom[(((base + i)*2 + 1) & 0x3f) << 16];
}
return; return;
case 0x400000: /* two higher bits of ROM base address */ case 0x400000: /* two higher bits of ROM base address */
cart_hw.regs[1] = value; cart_hw.regs[1] = data & 6;
base_addr = ((cart_hw.regs[0] & 7) | ((value & 6) << 2)) << 17; base = cart_hw.regs[0] | ((data & 6) << 2);
rom_readmap[0] = &cart_rom[base_addr]; for (i=0; i<=cart_hw.regs[2]; i++)
{
m68k_memory_map[i*2].base = &cart_rom[((base + i)*2 & 0x3f) << 16];
m68k_memory_map[i*2+1].base = &cart_rom[(((base + i)*2 + 1) & 0x3f) << 16];
}
return; return;
case 0x402000: /* size of ROM range to map */ case 0x402000: /* number of 128k blocks to map */
cart_hw.regs[2] = value; cart_hw.regs[2] = data & 0x1f;
base = cart_hw.regs[0] | (cart_hw.regs[1] << 2);
for (i=0; i<=(data & 0x1f); i++)
{
m68k_memory_map[i*2].base = &cart_rom[((base + i)*2 & 0x3f) << 16];
m68k_memory_map[i*2+1].base = &cart_rom[(((base + i)*2 + 1) & 0x3f) << 16];
}
return; return;
default:
return;
} }
} }
/* Game no Kanzume Otokuyou ROM Mapper */ /* Game no Kanzume Otokuyou ROM Mapper */
void seganet_mapper_w(unsigned int address, unsigned int value) void seganet_mapper_w(uint32 address, uint32 data)
{ {
if ((address & 0xff) == 0xf1)
{
int i; int i;
switch (address & 0xff) if (data & 1)
{ {
case 0x01: /* ROM Write protected */
if (value & 1) for (i=0; i<0x40; i++)
{ {
/* ROM disabled */ m68k_memory_map[i].write8 = m68k_unused_8_w;
for (i=0; i<8; i++) m68k_memory_map[i].write16 = m68k_unused_16_w;
{ zbank_memory_map[i].write = zbank_unused_w;
m68k_readmap_8[i] = UNUSED;
m68k_readmap_16[i] = UNUSED;
}
}
else
{
/* ROM enabled */
for (i=0; i<8; i++)
{
m68k_readmap_8[i] = ROM;
m68k_readmap_16[i] = ROM;
}
}
break;;
case 0xf1:
if (value & 1)
{
/* ROM Write protected*/
for (i=0; i<8; i++)
{
m68k_writemap_8[i] = UNUSED;
m68k_writemap_16[i] = UNUSED;
} }
} }
else else
{ {
/* ROM Write enabled */ /* ROM Write enabled */
for (i=0; i<8; i++) for (i=0; i<0x40; i++);
{ {
m68k_writemap_8[i] = ROM; m68k_memory_map[i].write8 = NULL;
m68k_writemap_16[i] = ROM; m68k_memory_map[i].write16 = NULL;
zbank_memory_map[i].write = NULL;
} }
} }
break;
default:
break;
} }
} }
/* /*
RADICA ROM Bankswitch RADICA ROM Bankswitch (use !TIME)
(documented by Haze)
*/ */
unsigned int radica_mapper_r(unsigned int address) uint32 radica_mapper_r(uint32 address)
{ {
/* 64KB ROM banks */ int i = 0;
uint8 bank = (address >> 1) & 0x3F; address = (address >> 1);
rom_readmap[0] = &cart_rom[bank * 0x10000];
rom_readmap[1] = &cart_rom[bank * 0x10000 + 0x80000]; /* ROM is max. 1MB */ /* 64 x 64k banks */
for (i = 0; i < 64; i++)
{
m68k_memory_map[i].base = &cart_rom[((address++)& 0x3f)<< 16];
}
return 0xff; return 0xff;
} }
@ -553,19 +583,20 @@ unsigned int radica_mapper_r(unsigned int address)
*************************************************************/ *************************************************************/
/* default ROM bankswitch */ /* default ROM bankswitch */
void default_time_w(unsigned int address, unsigned int value) void default_time_w(uint32 address, uint32 data)
{ {
if ((address & 0xf1) == 0xf1) sega_mapper_w(address, value); if ((address & 0xf1) == 0xf1) sega_mapper_w(address, data);
else if (address < 0xa13040) multi_mapper_w(address, value); else if (address < 0xa13040) multi_mapper_w(address, data);
} }
/************************************************************ /************************************************************
Internal register handlers Internal register handlers
*************************************************************/ *************************************************************/
unsigned int default_regs_r(unsigned int address) uint32 default_regs_r(uint32 address)
{ {
uint8 i; int i;
for (i=0; i<4; i++) for (i=0; i<4; i++)
{ {
if ((address & cart_hw.mask[i]) == cart_hw.addr[i]) if ((address & cart_hw.mask[i]) == cart_hw.addr[i])
@ -573,36 +604,36 @@ unsigned int default_regs_r(unsigned int address)
} }
/* unused */ /* unused */
return -1; return 0xffff;
} }
void default_regs_w(unsigned int address, unsigned int value) void default_regs_w(uint32 address, uint32 data)
{ {
uint8 i; int i;
for (i=0; i<4; i++) for (i=0; i<4; i++)
{ {
if ((address & cart_hw.mask[i]) == cart_hw.addr[i]) if ((address & cart_hw.mask[i]) == cart_hw.addr[i])
{ {
cart_hw.regs[i] = value; cart_hw.regs[i] = data;
} }
} }
} }
/* special register behaviour (Lion King III, Super Donkey Kong 99) */ /* special register behaviour (Lion King III, Super Donkey Kong 99) */
void special_regs_w(unsigned int address, unsigned int value) void special_regs_w(uint32 address, uint32 data)
{ {
/* ROM bankswitch */ /* ROM bankswitch */
if ((address >> 16) > 0x6f) if ((address >> 16) > 0x6f)
{ {
special_mapper_w(address, value); special_mapper_w(address, data);
return; return;
} }
/* write regs */ /* write regs */
default_regs_w(address, value); default_regs_w(address, data);
/* bitswapping (documented by Haze) */ /* bitswapping (documented by Haze) */
uint8 temp = cart_hw.regs[0]; uint32 temp = cart_hw.regs[0];
switch (cart_hw.regs[1]) switch (cart_hw.regs[1])
{ {
case 1: case 1:

View File

@ -33,7 +33,8 @@ typedef struct
uint8 regs[4]; /* internal registers (R/W) */ uint8 regs[4]; /* internal registers (R/W) */
uint32 mask[4]; /* registers address mask */ uint32 mask[4]; /* registers address mask */
uint32 addr[4]; /* registers address */ uint32 addr[4]; /* registers address */
uint8 realtec; /* bit 0: realtec mapper detected, bit 1: bootrom enabled */ uint32 realtec; /* bit 0: realtec mapper detected, bit 1: bootrom enabled */
uint32 bankshift; /* cartridge with bankshift mecanism */
unsigned int (*time_r)(unsigned int address); /* !TIME signal ($a130xx) read handler */ unsigned int (*time_r)(unsigned int address); /* !TIME signal ($a130xx) read handler */
void (*time_w)(unsigned int address, unsigned int data); /* !TIME signal ($a130xx) write handler */ void (*time_w)(unsigned int address, unsigned int data); /* !TIME signal ($a130xx) write handler */
unsigned int (*regs_r)(unsigned int address); /* cart hardware region ($400000-$7fffff) read handler */ unsigned int (*regs_r)(unsigned int address); /* cart hardware region ($400000-$7fffff) read handler */
@ -41,8 +42,9 @@ typedef struct
} T_CART_HW; } T_CART_HW;
/* global variables */ /* global variables */
extern T_CART_HW cart_hw; T_CART_HW cart_hw;
extern uint8 j_cart; uint8 j_cart;
uint8 *default_rom;
/* Function prototypes */ /* Function prototypes */
extern void cart_hw_reset(); extern void cart_hw_reset();

View File

@ -24,3 +24,25 @@ void svp_reset(void)
memcpy(svp->iram_rom + 0x800, cart_rom + 0x800, 0x20000 - 0x800); memcpy(svp->iram_rom + 0x800, cart_rom + 0x800, 0x20000 - 0x800);
ssp1601_reset(&svp->ssp1601); ssp1601_reset(&svp->ssp1601);
} }
void svp_write_dram(uint32 address, uint32 data)
{
*(uint16 *)(svp->dram + (address & 0x1fffe)) = data;
if ((address == 0x30fe06) && data) svp->ssp1601.emu_status &= ~SSP_WAIT_30FE06;
if ((address == 0x30fe08) && data) svp->ssp1601.emu_status &= ~SSP_WAIT_30FE08;
}
uint32 svp_read_cell_1(uint32 address)
{
address >>= 1;
address = (address & 0x7001) | ((address & 0x3e) << 6) | ((address & 0xfc0) >> 5);
return *(uint16 *)(svp->dram + (address & 0x1fffe));
}
uint32 svp_read_cell_2(uint32 address)
{
address >>= 1;
address = (address & 0x7801) | ((address & 0x1e) << 6) | ((address & 0x7e0) >> 4);
return *(uint16 *)(svp->dram + (address & 0x1fffe));
}

View File

@ -26,5 +26,8 @@ extern uint16 SVP_cycles;
extern void svp_init(void); extern void svp_init(void);
extern void svp_reset(void); extern void svp_reset(void);
extern void svp_write_dram(uint32 address, uint32 data);
extern uint32 svp_read_cell_1(uint32 address);
extern uint32 svp_read_cell_2(uint32 address);
#endif #endif

View File

@ -77,23 +77,25 @@ static inline void lightgun_update(int num)
if (io_reg[5] & 0x80) if (io_reg[5] & 0x80)
{ {
/* External Interrupt ? */ /* External Interrupt ? */
if (reg[11] & 0x08) m68k_set_irq(2); if (reg[11] & 0x08) {irq_status &= 0xff; irq_status |= 0x12;}
/* HVC Latch: /* HVC Latch:
1) some games does not set HVC latch but instead use bigger X offset 1) some games does not set HVC latch but instead use bigger X offset
2) for games using H40 mode, the gun routine scales up the Hcounter value, 2) for games using H40 mode, the gun routine scales up the Hcounter value,
H-Counter range is approx. 292 pixel clocks H-Counter range is approx. 292 pixel clocks
*/ */
hc_latch = 0x100;
if (reg[12] & 1) if (reg[12] & 1)
hc_latch = hc_320[((input.analog[num][0] * 290) / (2 * 320) + input.x_offset) % 210]; hc_latch |= hc_320[((input.analog[num][0] * 290) / (2 * 320) + input.x_offset) % 210];
else else
hc_latch = hc_256[(input.analog[num][0] / 2 + input.x_offset)%171]; hc_latch |= hc_256[(input.analog[num][0] / 2 + input.x_offset)%171];
} }
} }
} }
/* Sega Menacer specific */ /* Sega Menacer specific */
unsigned int menacer_read() uint32 menacer_read()
{ {
/* pins should return 0 by default (fix Body Count when mouse is enabled) */ /* pins should return 0 by default (fix Body Count when mouse is enabled) */
int retval = 0x00; int retval = 0x00;
@ -106,7 +108,7 @@ unsigned int menacer_read()
} }
/* Konami Justifier specific */ /* Konami Justifier specific */
unsigned int justifier_read() uint32 justifier_read()
{ {
/* TL & TR pins should always return 1 (write only) */ /* TL & TR pins should always return 1 (write only) */
/* LEFT & RIGHT pins should always return 0 (needed during gun detection) */ /* LEFT & RIGHT pins should always return 0 (needed during gun detection) */
@ -152,7 +154,7 @@ static inline void mouse_reset()
mouse.Port = (input.system[0] == SYSTEM_MOUSE) ? 0 : 4; mouse.Port = (input.system[0] == SYSTEM_MOUSE) ? 0 : 4;
} }
void mouse_write(unsigned int data) void mouse_write(uint32 data)
{ {
if (mouse.Counter == 0) if (mouse.Counter == 0)
{ {
@ -182,7 +184,7 @@ void mouse_write(unsigned int data)
mouse.State = data; mouse.State = data;
} }
unsigned int mouse_read() uint32 mouse_read()
{ {
int temp = 0x00; int temp = 0x00;
@ -263,24 +265,24 @@ struct pad
uint8 Delay; uint8 Delay;
} gamepad[MAX_DEVICES]; } gamepad[MAX_DEVICES];
static inline void gamepad_raz(unsigned int i) static inline void gamepad_raz(uint32 i)
{ {
gamepad[i].Counter = 0; gamepad[i].Counter = 0;
gamepad[i].Delay = 0; gamepad[i].Delay = 0;
} }
static inline void gamepad_reset(unsigned int i) static inline void gamepad_reset(uint32 i)
{ {
gamepad[i].State = 0x40; gamepad[i].State = 0x40;
if (input.dev[i] == DEVICE_6BUTTON) gamepad_raz(i); if (input.dev[i] == DEVICE_6BUTTON) gamepad_raz(i);
} }
static inline void gamepad_update(unsigned int i) static inline void gamepad_update(uint32 i)
{ {
if (gamepad[i].Delay++ > 25) gamepad_raz(i); if (gamepad[i].Delay++ > 25) gamepad_raz(i);
} }
static inline unsigned int gamepad_read(unsigned int i) static inline uint32 gamepad_read(uint32 i)
{ {
int control; int control;
int retval = 0x7F; int retval = 0x7F;
@ -365,7 +367,7 @@ static inline unsigned int gamepad_read(unsigned int i)
return retval; return retval;
} }
static inline void gamepad_write(unsigned int i, unsigned int data) static inline void gamepad_write(uint32 i, uint32 data)
{ {
if (input.dev[i] == DEVICE_6BUTTON) if (input.dev[i] == DEVICE_6BUTTON)
{ {
@ -392,7 +394,7 @@ struct teamplayer
uint8 Table[12]; uint8 Table[12];
} teamplayer[2]; } teamplayer[2];
static inline void teamplayer_reset(unsigned int port) static inline void teamplayer_reset(uint32 port)
{ {
int i; int i;
int index = 0; int index = 0;
@ -433,7 +435,7 @@ static inline void teamplayer_reset(unsigned int port)
2/ START,A,C,B buttons 2/ START,A,C,B buttons
3/ MODE, X,Y,Z buttons (6Button only !) 3/ MODE, X,Y,Z buttons (6Button only !)
*/ */
static inline unsigned int teamplayer_read_device(unsigned int port, unsigned int index) static inline uint32 teamplayer_read_device(uint32 port, uint32 index)
{ {
int retval = 0x7F; int retval = 0x7F;
int pad_input = teamplayer[port].Table[index] & 0x03; int pad_input = teamplayer[port].Table[index] & 0x03;
@ -469,7 +471,7 @@ static inline unsigned int teamplayer_read_device(unsigned int port, unsigned in
return retval; return retval;
} }
static inline unsigned int teamplayer_read(unsigned int port) static inline uint32 teamplayer_read(uint32 port)
{ {
int retval = 0x7F; int retval = 0x7F;
int padnum; int padnum;
@ -509,7 +511,7 @@ static inline unsigned int teamplayer_read(unsigned int port)
return retval; return retval;
} }
static inline void teamplayer_write(unsigned int port, unsigned int data) static inline void teamplayer_write(uint32 port, uint32 data)
{ {
int old_state = teamplayer[port].State; int old_state = teamplayer[port].State;
teamplayer[port].State = (data & io_reg[port+4]) | (teamplayer[port].State & ~io_reg[port+4]); teamplayer[port].State = (data & io_reg[port+4]) | (teamplayer[port].State & ~io_reg[port+4]);
@ -521,13 +523,13 @@ static inline void teamplayer_write(unsigned int port, unsigned int data)
* 4WAYPLAY adapter * 4WAYPLAY adapter
* *
*****************************************************************************/ *****************************************************************************/
static inline void wayplay_write(unsigned int port, unsigned int data) static inline void wayplay_write(uint32 port, uint32 data)
{ {
if (port == 0) gamepad_write(input.current, data); if (port == 0) gamepad_write(input.current, data);
else input.current = (data >> 4) & 0x07; else input.current = (data >> 4) & 0x07;
} }
static inline unsigned int wayplay_read(unsigned int port) static inline uint32 wayplay_read(uint32 port)
{ {
if (port == 1) return 0x7F; if (port == 1) return 0x7F;
if (input.current >= 4) return 0x70; /* multitap detection (TH2 = 1) */ if (input.current >= 4) return 0x70; /* multitap detection (TH2 = 1) */
@ -539,72 +541,72 @@ static inline unsigned int wayplay_read(unsigned int port)
* I/O wrappers * I/O wrappers
* *
*****************************************************************************/ *****************************************************************************/
unsigned int gamepad_1_read (void) uint32 gamepad_1_read (void)
{ {
return gamepad_read(0); return gamepad_read(0);
} }
unsigned int gamepad_2_read (void) uint32 gamepad_2_read (void)
{ {
return gamepad_read(4); return gamepad_read(4);
} }
void gamepad_1_write (unsigned int data) void gamepad_1_write (uint32 data)
{ {
gamepad_write(0, data); gamepad_write(0, data);
} }
void gamepad_2_write (unsigned int data) void gamepad_2_write (uint32 data)
{ {
gamepad_write(4, data); gamepad_write(4, data);
} }
unsigned int wayplay_1_read (void) uint32 wayplay_1_read (void)
{ {
return wayplay_read(0); return wayplay_read(0);
} }
unsigned int wayplay_2_read (void) uint32 wayplay_2_read (void)
{ {
return wayplay_read(1); return wayplay_read(1);
} }
void wayplay_1_write (unsigned int data) void wayplay_1_write (uint32 data)
{ {
wayplay_write(0, data); wayplay_write(0, data);
} }
void wayplay_2_write (unsigned int data) void wayplay_2_write (uint32 data)
{ {
wayplay_write(1, data); wayplay_write(1, data);
} }
unsigned int teamplayer_1_read (void) uint32 teamplayer_1_read (void)
{ {
return teamplayer_read(0); return teamplayer_read(0);
} }
unsigned int teamplayer_2_read (void) uint32 teamplayer_2_read (void)
{ {
return teamplayer_read(1); return teamplayer_read(1);
} }
void teamplayer_1_write (unsigned int data) void teamplayer_1_write (uint32 data)
{ {
teamplayer_write(0, data); teamplayer_write(0, data);
} }
void teamplayer_2_write (unsigned int data) void teamplayer_2_write (uint32 data)
{ {
teamplayer_write(1, data); teamplayer_write(1, data);
} }
unsigned int jcart_read(void) uint32 jcart_read(uint32 address)
{ {
return (gamepad_read(5) | ((gamepad_read(6)&0x3f) << 8)); /* fixes Micro Machines 2 (is it correct ?) */ return (gamepad_read(5) | ((gamepad_read(6)&0x3f) << 8)); /* fixes Micro Machines 2 (is it correct ?) */
} }
void jcart_write(unsigned int data) void jcart_write(uint32 address, uint32 data)
{ {
gamepad_write(5, (data&1) << 6); gamepad_write(5, (data&1) << 6);
gamepad_write(6, (data&1) << 6); gamepad_write(6, (data&1) << 6);

View File

@ -90,23 +90,23 @@ extern void input_update(void);
extern void input_raz(void); extern void input_raz(void);
/* Peripherals specific */ /* Peripherals specific */
extern void mouse_write(unsigned int data); extern void mouse_write(uint32 data);
extern unsigned int mouse_read(void); extern uint32 mouse_read(void);
extern unsigned int menacer_read (void); extern uint32 menacer_read (void);
extern unsigned int justifier_read (void); extern uint32 justifier_read (void);
extern unsigned int gamepad_1_read (void); extern uint32 gamepad_1_read (void);
extern unsigned int gamepad_2_read (void); extern uint32 gamepad_2_read (void);
extern void gamepad_1_write (unsigned int data); extern void gamepad_1_write (uint32 data);
extern void gamepad_2_write (unsigned int data); extern void gamepad_2_write (uint32 data);
extern unsigned int wayplay_1_read (void); extern uint32 wayplay_1_read (void);
extern unsigned int wayplay_2_read (void); extern uint32 wayplay_2_read (void);
extern void wayplay_1_write (unsigned int data); extern void wayplay_1_write (uint32 data);
extern void wayplay_2_write (unsigned int data); extern void wayplay_2_write (uint32 data);
extern unsigned int teamplayer_1_read (void); extern uint32 teamplayer_1_read (void);
extern unsigned int teamplayer_2_read (void); extern uint32 teamplayer_2_read (void);
extern void teamplayer_1_write (unsigned int data); extern void teamplayer_1_write (uint32 data);
extern void teamplayer_2_write (unsigned int data); extern void teamplayer_2_write (uint32 data);
extern unsigned int jcart_read(void); extern uint32 jcart_read(uint32 address);
extern void jcart_write(unsigned int data); extern void jcart_write(uint32 address, uint32 data);
#endif #endif

View File

@ -24,7 +24,7 @@
#include "shared.h" #include "shared.h"
uint8 *cart_rom; /* cart_rom NEED to be previously dynamically allocated */ uint8 *cart_rom; /* cart_rom NEED to be previously dynamically allocated */
uint8 bios_rom[0x800]; uint8 bios_rom[0x10000];
uint8 work_ram[0x10000]; /* 68K work RAM */ uint8 work_ram[0x10000]; /* 68K work RAM */
uint8 zram[0x2000]; /* Z80 work RAM */ uint8 zram[0x2000]; /* Z80 work RAM */
uint8 zbusreq; /* /BUSREQ from Z80 */ uint8 zbusreq; /* /BUSREQ from Z80 */
@ -34,9 +34,8 @@ uint8 zirq; /* /IRQ to Z80 */
uint32 zbank; /* Address of Z80 bank window */ uint32 zbank; /* Address of Z80 bank window */
uint8 gen_running; uint8 gen_running;
uint32 genromsize; uint32 genromsize;
uint32 rom_size;
int32 resetline; int32 resetline;
uint8 *rom_readmap[8];
/*--------------------------------------------------------------------------*/ /*--------------------------------------------------------------------------*/
/* Init, reset, shutdown functions */ /* Init, reset, shutdown functions */
@ -55,86 +54,115 @@ void gen_init (void)
m68k_init(); m68k_init();
z80_init(0,0,0,z80_irq_callback); z80_init(0,0,0,z80_irq_callback);
/* default 68000 mapping */ /* initialize 68k default address space */
for (i=16; i<24; i++) for (i=0x0; i<0x100; i++)
{ {
m68k_readmap_8[i] = ILLEGAL; m68k_memory_map[i].base = work_ram;
m68k_readmap_16[i] = ILLEGAL; m68k_memory_map[i].read8 = NULL;
m68k_writemap_8[i] = ILLEGAL; m68k_memory_map[i].read16 = NULL;
m68k_writemap_16[i] = ILLEGAL; m68k_memory_map[i].write8 = NULL;
m68k_memory_map[i].write16 = NULL;
zbank_memory_map[i].read = NULL;
zbank_memory_map[i].write = NULL;
} }
/* Z80, I/O, CONTROL */ /* initialize 68k memory map */
m68k_readmap_8[20] = SYSTEM_IO; for (i=0x80; i<0xe0; i++)
m68k_readmap_16[20] = SYSTEM_IO; {
m68k_writemap_8[20] = SYSTEM_IO; /* illegal area */
m68k_writemap_16[20] = SYSTEM_IO; m68k_memory_map[i].read8 = m68k_lockup_r_8;
m68k_memory_map[i].read16 = m68k_lockup_r_16;
m68k_memory_map[i].write8 = m68k_lockup_w_8;
m68k_memory_map[i].write16 = m68k_lockup_w_16;
zbank_memory_map[i].read = zbank_lockup_r;
zbank_memory_map[i].write = zbank_lockup_w;
}
/* Z80 bus */
m68k_memory_map[0xa0].read8 = z80_read_byte;
m68k_memory_map[0xa0].read16 = z80_read_word;
m68k_memory_map[0xa0].write8 = z80_write_byte;
m68k_memory_map[0xa0].write16 = z80_write_word;
zbank_memory_map[0xa0].read = zbank_lockup_r;
zbank_memory_map[0xa0].write = zbank_lockup_w;
/* I/O & Control registers */
m68k_memory_map[0xa1].read8 = ctrl_io_read_byte;
m68k_memory_map[0xa1].read16 = ctrl_io_read_word;
m68k_memory_map[0xa1].write8 = ctrl_io_write_byte;
m68k_memory_map[0xa1].write16 = ctrl_io_write_word;
zbank_memory_map[0xa1].read = zbank_read_ctrl_io;
zbank_memory_map[0xa1].write = zbank_write_ctrl_io;
/* SEGA PICO */ /* SEGA PICO */
if (system_hw == SYSTEM_PICO) if (system_hw == SYSTEM_PICO)
{ {
m68k_readmap_8[16] = PICO_HW; m68k_memory_map[0x80].read8 = pico_read_byte;
m68k_readmap_16[16] = PICO_HW; m68k_memory_map[0x80].read16 = pico_read_word;
m68k_writemap_8[16] = PICO_HW; m68k_memory_map[0x80].write8 = m68k_unused_8_w;
m68k_writemap_16[16] = PICO_HW; m68k_memory_map[0x80].write16 = m68k_unused_16_w;
/* Notaz: there is no IO CONTROL area (Z80/YM2612/IO) */ /* there is no I/O area (Notaz) */
m68k_readmap_8[20] = UNUSED; m68k_memory_map[0xa0].read8 = m68k_read_bus_8;
m68k_readmap_16[20] = UNUSED; m68k_memory_map[0xa0].read16 = m68k_read_bus_16;
m68k_writemap_8[20] = UNUSED; m68k_memory_map[0xa0].write8 = m68k_unused_8_w;
m68k_writemap_16[20] = UNUSED; m68k_memory_map[0xa0].write16 = m68k_unused_16_w;
m68k_memory_map[0xa1].read8 = m68k_read_bus_8;
m68k_memory_map[0xa1].read16 = m68k_read_bus_16;
m68k_memory_map[0xa1].write8 = m68k_unused_8_w;
m68k_memory_map[0xa1].write16 = m68k_unused_16_w;
} }
/* VDP */ /* VDP */
for (i=24; i<28; i++) m68k_memory_map[0xc0].read8 = vdp_read_byte;
{ m68k_memory_map[0xc0].read16 = vdp_read_word;
m68k_readmap_8[i] = VDP; m68k_memory_map[0xc0].write8 = vdp_write_byte;
m68k_readmap_16[i] = VDP; m68k_memory_map[0xc0].write16 = vdp_write_word;
m68k_writemap_8[i] = VDP; m68k_memory_map[0xc8].read8 = vdp_read_byte;
m68k_writemap_16[i] = VDP; m68k_memory_map[0xc8].read16 = vdp_read_word;
} m68k_memory_map[0xc8].write8 = vdp_write_byte;
m68k_memory_map[0xc8].write16 = vdp_write_word;
/* WRAM */ m68k_memory_map[0xd0].read8 = vdp_read_byte;
for (i=28; i<32; i++) m68k_memory_map[0xd0].read16 = vdp_read_word;
{ m68k_memory_map[0xd0].write8 = vdp_write_byte;
m68k_readmap_8[i] = WRAM; m68k_memory_map[0xd0].write16 = vdp_write_word;
m68k_readmap_16[i] = WRAM; m68k_memory_map[0xd8].read8 = vdp_read_byte;
m68k_writemap_8[i] = WRAM; m68k_memory_map[0xd8].read16 = vdp_read_word;
m68k_writemap_16[i] = WRAM; m68k_memory_map[0xd8].write8 = vdp_write_byte;
} m68k_memory_map[0xd8].write16 = vdp_write_word;
zbank_memory_map[0xc0].read = zbank_read_vdp;
zbank_memory_map[0xc0].write = zbank_write_vdp;
zbank_memory_map[0xc8].read = zbank_read_vdp;
zbank_memory_map[0xc8].write = zbank_write_vdp;
zbank_memory_map[0xd0].read = zbank_read_vdp;
zbank_memory_map[0xd0].write = zbank_write_vdp;
zbank_memory_map[0xd8].read = zbank_read_vdp;
zbank_memory_map[0xd8].write = zbank_write_vdp;
} }
void gen_reset (unsigned int hard_reset) void gen_reset (uint32 hard_reset)
{ {
if (hard_reset) if (hard_reset)
{ {
/* Clear RAM */ /* Clear RAM */
memset (work_ram, 0, sizeof (work_ram)); memset (work_ram, 0x00, sizeof (work_ram));
memset (zram, 0, sizeof (zram)); memset (zram, 0x00, sizeof (zram));
/* Reset ROM mapping */ /* TMSS BIOS */
if (config.bios_enabled == 3) if (config.bios_enabled == 3)
{ {
rom_readmap[0] = &bios_rom[0]; m68k_memory_map[0].base = bios_rom;
rom_size = 0x800;
} }
else
{
rom_readmap[0] = &cart_rom[0];
rom_size = genromsize;
}
uint8 i;
for (i=1; i<8; i++) rom_readmap[i] = &cart_rom[i << 19];
} }
gen_running = 1; gen_running = 1;
resetline = -1;
zreset = 0; /* Z80 is reset */ zreset = 0; /* Z80 is reset */
zbusreq = 0; /* Z80 has control of the Z bus */ zbusreq = 0; /* Z80 has control of the Z bus */
zbusack = 1; /* Z80 is busy using the Z bus */ zbusack = 1; /* Z80 is busy using the Z bus */
zbank = 0; /* Assume default bank is 000000-007FFF */
zirq = 0; /* No interrupts occuring */ zirq = 0; /* No interrupts occuring */
resetline = -1; zbank = 0; /* Assume default bank is 000000-007FFF */
/* Reset CPUs */ /* Reset CPUs */
m68k_pulse_reset (); m68k_pulse_reset ();
@ -155,14 +183,9 @@ void gen_shutdown (void)
/*----------------------------------------------------------------------- /*-----------------------------------------------------------------------
Bus controller chip functions Bus controller chip functions
-----------------------------------------------------------------------*/ -----------------------------------------------------------------------*/
unsigned int gen_busack_r (void) void gen_busreq_w (uint32 state)
{ {
return zbusack; uint32 z80_cycles_to_run;
}
void gen_busreq_w (unsigned int state)
{
int z80_cycles_to_run;
input_raz (); /* from Gens */ input_raz (); /* from Gens */
@ -175,7 +198,8 @@ void gen_busreq_w (unsigned int state)
/* z80 was ON during the last 68k cycles */ /* z80 was ON during the last 68k cycles */
/* we execute the appropriate number of z80 cycles */ /* we execute the appropriate number of z80 cycles */
z80_cycles_to_run = line_z80 + ((count_m68k - line_m68k)*7)/15; z80_cycles_to_run = line_z80 + ((count_m68k - line_m68k)*7)/15;
z80_run(z80_cycles_to_run); current_z80 = z80_cycles_to_run - count_z80;
if (current_z80 > 0) count_z80 += z80_execute(current_z80);
} }
} }
else else
@ -195,9 +219,9 @@ void gen_busreq_w (unsigned int state)
zbusack = 1 ^ (zbusreq & zreset); zbusack = 1 ^ (zbusreq & zreset);
} }
void gen_reset_w (unsigned int state) void gen_reset_w (uint32 state)
{ {
int z80_cycles_to_run; uint32 z80_cycles_to_run;
if (state) if (state)
{ {
@ -220,7 +244,8 @@ void gen_reset_w (unsigned int state)
/* z80 was ON during the last 68k cycles */ /* z80 was ON during the last 68k cycles */
/* we execute the appropriate number of z80 cycles */ /* we execute the appropriate number of z80 cycles */
z80_cycles_to_run = line_z80 + ((count_m68k - line_m68k)*7)/15; z80_cycles_to_run = line_z80 + ((count_m68k - line_m68k)*7)/15;
z80_run(z80_cycles_to_run); current_z80 = z80_cycles_to_run - count_z80;
if (current_z80 > 0) count_z80 += z80_execute(current_z80);
} }
/* Reset Z80 & YM2612 */ /* Reset Z80 & YM2612 */
@ -232,7 +257,7 @@ void gen_reset_w (unsigned int state)
zbusack = 1 ^ (zbusreq & zreset); zbusack = 1 ^ (zbusreq & zreset);
} }
void gen_bank_w (unsigned int state) void gen_bank_w (uint32 state)
{ {
zbank = ((zbank >> 1) | ((state & 1) << 23)) & 0xFF8000; zbank = ((zbank >> 1) | ((state & 1) << 23)) & 0xFF8000;
} }

View File

@ -26,7 +26,7 @@
/* Global variables */ /* Global variables */
extern uint8 *cart_rom; extern uint8 *cart_rom;
extern uint8 bios_rom[0x800]; 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 uint8 zbusreq;
@ -36,18 +36,15 @@ extern uint8 zirq;
extern uint32 zbank; extern uint32 zbank;
extern uint8 gen_running; extern uint8 gen_running;
extern uint32 genromsize; extern uint32 genromsize;
extern uint32 rom_size;
extern int32 resetline; extern int32 resetline;
extern uint8 *rom_readmap[8];
/* Function prototypes */ /* Function prototypes */
extern void gen_init(void); extern void gen_init(void);
extern void gen_reset(unsigned int hard_reset); extern void gen_reset(uint32 hard_reset);
extern void gen_shutdown(void); extern void gen_shutdown(void);
extern unsigned int gen_busack_r(void); extern void gen_busreq_w(uint32 state);
extern void gen_busreq_w(unsigned int state); extern void gen_reset_w(uint32 state);
extern void gen_reset_w(unsigned int state); extern void gen_bank_w(uint32 state);
extern void gen_bank_w(unsigned int state);
extern int z80_irq_callback(int param); extern int z80_irq_callback(int param);
extern void set_softreset(void); extern void set_softreset(void);

View File

@ -153,15 +153,6 @@ unsigned int m68k_read_memory_8(unsigned int address);
unsigned int m68k_read_memory_16(unsigned int address); unsigned int m68k_read_memory_16(unsigned int address);
unsigned int m68k_read_memory_32(unsigned int address); unsigned int m68k_read_memory_32(unsigned int address);
/* Read data immediately following the PC */
unsigned int m68k_read_immediate_16(unsigned int address);
unsigned int m68k_read_immediate_32(unsigned int address);
/* Read data relative to the PC */
unsigned int m68k_read_pcrelative_8(unsigned int address);
unsigned int m68k_read_pcrelative_16(unsigned int address);
unsigned int m68k_read_pcrelative_32(unsigned int address);
/* Memory access for the disassembler */ /* Memory access for the disassembler */
unsigned int m68k_read_disassembler_8 (unsigned int address); unsigned int m68k_read_disassembler_8 (unsigned int address);
unsigned int m68k_read_disassembler_16 (unsigned int address); unsigned int m68k_read_disassembler_16 (unsigned int address);
@ -172,6 +163,30 @@ void m68k_write_memory_8(unsigned int address, unsigned int value);
void m68k_write_memory_16(unsigned int address, unsigned int value); void m68k_write_memory_16(unsigned int address, unsigned int value);
void m68k_write_memory_32(unsigned int address, unsigned int value); void m68k_write_memory_32(unsigned int address, unsigned int value);
#include "macros.h"
typedef struct
{
unsigned char *base;
unsigned int (*read8)(unsigned int address);
unsigned int (*read16)(unsigned int address);
void (*write8)(unsigned int address, unsigned int data);
void (*write16)(unsigned int address, unsigned int data);
} _m68k_memory_map;
_m68k_memory_map m68k_memory_map[256];
/* Read data immediately following the PC */
#define m68k_read_immediate_16(address) *(uint16 *)(m68k_memory_map[((address)>>16)&0xff].base + ((address) & 0xffff))
#define m68k_read_immediate_32(address) (m68k_read_immediate_16(address) << 16) | (m68k_read_immediate_16(address+2))
/* Read data relative to the PC */
#define m68k_read_pcrelative_8(address) READ_BYTE(m68k_memory_map[((address)>>16)&0xff].base, (address) & 0xffff)
#define m68k_read_pcrelative_16(address) m68k_read_immediate_16(address)
#define m68k_read_pcrelative_32(address) m68k_read_immediate_32(address)
/* Special call to simulate undocumented 68k behavior when move.l with a /* Special call to simulate undocumented 68k behavior when move.l with a
* predecrement destination mode is executed. * predecrement destination mode is executed.
* To simulate real 68k behavior, first write the high word to * To simulate real 68k behavior, first write the high word to
@ -302,7 +317,8 @@ void m68k_init(void);
void m68k_pulse_reset(void); 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);
/* 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.
@ -318,7 +334,7 @@ void m68k_end_timeslice(void); /* End timeslice now */
* 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. */

View File

@ -67,7 +67,7 @@
* and m68k_read_pcrelative_xx() for PC-relative addressing. * and m68k_read_pcrelative_xx() for PC-relative addressing.
* If off, all read requests from the CPU will be redirected to m68k_read_xx() * If off, all read requests from the CPU will be redirected to m68k_read_xx()
*/ */
#define M68K_SEPARATE_READS OPT_OFF #define M68K_SEPARATE_READS OPT_ON
/* If ON, the CPU will call m68k_write_32_pd() when it executes move.l with a /* If ON, the CPU will call m68k_write_32_pd() when it executes move.l with a
* predecrement destination EA mode instead of m68k_write_32(). * predecrement destination EA mode instead of m68k_write_32().
@ -157,7 +157,7 @@
* access a word or longword at an odd address. * access a word or longword at an odd address.
* NOTE: This is only emulated properly for 68000 mode. * NOTE: This is only emulated properly for 68000 mode.
*/ */
#define M68K_EMULATE_ADDRESS_ERROR OPT_ON #define M68K_EMULATE_ADDRESS_ERROR OPT_OFF
/* Turn ON to enable logging of illegal instruction calls. /* Turn ON to enable logging of illegal instruction calls.

View File

@ -783,7 +783,7 @@ void m68k_set_cpu_type(unsigned int cpu_type)
/* Execute some instructions until we use up num_cycles clock cycles */ /* Execute some instructions until we use up num_cycles clock cycles */
/* ASG: removed per-instruction interrupt checks */ /* ASG: removed per-instruction interrupt checks */
int m68k_execute(int num_cycles) INLINE int m68k_execute(int num_cycles)
{ {
/* Make sure we're not stopped */ /* Make sure we're not stopped */
if(!CPU_STOPPED) if(!CPU_STOPPED)
@ -841,6 +841,50 @@ int m68k_execute(int num_cycles)
return num_cycles; return num_cycles;
} }
/* ASG: rewrote so that the int_level is a mask of the IPL0/IPL1/IPL2 bits */
/* KS: Modified so that IPL* bits match with mask positions in the SR
* and cleaned out remenants of the interrupt controller.
*/
INLINE void m68k_set_irq(unsigned int int_level)
{
uint old_level = CPU_INT_LEVEL;
CPU_INT_LEVEL = int_level << 8;
/* A transition from < 7 to 7 always interrupts (NMI) */
/* Note: Level 7 can also level trigger like a normal IRQ */
if(old_level != 0x0700 && CPU_INT_LEVEL == 0x0700)
m68ki_exception_interrupt(7); /* Edge triggered level 7 (NMI) */
else
m68ki_check_interrupts(); /* Level triggered (IRQ) */
}
extern uint16 irq_status;
extern uint32 count_m68k;
void m68k_run (int cyc)
{
int temp;
while (count_m68k < cyc)
{
/* check interrupt updates */
if (irq_status & 0x10)
{
irq_status &= ~0x10;
/* hardware latency */
temp = irq_status >> 8;
if (temp) count_m68k += m68k_execute(temp);
/* interrupt level */
temp = irq_status & 6;
if (temp == 6) irq_status |= 0x20;
m68k_set_irq(temp);
}
/* execute a single instruction */
count_m68k += m68k_execute(1);
}
}
int m68k_cycles_run(void) int m68k_cycles_run(void)
{ {
@ -866,24 +910,6 @@ void m68k_end_timeslice(void)
SET_CYCLES(0); SET_CYCLES(0);
} }
/* ASG: rewrote so that the int_level is a mask of the IPL0/IPL1/IPL2 bits */
/* KS: Modified so that IPL* bits match with mask positions in the SR
* and cleaned out remenants of the interrupt controller.
*/
void m68k_set_irq(unsigned int int_level)
{
uint old_level = CPU_INT_LEVEL;
CPU_INT_LEVEL = int_level << 8;
/* A transition from < 7 to 7 always interrupts (NMI) */
/* Note: Level 7 can also level trigger like a normal IRQ */
if(old_level != 0x0700 && CPU_INT_LEVEL == 0x0700)
m68ki_exception_interrupt(7); /* Edge triggered level 7 (NMI) */
else
m68ki_check_interrupts(); /* Level triggered (IRQ) */
}
void m68k_init(void) void m68k_init(void)
{ {
static uint emulation_initialized = 0; static uint emulation_initialized = 0;

View File

@ -1116,37 +1116,62 @@ INLINE uint m68ki_read_imm_32(void)
INLINE uint m68ki_read_8_fc(uint address, uint fc) INLINE uint m68ki_read_8_fc(uint address, uint fc)
{ {
m68ki_set_fc(fc); /* auto-disable (see m68kcpu.h) */ m68ki_set_fc(fc); /* auto-disable (see m68kcpu.h) */
return m68k_read_memory_8(ADDRESS_68K(address));
_m68k_memory_map *temp = &m68k_memory_map[((address)>>16)&0xff];
if (temp->read8) return (*temp->read8)(address);
else return READ_BYTE(temp->base, (address) & 0xffff);
} }
INLINE uint m68ki_read_16_fc(uint address, uint fc) INLINE uint m68ki_read_16_fc(uint address, uint fc)
{ {
m68ki_set_fc(fc); /* auto-disable (see m68kcpu.h) */ m68ki_set_fc(fc); /* auto-disable (see m68kcpu.h) */
m68ki_check_address_error_010_less(address, MODE_READ, fc); /* auto-disable (see m68kcpu.h) */ m68ki_check_address_error_010_less(address, MODE_READ, fc); /* auto-disable (see m68kcpu.h) */
return m68k_read_memory_16(ADDRESS_68K(address));
_m68k_memory_map *temp = &m68k_memory_map[((address)>>16)&0xff];
if (temp->read16) return (*temp->read16)(address);
else return *(uint16 *)(temp->base + ((address) & 0xffff));
} }
INLINE uint m68ki_read_32_fc(uint address, uint fc) INLINE uint m68ki_read_32_fc(uint address, uint fc)
{ {
m68ki_set_fc(fc); /* auto-disable (see m68kcpu.h) */ m68ki_set_fc(fc); /* auto-disable (see m68kcpu.h) */
m68ki_check_address_error_010_less(address, MODE_READ, fc); /* auto-disable (see m68kcpu.h) */ m68ki_check_address_error_010_less(address, MODE_READ, fc); /* auto-disable (see m68kcpu.h) */
return m68k_read_memory_32(ADDRESS_68K(address));
_m68k_memory_map *temp = &m68k_memory_map[((address)>>16)&0xff];
if (temp->read16) return ((*temp->read16)(address) << 16) | ((*temp->read16)(address + 2));
else return m68k_read_immediate_32(address);
} }
INLINE void m68ki_write_8_fc(uint address, uint fc, uint value) INLINE void m68ki_write_8_fc(uint address, uint fc, uint value)
{ {
m68ki_set_fc(fc); /* auto-disable (see m68kcpu.h) */ m68ki_set_fc(fc); /* auto-disable (see m68kcpu.h) */
m68k_write_memory_8(ADDRESS_68K(address), value); _m68k_memory_map *temp = &m68k_memory_map[((address)>>16)&0xff];
if (temp->write8) (*temp->write8)(address,value);
else WRITE_BYTE(temp->base, (address) & 0xffff, value);
} }
INLINE void m68ki_write_16_fc(uint address, uint fc, uint value) INLINE void m68ki_write_16_fc(uint address, uint fc, uint value)
{ {
m68ki_set_fc(fc); /* auto-disable (see m68kcpu.h) */ m68ki_set_fc(fc); /* auto-disable (see m68kcpu.h) */
m68ki_check_address_error_010_less(address, MODE_WRITE, fc); /* auto-disable (see m68kcpu.h) */ m68ki_check_address_error_010_less(address, MODE_WRITE, fc); /* auto-disable (see m68kcpu.h) */
m68k_write_memory_16(ADDRESS_68K(address), value); _m68k_memory_map *temp = &m68k_memory_map[((address)>>16)&0xff];
if (temp->write16) (*temp->write16)(address,value);
else *(uint16 *)(temp->base + ((address) & 0xffff)) = value;
} }
INLINE void m68ki_write_32_fc(uint address, uint fc, uint value) INLINE void m68ki_write_32_fc(uint address, uint fc, uint value)
{ {
m68ki_set_fc(fc); /* auto-disable (see m68kcpu.h) */ m68ki_set_fc(fc); /* auto-disable (see m68kcpu.h) */
m68ki_check_address_error_010_less(address, MODE_WRITE, fc); /* auto-disable (see m68kcpu.h) */ m68ki_check_address_error_010_less(address, MODE_WRITE, fc); /* auto-disable (see m68kcpu.h) */
m68k_write_memory_32(ADDRESS_68K(address), value); _m68k_memory_map *temp = &m68k_memory_map[((address)>>16)&0xff];
if (temp->write16)
{
(*temp->write16)(address,value>>16);
(*temp->write16)(address+2,value&0xffff);
}
else
{
*(uint16 *)(temp->base + ((address) & 0xffff)) = value >> 16;
temp = &m68k_memory_map[((address + 2)>>16)&0xff];
*(uint16 *)(temp->base + ((address + 2) & 0xffff)) = value;
}
} }
#if M68K_SIMULATE_PD_WRITES #if M68K_SIMULATE_PD_WRITES

File diff suppressed because it is too large Load Diff

View File

@ -24,28 +24,48 @@
#ifndef _MEM68K_H_ #ifndef _MEM68K_H_
#define _MEM68K_H_ #define _MEM68K_H_
enum { /* unused areas */
SRAM, extern uint32 m68k_read_bus_8(uint32 address);
EEPROM, extern uint32 m68k_read_bus_16(uint32 address);
J_CART, extern void m68k_unused_8_w (uint32 address, uint32 data);
SVP_DRAM, extern void m68k_unused_16_w (uint32 address, uint32 data);
SVP_CELL,
CART_HW,
REALTEC_ROM,
VDP,
SYSTEM_IO,
UNUSED,
ILLEGAL,
WRAM,
UMK3_HACK,
PICO_HW,
ROM
};
extern uint8 m68k_readmap_8[32]; /* illegal areas */
extern uint8 m68k_readmap_16[32]; extern uint32 m68k_lockup_r_8 (uint32 address);
extern uint8 m68k_writemap_8[32]; extern uint32 m68k_lockup_r_16 (uint32 address);
extern uint8 m68k_writemap_16[32]; extern void m68k_lockup_w_8 (uint32 address, uint32 data);
extern void m68k_lockup_w_16 (uint32 address, uint32 data);
/* eeprom */
extern uint32 eeprom_read_byte(uint32 address);
extern uint32 eeprom_read_word(uint32 address);
extern void eeprom_write_byte(uint32 address, uint32 data);
extern void eeprom_write_word(uint32 address, uint32 data);
/* Z80 bus */
extern uint32 z80_read_byte(uint32 address);
extern uint32 z80_read_word(uint32 address);
extern void z80_write_byte(uint32 address, uint32 data);
extern void z80_write_word(uint32 address, uint32 data);
/* I/O & Control registers */
extern uint32 ctrl_io_read_byte(uint32 address);
extern uint32 ctrl_io_read_word(uint32 address);
extern void ctrl_io_write_byte(uint32 address, uint32 data);
extern void ctrl_io_write_word(uint32 address, uint32 data);
/* VDP */
extern uint32 vdp_read_byte(uint32 address);
extern uint32 vdp_read_word(uint32 address);
extern void vdp_write_byte(uint32 address, uint32 data);
extern void vdp_write_word(uint32 address, uint32 data);
/* PICO */
extern uint32 pico_read_byte(uint32 address);
extern uint32 pico_read_word(uint32 address);
uint8 m68k_readmap[256];
uint8 m68k_writemap[256];
uint32 pico_current;
#endif /* _MEM68K_H_ */ #endif /* _MEM68K_H_ */

View File

@ -26,14 +26,8 @@
Handlers for access to unused addresses and those which make the Handlers for access to unused addresses and those which make the
machine lock up. machine lock up.
*/ */
static inline void z80bank_unused_w(unsigned int address, unsigned int data)
{
#ifdef LOGERROR
error("Z80 bank unused write %06X = %02X\n", address, data);
#endif
}
static inline unsigned int z80bank_unused_r(unsigned int address) uint32 zbank_unused_r(uint32 address)
{ {
#ifdef LOGERROR #ifdef LOGERROR
error("Z80 bank unused read %06X\n", address); error("Z80 bank unused read %06X\n", address);
@ -41,15 +35,14 @@ static inline unsigned int z80bank_unused_r(unsigned int address)
return (address & 1) ? 0x00 : 0xFF; return (address & 1) ? 0x00 : 0xFF;
} }
static inline void z80bank_lockup_w(unsigned int address, unsigned int data) void zbank_unused_w(uint32 address, uint32 data)
{ {
#ifdef LOGERROR #ifdef LOGERROR
error("Z80 bank lockup write %06X = %02X\n", address, data); error("Z80 bank unused write %06X = %02X\n", address, data);
#endif #endif
gen_running = config.force_dtack;
} }
static inline unsigned int z80bank_lockup_r(unsigned int address) uint32 zbank_lockup_r(uint32 address)
{ {
#ifdef LOGERROR #ifdef LOGERROR
error("Z80 bank lockup read %06X\n", address); error("Z80 bank lockup read %06X\n", address);
@ -58,132 +51,84 @@ static inline unsigned int z80bank_lockup_r(unsigned int address)
return 0xFF; return 0xFF;
} }
/* void zbank_lockup_w(uint32 address, uint32 data)
Z80 memory handlers
*/
void z80_write_banked_memory (unsigned int address, unsigned int data)
{ {
int offset = address >> 19; #ifdef LOGERROR
error("Z80 bank lockup write %06X = %02X\n", address, data);
#endif
gen_running = config.force_dtack;
}
switch (m68k_writemap_8[offset]) /* I/O & Control registers */
uint32 zbank_read_ctrl_io(uint32 address)
{
switch ((address >> 8) & 0xff)
{ {
case VDP: case 0x00: /* I/O chip */
/* Valid VDP addresses */ if (address & 0xe0) return zbank_unused_r(address);
if (((address >> 16) & 0x07) == 0) else return (io_read((address >> 1) & 0x0f));
{
switch (address & 0xff)
{
case 0x00: /* Data port */
case 0x01:
case 0x02:
case 0x03:
vdp_data_w(data << 8 | data);
return;
case 0x04: /* Control port */ case 0x11: /* BUSACK */
case 0x05: if (address & 1) return zbank_unused_r(address);
case 0x06: else return (0xfe | zbusack);
case 0x07:
vdp_ctrl_w(data << 8 | data);
return;
case 0x10: /* Unused */ case 0x30: /* TIME */
case 0x12: if (cart_hw.time_r) return cart_hw.time_r(address);
case 0x14: else return zbank_unused_r(address);
case 0x16:
z80bank_unused_w(address, data);
return;
case 0x11: /* PSG */ case 0x10: /* MEMORY MODE */
case 0x13: case 0x12: /* RESET */
case 0x15: case 0x20: /* MEGA-CD */
case 0x17: case 0x40: /* TMSS */
psg_write(0, data); case 0x41: /* BOOTROM */
return; case 0x44: /* RADICA */
case 0x50: /* SVP REGISTERS */
case 0x18: /* Unused */ return zbank_unused_r(address);
case 0x19:
case 0x1a:
case 0x1b:
z80bank_unused_w(address, data);
return;
case 0x1c: /* Test register */
case 0x1d:
case 0x1e:
case 0x1f:
vdp_test_w(data << 8 | data);
return;
default: /* Invalid address */ default: /* Invalid address */
z80bank_lockup_w(address, data); return zbank_lockup_r(address);
return;
} }
} }
/* Invalid address */ void zbank_write_ctrl_io(uint32 address, uint32 data)
z80bank_lockup_w(address, data);
return;
case SYSTEM_IO:
{ {
unsigned int base = address >> 8; switch ((address >> 8) & 0xff)
/* Z80 (access prohibited) */
if (base <= 0xa0ff)
{ {
z80bank_lockup_w(address, data); case 0x00: /* I/O chip */
return; if ((address & 0xe1) == 0x01) io_write((address >> 1) & 0x0f, data); /* get /LWR only */
} else zbank_unused_w(address, data);
/* CONTROL registers */
if (base <= 0xa1ff)
{
switch (base & 0xff)
{
case 0x00: /* I/O chip (only gets /LWR) */
if ((address & 0xe1) == 0x01) io_write((address >> 1) & 0x0f, data);
else z80bank_unused_w(address, data);
return; return;
case 0x11: /* BUSREQ */ case 0x11: /* BUSREQ */
if (address & 1) z80bank_unused_w(address, data); if (address & 1) zbank_unused_w(address, data);
else gen_busreq_w(data & 1); else gen_busreq_w(data & 1);
return; return;
case 0x12: /* RESET */ case 0x12: /* RESET */
if (address & 1) z80bank_unused_w(address, data); if (address & 1) zbank_unused_w(address, data);
else gen_reset_w(data & 1); else gen_reset_w(data & 1);
return; return;
case 0x30: /* TIME */ case 0x30: /* TIME */
if (cart_hw.time_w) return cart_hw.time_w(address, data); if (cart_hw.time_w) cart_hw.time_w(address, data);
else z80bank_unused_w(address, data); else zbank_unused_w(address, data);
return; return;
case 0x41: /* BOOTROM */ case 0x41: /* BOOTROM */
if (address & 1) if (address & 1)
{ {
if (data & 1) m68k_memory_map[0].base = (data & 1) ? default_rom : bios_rom;
{
rom_readmap[0] = &cart_rom[0];
rom_size = genromsize;
}
else
{
rom_readmap[0] = &bios_rom[0];
rom_size = 0x800;
}
/* autodetect BIOS ROM file */
if (!(config.bios_enabled & 2)) if (!(config.bios_enabled & 2))
{ {
config.bios_enabled |= 2; config.bios_enabled |= 2;
memcpy(bios_rom, cart_rom, 0x800); memcpy(bios_rom, cart_rom, 0x800);
memset(cart_rom, 0, 0x500000); memset(cart_rom, 0, genromsize);
} }
} }
else z80bank_unused_w (address, data); else zbank_unused_w (address, data);
return; return;
case 0x10: /* MEMORY MODE */ case 0x10: /* MEMORY MODE */
@ -191,177 +136,81 @@ void z80_write_banked_memory (unsigned int address, unsigned int data)
case 0x40: /* TMSS */ case 0x40: /* TMSS */
case 0x44: /* RADICA */ case 0x44: /* RADICA */
case 0x50: /* SVP REGISTERS */ case 0x50: /* SVP REGISTERS */
z80bank_unused_w(address, data); zbank_unused_w(address, data);
return; return;
default: /* Invalid address */ default: /* Invalid address */
z80bank_lockup_w(address, data); zbank_lockup_w(address, data);
return; return;
} }
} }
/* Invalid address */
z80bank_lockup_w(address, data);
return;
}
case ROM: /* VDP */
WRITE_BYTE(rom_readmap[offset], address & 0x7ffff, data);
return;
case SRAM: uint32 zbank_read_vdp(uint32 address)
if (address <= sram.end) WRITE_BYTE(sram.sram, address - sram.start, data);
else z80bank_unused_w(address, data);
return;
case EEPROM:
if ((address == eeprom.type.sda_in_adr) || (address == eeprom.type.scl_adr)) eeprom_write(address, data, 0);
else z80bank_unused_w(address, data);
return;
case CART_HW:
cart_hw.regs_w(address, data);
return;
case UNUSED:
z80bank_unused_w(address, data);
return;
case ILLEGAL:
z80bank_lockup_w(address, data);
return;
default: /* WRAM */
/* Mamono Hunter Youko - Dai 7 no Keishou need this */
WRITE_BYTE(work_ram, address & 0xffff, data);
return;
}
}
unsigned int z80_read_banked_memory(unsigned int address)
{
int offset = address >> 19;
switch (m68k_readmap_8[offset])
{ {
case WRAM: /* NOTE: can't be read on some Genesis models (!), only japanese ones ??? */ switch (address & 0xfd)
return READ_BYTE(work_ram, address);
case SYSTEM_IO:
{
unsigned int base = address >> 8;
/* Z80 (access prohibited) */
if (base <= 0xa0ff) return z80bank_lockup_r(address);
/* I/O & CONTROL registers */
if (base <= 0xa1ff)
{
switch (base & 0xff)
{
case 0x00: /* I/O chip */
if (address & 0xe0) return z80bank_unused_r(address);
return (io_read((address >> 1) & 0x0f));
case 0x11: /* BUSACK */
if (address & 0x01) return 0xff;
else return (zbusack | 0xfe);
case 0x30: /* TIME */
if (cart_hw.time_r) return cart_hw.time_r(address);
else z80bank_unused_r(address);
case 0x10: /* MEMORY MODE */
case 0x12: /* RESET */
case 0x20: /* MEGA-CD */
case 0x40: /* TMSS */
case 0x41: /* BOOTROM */
case 0x44: /* RADICA */
case 0x50: /* SVP REGISTERS */
return z80bank_unused_r(address);
default: /* Invalid address */
return z80bank_lockup_r(address);
}
}
/* Invalid address */
return z80bank_lockup_r(address);
}
case VDP:
/* Valid VDP addresses */
if (((address >> 16) & 0x07) == 0)
{
switch (address & 0xff)
{ {
case 0x00: /* DATA */ case 0x00: /* DATA */
case 0x02:
return (vdp_data_r() >> 8); return (vdp_data_r() >> 8);
case 0x01: /* DATA */ case 0x01: /* DATA */
case 0x03:
return (vdp_data_r() & 0xff); return (vdp_data_r() & 0xff);
case 0x04: /* CTRL */ case 0x04: /* CTRL */
case 0x06:
return (0xfc | ((vdp_ctrl_r() >> 8) & 3)); return (0xfc | ((vdp_ctrl_r() >> 8) & 3));
case 0x05: /* CTRL */ case 0x05: /* CTRL */
case 0x07:
return (vdp_ctrl_r() & 0xff); return (vdp_ctrl_r() & 0xff);
case 0x08: /* HVC */ case 0x08: /* HVC */
case 0x0a:
case 0x0c: case 0x0c:
case 0x0e:
return (vdp_hvc_r() >> 8); return (vdp_hvc_r() >> 8);
case 0x09: /* HVC */ case 0x09: /* HVC */
case 0x0b:
case 0x0d: case 0x0d:
case 0x0f:
return (vdp_hvc_r() & 0xff); return (vdp_hvc_r() & 0xff);
case 0x18: /* Unused */ case 0x18: /* Unused */
case 0x19: case 0x19:
case 0x1a:
case 0x1b:
case 0x1c: case 0x1c:
case 0x1d: case 0x1d:
case 0x1e: return zbank_unused_r(address);
case 0x1f:
return (z80bank_unused_r(address) | 0xff);
default: /* Invalid address */ default: /* Invalid address */
return z80bank_lockup_r(address); return zbank_lockup_r(address);
} }
} }
/* Invalid address */ void zbank_write_vdp(uint32 address, uint32 data)
return (z80bank_lockup_r (address)); {
switch (address & 0xfc)
{
case 0x00: /* Data port */
vdp_data_w(data << 8 | data);
return;
case SRAM: case 0x04: /* Control port */
if (address <= sram.end) return READ_BYTE(sram.sram, address - sram.start); vdp_ctrl_w(data << 8 | data);
return READ_BYTE(rom_readmap[offset], address & 0x7ffff); return;
case EEPROM: case 0x10: /* PSG */
if (address == eeprom.type.sda_out_adr) return eeprom_read(address, 0); case 0x14:
return READ_BYTE(rom_readmap[offset], address & 0x7ffff); if (address & 1) psg_write(0, data);
else zbank_unused_w(address, data);
return;
case CART_HW: case 0x18: /* Unused */
return cart_hw.regs_r(address); zbank_unused_w(address, data);
return;
case UNUSED: case 0x1c: /* TEST register */
return z80bank_unused_r(address); vdp_test_w(data << 8 | data);
return;
case ILLEGAL: default: /* Invalid address */
return z80bank_lockup_r(address); zbank_lockup_w(address, data);
return;
case UMK3_HACK:
return READ_BYTE(&cart_rom[offset<<19], address & 0x7ffff);
default: /* ROM */
return READ_BYTE(rom_readmap[offset], address & 0x7ffff);
} }
} }

View File

@ -23,8 +23,19 @@
#ifndef _MEMBNK_H_ #ifndef _MEMBNK_H_
#define _MEMBNK_H_ #define _MEMBNK_H_
/* Function prototypes */ extern uint32 zbank_unused_r(uint32 address);
extern void z80_write_banked_memory(unsigned int address, unsigned int data); extern void zbank_unused_w(uint32 address, uint32 data);
extern unsigned int z80_read_banked_memory(unsigned int address); extern uint32 zbank_lockup_r(uint32 address);
extern void zbank_lockup_w(uint32 address, uint32 data);
extern uint32 zbank_read_ctrl_io(uint32 address);
extern void zbank_write_ctrl_io(uint32 address, uint32 data);
extern uint32 zbank_read_vdp(uint32 address);
extern void zbank_write_vdp(uint32 address, uint32 data);
struct _zbank_memory_map
{
unsigned int (*read)(unsigned int address);
void (*write)(unsigned int address, unsigned int data);
} zbank_memory_map[256];
#endif /* _MEMBNK_H_ */ #endif /* _MEMBNK_H_ */

View File

@ -1,93 +0,0 @@
/***************************************************************************************
* Genesis Plus 1.2a
* 68k memory from VDP handler
*
* Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 Charles Mac Donald (original code)
* modified by Eke-Eke (compatibility fixes & additional code), GC/Wii port
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
****************************************************************************************/
#include "shared.h"
unsigned int vdp_dma_r(unsigned int address)
{
int offset = address >> 19;
switch (m68k_readmap_16[offset])
{
case ROM:
if (svp) address -= 2;
return *(uint16 *)(rom_readmap[offset] + (address & 0x7ffff));
case UMK3_HACK:
return *(uint16 *)(&cart_rom[offset << 19] + (address & 0x7ffff));
case SVP_DRAM:
address -= 2;
return *(uint16 *)(svp->dram + (address & 0x1fffe));
case SVP_CELL:
address -= 2;
switch (address >> 16)
{
case 0x39:
address >>= 1;
address = (address & 0x7001) | ((address & 0x3e) << 6) | ((address & 0xfc0) >> 5);
return ((uint16 *)svp->dram)[address];
case 0x3A:
address >>= 1;
address = (address & 0x7801) | ((address & 0x1e) << 6) | ((address & 0x7e0) >> 4);
return ((uint16 *)svp->dram)[address];
default:
return 0xffff;
}
case SYSTEM_IO:
/* Z80 area */
/* Return $FFFF only when the Z80 isn't hogging the Z-bus.
(e.g. Z80 isn't reset and 68000 has the bus) */
if (address <= 0xa0ffff) return (zbusack ? *(uint16 *)(work_ram + (address & 0xffff)) : 0xffff);
/* The I/O chip and work RAM try to drive the data bus which
results in both values being combined in random ways when read.
We return the I/O chip values which seem to have precedence, */
if (address <= 0xa1001f)
{
int temp = io_read((address >> 1) & 0x0f);
return (temp << 8 | temp);
}
/* All remaining locations access work RAM */
return *(uint16 *)(work_ram + (address & 0xffff));
case SRAM:
if (address <= sram.end) return *(uint16 *)(sram.sram + (address - sram.start));
return *(uint16 *)(rom_readmap[address >> 19] + (address & 0x7ffff));
case EEPROM:
if (address == (eeprom.type.sda_out_adr & 0xfffffe)) return eeprom_read(address, 1);
return *(uint16 *)(rom_readmap[address >> 19] + (address & 0x7ffff));
case J_CART:
return jcart_read();
default:
return *(uint16 *)(work_ram + (address & 0xffff));
}
}

View File

@ -1,29 +0,0 @@
/***************************************************************************************
* Genesis Plus 1.2a
* 68k memory from VDP handler
*
* Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 Charles Mac Donald (original code)
* modified by Eke-Eke (compatibility fixes & additional code), GC/Wii port
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
****************************************************************************************/
#ifndef _MEMVDP_H_
#define _MEMVDP_H_
/* Function prototypes */
extern unsigned int vdp_dma_r(unsigned int address);
#endif /* _MEMVDP_H_ */

View File

@ -63,118 +63,66 @@ static inline unsigned int z80_lockup_r(unsigned int address)
*/ */
static inline unsigned int z80_vdp_r(unsigned int address) static inline unsigned int z80_vdp_r(unsigned int address)
{ {
switch (address & 0xff) switch (address & 0xfd)
{ {
case 0x00: /* VDP data port */ case 0x00: /* DATA */
case 0x02: return (vdp_data_r() >> 8);
return (vdp_data_r() >> 8) & 0xff;
case 0x01: /* VDP data port */ case 0x01: /* DATA */
case 0x03:
return (vdp_data_r() & 0xff); return (vdp_data_r() & 0xff);
case 0x04: /* VDP control port */ case 0x04: /* CTRL */
case 0x06:
return (0xfc | ((vdp_ctrl_r() >> 8) & 3)); return (0xfc | ((vdp_ctrl_r() >> 8) & 3));
case 0x05: /* VDP control port */ case 0x05: /* CTRL */
case 0x07:
return (vdp_ctrl_r() & 0xff); return (vdp_ctrl_r() & 0xff);
case 0x08: /* HV counter */ case 0x08: /* HVC */
case 0x0a:
case 0x0c: case 0x0c:
case 0x0e: return (vdp_hvc_r() >> 8);
return (vdp_hvc_r() >> 8) & 0xff;
case 0x09: /* HV counter */ case 0x09: /* HVC */
case 0x0b:
case 0x0d: case 0x0d:
case 0x0f:
return (vdp_hvc_r() & 0xff); return (vdp_hvc_r() & 0xff);
case 0x10: /* Unused (PSG) */
case 0x11:
case 0x12:
case 0x13:
case 0x14:
case 0x15:
case 0x16:
case 0x17:
return z80_lockup_r (address);
case 0x18: /* Unused */ case 0x18: /* Unused */
case 0x19: case 0x19:
case 0x1a: case 0x1c:
case 0x1b:
return z80_unused_r(address);
case 0x1c: /* Unused (test register) */
case 0x1d: case 0x1d:
case 0x1e:
case 0x1f:
return z80_unused_r(address); return z80_unused_r(address);
default: /* Invalid VDP addresses */ default: /* Invalid address */
return z80_lockup_r(address); return z80_lockup_r(address);
} }
} }
static inline void z80_vdp_w(unsigned int address, unsigned int data) static inline void z80_vdp_w(unsigned int address, unsigned int data)
{ {
switch (address & 0xff) switch (address & 0xfc)
{ {
case 0x00: /* VDP data port */ case 0x00: /* Data port */
case 0x01:
case 0x02:
case 0x03:
vdp_data_w(data << 8 | data); vdp_data_w(data << 8 | data);
return; return;
case 0x04: /* VDP control port */ case 0x04: /* Control port */
case 0x05:
case 0x06:
case 0x07:
vdp_ctrl_w(data << 8 | data); vdp_ctrl_w(data << 8 | data);
return; return;
case 0x08: /* Unused (HV counter) */ case 0x10: /* PSG */
case 0x09:
case 0x0a:
case 0x0b:
case 0x0c:
case 0x0d:
case 0x0e:
case 0x0f:
z80_lockup_w(address, data);
return;
case 0x11: /* PSG */
case 0x13:
case 0x15:
case 0x17:
psg_write(1, data);
return;
case 0x10: /* Unused */
case 0x12:
case 0x14: case 0x14:
case 0x16: if (address & 1) psg_write(0, data);
case 0x18: else z80_unused_w(address, data);
case 0x19: return;
case 0x1a:
case 0x1b: case 0x18: /* Unused */
z80_unused_w(address, data); z80_unused_w(address, data);
return; return;
case 0x1c: /* Test register */ case 0x1c: /* Test register */
case 0x1d:
case 0x1e:
case 0x1f:
vdp_test_w(data << 8 | data); vdp_test_w(data << 8 | data);
return; return;
default: /* Invalid VDP addresses */ default: /* Invalid address */
z80_lockup_w(address, data); z80_lockup_w(address, data);
return; return;
} }
@ -195,11 +143,16 @@ unsigned int cpu_readmem16(unsigned int address)
return fm_read(1, address & 3); return fm_read(1, address & 3);
case 3: /* VDP */ case 3: /* VDP */
if ((address & 0xff00) == 0x7f00) return z80_vdp_r (address); if ((address >> 8) == 0x7f) return z80_vdp_r (address);
return (z80_unused_r(address) | 0xff); return z80_unused_r(address);
default: /* V-bus bank */ default: /* V-bus bank */
return z80_read_banked_memory(zbank | (address & 0x7fff)); {
address = zbank | (address & 0x7fff);
int slot = address >> 16;
if (zbank_memory_map[slot].read) return (*zbank_memory_map[slot].read)(address);
else return READ_BYTE(m68k_memory_map[slot].base, address&0xffff);
}
} }
} }
@ -218,13 +171,13 @@ void cpu_writemem16(unsigned int address, unsigned int data)
return; return;
case 3: /* Bank register and VDP */ case 3: /* Bank register and VDP */
switch(address & 0xff00) switch(address >> 8)
{ {
case 0x6000: case 0x60:
gen_bank_w(data & 1); gen_bank_w(data & 1);
return; return;
case 0x7f00: case 0x7f:
z80_vdp_w(address, data); z80_vdp_w(address, data);
return; return;
@ -235,10 +188,15 @@ void cpu_writemem16(unsigned int address, unsigned int data)
return; return;
default: /* V-bus bank */ default: /* V-bus bank */
z80_write_banked_memory(zbank | (address & 0x7fff), data); {
address = zbank | (address & 0x7fff);
int slot = address >> 16;
if (zbank_memory_map[slot].write) (*zbank_memory_map[slot].write)(address, data);
else WRITE_BYTE(m68k_memory_map[slot].base, address&0xffff, data);
return; return;
} }
} }
}
/* /*
Port handlers. Ports are unused when not in Mark III compatability mode. Port handlers. Ports are unused when not in Mark III compatability mode.

View File

@ -74,7 +74,11 @@ void set_config_defaults(void)
/* system options */ /* system options */
config.freeze_auto = -1; config.freeze_auto = -1;
#ifdef HW_RVL
config.sram_auto = 0; /* assume we always got SDCARD */
#else
config.sram_auto = -1; config.sram_auto = -1;
#endif
config.region_detect = 0; config.region_detect = 0;
config.force_dtack = 0; config.force_dtack = 0;
config.bios_enabled = 0; config.bios_enabled = 0;

View File

@ -791,22 +791,6 @@ void optionmenu ()
****************************************************************************/ ****************************************************************************/
static u8 device = 0; static u8 device = 0;
/****************************************************************************
* fat_is_mounted
* to check whether FAT media are detected.
***************************************************************************/
bool FatIsMounted(PARTITION_INTERFACE partition) {
char prefix[] = "fatX:/";
prefix[3] = partition + '0';
DIR_ITER *dir = diropen(prefix);
if (dir) {
dirclose(dir);
return true;
}
return false;
}
int loadsavemenu (int which) int loadsavemenu (int which)
{ {
int prevmenu = menu; int prevmenu = menu;
@ -955,6 +939,7 @@ int loadmenu ()
dvd_motor_off(); dvd_motor_off();
dvd_on = 0; dvd_on = 0;
count = 3 + dvd_on; count = 3 + dvd_on;
menu = load_menu;
break; break;
} }
} }

View File

@ -83,7 +83,7 @@ static void init_machine()
bitmap.viewport.x = 0; bitmap.viewport.x = 0;
bitmap.viewport.y = 0; bitmap.viewport.y = 0;
bitmap.remap = 1; bitmap.remap = 1;
bitmap.data = memalign (32, bitmap.width * bitmap.height * bitmap.granularity); bitmap.data = texturemem;
/* default system */ /* default system */
input.system[0] = SYSTEM_GAMEPAD; input.system[0] = SYSTEM_GAMEPAD;
@ -145,7 +145,7 @@ int main (int argc, char *argv[])
if (fatInitDefault() == true) if (fatInitDefault() == true)
{ {
use_FAT = 1; use_FAT = 1;
fatEnableReadAhead (PI_DEFAULT, 6, 64); // fatEnableReadAhead (PI_DEFAULT, 6, 64);
} }
/* Restore User Configuration */ /* Restore User Configuration */

View File

@ -21,6 +21,7 @@
#include "shared.h" #include "shared.h"
#include "ogc_input.h" #include "ogc_input.h"
//#include <asndlib.h>
/* global datas */ /* global datas */
unsigned char soundbuffer[16][3840] ATTRIBUTE_ALIGN(32); unsigned char soundbuffer[16][3840] ATTRIBUTE_ALIGN(32);
@ -49,15 +50,16 @@ static void AudioSwitchBuffers()
AUDIO_InitDMA((u32) soundbuffer[playbuffer], dma_len); AUDIO_InitDMA((u32) soundbuffer[playbuffer], dma_len);
DCFlushRange(soundbuffer[playbuffer], dma_len); DCFlushRange(soundbuffer[playbuffer], dma_len);
AUDIO_StartDMA(); AUDIO_StartDMA();
//ASND_SetVoice(0, VOICE_STEREO_16BIT, 48000, 0, soundbuffer[playbuffer], dma_len, 255, 255, AudioSwitchBuffers);
/* increment soundbuffers index */ /* increment soundbuffers index */
playbuffer++;
playbuffer &= 0xf;
if (playbuffer == mixbuffer) if (playbuffer == mixbuffer)
{ {
playbuffer--; playbuffer--;
if ( playbuffer < 0 ) playbuffer = 15; if ( playbuffer < 0 ) playbuffer = 15;
} }
playbuffer++;
playbuffer &= 0xf;
IsPlaying = 1; IsPlaying = 1;
} }
@ -68,12 +70,14 @@ void ogc_audio__init(void)
AUDIO_Init (NULL); AUDIO_Init (NULL);
AUDIO_SetDSPSampleRate (AI_SAMPLERATE_48KHZ); AUDIO_SetDSPSampleRate (AI_SAMPLERATE_48KHZ);
AUDIO_RegisterDMACallback (AudioSwitchBuffers); AUDIO_RegisterDMACallback (AudioSwitchBuffers);
//ASND_Init();
memset(soundbuffer, 0, 16 * 3840); memset(soundbuffer, 0, 16 * 3840);
} }
void ogc_audio__reset(void) void ogc_audio__reset(void)
{ {
AUDIO_StopDMA (); AUDIO_StopDMA ();
//ASND_Pause(1);
IsPlaying = 0; IsPlaying = 0;
mixbuffer = 0; mixbuffer = 0;
playbuffer = 0; playbuffer = 0;
@ -82,5 +86,9 @@ void ogc_audio__reset(void)
void ogc_audio__update(void) void ogc_audio__update(void)
{ {
/* restart Audio DMA if needed */ /* restart Audio DMA if needed */
if (!IsPlaying) AudioSwitchBuffers(); if (!IsPlaying)
{
//ASND_Pause(0);
AudioSwitchBuffers();
}
} }

View File

@ -604,7 +604,6 @@ void ogc_input__set_defaults(void)
} }
#ifdef HW_RVL #ifdef HW_RVL
u32 exp;
for (i=0; i<4; i++) for (i=0; i<4; i++)
{ {
/* WIIMOTE */ /* WIIMOTE */
@ -648,6 +647,8 @@ void ogc_input__set_defaults(void)
} }
#ifdef HW_RVL #ifdef HW_RVL
u32 exp;
VIDEO_WaitVSync();
int j; int j;
for (i=0; i<4; i++) for (i=0; i<4; i++)
{ {

View File

@ -43,6 +43,7 @@ u8 *texturemem; /*** Texture Data ***/
/*** GX ***/ /*** GX ***/
#define TEX_WIDTH 360 * 2 #define TEX_WIDTH 360 * 2
#define TEX_HEIGHT 576 #define TEX_HEIGHT 576
#define TEX_SIZE TEX_WIDTH * TEX_HEIGHT * 2
#define DEFAULT_FIFO_SIZE 256 * 1024 #define DEFAULT_FIFO_SIZE 256 * 1024
#define HASPECT 320 #define HASPECT 320
#define VASPECT 240 #define VASPECT 240
@ -611,40 +612,10 @@ void ogc_video__update()
GX_LoadTexObj (&texobj, GX_TEXMAP0); GX_LoadTexObj (&texobj, GX_TEXMAP0);
} }
/* texture is now directly mapped by the line renderer */
/* texture map is now directly done by the line renderer */
if (config.ntsc && !(reg[12]&1))
{
int h, w;
/* texture and bitmap buffers (buffers pitch is fixed to 720*2 pixels) */
long long int *dst = (long long int *)texturemem;
long long int *src1 = (long long int *)(bitmap.data); /* line n */
long long int *src2 = src1 + 180; /* line n+1 */
long long int *src3 = src2 + 180; /* line n+2 */
long long int *src4 = src3 + 180; /* line n+3 */
/* update texture texels */
for (h = 0; h < vheight; h++)
{
for (w = 0; w < vwidth; w++)
{
*dst++ = *src1++;
*dst++ = *src2++;
*dst++ = *src3++;
*dst++ = *src4++;
}
/* jump to next four lines */
src1 += stride;
src2 += stride;
src3 += stride;
src4 += stride;
}
}
/* update texture cache */ /* update texture cache */
DCFlushRange (texturemem, TEX_WIDTH * TEX_HEIGHT * 2); DCFlushRange (texturemem, TEX_SIZE);
GX_InvalidateTexAll (); GX_InvalidateTexAll ();
/* render textured quad */ /* render textured quad */

View File

@ -99,7 +99,17 @@ void sms_ntsc_blit( sms_ntsc_t const* ntsc, SMS_NTSC_IN_T const* table, unsigned
(SMS_NTSC_ADJ_IN( table[input[0]] )) & extra2, (SMS_NTSC_ADJ_IN( table[input[0]] )) & extra2,
(SMS_NTSC_ADJ_IN( table[input[extra2 & 1]] )) & extra1 ); (SMS_NTSC_ADJ_IN( table[input[extra2 & 1]] )) & extra1 );
#ifdef NGC
/* directly fill the RGB565 texture */
/* one tile is 32 byte = 4x4 pixels */
/* tiles are stored continuously in texture memory */
in_width = SMS_NTSC_OUT_WIDTH(in_width) >> 2;
int offset = ((in_width << 5) * (vline >> 2)) + ((vline & 3) * 8);
sms_ntsc_out_t* restrict line_out = (sms_ntsc_out_t*)(texturemem + offset);
offset = 0;
#else
sms_ntsc_out_t* restrict line_out = (sms_ntsc_out_t*)(&bitmap.data[(vline * bitmap.pitch)]); sms_ntsc_out_t* restrict line_out = (sms_ntsc_out_t*)(&bitmap.data[(vline * bitmap.pitch)]);
#endif
int n; int n;
input += in_extra; input += in_extra;
@ -107,31 +117,76 @@ void sms_ntsc_blit( sms_ntsc_t const* ntsc, SMS_NTSC_IN_T const* table, unsigned
{ {
/* order of input and output pixels must not be altered */ /* order of input and output pixels must not be altered */
SMS_NTSC_COLOR_IN( 0, ntsc, SMS_NTSC_ADJ_IN( table[*input++] ) ); SMS_NTSC_COLOR_IN( 0, ntsc, SMS_NTSC_ADJ_IN( table[*input++] ) );
#ifdef NGC
SMS_NTSC_RGB_OUT( 0, line_out[16*(offset/4) + (offset%4)], SMS_NTSC_OUT_DEPTH );
offset ++;
SMS_NTSC_RGB_OUT( 1, line_out[16*(offset/4) + (offset%4)], SMS_NTSC_OUT_DEPTH );
offset ++;
#else
SMS_NTSC_RGB_OUT( 0, *line_out++, SMS_NTSC_OUT_DEPTH ); SMS_NTSC_RGB_OUT( 0, *line_out++, SMS_NTSC_OUT_DEPTH );
SMS_NTSC_RGB_OUT( 1, *line_out++, SMS_NTSC_OUT_DEPTH ); SMS_NTSC_RGB_OUT( 1, *line_out++, SMS_NTSC_OUT_DEPTH );
#endif
SMS_NTSC_COLOR_IN( 1, ntsc, SMS_NTSC_ADJ_IN( table[*input++] ) ); SMS_NTSC_COLOR_IN( 1, ntsc, SMS_NTSC_ADJ_IN( table[*input++] ) );
#ifdef NGC
SMS_NTSC_RGB_OUT( 2, line_out[16*(offset/4) + (offset%4)], SMS_NTSC_OUT_DEPTH );
offset ++;
SMS_NTSC_RGB_OUT( 3, line_out[16*(offset/4) + (offset%4)], SMS_NTSC_OUT_DEPTH );
offset ++;
#else
SMS_NTSC_RGB_OUT( 2, *line_out++, SMS_NTSC_OUT_DEPTH ); SMS_NTSC_RGB_OUT( 2, *line_out++, SMS_NTSC_OUT_DEPTH );
SMS_NTSC_RGB_OUT( 3, *line_out++, SMS_NTSC_OUT_DEPTH ); SMS_NTSC_RGB_OUT( 3, *line_out++, SMS_NTSC_OUT_DEPTH );
#endif
SMS_NTSC_COLOR_IN( 2, ntsc, SMS_NTSC_ADJ_IN( table[*input++] ) ); SMS_NTSC_COLOR_IN( 2, ntsc, SMS_NTSC_ADJ_IN( table[*input++] ) );
#ifdef NGC
SMS_NTSC_RGB_OUT( 4, line_out[16*(offset/4) + (offset%4)], SMS_NTSC_OUT_DEPTH );
offset ++;
SMS_NTSC_RGB_OUT( 5, line_out[16*(offset/4) + (offset%4)], SMS_NTSC_OUT_DEPTH );
offset ++;
SMS_NTSC_RGB_OUT( 6, line_out[16*(offset/4) + (offset%4)], SMS_NTSC_OUT_DEPTH );
offset ++;
#else
SMS_NTSC_RGB_OUT( 4, *line_out++, SMS_NTSC_OUT_DEPTH ); SMS_NTSC_RGB_OUT( 4, *line_out++, SMS_NTSC_OUT_DEPTH );
SMS_NTSC_RGB_OUT( 5, *line_out++, SMS_NTSC_OUT_DEPTH ); SMS_NTSC_RGB_OUT( 5, *line_out++, SMS_NTSC_OUT_DEPTH );
SMS_NTSC_RGB_OUT( 6, *line_out++, SMS_NTSC_OUT_DEPTH ); SMS_NTSC_RGB_OUT( 6, *line_out++, SMS_NTSC_OUT_DEPTH );
#endif
} }
/* finish final pixels */ /* finish final pixels */
SMS_NTSC_COLOR_IN( 0, ntsc, sms_ntsc_black ); SMS_NTSC_COLOR_IN( 0, ntsc, sms_ntsc_black );
#ifdef NGC
SMS_NTSC_RGB_OUT( 0, line_out[16*(offset/4) + (offset%4)], SMS_NTSC_OUT_DEPTH );
offset ++;
SMS_NTSC_RGB_OUT( 1, line_out[16*(offset/4) + (offset%4)], SMS_NTSC_OUT_DEPTH );
offset ++;
#else
SMS_NTSC_RGB_OUT( 0, *line_out++, SMS_NTSC_OUT_DEPTH ); SMS_NTSC_RGB_OUT( 0, *line_out++, SMS_NTSC_OUT_DEPTH );
SMS_NTSC_RGB_OUT( 1, *line_out++, SMS_NTSC_OUT_DEPTH ); SMS_NTSC_RGB_OUT( 1, *line_out++, SMS_NTSC_OUT_DEPTH );
#endif
SMS_NTSC_COLOR_IN( 1, ntsc, sms_ntsc_black ); SMS_NTSC_COLOR_IN( 1, ntsc, sms_ntsc_black );
#ifdef NGC
SMS_NTSC_RGB_OUT( 2, line_out[16*(offset/4) + (offset%4)], SMS_NTSC_OUT_DEPTH );
offset ++;
SMS_NTSC_RGB_OUT( 3, line_out[16*(offset/4) + (offset%4)], SMS_NTSC_OUT_DEPTH );
offset ++;
#else
SMS_NTSC_RGB_OUT( 2, *line_out++, SMS_NTSC_OUT_DEPTH ); SMS_NTSC_RGB_OUT( 2, *line_out++, SMS_NTSC_OUT_DEPTH );
SMS_NTSC_RGB_OUT( 3, *line_out++, SMS_NTSC_OUT_DEPTH ); SMS_NTSC_RGB_OUT( 3, *line_out++, SMS_NTSC_OUT_DEPTH );
#endif
SMS_NTSC_COLOR_IN( 2, ntsc, sms_ntsc_black ); SMS_NTSC_COLOR_IN( 2, ntsc, sms_ntsc_black );
#ifdef NGC
SMS_NTSC_RGB_OUT( 4, line_out[16*(offset/4) + (offset%4)], SMS_NTSC_OUT_DEPTH );
offset ++;
SMS_NTSC_RGB_OUT( 5, line_out[16*(offset/4) + (offset%4)], SMS_NTSC_OUT_DEPTH );
offset ++;
SMS_NTSC_RGB_OUT( 6, line_out[16*(offset/4) + (offset%4)], SMS_NTSC_OUT_DEPTH );
#else
SMS_NTSC_RGB_OUT( 4, *line_out++, SMS_NTSC_OUT_DEPTH ); SMS_NTSC_RGB_OUT( 4, *line_out++, SMS_NTSC_OUT_DEPTH );
SMS_NTSC_RGB_OUT( 5, *line_out++, SMS_NTSC_OUT_DEPTH ); SMS_NTSC_RGB_OUT( 5, *line_out++, SMS_NTSC_OUT_DEPTH );
SMS_NTSC_RGB_OUT( 6, *line_out++, SMS_NTSC_OUT_DEPTH ); SMS_NTSC_RGB_OUT( 6, *line_out++, SMS_NTSC_OUT_DEPTH );
#endif
} }
#endif #endif

File diff suppressed because it is too large Load Diff

View File

@ -34,16 +34,19 @@ extern int render_init(void);
extern void palette_init(void); extern void palette_init(void);
extern void render_reset(void); extern void render_reset(void);
extern void render_shutdown(void); extern void render_shutdown(void);
extern void render_line(int line, uint8 odd_frame); extern void render_line(uint32 line, uint32 overscan);
extern void parse_satb(uint32 line);
extern void remap_buffer(uint32 line,uint32 width);
extern void window_clip(uint8 reg_12, uint8 reg_17);
#ifndef NGC #ifndef NGC
extern void color_update_8(int index, uint16 data); extern void color_update_8(int index, uint16 data);
extern void color_update_15(int index, uint16 data); extern void color_update_15(int index, uint16 data);
extern void color_update_32(int index, uint16 data); extern void color_update_32(int index, uint16 data);
#endif #endif
extern void color_update_16(int index, uint16 data); extern void color_update_16(int index, uint16 data);
extern void parse_satb(int line);
extern void (*color_update)(int index, uint16 data); void (*color_update)(int index, uint16 data);
extern void remap_buffer(int line,int width);
#endif /* _RENDER_H_ */ #endif /* _RENDER_H_ */

View File

@ -16,7 +16,6 @@
#include "mem68k.h" #include "mem68k.h"
#include "memz80.h" #include "memz80.h"
#include "membnk.h" #include "membnk.h"
#include "memvdp.h"
#include "gen_io.h" #include "gen_io.h"
#include "gen_input.h" #include "gen_input.h"
#include "state.h" #include "state.h"

View File

@ -670,7 +670,7 @@ INLINE void FM_KEYOFF(FM_CH *CH , int s )
} }
/* set algorithm connection */ /* set algorithm connection */
static void setup_connection( FM_CH *CH, int ch ) INLINE void setup_connection( FM_CH *CH, int ch )
{ {
INT32 *carrier = &out_fm[ch]; INT32 *carrier = &out_fm[ch];
@ -1397,7 +1397,7 @@ INLINE void CSMKeyControll(FM_CH *CH)
} }
} }
static void INTERNAL_TIMER_A() INLINE void INTERNAL_TIMER_A()
{ {
if (ym2612.OPN.ST.mode & 0x01) if (ym2612.OPN.ST.mode & 0x01)
{ {
@ -1416,7 +1416,7 @@ static void INTERNAL_TIMER_A()
} }
} }
static void INTERNAL_TIMER_B(int step) INLINE void INTERNAL_TIMER_B(int step)
{ {
if (ym2612.OPN.ST.mode & 0x02) if (ym2612.OPN.ST.mode & 0x02)
{ {

View File

@ -25,13 +25,13 @@
static unsigned char state[0x24000]; static unsigned char state[0x24000];
static unsigned int bufferptr; static unsigned int bufferptr;
void load_param(void *param, unsigned int size) static inline void load_param(void *param, unsigned int size)
{ {
memcpy(param, &state[bufferptr], size); memcpy(param, &state[bufferptr], size);
bufferptr+= size; bufferptr+= size;
} }
void save_param(void *param, unsigned int size) static inline void save_param(void *param, unsigned int size)
{ {
memcpy(&state[bufferptr], param, size); memcpy(&state[bufferptr], param, size);
bufferptr+= size; bufferptr+= size;
@ -39,27 +39,18 @@ void save_param(void *param, unsigned int size)
void state_load(unsigned char *buffer) void state_load(unsigned char *buffer)
{ {
uint32 tmp32; /* reset buffer pointer */
uint16 tmp16;
uint8 temp_reg[0x20];
unsigned long inbytes, outbytes;
/* get compressed state size & uncompress state file */
memcpy(&inbytes, buffer, 4);
bufferptr = 0; bufferptr = 0;
#ifdef NGC /* uncompress savestate */
unsigned long inbytes, outbytes;
memcpy(&inbytes, buffer, 4);
outbytes = 0x24000; outbytes = 0x24000;
uncompress ((Bytef *)state, &outbytes, (Bytef *)(buffer + 4), inbytes); uncompress ((Bytef *)state, &outbytes, (Bytef *)(buffer + 4), inbytes);
#else
outbytes = inbytes;
memcpy(state, buffer + 4, outbytes);
#endif
/* SYSTEM RESET */ /* reset system */
system_reset(); system_reset();
rom_readmap[0] = &cart_rom[0]; m68k_memory_map[0].base = default_rom;
rom_size = genromsize;
// GENESIS // GENESIS
load_param(work_ram, sizeof(work_ram)); load_param(work_ram, sizeof(work_ram));
@ -73,6 +64,7 @@ void state_load(unsigned char *buffer)
load_param(io_reg, sizeof(io_reg)); load_param(io_reg, sizeof(io_reg));
// VDP // VDP
uint8 temp_reg[0x20];
load_param(sat, sizeof(sat)); load_param(sat, sizeof(sat));
load_param(vram, sizeof(vram)); load_param(vram, sizeof(vram));
load_param(cram, sizeof(cram)); load_param(cram, sizeof(cram));
@ -86,8 +78,7 @@ void state_load(unsigned char *buffer)
load_param(&dmafill, sizeof(dmafill)); load_param(&dmafill, sizeof(dmafill));
load_param(&hint_pending, sizeof(hint_pending)); load_param(&hint_pending, sizeof(hint_pending));
load_param(&vint_pending, sizeof(vint_pending)); load_param(&vint_pending, sizeof(vint_pending));
load_param(&vint_triggered, sizeof(vint_triggered)); load_param(&irq_status, sizeof(irq_status));
load_param(&hvint_updated, sizeof(hvint_updated));
vdp_restore(temp_reg); vdp_restore(temp_reg);
// FM // FM
@ -98,6 +89,8 @@ void state_load(unsigned char *buffer)
load_param(SN76489_GetContextPtr (0),SN76489_GetContextSize ()); load_param(SN76489_GetContextPtr (0),SN76489_GetContextSize ());
// 68000 // 68000
uint16 tmp16;
uint32 tmp32;
load_param(&tmp32, 4); m68k_set_reg(M68K_REG_D0, tmp32); load_param(&tmp32, 4); m68k_set_reg(M68K_REG_D0, tmp32);
load_param(&tmp32, 4); m68k_set_reg(M68K_REG_D1, tmp32); load_param(&tmp32, 4); m68k_set_reg(M68K_REG_D1, tmp32);
load_param(&tmp32, 4); m68k_set_reg(M68K_REG_D2, tmp32); load_param(&tmp32, 4); m68k_set_reg(M68K_REG_D2, tmp32);
@ -124,11 +117,7 @@ void state_load(unsigned char *buffer)
int state_save(unsigned char *buffer) int state_save(unsigned char *buffer)
{ {
uint32 tmp32; /* reset buffer pointer */
uint16 tmp16;
unsigned long inbytes, outbytes;
/* save state */
bufferptr = 0; bufferptr = 0;
// GENESIS // GENESIS
@ -155,8 +144,7 @@ int state_save(unsigned char *buffer)
save_param(&dmafill, sizeof(dmafill)); save_param(&dmafill, sizeof(dmafill));
save_param(&hint_pending, sizeof(hint_pending)); save_param(&hint_pending, sizeof(hint_pending));
save_param(&vint_pending, sizeof(vint_pending)); save_param(&vint_pending, sizeof(vint_pending));
save_param(&vint_triggered, sizeof(vint_triggered)); save_param(&irq_status, sizeof(irq_status));
save_param(&hvint_updated, sizeof(hvint_updated));
// FM // FM
save_param(fm_reg,sizeof(fm_reg)); save_param(fm_reg,sizeof(fm_reg));
@ -165,6 +153,8 @@ int state_save(unsigned char *buffer)
save_param(SN76489_GetContextPtr (0),SN76489_GetContextSize ()); save_param(SN76489_GetContextPtr (0),SN76489_GetContextSize ());
// 68000 // 68000
uint16 tmp16;
uint32 tmp32;
tmp32 = m68k_get_reg(NULL, M68K_REG_D0); save_param(&tmp32, 4); tmp32 = m68k_get_reg(NULL, M68K_REG_D0); save_param(&tmp32, 4);
tmp32 = m68k_get_reg(NULL, M68K_REG_D1); save_param(&tmp32, 4); tmp32 = m68k_get_reg(NULL, M68K_REG_D1); save_param(&tmp32, 4);
tmp32 = m68k_get_reg(NULL, M68K_REG_D2); save_param(&tmp32, 4); tmp32 = m68k_get_reg(NULL, M68K_REG_D2); save_param(&tmp32, 4);
@ -188,18 +178,10 @@ int state_save(unsigned char *buffer)
// Z80 // Z80
save_param(&Z80, sizeof(Z80_Regs)); save_param(&Z80, sizeof(Z80_Regs));
inbytes = bufferptr;
#ifdef NGC
/* compress state file */ /* compress state file */
outbytes = 0x26000; unsigned long inbytes = bufferptr;
unsigned long outbytes = 0x26000;
compress2 ((Bytef *)(buffer + 4), &outbytes, (Bytef *)state, inbytes, 9); compress2 ((Bytef *)(buffer + 4), &outbytes, (Bytef *)state, inbytes, 9);
#else
outbytes = inbytes;
memcpy(buffer + 4, state, outbytes);
#endif
/* write compressed size in the first 32 bits for decompression */
memcpy(buffer, &outbytes, 4); memcpy(buffer, &outbytes, 4);
/* return total size */ /* return total size */

View File

@ -43,60 +43,9 @@ uint32 line_z80;
int32 current_z80; int32 current_z80;
uint8 odd_frame; uint8 odd_frame;
uint8 interlaced; uint8 interlaced;
uint32 frame_cnt;
uint8 system_hw; uint8 system_hw;
/**************************************************************** static inline void audio_update (void);
* CPU execution managment
****************************************************************/
/* Interrupt Manager
this is called before each new executed instruction
only if interrupts have been updated
*/
static inline void update_interrupts(void)
{
uint8 latency = hvint_updated;
hvint_updated = -1;
/* VDP hardware latency */
if (latency) count_m68k += m68k_execute(latency);
/* Level 6 interrupt */
if (vint_pending && (reg[1] & 0x20))
{
vint_triggered = 1;
m68k_set_irq(6);
}
/* Level 4 interrupt */
else if (hint_pending && (reg[0] & 0x10))
{
m68k_set_irq(4);
}
/* Clear all interrupts */
else
{
m68k_set_irq(0);
}
}
static inline void m68k_run (int cyc)
{
while (count_m68k < cyc)
{
/* check interrupts */
if (hvint_updated >= 0) update_interrupts();
/* execute a single instruction */
count_m68k += m68k_execute(1);
}
}
void z80_run (int cyc)
{
current_z80 = cyc - count_z80;
if (current_z80 > 0) count_z80 += z80_execute(current_z80);
}
/**************************************************************** /****************************************************************
* Virtual Genesis initialization * Virtual Genesis initialization
@ -128,7 +77,6 @@ void system_reset (void)
current_z80 = 0; current_z80 = 0;
odd_frame = 0; odd_frame = 0;
interlaced = 0; interlaced = 0;
frame_cnt = 0;
/* Cart Hardware reset */ /* Cart Hardware reset */
cart_hw_reset(); cart_hw_reset();
@ -161,7 +109,11 @@ void system_shutdown (void)
****************************************************************/ ****************************************************************/
int system_frame (int do_skip) int system_frame (int do_skip)
{ {
int line; if (!gen_running)
{
update_input();
return 0;
}
/* reset cycles counts */ /* reset cycles counts */
count_m68k = 0; count_m68k = 0;
@ -171,37 +123,31 @@ int system_frame (int do_skip)
fifo_write_cnt = 0; fifo_write_cnt = 0;
fifo_lastwrite = 0; fifo_lastwrite = 0;
/* increment frame counter */ /* update display settings */
frame_cnt ++; int line;
int reset = resetline;
if (!gen_running) int vdp_height = bitmap.viewport.h;
{ int end_line = vdp_height + bitmap.viewport.y;
update_input(); int start_line = lines_per_frame - bitmap.viewport.y;
return 0; int old_interlaced = interlaced;
} interlaced = (reg[12] >> 1) & 3;
/* Clear VBLANK & DMA BUSY flags */
status &= 0xFFF5;
/* Look for interlace mode change */
uint8 old_interlaced = interlaced;
interlaced = (reg[12] & 2) >> 1;
if (old_interlaced != interlaced) if (old_interlaced != interlaced)
{ {
bitmap.viewport.changed = 2; bitmap.viewport.changed = 2;
im2_flag = ((reg[12] & 6) == 6) ? 1 : 0; im2_flag = (interlaced == 3);
odd_frame = 1; odd_frame = 1;
} }
/* Toggle even/odd field flag (interlaced modes only) */
odd_frame ^= 1; odd_frame ^= 1;
if (odd_frame && interlaced) status |= 0x0010;
/* update VDP status */
status &= 0xFFF5; // clear VBLANK and DMA flags
if (odd_frame && interlaced) status |= 0x0010; // even/odd field flag (interlaced modes only)
else status &= 0xFFEF; else status &= 0xFFEF;
/* Reset HCounter */ /* Reload H Counter */
h_counter = reg[10]; int h_counter = reg[10];
/* Parse sprites for line 0 (done on line 261 or 312) */ /* parse sprites for line 0 (done on last line) */
parse_satb (0x80); parse_satb (0x80);
/* Line processing */ /* Line processing */
@ -220,8 +166,8 @@ int system_frame (int do_skip)
aim_z80 += z80cycles_per_line; aim_z80 += z80cycles_per_line;
aim_m68k += m68cycles_per_line; aim_m68k += m68cycles_per_line;
/* Check "soft reset" */ /* Soft Reset ? */
if (line == resetline) if (line == reset)
{ {
#ifdef NGC #ifdef NGC
/* wait for RESET button to be released */ /* wait for RESET button to be released */
@ -231,15 +177,15 @@ int system_frame (int do_skip)
} }
/* Horizontal Interrupt */ /* Horizontal Interrupt */
if (line <= bitmap.viewport.h) if (line <= vdp_height)
{ {
if(--h_counter < 0) if(--h_counter < 0)
{ {
h_counter = reg[10]; h_counter = reg[10];
hint_pending = 1; hint_pending = 1;
hvint_updated = 0; if (reg[0] & 0x10) irq_status = (irq_status & 0xff) | 0x14;
/* adjust timings to take decrement in account */ /* adjust timings to take further decrement in account (see below) */
if ((line != 0) || (h_counter == 0)) aim_m68k += 36; if ((line != 0) || (h_counter == 0)) aim_m68k += 36;
} }
@ -247,22 +193,17 @@ int system_frame (int do_skip)
/* during this period, any VRAM/CRAM/VSRAM writes should NOT be taken in account before next line */ /* during this period, any VRAM/CRAM/VSRAM writes should NOT be taken in account before next line */
/* as a result, current line is shortened */ /* as a result, current line is shortened */
/* fix Lotus 1, Lotus 2 RECS, Striker, Zero the Kamikaze Squirell */ /* fix Lotus 1, Lotus 2 RECS, Striker, Zero the Kamikaze Squirell */
if ((line < bitmap.viewport.h)&&(h_counter == 0)) aim_m68k -= 36; if ((line < vdp_height) && (h_counter == 0)) aim_m68k -= 36;
}
/* Check if there is any DMA in progess */ /* update DMA timings */
if (dma_length) dma_update(); if (dma_length) dma_update();
/* Render Line */
if (!do_skip)
{
render_line(line,odd_frame);
if (line < (bitmap.viewport.h-1)) parse_satb(0x81 + line);
}
/* Vertical Retrace */ /* Vertical Retrace */
if (line == bitmap.viewport.h) if (line == vdp_height)
{ {
/* render overscan */
if ((line < end_line) && (!do_skip)) render_line(line, 1);
/* update inputs */ /* update inputs */
update_input(); update_input();
@ -275,24 +216,51 @@ int system_frame (int do_skip)
/* delay between HINT, VBLANK and VINT (Dracula, OutRunners, VR Troopers) */ /* delay between HINT, VBLANK and VINT (Dracula, OutRunners, VR Troopers) */
m68k_run(line_m68k + 84); m68k_run(line_m68k + 84);
if (zreset && !zbusreq) z80_run(line_z80 + 39); 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; else count_z80 = line_z80 + 39;
/* Vertical Interrupt */ /* Vertical Interrupt */
status |= 0x80; status |= 0x80;
vint_pending = 1; vint_pending = 1;
hvint_updated = 36; /* Tyrants, Mega-Lo-Mania & Ex Mutant need some cycles to read VINT flag */ if (reg[1] & 0x20) irq_status = (irq_status & 0xff) | 0x2416; // 36 cycles latency after VINT occurence flag (Ex-Mutants, Tyrant)
} }
else if (zirq) else if (!do_skip)
{ {
/* render scanline and parse sprites for line n+1 */
render_line(line, 0);
if (line < (vdp_height-1)) parse_satb(0x81 + line);
}
}
else
{
/* update DMA timings */
if (dma_length) dma_update();
/* render overscan */
if ((line < end_line) || (line >= start_line))
{
if (!do_skip) render_line(line, 1);
}
/* clear any pending Z80 interrupt */ /* clear any pending Z80 interrupt */
if (zirq)
{
zirq = 0; zirq = 0;
z80_set_irq_line(0, CLEAR_LINE); z80_set_irq_line(0, CLEAR_LINE);
}
} }
/* Process line */ /* Process line */
m68k_run(aim_m68k); m68k_run(aim_m68k);
if (zreset == 1 && zbusreq == 0) z80_run(aim_z80); if (zreset == 1 && zbusreq == 0)
{
current_z80 = aim_z80 - count_z80;
if (current_z80 > 0) count_z80 += z80_execute(current_z80);
}
else count_z80 = aim_z80; else count_z80 = aim_z80;
/* SVP chip */ /* SVP chip */
@ -372,7 +340,7 @@ void audio_shutdown(void)
static int ll, rr; static int ll, rr;
void audio_update (void) static inline void audio_update (void)
{ {
int i; int i;
int l, r; int l, r;

View File

@ -32,6 +32,7 @@
#define z80cycles_per_line 228 #define z80cycles_per_line 228
#define m68cycles_per_line 488 #define m68cycles_per_line 488
typedef struct typedef struct
{ {
uint8 *data; /* Bitmap data */ uint8 *data; /* Bitmap data */
@ -90,7 +91,6 @@ extern uint32 line_z80;
extern int32 current_z80; extern int32 current_z80;
extern uint8 interlaced; extern uint8 interlaced;
extern uint8 odd_frame; extern uint8 odd_frame;
extern uint32 frame_cnt;
extern uint8 system_hw; extern uint8 system_hw;
/* Function prototypes */ /* Function prototypes */
@ -100,8 +100,6 @@ extern void system_shutdown (void);
extern int system_frame(int skip); extern int system_frame(int skip);
extern int audio_init (int rate); extern int audio_init (int rate);
extern void audio_shutdown (void); extern void audio_shutdown (void);
extern void audio_update (void);
extern void z80_run (int cyc);
#endif /* _SYSTEM_H_ */ #endif /* _SYSTEM_H_ */

View File

@ -31,7 +31,7 @@
/* Mark a pattern as dirty */ /* Mark a pattern as dirty */
#define MARK_BG_DIRTY(addr) \ #define MARK_BG_DIRTY(addr) \
{ \ { \
int name = (addr >> 5) & 0x7FF; \ name = (addr >> 5) & 0x7FF; \
if(bg_name_dirty[name] == 0) bg_name_list[bg_list_index++] = name; \ if(bg_name_dirty[name] == 0) bg_name_list[bg_list_index++] = name; \
bg_name_dirty[name] |= (1 << ((addr >> 2) & 0x07)); \ bg_name_dirty[name] |= (1 << ((addr >> 2) & 0x07)); \
} }
@ -50,8 +50,7 @@ uint16 status; /* VDP status flags */
uint8 dmafill; /* next VDP Write is DMA Fill */ uint8 dmafill; /* next VDP Write is DMA Fill */
uint8 hint_pending; /* 0= Line interrupt is pending */ uint8 hint_pending; /* 0= Line interrupt is pending */
uint8 vint_pending; /* 1= Frame interrupt is pending */ uint8 vint_pending; /* 1= Frame interrupt is pending */
uint8 vint_triggered; /* 1= Frame interrupt has been triggered */ uint16 irq_status; /* Interrupt lines updated */
int8 hvint_updated; /* >= 0: Interrupt lines updated */
/* Global variables */ /* Global variables */
uint16 ntab; /* Name table A base address */ uint16 ntab; /* Name table A base address */
@ -68,8 +67,7 @@ uint8 playfield_shift; /* Width of planes A, B (in bits) */
uint8 playfield_col_mask; /* Vertical scroll mask */ uint8 playfield_col_mask; /* Vertical scroll mask */
uint16 playfield_row_mask; /* Horizontal scroll mask */ uint16 playfield_row_mask; /* Horizontal scroll mask */
uint32 y_mask; /* Name table Y-index bits mask */ uint32 y_mask; /* Name table Y-index bits mask */
int16 h_counter; /* Raster counter */ uint16 hc_latch; /* latched HCounter (INT2) */
int16 hc_latch; /* latched HCounter (INT2) */
uint16 v_counter; /* VDP scanline counter */ uint16 v_counter; /* VDP scanline counter */
uint8 im2_flag; /* 1= Interlace mode 2 is being used */ uint8 im2_flag; /* 1= Interlace mode 2 is being used */
uint32 dma_length; /* Current DMA remaining bytes */ uint32 dma_length; /* Current DMA remaining bytes */
@ -91,6 +89,8 @@ 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; /* Type of DMA */ static uint8 dma_type; /* Type of DMA */
static inline void vdp_reg_w(unsigned int r, unsigned int d);
/* DMA Timings /* DMA Timings
According to the manual, here's a table that describes the transfer According to the manual, here's a table that describes the transfer
@ -183,11 +183,9 @@ void vdp_reset(void)
hint_pending = 0; hint_pending = 0;
vint_pending = 0; vint_pending = 0;
vint_triggered = 0; irq_status = 0;
hvint_updated = -1;
h_counter = 0; hc_latch = 0;
hc_latch = -1;
v_counter = 0; v_counter = 0;
dmafill = 0; dmafill = 0;
@ -221,6 +219,7 @@ void vdp_reset(void)
vdp_reg_w(10, 0xff); /* HINT disabled */ vdp_reg_w(10, 0xff); /* HINT disabled */
vdp_reg_w(12, 0x81); /* H40 mode */ vdp_reg_w(12, 0x81); /* H40 mode */
vdp_reg_w(15, 0x02); /* auto increment */ vdp_reg_w(15, 0x02); /* auto increment */
window_clip(1,0);
} }
/* default latency */ /* default latency */
@ -325,6 +324,7 @@ void dma_update()
*/ */
static inline void dma_copy(void) static inline void dma_copy(void)
{ {
int name;
int length = (reg[20] << 8 | reg[19]) & 0xFFFF; int length = (reg[20] << 8 | reg[19]) & 0xFFFF;
int source = (reg[22] << 8 | reg[21]) & 0xFFFF; int source = (reg[22] << 8 | reg[21]) & 0xFFFF;
if (!length) length = 0x10000; if (!length) length = 0x10000;
@ -355,6 +355,7 @@ static inline void dma_vbus (void)
{ {
uint32 base, source = ((reg[23] & 0x7F) << 17 | reg[22] << 9 | reg[21] << 1) & 0xFFFFFE; uint32 base, source = ((reg[23] & 0x7F) << 17 | reg[22] << 9 | reg[21] << 1) & 0xFFFFFE;
uint32 length = (reg[20] << 8 | reg[19]) & 0xFFFF; uint32 length = (reg[20] << 8 | reg[19]) & 0xFFFF;
uint32 temp;
if (!length) length = 0x10000; if (!length) length = 0x10000;
base = source; base = source;
@ -364,15 +365,49 @@ static inline void dma_vbus (void)
dma_length = length; dma_length = length;
dma_update(); dma_update();
/* proceed DMA */ switch (source >> 21)
{
case 5:
do do
{ {
unsigned int temp = vdp_dma_r(source); /* Return $FFFF only when the Z80 isn't hogging the Z-bus.
(e.g. Z80 isn't reset and 68000 has the bus) */
if (source <= 0xa0ffff) temp = (zbusack ? *(uint16 *)(work_ram + (source & 0xffff)) : 0xffff);
/* 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.
We return the I/O chip values which seem to have precedence, */
else if (source <= 0xa1001f)
{
temp = io_read((source >> 1) & 0x0f);
temp = (temp << 8 | temp);
}
/* All remaining locations access work RAM */
else temp = *(uint16 *)(work_ram + (source & 0xffff));
source += 2; source += 2;
source = ((base & 0xFE0000) | (source & 0x1FFFF)); source = ((base & 0xFE0000) | (source & 0x1FFFF));
data_write (temp); data_write (temp);
} }
while (--length); while (--length);
break;
case 0:
case 1:
if (svp) source = source - 2;
default:
do
{
temp = *(uint16 *)(m68k_memory_map[source>>16].base + (source & 0xffff));
source += 2;
source = ((base & 0xFE0000) | (source & 0x1FFFF));
data_write (temp);
}
while (--length);
break;
}
/* update length & source address registers */ /* update length & source address registers */
reg[19] = length & 0xFF; reg[19] = length & 0xFF;
@ -385,6 +420,7 @@ static inline void dma_vbus (void)
/* VRAM FILL */ /* VRAM FILL */
static inline void dma_fill(unsigned int data) static inline void dma_fill(unsigned int data)
{ {
int name;
int length = (reg[20] << 8 | reg[19]) & 0xFFFF; int length = (reg[20] << 8 | reg[19]) & 0xFFFF;
if (!length) length = 0x10000; if (!length) length = 0x10000;
@ -475,6 +511,7 @@ static inline void data_write (unsigned int data)
*(uint16 *) &vram[addr & 0xFFFE] = data; *(uint16 *) &vram[addr & 0xFFFE] = data;
/* Update the pattern cache */ /* Update the pattern cache */
int name;
MARK_BG_DIRTY (addr); MARK_BG_DIRTY (addr);
} }
break; break;
@ -566,6 +603,178 @@ void vdp_ctrl_w(unsigned int data)
} }
/*
The reg[] array is updated at the *end* of this function, so the new
register data can be compared with the previous data.
*/
static inline void vdp_reg_w(unsigned int r, unsigned int d)
{
/* Check if Mode 4 (SMS mode) has been activated
According to official doc, VDP registers #11 to #23 can not be written unless bit2 in register #1 is set
Fix Captain Planet & Avengers (Alt version), Bass Master Classic Pro Edition (they incidentally activate Mode 4)
*/
if (!(reg[1] & 4) && (r > 10)) return;
switch(r)
{
case 0x00: /* CTRL #1 */
/* Check if HINT has been enabled or disabled */
if (hint_pending && ((d&0x10) != (reg[0]&0x10)))
{
irq_status &= 0x20;
irq_status |= 0x10;
if (vint_pending && (reg[1] & 0x20))
{
irq_status |= 6;
}
else if (d & 0x10)
{
irq_status |= 4;
}
}
break;
case 0x01: /* CTRL #2 */
/* Check if VINT has been enabled or disabled */
if (vint_pending && ((d&0x20) != (reg[1]&0x20)))
{
irq_status &= 0x20;
irq_status |= 0x110;
if (d & 0x20)
{
irq_status |= 6;
}
else if (hint_pending && (reg[0] & 0x10))
{
irq_status |= 4;
}
}
/* Check if the viewport height has actually been changed */
if((reg[1] & 8) != (d & 8))
{
/* Update the height of the viewport */
bitmap.viewport.h = (d & 8) ? 240 : 224;
if (config.overscan) bitmap.viewport.y = ((vdp_pal ? 288 : 240) - bitmap.viewport.h) / 2;
bitmap.viewport.changed = 1;
/* update VC table */
if (vdp_pal) vctab = (d & 8) ? vc_pal_240 : vc_pal_224;
}
/* DISPLAY switched ON/OFF during HBLANK */
if ((v_counter < bitmap.viewport.h) && ((d&0x40) != (reg[1]&0x40)))
{
if (count_m68k <= (hint_m68k + 120))
{
/* Redraw the current line :
- Legend of Galahad, Lemmings 2, Nigel Mansell's World Championship Racing (set display OFF)
- Deadly Moves aka Power Athlete (set display ON)
*/
reg[1] = d;
render_line(v_counter, 0);
}
}
break;
case 0x02: /* NTAB */
ntab = (d << 10) & 0xE000;
break;
case 0x03: /* NTWB */
ntwb = (d << 10) & 0xF800;
if(reg[12] & 1) ntwb &= 0xF000;
break;
case 0x04: /* NTBB */
ntbb = (d << 13) & 0xE000;
break;
case 0x05: /* SATB */
sat_base_mask = (reg[12] & 1) ? 0xFC00 : 0xFE00;
sat_addr_mask = (reg[12] & 1) ? 0x03FF : 0x01FF;
satb = (d << 9) & sat_base_mask;
break;
case 0x07: /* Border Color index */
/* Check if the border color has actually changed */
d &= 0x3F;
if(border != d)
{
/* Mark the border color as modified */
border = d;
color_update(0x00, *(uint16 *)&cram[(border << 1)]);
/* background color modified during HBLANK */
if ((v_counter < bitmap.viewport.h) && (count_m68k <= (line_m68k + 84)))
{
/* remap current line (see Road Rash I,II,III) */
reg[7] = d;
remap_buffer(v_counter,bitmap.viewport.w + 2*bitmap.viewport.x);
}
}
break;
case 0x0C:
/* Check if the viewport width has actually been changed */
if((reg[0x0C] & 1) != (d & 1))
{
/* Update the width of the viewport */
bitmap.viewport.w = (d & 1) ? 320 : 256;
if (config.overscan) bitmap.viewport.x = (d & 1) ? 16 : 12;
bitmap.viewport.changed = 1;
/* update HC table */
hctab = (d & 1) ? cycle2hc40 : cycle2hc32;
/* update clipping */
window_clip(d,reg[17]);
}
/* See if the S/TE mode bit has changed */
if((reg[0x0C] & 8) != (d & 8))
{
int i;
/* The following color update check this value */
reg[0x0C] = d;
/* Update colors */
for (i = 0; i < 0x40; i += 1) color_update (i, *(uint16 *) & cram[i << 1]);
color_update (0x00, *(uint16 *) & cram[border << 1]);
}
/* The following register updates check this value */
reg[0x0C] = d;
/* Update display-dependant registers */
vdp_reg_w(0x03, reg[0x03]);
vdp_reg_w(0x05, reg[0x05]);
break;
case 0x0D: /* HSCB */
hscb = (d << 10) & 0xFC00;
break;
case 0x10: /* Playfield size */
playfield_shift = shift_table[(d & 3)];
playfield_col_mask = col_mask_table[(d & 3)];
playfield_row_mask = row_mask_table[(d >> 4) & 3];
y_mask = y_mask_table[(d & 3)];
break;
case 0x11: /* update clipping */
window_clip(reg[12],d);
break;
}
/* Write new register value */
reg[r] = d;
}
unsigned int vdp_ctrl_r(void) unsigned int vdp_ctrl_r(void)
{ {
/* /*
@ -686,150 +895,9 @@ unsigned int vdp_data_r(void)
return (temp); return (temp);
} }
/*
The reg[] array is updated at the *end* of this function, so the new
register data can be compared with the previous data.
*/
void vdp_reg_w(unsigned int r, unsigned int d)
{
/* Check if Mode 4 (SMS mode) has been activated
According to official doc, VDP registers #11 to #23 can not be written unless bit2 in register #1 is set
Fix Captain Planet & Avengers (Alt version), Bass Master Classic Pro Edition (they incidentally activate Mode 4)
*/
if (!(reg[1] & 4) && (r > 10)) return;
switch(r)
{
case 0x00: /* CTRL #1 */
if ((d&0x10) != (reg[0]&0x10)) hvint_updated = 0;
break;
case 0x01: /* CTRL #2 */
/* Sesame Street Counting Cafe need to execute one instruction */
if ((d&0x20) != (reg[1]&0x20)) hvint_updated = 1;
/* Check if the viewport height has actually been changed */
if((reg[1] & 8) != (d & 8))
{
/* Update the height of the viewport */
bitmap.viewport.oh = bitmap.viewport.h;
bitmap.viewport.h = (d & 8) ? 240 : 224;
if (config.overscan) bitmap.viewport.y = ((vdp_pal ? 288 : 240) - bitmap.viewport.h) / 2;
bitmap.viewport.changed = 1;
/* update VC table */
if (vdp_pal) vctab = (d & 8) ? vc_pal_240 : vc_pal_224;
}
/* DISPLAY switched ON/OFF during HBLANK */
if ((v_counter < bitmap.viewport.h) && ((d&0x40) != (reg[1]&0x40)))
{
if (count_m68k <= (hint_m68k + 120))
{
/* Redraw the current line :
- Legend of Galahad, Lemmings 2, Nigel Mansell's World Championship Racing (set display OFF)
- Deadly Moves aka Power Athlete (set display ON)
*/
reg[1] = d;
render_line(v_counter,odd_frame);
}
}
break;
case 0x02: /* NTAB */
ntab = (d << 10) & 0xE000;
break;
case 0x03: /* NTWB */
ntwb = (d << 10) & 0xF800;
if(reg[12] & 1) ntwb &= 0xF000;
break;
case 0x04: /* NTBB */
ntbb = (d << 13) & 0xE000;
break;
case 0x05: /* SATB */
sat_base_mask = (reg[12] & 1) ? 0xFC00 : 0xFE00;
sat_addr_mask = (reg[12] & 1) ? 0x03FF : 0x01FF;
satb = (d << 9) & sat_base_mask;
break;
case 0x07: /* Border Color index */
/* Check if the border color has actually changed */
d &= 0x3F;
if(border != d)
{
/* Mark the border color as modified */
border = d;
color_update(0x00, *(uint16 *)&cram[(border << 1)]);
/* background color modified during HBLANK */
if ((v_counter < bitmap.viewport.h) && (count_m68k <= (line_m68k + 84)))
{
/* remap current line (see Road Rash I,II,III) */
reg[7] = d;
remap_buffer(v_counter,bitmap.viewport.w + 2*bitmap.viewport.x);
}
}
break;
case 0x0C:
/* Check if the viewport width has actually been changed */
if((reg[0x0C] & 1) != (d & 1))
{
/* Update the width of the viewport */
bitmap.viewport.ow = bitmap.viewport.w;
bitmap.viewport.w = (d & 1) ? 320 : 256;
if (config.overscan) bitmap.viewport.x = (d & 1) ? 16 : 12;
bitmap.viewport.changed = 1;
/* update HC table */
hctab = (d & 1) ? cycle2hc40 : cycle2hc32;
}
/* See if the S/TE mode bit has changed */
if((reg[0x0C] & 8) != (d & 8))
{
int i;
/* The following color update check this value */
reg[0x0C] = d;
/* Update colors */
for (i = 0; i < 0x40; i += 1) color_update (i, *(uint16 *) & cram[i << 1]);
color_update (0x00, *(uint16 *) & cram[border << 1]);
}
/* The following register updates check this value */
reg[0x0C] = d;
/* Update display-dependant registers */
vdp_reg_w(0x03, reg[0x03]);
vdp_reg_w(0x05, reg[0x05]);
break;
case 0x0D: /* HSCB */
hscb = (d << 10) & 0xFC00;
break;
case 0x10: /* Playfield size */
playfield_shift = shift_table[(d & 3)];
playfield_col_mask = col_mask_table[(d & 3)];
playfield_row_mask = row_mask_table[(d >> 4) & 3];
y_mask = y_mask_table[(d & 3)];
break;
}
/* Write new register value */
reg[r] = d;
}
unsigned int vdp_hvc_r(void) unsigned int vdp_hvc_r(void)
{ {
uint8 hc = (hc_latch == -1) ? hctab[count_m68k%488] : (hc_latch & 0xFF); uint8 hc = (hc_latch & 0x100) ? (hc_latch & 0xFF) : hctab[count_m68k % m68cycles_per_line];
uint8 vc = vctab[v_counter]; uint8 vc = vctab[v_counter];
/* interlace mode 2 */ /* interlace mode 2 */
@ -848,13 +916,26 @@ void vdp_test_w(unsigned int value)
int vdp_int_ack_callback(int int_level) int vdp_int_ack_callback(int int_level)
{ {
if (vint_triggered)
if (irq_status&0x20)
{ {
vint_pending = 0; vint_pending = 0;
vint_triggered = 0; status &= ~0x80; /* clear VINT flag */
status &= ~0x0080; /* clear VINT flag */
} }
else hint_pending = 0; else
hvint_updated = 0; {
hint_pending = 0;
}
irq_status = 0x10;
if (vint_pending && (reg[1] & 0x20))
{
irq_status |= 6;
}
else if (hint_pending && (reg[0] & 0x10))
{
irq_status |= 4;
}
return M68K_INT_ACK_AUTOVECTOR; return M68K_INT_ACK_AUTOVECTOR;
} }

View File

@ -38,8 +38,7 @@ extern uint16 status;
extern uint8 dmafill; extern uint8 dmafill;
extern uint8 hint_pending; extern uint8 hint_pending;
extern uint8 vint_pending; extern uint8 vint_pending;
extern uint8 vint_triggered; extern uint16 irq_status;
extern int8 hvint_updated;
/* Global variables */ /* Global variables */
extern uint16 ntab; extern uint16 ntab;
@ -56,8 +55,7 @@ extern uint8 playfield_shift;
extern uint8 playfield_col_mask; extern uint8 playfield_col_mask;
extern uint16 playfield_row_mask; extern uint16 playfield_row_mask;
extern uint32 y_mask; extern uint32 y_mask;
extern int16 h_counter; extern uint16 hc_latch;
extern int16 hc_latch;
extern uint16 v_counter; extern uint16 v_counter;
extern uint8 im2_flag; extern uint8 im2_flag;
extern uint32 dma_length; extern uint32 dma_length;
@ -85,7 +83,6 @@ extern unsigned int vdp_ctrl_r(void);
extern void vdp_data_w(unsigned int data); extern void vdp_data_w(unsigned int data);
extern unsigned int vdp_data_r(void); extern unsigned int vdp_data_r(void);
extern unsigned int vdp_hvc_r(void); extern unsigned int vdp_hvc_r(void);
extern void vdp_reg_w(unsigned int r, unsigned int d);
extern void dma_update(); extern void dma_update();
extern void vdp_test_w(unsigned int value); extern void vdp_test_w(unsigned int value);