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"
.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"
.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 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"
- modified JCART emulation: fixes corrupted tracks logo in "Micro Machines 2"
- 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]
@ -27,10 +28,9 @@ CURRENT:
- 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
- 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)
- 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
@ -40,8 +40,9 @@ CURRENT:
[Wii only]
- added "Power" button support, including shutdown from the wiimote (libogc CVS)
- added SDHC support (libogc CVS)
- added "Power" button support
- 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
* Cartridge Hardware support
*
* 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/)
*
* 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
* it under the terms of the GNU General Public License as published by
@ -30,14 +31,14 @@
#define CART_CNT 26
/* Function prototypes */
void default_time_w(unsigned int address, unsigned int value);
void special_mapper_w(unsigned int address, unsigned int value);
void realtec_mapper_w(unsigned int address, unsigned int value);
void seganet_mapper_w(unsigned int address, unsigned int value);
unsigned int radica_mapper_r(unsigned int address);
void default_regs_w(unsigned int address, unsigned int value);
unsigned int default_regs_r(unsigned int address);
void special_regs_w(unsigned int address, unsigned int value);
void default_time_w(uint32 address, uint32 data);
void special_mapper_w(uint32 address, uint32 data);
void realtec_mapper_w(uint32 address, uint32 data);
void seganet_mapper_w(uint32 address, uint32 data);
uint32 radica_mapper_r(uint32 address);
void default_regs_w(uint32 address, uint32 data);
uint32 default_regs_r(uint32 address);
void special_regs_w(uint32 address, uint32 data);
/* Cart database entry */
typedef struct
@ -56,64 +57,65 @@ typedef struct
T_CART_ENTRY rom_database[CART_CNT] =
{
/* 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) */
{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) */
{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) */
{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 */
{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 */
{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 */
{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 */
{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 */
{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 */
{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 */
{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 */
{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 */
{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 */
{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 */
{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 */
{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 */
{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 */
{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 */
{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 */
{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 */
{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 */
{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 */
{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 */
{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 */
{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 */
{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 */
T_CART_HW cart_hw;
uint8 j_cart;
int old_system[2] = {-1,-1};
/* previous inputs */
static int old_system[2] = {-1,-1};
/* temporary memory chunk */
uint8 mem_chunk[0x10000];
/************************************************************
Cart Hardware initialization
@ -122,16 +124,27 @@ int old_system[2] = {-1,-1};
/* hardware that need to be reseted on power on */
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 */
if (cart_hw.realtec & 1)
{
int i;
/* 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;
}
/* save default cartridge slot mapping */
default_rom = m68k_memory_map[0].base;
/* SVP chip */
if (svp) svp_reset();
}
@ -142,22 +155,29 @@ void cart_hw_init()
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;
m68k_readmap_16[i] = ROM;
m68k_writemap_8[i] = UNUSED;
m68k_writemap_16[i] = UNUSED;
/* cartridge ROM */
m68k_memory_map[i].base = cart_rom + (i<<16);
m68k_memory_map[i].read8 = NULL;
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;
m68k_readmap_16[i] = UNUSED;
m68k_writemap_8[i] = UNUSED;
m68k_writemap_16[i] = UNUSED;
/* unused area */
m68k_memory_map[i].read8 = m68k_read_bus_8;
m68k_memory_map[i].read16 = m68k_read_bus_16;
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 */
@ -174,25 +194,29 @@ void cart_hw_init()
if (sram.custom)
{
/* serial EEPROM */
m68k_readmap_8[eeprom.type.sda_out_adr >> 19] = EEPROM;
m68k_readmap_16[eeprom.type.sda_out_adr >> 19] = EEPROM;
m68k_writemap_8[eeprom.type.sda_in_adr >> 19] = EEPROM;
m68k_writemap_16[eeprom.type.sda_in_adr >> 19] = EEPROM;
m68k_writemap_8[eeprom.type.scl_adr >> 19] = EEPROM;
m68k_writemap_16[eeprom.type.scl_adr >> 19] = EEPROM;
m68k_memory_map[eeprom.type.sda_out_adr >> 16].read8 = eeprom_read_byte;
m68k_memory_map[eeprom.type.sda_out_adr >> 16].read16 = eeprom_read_word;
m68k_memory_map[eeprom.type.sda_in_adr >> 16].read8 = eeprom_read_byte;
m68k_memory_map[eeprom.type.sda_in_adr >> 16].read16 = eeprom_read_word;
m68k_memory_map[eeprom.type.scl_adr >> 16].write8 = eeprom_write_byte;
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
{
/* 64KB SRAM */
m68k_readmap_8[sram.start >> 19] = SRAM;
m68k_readmap_16[sram.start >> 19] = SRAM;
if (sram.write)
{
m68k_writemap_8[sram.start >> 19] = SRAM;
m68k_writemap_16[sram.start >> 19] = SRAM;
}
/* Static RAM (64k max.) */
m68k_memory_map[sram.start >> 16].base = sram.sram;
m68k_memory_map[sram.start >> 16].read8 = NULL;
m68k_memory_map[sram.start >> 16].read16 = NULL;
m68k_memory_map[sram.start >> 16].write8 = NULL;
m68k_memory_map[sram.start >> 16].write16 = NULL;
zbank_memory_map[sram.start >> 16].read = NULL;
zbank_memory_map[sram.start >> 16].write = NULL;
}
}
/**********************************************
SVP CHIP
***********************************************/
@ -200,12 +224,20 @@ void cart_hw_init()
if (strstr(rominfo.international,"Virtua Racing") != NULL)
{
svp_init();
m68k_readmap_16[6] = SVP_DRAM;
m68k_writemap_16[6] = SVP_DRAM;
m68k_readmap_16[7] = SVP_CELL;
m68k_writemap_16[7] = SVP_CELL;
m68k_memory_map[0x30].base = svp->dram;
m68k_memory_map[0x30].read16 = NULL;
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 */
input.x_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) */
{
j_cart = 1;
m68k_readmap_16[7] = J_CART;
m68k_writemap_16[7] = J_CART;
m68k_memory_map[0x38].read16 = jcart_read;
m68k_memory_map[0x38].write16 = jcart_write;
m68k_memory_map[0x3f].read16 = jcart_read;
m68k_memory_map[0x3f].write16 = jcart_write;
/* save current setting */
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
***********************************************/
@ -345,13 +358,53 @@ void cart_hw_init()
int j = rom_database[i].bank_start;
while (j <= rom_database[i].bank_end)
{
if (cart_hw.regs_r) m68k_readmap_8[j] = CART_HW;
if (cart_hw.regs_w) m68k_writemap_8[j] = CART_HW;
if (cart_hw.regs_r)
{
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++;
}
/* leave loop */
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
*/
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:
{
/* ROM/RAM switch (Phantasy Star IV, Story of Thor/Beyond Oasis, Sonic 3 & Knuckles) */
if (value & 1)
{
/* SRAM is mapped above 200000h */
m68k_readmap_8[4] = SRAM;
m68k_readmap_16[4] = SRAM;
/* ROM/SRAM switch (Phantasy Star IV, Story of Thor/Beyond Oasis, Sonic 3 & Knuckles) */
if (data & 1)
{
/* SRAM enabled */
m68k_memory_map[0x20].base = sram.sram;
if (value & 2)
{
/* SRAM write protected */
m68k_writemap_8[4] = UNUSED;
m68k_writemap_16[4] = UNUSED;
}
else
{
/* SRAM write enabled */
m68k_writemap_8[4] = SRAM;
m68k_writemap_16[4] = SRAM;
}
}
else
{
/* ROM is mapped above 200000h */
m68k_readmap_8[4] = ROM;
m68k_readmap_16[4] = ROM;
m68k_writemap_8[4] = UNUSED;
m68k_writemap_16[4] = UNUSED;
}
if (data & 2)
{
/* SRAM write disabled */
m68k_memory_map[0x20].write8 = m68k_unused_8_w;
m68k_memory_map[0x20].write16 = m68k_unused_16_w;
zbank_memory_map[0x20].write = zbank_unused_w;
}
else
{
/* SRAM write enabled */
m68k_memory_map[0x20].write8 = NULL;
m68k_memory_map[0x20].write16 = NULL;
zbank_memory_map[0x20].write = NULL;
}
}
else
{
/* ROM enabled */
m68k_memory_map[0x20].base = cart_rom + 0x200000;
}
break;
}
default:
/* ROM Bankswitch (Super Street Fighter 2)
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;
}
}
/*
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;
uint32 bank_addr = (address & 0x3F) << 16;
/* those games are generally not bigger than 1MB but it's safer to update all 512K banks */
for (i=0; i<8; i++)
cart_hw.bankshift = 1;
/* 64 x 64k banks */
for (i=0; i<64; i++)
{
if (bank_addr >= genromsize) return;
rom_readmap[i] = &cart_rom[bank_addr];
bank_addr += 0x80000;
m68k_memory_map[i].base = &cart_rom[((address++) & 0x3f) << 16];
}
}
/*
Special ROM Bankswitch used for copy protection
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)
(documented by TascoDeluxe)
*/
void realtec_mapper_w(unsigned int address, unsigned int value)
{
uint32 base_addr;
if (cart_hw.realtec & 2)
void realtec_mapper_w(uint32 address, uint32 data)
{
int i;
cart_hw.realtec &= ~2;
/* disable Realtec BOOTROM */
for (i=0; i<8; i++)
{
m68k_readmap_8[i] = ROM;
m68k_readmap_16[i] = ROM;
}
}
uint32 base;
/* 32 x 128k banks */
switch (address)
{
case 0x404000: /* three lower bits of ROM base address */
cart_hw.regs[0] = value;
base_addr = (value | ((cart_hw.regs[1] & 6) << 2)) << 17;
rom_readmap[0] = &cart_rom[base_addr];
cart_hw.regs[0] = data & 7;
base = ((data & 7) | (cart_hw.regs[1] << 2));
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;
case 0x400000: /* two higher bits of ROM base address */
cart_hw.regs[1] = value;
base_addr = ((cart_hw.regs[0] & 7) | ((value & 6) << 2)) << 17;
rom_readmap[0] = &cart_rom[base_addr];
cart_hw.regs[1] = data & 6;
base = cart_hw.regs[0] | ((data & 6) << 2);
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;
case 0x402000: /* size of ROM range to map */
cart_hw.regs[2] = value;
case 0x402000: /* number of 128k blocks to map */
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;
default:
return;
}
}
/* 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;
switch (address & 0xff)
{
case 0x01:
if (value & 1)
if (data & 1)
{
/* ROM disabled */
for (i=0; i<8; i++)
{
m68k_readmap_8[i] = UNUSED;
m68k_readmap_16[i] = UNUSED;
}
}
else
/* ROM Write protected */
for (i=0; i<0x40; i++)
{
/* 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;
m68k_memory_map[i].write8 = m68k_unused_8_w;
m68k_memory_map[i].write16 = m68k_unused_16_w;
zbank_memory_map[i].write = zbank_unused_w;
}
}
else
{
/* ROM Write enabled */
for (i=0; i<8; i++)
{
m68k_writemap_8[i] = ROM;
m68k_writemap_16[i] = ROM;
}
for (i=0; i<0x40; i++);
{
m68k_memory_map[i].write8 = NULL;
m68k_memory_map[i].write16 = NULL;
zbank_memory_map[i].write = NULL;
}
}
break;
default:
break;
}
}
/*
RADICA ROM Bankswitch
(documented by Haze)
RADICA ROM Bankswitch (use !TIME)
*/
unsigned int radica_mapper_r(unsigned int address)
uint32 radica_mapper_r(uint32 address)
{
/* 64KB ROM banks */
uint8 bank = (address >> 1) & 0x3F;
rom_readmap[0] = &cart_rom[bank * 0x10000];
rom_readmap[1] = &cart_rom[bank * 0x10000 + 0x80000]; /* ROM is max. 1MB */
int i = 0;
address = (address >> 1);
/* 64 x 64k banks */
for (i = 0; i < 64; i++)
{
m68k_memory_map[i].base = &cart_rom[((address++)& 0x3f)<< 16];
}
return 0xff;
}
@ -553,19 +583,20 @@ unsigned int radica_mapper_r(unsigned int address)
*************************************************************/
/* 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);
else if (address < 0xa13040) multi_mapper_w(address, value);
if ((address & 0xf1) == 0xf1) sega_mapper_w(address, data);
else if (address < 0xa13040) multi_mapper_w(address, data);
}
/************************************************************
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++)
{
if ((address & cart_hw.mask[i]) == cart_hw.addr[i])
@ -573,36 +604,36 @@ unsigned int default_regs_r(unsigned int address)
}
/* 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++)
{
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) */
void special_regs_w(unsigned int address, unsigned int value)
void special_regs_w(uint32 address, uint32 data)
{
/* ROM bankswitch */
if ((address >> 16) > 0x6f)
{
special_mapper_w(address, value);
special_mapper_w(address, data);
return;
}
/* write regs */
default_regs_w(address, value);
default_regs_w(address, data);
/* bitswapping (documented by Haze) */
uint8 temp = cart_hw.regs[0];
uint32 temp = cart_hw.regs[0];
switch (cart_hw.regs[1])
{
case 1:

View File

@ -33,7 +33,8 @@ typedef struct
uint8 regs[4]; /* internal registers (R/W) */
uint32 mask[4]; /* registers address mask */
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 */
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 */
@ -41,8 +42,9 @@ typedef struct
} T_CART_HW;
/* global variables */
extern T_CART_HW cart_hw;
extern uint8 j_cart;
T_CART_HW cart_hw;
uint8 j_cart;
uint8 *default_rom;
/* Function prototypes */
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);
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_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

View File

@ -77,23 +77,25 @@ static inline void lightgun_update(int num)
if (io_reg[5] & 0x80)
{
/* External Interrupt ? */
if (reg[11] & 0x08) m68k_set_irq(2);
if (reg[11] & 0x08) {irq_status &= 0xff; irq_status |= 0x12;}
/* HVC Latch:
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,
H-Counter range is approx. 292 pixel clocks
*/
hc_latch = 0x100;
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
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 */
unsigned int menacer_read()
uint32 menacer_read()
{
/* pins should return 0 by default (fix Body Count when mouse is enabled) */
int retval = 0x00;
@ -106,7 +108,7 @@ unsigned int menacer_read()
}
/* Konami Justifier specific */
unsigned int justifier_read()
uint32 justifier_read()
{
/* TL & TR pins should always return 1 (write only) */
/* 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;
}
void mouse_write(unsigned int data)
void mouse_write(uint32 data)
{
if (mouse.Counter == 0)
{
@ -182,7 +184,7 @@ void mouse_write(unsigned int data)
mouse.State = data;
}
unsigned int mouse_read()
uint32 mouse_read()
{
int temp = 0x00;
@ -263,24 +265,24 @@ struct pad
uint8 Delay;
} gamepad[MAX_DEVICES];
static inline void gamepad_raz(unsigned int i)
static inline void gamepad_raz(uint32 i)
{
gamepad[i].Counter = 0;
gamepad[i].Delay = 0;
}
static inline void gamepad_reset(unsigned int i)
static inline void gamepad_reset(uint32 i)
{
gamepad[i].State = 0x40;
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);
}
static inline unsigned int gamepad_read(unsigned int i)
static inline uint32 gamepad_read(uint32 i)
{
int control;
int retval = 0x7F;
@ -365,7 +367,7 @@ static inline unsigned int gamepad_read(unsigned int i)
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)
{
@ -392,7 +394,7 @@ struct teamplayer
uint8 Table[12];
} teamplayer[2];
static inline void teamplayer_reset(unsigned int port)
static inline void teamplayer_reset(uint32 port)
{
int i;
int index = 0;
@ -433,7 +435,7 @@ static inline void teamplayer_reset(unsigned int port)
2/ START,A,C,B buttons
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 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;
}
static inline unsigned int teamplayer_read(unsigned int port)
static inline uint32 teamplayer_read(uint32 port)
{
int retval = 0x7F;
int padnum;
@ -509,7 +511,7 @@ static inline unsigned int teamplayer_read(unsigned int port)
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;
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
*
*****************************************************************************/
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);
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 (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
*
*****************************************************************************/
unsigned int gamepad_1_read (void)
uint32 gamepad_1_read (void)
{
return gamepad_read(0);
}
unsigned int gamepad_2_read (void)
uint32 gamepad_2_read (void)
{
return gamepad_read(4);
}
void gamepad_1_write (unsigned int data)
void gamepad_1_write (uint32 data)
{
gamepad_write(0, data);
}
void gamepad_2_write (unsigned int data)
void gamepad_2_write (uint32 data)
{
gamepad_write(4, data);
}
unsigned int wayplay_1_read (void)
uint32 wayplay_1_read (void)
{
return wayplay_read(0);
}
unsigned int wayplay_2_read (void)
uint32 wayplay_2_read (void)
{
return wayplay_read(1);
}
void wayplay_1_write (unsigned int data)
void wayplay_1_write (uint32 data)
{
wayplay_write(0, data);
}
void wayplay_2_write (unsigned int data)
void wayplay_2_write (uint32 data)
{
wayplay_write(1, data);
}
unsigned int teamplayer_1_read (void)
uint32 teamplayer_1_read (void)
{
return teamplayer_read(0);
}
unsigned int teamplayer_2_read (void)
uint32 teamplayer_2_read (void)
{
return teamplayer_read(1);
}
void teamplayer_1_write (unsigned int data)
void teamplayer_1_write (uint32 data)
{
teamplayer_write(0, data);
}
void teamplayer_2_write (unsigned int data)
void teamplayer_2_write (uint32 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 ?) */
}
void jcart_write(unsigned int data)
void jcart_write(uint32 address, uint32 data)
{
gamepad_write(5, (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);
/* Peripherals specific */
extern void mouse_write(unsigned int data);
extern unsigned int mouse_read(void);
extern unsigned int menacer_read (void);
extern unsigned int justifier_read (void);
extern unsigned int gamepad_1_read (void);
extern unsigned int gamepad_2_read (void);
extern void gamepad_1_write (unsigned int data);
extern void gamepad_2_write (unsigned int data);
extern unsigned int wayplay_1_read (void);
extern unsigned int wayplay_2_read (void);
extern void wayplay_1_write (unsigned int data);
extern void wayplay_2_write (unsigned int data);
extern unsigned int teamplayer_1_read (void);
extern unsigned int teamplayer_2_read (void);
extern void teamplayer_1_write (unsigned int data);
extern void teamplayer_2_write (unsigned int data);
extern unsigned int jcart_read(void);
extern void jcart_write(unsigned int data);
extern void mouse_write(uint32 data);
extern uint32 mouse_read(void);
extern uint32 menacer_read (void);
extern uint32 justifier_read (void);
extern uint32 gamepad_1_read (void);
extern uint32 gamepad_2_read (void);
extern void gamepad_1_write (uint32 data);
extern void gamepad_2_write (uint32 data);
extern uint32 wayplay_1_read (void);
extern uint32 wayplay_2_read (void);
extern void wayplay_1_write (uint32 data);
extern void wayplay_2_write (uint32 data);
extern uint32 teamplayer_1_read (void);
extern uint32 teamplayer_2_read (void);
extern void teamplayer_1_write (uint32 data);
extern void teamplayer_2_write (uint32 data);
extern uint32 jcart_read(uint32 address);
extern void jcart_write(uint32 address, uint32 data);
#endif

View File

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

View File

@ -26,7 +26,7 @@
/* Global variables */
extern uint8 *cart_rom;
extern uint8 bios_rom[0x800];
extern uint8 bios_rom[0x10000];
extern uint8 work_ram[0x10000];
extern uint8 zram[0x2000];
extern uint8 zbusreq;
@ -36,18 +36,15 @@ extern uint8 zirq;
extern uint32 zbank;
extern uint8 gen_running;
extern uint32 genromsize;
extern uint32 rom_size;
extern int32 resetline;
extern uint8 *rom_readmap[8];
/* Function prototypes */
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 unsigned int gen_busack_r(void);
extern void gen_busreq_w(unsigned int state);
extern void gen_reset_w(unsigned int state);
extern void gen_bank_w(unsigned int state);
extern void gen_busreq_w(uint32 state);
extern void gen_reset_w(uint32 state);
extern void gen_bank_w(uint32 state);
extern int z80_irq_callback(int param);
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_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 */
unsigned int m68k_read_disassembler_8 (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_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
* predecrement destination mode is executed.
* To simulate real 68k behavior, first write the high word to
@ -302,7 +317,8 @@ void m68k_init(void);
void m68k_pulse_reset(void);
/* 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
* 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).
* 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. */

View File

@ -67,7 +67,7 @@
* and m68k_read_pcrelative_xx() for PC-relative addressing.
* 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
* predecrement destination EA mode instead of m68k_write_32().
@ -157,7 +157,7 @@
* access a word or longword at an odd address.
* 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.

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 */
/* 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 */
if(!CPU_STOPPED)
@ -841,6 +841,50 @@ int m68k_execute(int 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)
{
@ -866,24 +910,6 @@ void m68k_end_timeslice(void)
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)
{
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)
{
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)
{
m68ki_set_fc(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)
{
m68ki_set_fc(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)
{
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)
{
m68ki_set_fc(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)
{
m68ki_set_fc(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

File diff suppressed because it is too large Load Diff

View File

@ -24,28 +24,48 @@
#ifndef _MEM68K_H_
#define _MEM68K_H_
enum {
SRAM,
EEPROM,
J_CART,
SVP_DRAM,
SVP_CELL,
CART_HW,
REALTEC_ROM,
VDP,
SYSTEM_IO,
UNUSED,
ILLEGAL,
WRAM,
UMK3_HACK,
PICO_HW,
ROM
};
/* unused areas */
extern uint32 m68k_read_bus_8(uint32 address);
extern uint32 m68k_read_bus_16(uint32 address);
extern void m68k_unused_8_w (uint32 address, uint32 data);
extern void m68k_unused_16_w (uint32 address, uint32 data);
extern uint8 m68k_readmap_8[32];
extern uint8 m68k_readmap_16[32];
extern uint8 m68k_writemap_8[32];
extern uint8 m68k_writemap_16[32];
/* illegal areas */
extern uint32 m68k_lockup_r_8 (uint32 address);
extern uint32 m68k_lockup_r_16 (uint32 address);
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_ */

View File

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

View File

@ -23,8 +23,19 @@
#ifndef _MEMBNK_H_
#define _MEMBNK_H_
/* Function prototypes */
extern void z80_write_banked_memory(unsigned int address, unsigned int data);
extern unsigned int z80_read_banked_memory(unsigned int address);
extern uint32 zbank_unused_r(uint32 address);
extern void zbank_unused_w(uint32 address, uint32 data);
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_ */

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)
{
switch (address & 0xff)
switch (address & 0xfd)
{
case 0x00: /* VDP data port */
case 0x02:
return (vdp_data_r() >> 8) & 0xff;
case 0x00: /* DATA */
return (vdp_data_r() >> 8);
case 0x01: /* VDP data port */
case 0x03:
case 0x01: /* DATA */
return (vdp_data_r() & 0xff);
case 0x04: /* VDP control port */
case 0x06:
case 0x04: /* CTRL */
return (0xfc | ((vdp_ctrl_r() >> 8) & 3));
case 0x05: /* VDP control port */
case 0x07:
case 0x05: /* CTRL */
return (vdp_ctrl_r() & 0xff);
case 0x08: /* HV counter */
case 0x0a:
case 0x08: /* HVC */
case 0x0c:
case 0x0e:
return (vdp_hvc_r() >> 8) & 0xff;
return (vdp_hvc_r() >> 8);
case 0x09: /* HV counter */
case 0x0b:
case 0x09: /* HVC */
case 0x0d:
case 0x0f:
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 0x19:
case 0x1a:
case 0x1b:
return z80_unused_r(address);
case 0x1c: /* Unused (test register) */
case 0x1c:
case 0x1d:
case 0x1e:
case 0x1f:
return z80_unused_r(address);
default: /* Invalid VDP addresses */
default: /* Invalid address */
return z80_lockup_r(address);
}
}
static inline void z80_vdp_w(unsigned int address, unsigned int data)
{
switch (address & 0xff)
switch (address & 0xfc)
{
case 0x00: /* VDP data port */
case 0x01:
case 0x02:
case 0x03:
case 0x00: /* Data port */
vdp_data_w(data << 8 | data);
return;
case 0x04: /* VDP control port */
case 0x05:
case 0x06:
case 0x07:
case 0x04: /* Control port */
vdp_ctrl_w(data << 8 | data);
return;
case 0x08: /* Unused (HV counter) */
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);
case 0x10: /* PSG */
case 0x14:
if (address & 1) psg_write(0, data);
else z80_unused_w(address, data);
return;
case 0x10: /* Unused */
case 0x12:
case 0x14:
case 0x16:
case 0x18:
case 0x19:
case 0x1a:
case 0x1b:
case 0x18: /* Unused */
z80_unused_w(address, data);
return;
case 0x1c: /* Test register */
case 0x1d:
case 0x1e:
case 0x1f:
vdp_test_w(data << 8 | data);
return;
default: /* Invalid VDP addresses */
default: /* Invalid address */
z80_lockup_w(address, data);
return;
}
@ -195,11 +143,16 @@ unsigned int cpu_readmem16(unsigned int address)
return fm_read(1, address & 3);
case 3: /* VDP */
if ((address & 0xff00) == 0x7f00) return z80_vdp_r (address);
return (z80_unused_r(address) | 0xff);
if ((address >> 8) == 0x7f) return z80_vdp_r (address);
return z80_unused_r(address);
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;
case 3: /* Bank register and VDP */
switch(address & 0xff00)
switch(address >> 8)
{
case 0x6000:
case 0x60:
gen_bank_w(data & 1);
return;
case 0x7f00:
case 0x7f:
z80_vdp_w(address, data);
return;
@ -235,10 +188,15 @@ void cpu_writemem16(unsigned int address, unsigned int data)
return;
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;
}
}
}
/*
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 */
config.freeze_auto = -1;
#ifdef HW_RVL
config.sram_auto = 0; /* assume we always got SDCARD */
#else
config.sram_auto = -1;
#endif
config.region_detect = 0;
config.force_dtack = 0;
config.bios_enabled = 0;

View File

@ -791,22 +791,6 @@ void optionmenu ()
****************************************************************************/
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 prevmenu = menu;
@ -955,7 +939,8 @@ int loadmenu ()
dvd_motor_off();
dvd_on = 0;
count = 3 + dvd_on;
break;
menu = load_menu;
break;
}
}

View File

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

View File

@ -21,6 +21,7 @@
#include "shared.h"
#include "ogc_input.h"
//#include <asndlib.h>
/* global datas */
unsigned char soundbuffer[16][3840] ATTRIBUTE_ALIGN(32);
@ -49,15 +50,16 @@ static void AudioSwitchBuffers()
AUDIO_InitDMA((u32) soundbuffer[playbuffer], dma_len);
DCFlushRange(soundbuffer[playbuffer], dma_len);
AUDIO_StartDMA();
//ASND_SetVoice(0, VOICE_STEREO_16BIT, 48000, 0, soundbuffer[playbuffer], dma_len, 255, 255, AudioSwitchBuffers);
/* increment soundbuffers index */
playbuffer++;
playbuffer &= 0xf;
if (playbuffer == mixbuffer)
{
playbuffer--;
if ( playbuffer < 0 ) playbuffer = 15;
}
playbuffer++;
playbuffer &= 0xf;
IsPlaying = 1;
}
@ -68,12 +70,14 @@ void ogc_audio__init(void)
AUDIO_Init (NULL);
AUDIO_SetDSPSampleRate (AI_SAMPLERATE_48KHZ);
AUDIO_RegisterDMACallback (AudioSwitchBuffers);
//ASND_Init();
memset(soundbuffer, 0, 16 * 3840);
}
void ogc_audio__reset(void)
{
AUDIO_StopDMA ();
//ASND_Pause(1);
IsPlaying = 0;
mixbuffer = 0;
playbuffer = 0;
@ -82,5 +86,9 @@ void ogc_audio__reset(void)
void ogc_audio__update(void)
{
/* 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
u32 exp;
for (i=0; i<4; i++)
{
/* WIIMOTE */
@ -648,6 +647,8 @@ void ogc_input__set_defaults(void)
}
#ifdef HW_RVL
u32 exp;
VIDEO_WaitVSync();
int j;
for (i=0; i<4; i++)
{

View File

@ -43,6 +43,7 @@ u8 *texturemem; /*** Texture Data ***/
/*** GX ***/
#define TEX_WIDTH 360 * 2
#define TEX_HEIGHT 576
#define TEX_SIZE TEX_WIDTH * TEX_HEIGHT * 2
#define DEFAULT_FIFO_SIZE 256 * 1024
#define HASPECT 320
#define VASPECT 240
@ -611,40 +612,10 @@ void ogc_video__update()
GX_LoadTexObj (&texobj, GX_TEXMAP0);
}
/* 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;
}
}
/* texture is now directly mapped by the line renderer */
/* update texture cache */
DCFlushRange (texturemem, TEX_WIDTH * TEX_HEIGHT * 2);
DCFlushRange (texturemem, TEX_SIZE);
GX_InvalidateTexAll ();
/* render textured quad */

View File

@ -99,39 +99,94 @@ 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[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)]);
int n;
#endif
int n;
input += in_extra;
for ( n = chunk_count; n; --n )
{
/* order of input and output pixels must not be altered */
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( 1, *line_out++, SMS_NTSC_OUT_DEPTH );
#endif
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( 3, *line_out++, SMS_NTSC_OUT_DEPTH );
#endif
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( 5, *line_out++, SMS_NTSC_OUT_DEPTH );
SMS_NTSC_RGB_OUT( 6, *line_out++, SMS_NTSC_OUT_DEPTH );
#endif
}
/* finish final pixels */
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( 1, *line_out++, SMS_NTSC_OUT_DEPTH );
#endif
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( 3, *line_out++, SMS_NTSC_OUT_DEPTH );
#endif
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( 5, *line_out++, SMS_NTSC_OUT_DEPTH );
SMS_NTSC_RGB_OUT( 6, *line_out++, SMS_NTSC_OUT_DEPTH );
#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 render_reset(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
extern void color_update_8(int index, uint16 data);
extern void color_update_15(int index, uint16 data);
extern void color_update_32(int index, uint16 data);
#endif
extern void color_update_16(int index, uint16 data);
extern void parse_satb(int line);
extern void (*color_update)(int index, uint16 data);
extern void remap_buffer(int line,int width);
void (*color_update)(int index, uint16 data);
#endif /* _RENDER_H_ */

View File

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

View File

@ -670,7 +670,7 @@ INLINE void FM_KEYOFF(FM_CH *CH , int s )
}
/* 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];
@ -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)
{
@ -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)
{

View File

@ -25,13 +25,13 @@
static unsigned char state[0x24000];
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);
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);
bufferptr+= size;
@ -39,27 +39,18 @@ void save_param(void *param, unsigned int size)
void state_load(unsigned char *buffer)
{
uint32 tmp32;
uint16 tmp16;
uint8 temp_reg[0x20];
unsigned long inbytes, outbytes;
/* get compressed state size & uncompress state file */
memcpy(&inbytes, buffer, 4);
/* reset buffer pointer */
bufferptr = 0;
#ifdef NGC
/* uncompress savestate */
unsigned long inbytes, outbytes;
memcpy(&inbytes, buffer, 4);
outbytes = 0x24000;
uncompress ((Bytef *)state, &outbytes, (Bytef *)(buffer + 4), inbytes);
#else
outbytes = inbytes;
memcpy(state, buffer + 4, outbytes);
#endif
/* SYSTEM RESET */
/* reset system */
system_reset();
rom_readmap[0] = &cart_rom[0];
rom_size = genromsize;
m68k_memory_map[0].base = default_rom;
// GENESIS
load_param(work_ram, sizeof(work_ram));
@ -73,6 +64,7 @@ void state_load(unsigned char *buffer)
load_param(io_reg, sizeof(io_reg));
// VDP
uint8 temp_reg[0x20];
load_param(sat, sizeof(sat));
load_param(vram, sizeof(vram));
load_param(cram, sizeof(cram));
@ -86,8 +78,7 @@ void state_load(unsigned char *buffer)
load_param(&dmafill, sizeof(dmafill));
load_param(&hint_pending, sizeof(hint_pending));
load_param(&vint_pending, sizeof(vint_pending));
load_param(&vint_triggered, sizeof(vint_triggered));
load_param(&hvint_updated, sizeof(hvint_updated));
load_param(&irq_status, sizeof(irq_status));
vdp_restore(temp_reg);
// FM
@ -98,6 +89,8 @@ void state_load(unsigned char *buffer)
load_param(SN76489_GetContextPtr (0),SN76489_GetContextSize ());
// 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_D1, 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)
{
uint32 tmp32;
uint16 tmp16;
unsigned long inbytes, outbytes;
/* save state */
/* reset buffer pointer */
bufferptr = 0;
// GENESIS
@ -155,8 +144,7 @@ int state_save(unsigned char *buffer)
save_param(&dmafill, sizeof(dmafill));
save_param(&hint_pending, sizeof(hint_pending));
save_param(&vint_pending, sizeof(vint_pending));
save_param(&vint_triggered, sizeof(vint_triggered));
save_param(&hvint_updated, sizeof(hvint_updated));
save_param(&irq_status, sizeof(irq_status));
// FM
save_param(fm_reg,sizeof(fm_reg));
@ -165,6 +153,8 @@ int state_save(unsigned char *buffer)
save_param(SN76489_GetContextPtr (0),SN76489_GetContextSize ());
// 68000
uint16 tmp16;
uint32 tmp32;
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_D2); save_param(&tmp32, 4);
@ -188,18 +178,10 @@ int state_save(unsigned char *buffer)
// Z80
save_param(&Z80, sizeof(Z80_Regs));
inbytes = bufferptr;
#ifdef NGC
/* compress state file */
outbytes = 0x26000;
unsigned long inbytes = bufferptr;
unsigned long outbytes = 0x26000;
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);
/* return total size */

View File

@ -43,60 +43,9 @@ uint32 line_z80;
int32 current_z80;
uint8 odd_frame;
uint8 interlaced;
uint32 frame_cnt;
uint8 system_hw;
/****************************************************************
* 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);
}
static inline void audio_update (void);
/****************************************************************
* Virtual Genesis initialization
@ -128,7 +77,6 @@ void system_reset (void)
current_z80 = 0;
odd_frame = 0;
interlaced = 0;
frame_cnt = 0;
/* Cart Hardware reset */
cart_hw_reset();
@ -161,7 +109,11 @@ void system_shutdown (void)
****************************************************************/
int system_frame (int do_skip)
{
int line;
if (!gen_running)
{
update_input();
return 0;
}
/* reset cycles counts */
count_m68k = 0;
@ -171,37 +123,31 @@ int system_frame (int do_skip)
fifo_write_cnt = 0;
fifo_lastwrite = 0;
/* increment frame counter */
frame_cnt ++;
if (!gen_running)
{
update_input();
return 0;
}
/* Clear VBLANK & DMA BUSY flags */
status &= 0xFFF5;
/* Look for interlace mode change */
uint8 old_interlaced = interlaced;
interlaced = (reg[12] & 2) >> 1;
/* update display settings */
int line;
int reset = resetline;
int vdp_height = bitmap.viewport.h;
int end_line = vdp_height + bitmap.viewport.y;
int start_line = lines_per_frame - bitmap.viewport.y;
int old_interlaced = interlaced;
interlaced = (reg[12] >> 1) & 3;
if (old_interlaced != interlaced)
{
bitmap.viewport.changed = 2;
im2_flag = ((reg[12] & 6) == 6) ? 1 : 0;
im2_flag = (interlaced == 3);
odd_frame = 1;
}
/* Toggle even/odd field flag (interlaced modes only) */
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;
/* Reset HCounter */
h_counter = reg[10];
/* Reload H Counter */
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);
/* Line processing */
@ -220,8 +166,8 @@ int system_frame (int do_skip)
aim_z80 += z80cycles_per_line;
aim_m68k += m68cycles_per_line;
/* Check "soft reset" */
if (line == resetline)
/* Soft Reset ? */
if (line == reset)
{
#ifdef NGC
/* wait for RESET button to be released */
@ -231,15 +177,15 @@ int system_frame (int do_skip)
}
/* Horizontal Interrupt */
if (line <= bitmap.viewport.h)
if (line <= vdp_height)
{
if(--h_counter < 0)
{
h_counter = reg[10];
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;
}
@ -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 */
/* as a result, current line is shortened */
/* 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();
/* Render Line */
if (!do_skip)
{
render_line(line,odd_frame);
if (line < (bitmap.viewport.h-1)) parse_satb(0x81 + line);
}
/* 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_input();
@ -275,24 +216,51 @@ int system_frame (int do_skip)
/* delay between HINT, VBLANK and VINT (Dracula, OutRunners, VR Troopers) */
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;
/* Vertical Interrupt */
status |= 0x80;
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 (!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 if (zirq)
}
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 */
if (zirq)
{
zirq = 0;
z80_set_irq_line(0, CLEAR_LINE);
}
}
/* Process line */
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;
/* SVP chip */
@ -372,7 +340,7 @@ void audio_shutdown(void)
static int ll, rr;
void audio_update (void)
static inline void audio_update (void)
{
int i;
int l, r;

View File

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

View File

@ -31,7 +31,7 @@
/* Mark a pattern as dirty */
#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; \
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 hint_pending; /* 0= Line interrupt is pending */
uint8 vint_pending; /* 1= Frame interrupt is pending */
uint8 vint_triggered; /* 1= Frame interrupt has been triggered */
int8 hvint_updated; /* >= 0: Interrupt lines updated */
uint16 irq_status; /* Interrupt lines updated */
/* Global variables */
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 */
uint16 playfield_row_mask; /* Horizontal scroll mask */
uint32 y_mask; /* Name table Y-index bits mask */
int16 h_counter; /* Raster counter */
int16 hc_latch; /* latched HCounter (INT2) */
uint16 hc_latch; /* latched HCounter (INT2) */
uint16 v_counter; /* VDP scanline counter */
uint8 im2_flag; /* 1= Interlace mode 2 is being used */
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 uint8 dma_type; /* Type of DMA */
static inline void vdp_reg_w(unsigned int r, unsigned int d);
/* DMA Timings
According to the manual, here's a table that describes the transfer
@ -183,11 +183,9 @@ void vdp_reset(void)
hint_pending = 0;
vint_pending = 0;
vint_triggered = 0;
hvint_updated = -1;
irq_status = 0;
h_counter = 0;
hc_latch = -1;
hc_latch = 0;
v_counter = 0;
dmafill = 0;
@ -221,6 +219,7 @@ void vdp_reset(void)
vdp_reg_w(10, 0xff); /* HINT disabled */
vdp_reg_w(12, 0x81); /* H40 mode */
vdp_reg_w(15, 0x02); /* auto increment */
window_clip(1,0);
}
/* default latency */
@ -325,6 +324,7 @@ void dma_update()
*/
static inline void dma_copy(void)
{
int name;
int length = (reg[20] << 8 | reg[19]) & 0xFFFF;
int source = (reg[22] << 8 | reg[21]) & 0xFFFF;
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 length = (reg[20] << 8 | reg[19]) & 0xFFFF;
uint32 temp;
if (!length) length = 0x10000;
base = source;
@ -364,15 +365,49 @@ static inline void dma_vbus (void)
dma_length = length;
dma_update();
/* proceed DMA */
switch (source >> 21)
{
case 5:
do
{
/* 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 = ((base & 0xFE0000) | (source & 0x1FFFF));
data_write (temp);
}
while (--length);
break;
case 0:
case 1:
if (svp) source = source - 2;
default:
do
{
unsigned int temp = vdp_dma_r(source);
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 */
reg[19] = length & 0xFF;
@ -385,6 +420,7 @@ static inline void dma_vbus (void)
/* VRAM FILL */
static inline void dma_fill(unsigned int data)
{
int name;
int length = (reg[20] << 8 | reg[19]) & 0xFFFF;
if (!length) length = 0x10000;
@ -475,6 +511,7 @@ static inline void data_write (unsigned int data)
*(uint16 *) &vram[addr & 0xFFFE] = data;
/* Update the pattern cache */
int name;
MARK_BG_DIRTY (addr);
}
break;
@ -566,132 +603,11 @@ void vdp_ctrl_w(unsigned int data)
}
unsigned int vdp_ctrl_r(void)
{
/*
* Return vdp status
*
* Bits are
* 0 0:1 ntsc:pal
* 1 DMA Busy
* 2 During HBlank
* 3 During VBlank
* 4 Frame Interlace 0:even 1:odd
* 5 Sprite collision
* 6 Too many sprites per line
* 7 v interrupt occurred
* 8 Write FIFO full
* 9 Write FIFO empty
* 10 - 15 Next word on bus
*/
/* update FIFO flags */
fifo_update();
if (fifo_write_cnt < 4)
{
status &= 0xFEFF;
if (fifo_write_cnt == 0) status |= 0x200;
}
else status ^= 0x200;
/* update DMA Busy flag */
if ((status & 2) && !dma_length && (count_m68k >= dma_endCycles))
status &= 0xFFFD;
unsigned int temp = status | vdp_pal;
/* display OFF: VBLANK flag is set */
if (!(reg[1] & 0x40)) temp |= 0x8;
/* HBLANK flag (Sonic 3 and Sonic 2 "VS Modes", Lemmings 2) */
if ((count_m68k <= (line_m68k + 84)) || (count_m68k > (line_m68k + m68cycles_per_line))) temp |= 0x4;
/* clear pending flag */
pending = 0;
/* clear SPR/SCOL flags */
status &= 0xFF9F;
return (temp);
}
void vdp_data_w(unsigned int data)
{
/* Clear pending flag */
pending = 0;
if (dmafill)
{
dma_fill(data);
return;
}
/* update VDP FIFO (during HDISPLAY only) */
if (!(status&8) && (reg[1]&0x40))
{
fifo_update();
if (fifo_write_cnt == 0)
{
/* reset cycle counter */
fifo_lastwrite = count_m68k;
/* FIFO is not empty anymore */
status &= 0xFDFF;
}
/* increase write counter */
fifo_write_cnt ++;
/* is FIFO full ? */
if (fifo_write_cnt >= 4)
{
status |= 0x100;
/* VDP latency (Chaos Engine, Soldiers of Fortune, Double Clutch) */
if (fifo_write_cnt > 4) count_m68k = fifo_lastwrite + fifo_latency;
}
}
/* write data */
data_write(data);
}
unsigned int vdp_data_r(void)
{
uint16 temp = 0;
/* Clear pending flag */
pending = 0;
switch (code & 0x0F)
{
case 0x00: /* VRAM */
temp = *(uint16 *) & vram[(addr & 0xFFFE)];
break;
case 0x08: /* CRAM */
temp = *(uint16 *) & cram[(addr & 0x7E)];
temp = UNPACK_CRAM (temp);
break;
case 0x04: /* VSRAM */
temp = *(uint16 *) & vsram[(addr & 0x7E)];
break;
}
/* Increment address register */
addr += reg[15];
/* return data */
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)
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
@ -702,18 +618,43 @@ void vdp_reg_w(unsigned int r, unsigned int d)
switch(r)
{
case 0x00: /* CTRL #1 */
if ((d&0x10) != (reg[0]&0x10)) hvint_updated = 0;
/* 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 */
/* Sesame Street Counting Cafe need to execute one instruction */
if ((d&0x20) != (reg[1]&0x20)) hvint_updated = 1;
/* 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.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;
@ -732,7 +673,7 @@ void vdp_reg_w(unsigned int r, unsigned int d)
- Deadly Moves aka Power Athlete (set display ON)
*/
reg[1] = d;
render_line(v_counter,odd_frame);
render_line(v_counter, 0);
}
}
break;
@ -780,13 +721,15 @@ void vdp_reg_w(unsigned int r, unsigned int d)
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;
/* update clipping */
window_clip(d,reg[17]);
}
/* See if the S/TE mode bit has changed */
@ -820,6 +763,10 @@ void vdp_reg_w(unsigned int r, unsigned int d)
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 */
@ -827,9 +774,130 @@ void vdp_reg_w(unsigned int r, unsigned int d)
}
unsigned int vdp_ctrl_r(void)
{
/*
* Return vdp status
*
* Bits are
* 0 0:1 ntsc:pal
* 1 DMA Busy
* 2 During HBlank
* 3 During VBlank
* 4 Frame Interlace 0:even 1:odd
* 5 Sprite collision
* 6 Too many sprites per line
* 7 v interrupt occurred
* 8 Write FIFO full
* 9 Write FIFO empty
* 10 - 15 Next word on bus
*/
/* update FIFO flags */
fifo_update();
if (fifo_write_cnt < 4)
{
status &= 0xFEFF;
if (fifo_write_cnt == 0) status |= 0x200;
}
else status ^= 0x200;
/* update DMA Busy flag */
if ((status & 2) && !dma_length && (count_m68k >= dma_endCycles))
status &= 0xFFFD;
unsigned int temp = status | vdp_pal;
/* display OFF: VBLANK flag is set */
if (!(reg[1] & 0x40)) temp |= 0x8;
/* HBLANK flag (Sonic 3 and Sonic 2 "VS Modes", Lemmings 2) */
if ((count_m68k <= (line_m68k + 84)) || (count_m68k > (line_m68k + m68cycles_per_line))) temp |= 0x4;
/* clear pending flag */
pending = 0;
/* clear SPR/SCOL flags */
status &= 0xFF9F;
return (temp);
}
void vdp_data_w(unsigned int data)
{
/* Clear pending flag */
pending = 0;
if (dmafill)
{
dma_fill(data);
return;
}
/* update VDP FIFO (during HDISPLAY only) */
if (!(status&8) && (reg[1]&0x40))
{
fifo_update();
if (fifo_write_cnt == 0)
{
/* reset cycle counter */
fifo_lastwrite = count_m68k;
/* FIFO is not empty anymore */
status &= 0xFDFF;
}
/* increase write counter */
fifo_write_cnt ++;
/* is FIFO full ? */
if (fifo_write_cnt >= 4)
{
status |= 0x100;
/* VDP latency (Chaos Engine, Soldiers of Fortune, Double Clutch) */
if (fifo_write_cnt > 4) count_m68k = fifo_lastwrite + fifo_latency;
}
}
/* write data */
data_write(data);
}
unsigned int vdp_data_r(void)
{
uint16 temp = 0;
/* Clear pending flag */
pending = 0;
switch (code & 0x0F)
{
case 0x00: /* VRAM */
temp = *(uint16 *) & vram[(addr & 0xFFFE)];
break;
case 0x08: /* CRAM */
temp = *(uint16 *) & cram[(addr & 0x7E)];
temp = UNPACK_CRAM (temp);
break;
case 0x04: /* VSRAM */
temp = *(uint16 *) & vsram[(addr & 0x7E)];
break;
}
/* Increment address register */
addr += reg[15];
/* return data */
return (temp);
}
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];
/* interlace mode 2 */
@ -848,13 +916,26 @@ void vdp_test_w(unsigned int value)
int vdp_int_ack_callback(int int_level)
{
if (vint_triggered)
if (irq_status&0x20)
{
vint_pending = 0;
vint_triggered = 0;
status &= ~0x0080; /* clear VINT flag */
status &= ~0x80; /* clear VINT flag */
}
else hint_pending = 0;
hvint_updated = 0;
else
{
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;
}

View File

@ -38,8 +38,7 @@ extern uint16 status;
extern uint8 dmafill;
extern uint8 hint_pending;
extern uint8 vint_pending;
extern uint8 vint_triggered;
extern int8 hvint_updated;
extern uint16 irq_status;
/* Global variables */
extern uint16 ntab;
@ -56,8 +55,7 @@ extern uint8 playfield_shift;
extern uint8 playfield_col_mask;
extern uint16 playfield_row_mask;
extern uint32 y_mask;
extern int16 h_counter;
extern int16 hc_latch;
extern uint16 hc_latch;
extern uint16 v_counter;
extern uint8 im2_flag;
extern uint32 dma_length;
@ -85,7 +83,6 @@ extern unsigned int vdp_ctrl_r(void);
extern void vdp_data_w(unsigned int data);
extern unsigned int vdp_data_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 vdp_test_w(unsigned int value);