diff --git a/core/cart_hw/md_cart.c b/core/cart_hw/md_cart.c index f09217c..b49f310 100644 --- a/core/cart_hw/md_cart.c +++ b/core/cart_hw/md_cart.c @@ -4,7 +4,7 @@ * * Copyright (C) 2007-2013 Eke-Eke (Genesis Plus GX) * - * Most cartridge protections were initially documented by Haze + * Many cartridge protections were initially documented by Haze * (http://haze.mameworld.info/) * * Realtec mapper was documented by TascoDeluxe @@ -42,6 +42,7 @@ ****************************************************************************************/ #include "shared.h" +#include "eeprom_i2c.h" #include "eeprom_spi.h" #include "gamepad.h" @@ -356,7 +357,25 @@ void md_cart_init(void) BACKUP MEMORY ***********************************************/ sram_init(); - + eeprom_i2c_init(); + + /* external SRAM */ + if (sram.on && !sram.custom) + { + /* disabled on startup if ROM is mapped in same area */ + if (cart.romsize <= sram.start) + { + /* initialize m68k bus handlers */ + m68k.memory_map[sram.start >> 16].base = sram.sram; + m68k.memory_map[sram.start >> 16].read8 = sram_read_byte; + m68k.memory_map[sram.start >> 16].read16 = sram_read_word; + m68k.memory_map[sram.start >> 16].write8 = sram_write_byte; + m68k.memory_map[sram.start >> 16].write16 = sram_write_word; + zbank_memory_map[sram.start >> 16].read = sram_read_byte; + zbank_memory_map[sram.start >> 16].write = sram_write_byte; + } + } + /********************************************** SVP CHIP ***********************************************/ @@ -492,7 +511,7 @@ void md_cart_init(void) } /********************************************** - Cartridge Extra Hardware + CARTRIDGE EXTRA HARDWARE ***********************************************/ memset(&cart.hw, 0, sizeof(cart.hw)); @@ -607,7 +626,7 @@ void md_cart_init(void) m68k.memory_map[i].base = cart.rom + ((i & 0x03) << 16); } - /* 32K SRAM is initially disabled at $200000-$2FFFFF */ + /* 32K static RAM is mapped to $200000-$2FFFFF (disabled on startup) */ for (i=0x20; i<0x30; i++) { m68k.memory_map[i].base = sram.sram; @@ -789,10 +808,28 @@ int md_cart_context_load(uint8 *state) if (offset == 0xff) { /* SRAM */ - m68k.memory_map[i].base = sram.sram; + m68k.memory_map[i].base = sram.sram; + m68k.memory_map[i].read8 = sram_read_byte; + m68k.memory_map[i].read16 = sram_read_word; + m68k.memory_map[i].write8 = sram_write_byte; + m68k.memory_map[i].write16 = sram_write_word; + zbank_memory_map[i].read = sram_read_byte; + zbank_memory_map[i].write = sram_write_byte; + } else { + /* check if SRAM was mapped there before loading state */ + if (m68k.memory_map[i].base == sram.sram) + { + 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; + } + /* ROM */ m68k.memory_map[i].base = cart.rom + (offset << 16); } @@ -829,9 +866,9 @@ static void mapper_sega_w(uint32 data) { /* Backup RAM mapped to $200000-$20ffff (normally mirrored up to $3fffff but this breaks Sonic Megamix and no game need it) */ m68k.memory_map[0x20].base = sram.sram; - m68k.memory_map[0x20].write8 = NULL; - m68k.memory_map[0x20].write16 = NULL; - zbank_memory_map[0x20].write = NULL; + m68k.memory_map[0x20].read8 = sram_read_byte; + m68k.memory_map[0x20].read16 = sram_read_word; + zbank_memory_map[0x20].read = sram_read_byte; /* Backup RAM write protection */ if (data & 2) @@ -840,6 +877,12 @@ static void mapper_sega_w(uint32 data) m68k.memory_map[0x20].write16 = m68k_unused_16_w; zbank_memory_map[0x20].write = zbank_unused_w; } + else + { + m68k.memory_map[0x20].write8 = sram_write_byte; + m68k.memory_map[0x20].write16 = sram_write_word; + zbank_memory_map[0x20].write = sram_write_byte; + } } /* S&K lock-on chip */ @@ -857,10 +900,13 @@ static void mapper_sega_w(uint32 data) /* cartridge ROM mapped to $200000-$3fffff */ for (i=0x20; i<0x40; i++) { - m68k.memory_map[i].base = cart.rom + ((i<<16) & cart.mask); - 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; + m68k.memory_map[i].base = cart.rom + ((i<<16) & cart.mask); + m68k.memory_map[i].read8 = NULL; + m68k.memory_map[i].read16 = NULL; + zbank_memory_map[i].read = NULL; + 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; } } } @@ -907,10 +953,10 @@ static void mapper_sf001_w(uint32 address, uint32 data) m68k.memory_map[i].base = cart.rom + (i << 16); 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; + m68k.memory_map[i].write8 = (i > 0x00) ? m68k_unused_8_w : mapper_sf001_w; + m68k.memory_map[i].write16 = (i > 0x00) ? m68k_unused_16_w : mapper_sf001_w; zbank_memory_map[i].read = zbank_unused_r; - zbank_memory_map[i].write = m68k_unused_8_w; + zbank_memory_map[i].write = (i > 0x00) ? m68k_unused_8_w : mapper_sf001_w; } } @@ -939,12 +985,12 @@ static void mapper_sf001_w(uint32 address, uint32 data) while (i<0x40) { m68k.memory_map[i].base = sram.sram; - 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; + m68k.memory_map[i].read8 = sram_read_byte; + m68k.memory_map[i].read16 = sram_read_word; + m68k.memory_map[i].write8 = sram_write_byte; + m68k.memory_map[i].write16 = sram_write_word; + zbank_memory_map[i].read = sram_read_byte; + zbank_memory_map[i].write = sram_write_byte; i++; } } @@ -956,10 +1002,10 @@ static void mapper_sf001_w(uint32 address, uint32 data) 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; + m68k.memory_map[i].write8 = (i > 0x00) ? m68k_unused_8_w : mapper_sf001_w; + m68k.memory_map[i].write16 = (i > 0x00) ? m68k_unused_16_w : mapper_sf001_w; zbank_memory_map[i].read = NULL; - zbank_memory_map[i].write = m68k_unused_8_w; + zbank_memory_map[i].write = (i > 0x00) ? m68k_unused_8_w : mapper_sf001_w; } } @@ -1023,12 +1069,12 @@ static void mapper_sf004_w(uint32 address, uint32 data) /* 32KB static RAM mirrored into $200000-$2FFFFF (odd bytes only) */ for (i=0x20; i<0x30; i++) { - 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; + m68k.memory_map[i].read8 = sram_read_byte; + m68k.memory_map[i].read16 = sram_read_word; + m68k.memory_map[i].write8 = sram_write_byte; + m68k.memory_map[i].write16 = sram_write_word; + zbank_memory_map[i].read = sram_read_byte; + zbank_memory_map[i].write = sram_write_byte; } } else diff --git a/core/cart_hw/sram.c b/core/cart_hw/sram.c index 835ec15..382cf13 100644 --- a/core/cart_hw/sram.c +++ b/core/cart_hw/sram.c @@ -37,15 +37,9 @@ ****************************************************************************************/ #include "shared.h" -#include "eeprom_i2c.h" T_SRAM sram; -static unsigned int sram_read_byte(unsigned int address); -static unsigned int sram_read_word(unsigned int address); -static void sram_write_byte(unsigned int address, unsigned int data); -static void sram_write_word(unsigned int address, unsigned int data); - /**************************************************************************** * A quick guide to external RAM on the Genesis * @@ -194,44 +188,25 @@ void sram_init() sram.on = 1; } } - - /* autodetect games with serial EEPROM */ - eeprom_i2c_init(); - - /* initialize m68k bus handlers (if not already done) */ - if (sram.on && !sram.custom) - { - /* disabled on startup if ROM is mapped in same area */ - if (cart.romsize <= sram.start) - { - m68k.memory_map[sram.start >> 16].base = sram.sram; - m68k.memory_map[sram.start >> 16].read8 = sram_read_byte; - m68k.memory_map[sram.start >> 16].read16 = sram_read_word; - m68k.memory_map[sram.start >> 16].write8 = sram_write_byte; - m68k.memory_map[sram.start >> 16].write16 = sram_write_word; - zbank_memory_map[sram.start >> 16].read = sram_read_byte; - zbank_memory_map[sram.start >> 16].write = sram_write_byte; - } - } } -static unsigned int sram_read_byte(unsigned int address) +unsigned int sram_read_byte(unsigned int address) { return sram.sram[address & 0xffff]; } -static unsigned int sram_read_word(unsigned int address) +unsigned int sram_read_word(unsigned int address) { address &= 0xfffe; return (sram.sram[address + 1] | (sram.sram[address] << 8)); } -static void sram_write_byte(unsigned int address, unsigned int data) +void sram_write_byte(unsigned int address, unsigned int data) { sram.sram[address & 0xffff] = data; } -static void sram_write_word(unsigned int address, unsigned int data) +void sram_write_word(unsigned int address, unsigned int data) { address &= 0xfffe; sram.sram[address] = data >> 8; diff --git a/core/cart_hw/sram.h b/core/cart_hw/sram.h index d838e69..64934ca 100644 --- a/core/cart_hw/sram.h +++ b/core/cart_hw/sram.h @@ -52,6 +52,10 @@ typedef struct /* Function prototypes */ extern void sram_init(); +extern unsigned int sram_read_byte(unsigned int address); +extern unsigned int sram_read_word(unsigned int address); +extern void sram_write_byte(unsigned int address, unsigned int data); +extern void sram_write_word(unsigned int address, unsigned int data); /* global variables */ extern T_SRAM sram; diff --git a/core/input_hw/lightgun.c b/core/input_hw/lightgun.c index 4ed0b76..d6bf46e 100644 --- a/core/input_hw/lightgun.c +++ b/core/input_hw/lightgun.c @@ -129,14 +129,25 @@ void lightgun_refresh(int port) } } - /* External Interrupt ? */ + /* External Interrupt enabled ? */ if (reg[11] & 0x08) { m68k_update_irq(2); } - /* HACK: force HV Counter latch (some games does not lock HV Counter but instead use larger offset value) */ - hvc_latch = 0x10000 | (y << 8); + /* HVC latch enabled ? */ + if (reg[0] & 0x02) + { + /* line accurate V-Counter value */ + hvc_latch = 0x10000 | (y << 8); + } + else + { + /* HACK: force HVC latch even when disabled (a few games does not lock HV Counter but instead applies larger offset value) */ + hvc_latch = 0x20000 | (y << 8); + } + + /* pixel accurate H-Counter value */ if (reg[12] & 1) { hvc_latch |= hc_320[((x / 2) + input.x_offset) % 210]; @@ -147,6 +158,11 @@ void lightgun_refresh(int port) } } } + else if (hvc_latch & 0x20000) + { + /* HVC should be free-running on other lines when latch is disabled (fixes "Gunfight - 3 in 1" randomization) */ + hvc_latch = 0; + } } } diff --git a/core/vdp_ctrl.c b/core/vdp_ctrl.c index e2fe42e..7ec7d4f 100644 --- a/core/vdp_ctrl.c +++ b/core/vdp_ctrl.c @@ -1362,42 +1362,34 @@ unsigned int vdp_hvc_r(unsigned int cycles) int vc; unsigned int data = hvc_latch; - /* Check if HVC is frozen */ - if (!data) + /* Check if HVC latch is enabled */ + if (data) { - /* Cycle-accurate HCounter (Striker, Mickey Mania, Skitchin, Road Rash I,II,III, Sonic 3D Blast...) */ - data = hctab[cycles % MCYCLES_PER_LINE]; - } - else - { - /* Mode 5: HV counters are frozen (cf. lightgun games & Sunset Riders) */ - if (reg[1] & 4) + /* Mode 5: HV-counters are frozen (cf. lightgun games, Sunset Riders logo) */ + if (reg[1] & 0x04) { - /* check if HVC is really locked or is read within INT2 callback (HVC latch is forced for lightgun emulation, cf. lightgun.c) */ - if ((reg[0] & 0x02) || (m68k.int_mask == 0x0200)) - { #ifdef LOGVDP - error("[%d(%d)][%d(%d)] HVC read -> 0x%x (%x)\n", v_counter, (cycles/MCYCLES_PER_LINE-1)%lines_per_frame, cycles, cycles%MCYCLES_PER_LINE, data & 0xffff, m68k_get_reg(M68K_REG_PC)); + error("[%d(%d)][%d(%d)] HVC latch read -> 0x%x (%x)\n", v_counter, (cycles/MCYCLES_PER_LINE-1)%lines_per_frame, cycles, cycles%MCYCLES_PER_LINE, data & 0xffff, m68k_get_reg(M68K_REG_PC)); #endif - /* return latched HVC value */ - return (data & 0xffff); - } - - /* HV counters should be free-running (fixes "Gunfight - 3 in 1" randomization when Justifiers are enabled) */ - hvc_latch = 0; - data = hctab[cycles % MCYCLES_PER_LINE]; + /* return latched HVC value */ + return (data & 0xffff); } else { - /* Mode 4: V counter runs normally, H counter is frozen */ + /* Mode 4: by default, V-counter runs normally & H counter is frozen */ data &= 0xff; } } + else + { + /* Cycle-accurate H-Counter (Striker, Mickey Mania, Skitchin, Road Rash I,II,III, Sonic 3D Blast...) */ + data = hctab[cycles % MCYCLES_PER_LINE]; + } - /* Cycle-accurate VCounter (cycle counter starts from line -1) */ + /* Cycle-accurate V-Counter (cycle counter starts from line -1) */ vc = (cycles / MCYCLES_PER_LINE) - 1; - /* VCounter overflow */ + /* V-Counter overflow */ if (vc > vc_max) { vc -= lines_per_frame; @@ -1413,6 +1405,7 @@ unsigned int vdp_hvc_r(unsigned int cycles) vc = (vc & ~1) | ((vc >> 8) & 1); } + /* return H-Counter in LSB & V-Counter in MSB */ data |= ((vc & 0xff) << 8); #ifdef LOGVDP