mirror of
https://github.com/RaySollium99/picodrive.git
synced 2025-09-05 07:17:45 -04:00
32x, hacks for roms with caching related problems
This commit is contained in:
parent
ebd9c86a6c
commit
fe8f2d963e
7 changed files with 89 additions and 28 deletions
|
@ -537,12 +537,6 @@ void REGPARM(1) (*sh2_drc_restore_sr)(SH2 *sh2);
|
||||||
#define MF_POLLING 0x20 // include polling check in read
|
#define MF_POLLING 0x20 // include polling check in read
|
||||||
|
|
||||||
// address space stuff
|
// address space stuff
|
||||||
static int dr_is_rom(u32 a)
|
|
||||||
{
|
|
||||||
// tweak for WWF Raw which writes data to some high ROM addresses
|
|
||||||
return (a & 0xc6000000) == 0x02000000 && (a & 0x3f0000) < 0x3e0000;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int dr_ctx_get_mem_ptr(SH2 *sh2, u32 a, u32 *mask)
|
static int dr_ctx_get_mem_ptr(SH2 *sh2, u32 a, u32 *mask)
|
||||||
{
|
{
|
||||||
void *memptr;
|
void *memptr;
|
||||||
|
@ -2698,7 +2692,7 @@ static int emit_get_rom_data(SH2 *sh2, sh2_reg_e r, s32 offs, int size, u32 *val
|
||||||
if (gconst_get(r, &a)) {
|
if (gconst_get(r, &a)) {
|
||||||
a += offs;
|
a += offs;
|
||||||
// check if rom is memory mapped (not bank switched), and address is in rom
|
// check if rom is memory mapped (not bank switched), and address is in rom
|
||||||
if (dr_is_rom(a) && p32x_sh2_get_mem_ptr(a, &mask, sh2) == sh2->p_rom) {
|
if (p32x_sh2_mem_is_rom(a, sh2) && p32x_sh2_get_mem_ptr(a, &mask, sh2) == sh2->p_rom) {
|
||||||
switch (size & MF_SIZEMASK) {
|
switch (size & MF_SIZEMASK) {
|
||||||
case 0: *val = (s8)p32x_sh2_read8(a, sh2s); break; // 8
|
case 0: *val = (s8)p32x_sh2_read8(a, sh2s); break; // 8
|
||||||
case 1: *val = (s16)p32x_sh2_read16(a, sh2s); break; // 16
|
case 1: *val = (s16)p32x_sh2_read16(a, sh2s); break; // 16
|
||||||
|
@ -3830,14 +3824,12 @@ static void REGPARM(2) *sh2_translate(SH2 *sh2, int tcache_id)
|
||||||
case OP_LOAD_POOL:
|
case OP_LOAD_POOL:
|
||||||
#if PROPAGATE_CONSTANTS
|
#if PROPAGATE_CONSTANTS
|
||||||
if ((opd->imm && opd->imm >= base_pc && opd->imm < end_literals) ||
|
if ((opd->imm && opd->imm >= base_pc && opd->imm < end_literals) ||
|
||||||
dr_is_rom(opd->imm))
|
p32x_sh2_mem_is_rom(opd->imm, sh2))
|
||||||
{
|
{
|
||||||
if (opd->size == 2)
|
if (opd->size == 2)
|
||||||
u = FETCH32(opd->imm);
|
u = FETCH32(opd->imm);
|
||||||
else
|
else
|
||||||
u = (s16)FETCH_OP(opd->imm);
|
u = (s16)FETCH_OP(opd->imm);
|
||||||
// tweak for Blackthorne: avoid stack overwriting
|
|
||||||
if (GET_Rn() == SHR_SP && u == 0x0603f800) u = 0x0603f900;
|
|
||||||
gconst_new(GET_Rn(), u);
|
gconst_new(GET_Rn(), u);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
|
@ -816,7 +816,7 @@ static void p32x_sh2reg_write8(u32 a, u32 d, SH2 *sh2)
|
||||||
Pico32x.sh2_regs[0] &= ~0x80;
|
Pico32x.sh2_regs[0] &= ~0x80;
|
||||||
Pico32x.sh2_regs[0] |= d & 0x80;
|
Pico32x.sh2_regs[0] |= d & 0x80;
|
||||||
|
|
||||||
if ((d ^ old) & 1)
|
if ((old ^ d) & 1)
|
||||||
p32x_pwm_schedule_sh2(sh2);
|
p32x_pwm_schedule_sh2(sh2);
|
||||||
if ((old ^ d) & 2)
|
if ((old ^ d) & 2)
|
||||||
p32x_update_cmd_irq(sh2, 0);
|
p32x_update_cmd_irq(sh2, 0);
|
||||||
|
@ -1776,7 +1776,7 @@ static void REGPARM(3) sh2_write16_rom(u32 a, u32 d, SH2 *sh2)
|
||||||
// Presumably the write goes to the CPU cache and is read back from there,
|
// Presumably the write goes to the CPU cache and is read back from there,
|
||||||
// but it would be extremely costly to emulate cache behaviour. Just allow
|
// but it would be extremely costly to emulate cache behaviour. Just allow
|
||||||
// writes to that region, hoping that the original ROM values are never used.
|
// writes to that region, hoping that the original ROM values are never used.
|
||||||
if ((a1 & 0x3e0000) == 0x3e0000)
|
if ((a1 & 0x3e0000) == 0x3e0000 && (PicoIn.quirks & PQUIRK_WWFRAW_HACK))
|
||||||
((u16 *)sh2->p_rom)[a1 / 2] = d;
|
((u16 *)sh2->p_rom)[a1 / 2] = d;
|
||||||
else
|
else
|
||||||
sh2_write16_unmapped(a, d, sh2);
|
sh2_write16_unmapped(a, d, sh2);
|
||||||
|
@ -1951,6 +1951,16 @@ void *p32x_sh2_get_mem_ptr(u32 a, u32 *mask, SH2 *sh2)
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int p32x_sh2_mem_is_rom(u32 a, SH2 *sh2)
|
||||||
|
{
|
||||||
|
if ((a & 0xc6000000) == 0x02000000) {
|
||||||
|
// ROM, but mind tweak for WWF Raw
|
||||||
|
return !(PicoIn.quirks & PQUIRK_WWFRAW_HACK) || (a & 0x3f0000) < 0x3e0000;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
int p32x_sh2_memcpy(u32 dst, u32 src, int count, int size, SH2 *sh2)
|
int p32x_sh2_memcpy(u32 dst, u32 src, int count, int size, SH2 *sh2)
|
||||||
{
|
{
|
||||||
u32 mask;
|
u32 mask;
|
||||||
|
|
|
@ -137,15 +137,7 @@ static void dmac_memcpy(struct dma_chan *chan, SH2 *sh2)
|
||||||
|
|
||||||
if (!up || chan->tcr < 4)
|
if (!up || chan->tcr < 4)
|
||||||
return;
|
return;
|
||||||
#if MARS_CHECK_HACK
|
|
||||||
// XXX Mars Check Program copies 32K longwords (128KB) from a 64KB buffer in
|
|
||||||
// ROM or DRAM to SDRAM in 4-longword mode, overwriting an SDRAM comm area in
|
|
||||||
// turn, which crashes the test on emulators without CPU cache emulation.
|
|
||||||
// This may be a bug in Mars Check. As a kludge limit the transfer to 64KB,
|
|
||||||
// which is what the check program test uses for checking the result.
|
|
||||||
// A better way would clearly be to have a mechanism to patch the ROM...
|
|
||||||
if (size == 3 && chan->tcr == 32768 && chan->dar == 0x06020000) size = 1;
|
|
||||||
#endif
|
|
||||||
if (size == 3) size = 2; // 4-word xfer mode still counts in words
|
if (size == 3) size = 2; // 4-word xfer mode still counts in words
|
||||||
// XXX check TCR being a multiple of 4 in 4-word xfer mode?
|
// XXX check TCR being a multiple of 4 in 4-word xfer mode?
|
||||||
// XXX check alignment of sar/dar, generating a bus error if unaligned?
|
// XXX check alignment of sar/dar, generating a bus error if unaligned?
|
||||||
|
|
45
pico/cart.c
45
pico/cart.c
|
@ -1201,6 +1201,12 @@ static void parse_carthw(const char *carthw_cfg, int *fill_sram,
|
||||||
Pico.sv.flags &= ~SRF_EEPROM;
|
Pico.sv.flags &= ~SRF_EEPROM;
|
||||||
else if (strcmp(p, "filled_sram") == 0)
|
else if (strcmp(p, "filled_sram") == 0)
|
||||||
*fill_sram = 1;
|
*fill_sram = 1;
|
||||||
|
else if (strcmp(p, "wwfraw_hack") == 0)
|
||||||
|
PicoIn.quirks |= PQUIRK_WWFRAW_HACK;
|
||||||
|
else if (strcmp(p, "blackthorne_hack") == 0)
|
||||||
|
PicoIn.quirks |= PQUIRK_BLACKTHORNE_HACK;
|
||||||
|
else if (strcmp(p, "marscheck_hack") == 0)
|
||||||
|
PicoIn.quirks |= PQUIRK_MARSCHECK_HACK;
|
||||||
else if (strcmp(p, "force_6btn") == 0)
|
else if (strcmp(p, "force_6btn") == 0)
|
||||||
PicoIn.quirks |= PQUIRK_FORCE_6BTN;
|
PicoIn.quirks |= PQUIRK_FORCE_6BTN;
|
||||||
else {
|
else {
|
||||||
|
@ -1335,6 +1341,45 @@ static void PicoCartDetect(const char *carthw_cfg)
|
||||||
// Unusual region 'code'
|
// Unusual region 'code'
|
||||||
if (rom_strcmp(0x1f0, "EUROPE") == 0 || rom_strcmp(0x1f0, "Europe") == 0)
|
if (rom_strcmp(0x1f0, "EUROPE") == 0 || rom_strcmp(0x1f0, "Europe") == 0)
|
||||||
*(u32 *) (Pico.rom + 0x1f0) = CPU_LE4(0x20204520);
|
*(u32 *) (Pico.rom + 0x1f0) = CPU_LE4(0x20204520);
|
||||||
|
|
||||||
|
// tweak for Blackthorne: master SH2 overwrites stack of slave SH2 being in PWM
|
||||||
|
// interrupt. On real hardware, nothing happens since slave fetches the values
|
||||||
|
// it has written from its cache, but picodrive doesn't emulate caching.
|
||||||
|
// move master memory area down by 0x100 bytes.
|
||||||
|
// XXX replace this abominable hack. It might cause other problems in the game!
|
||||||
|
if (PicoIn.quirks & PQUIRK_BLACKTHORNE_HACK) {
|
||||||
|
int i;
|
||||||
|
unsigned a = 0;
|
||||||
|
for (i = 0; i < Pico.romsize; i += 4) {
|
||||||
|
unsigned v = CPU_BE2(*(u32 *) (Pico.rom + i));
|
||||||
|
if (a && v == a + 0x400) { // patch if 2 pointers with offset 0x400 are found
|
||||||
|
printf("auto-patching @%06x: %08x->%08x\n", i, v, v - 0x100);
|
||||||
|
*(u32 *) (Pico.rom + i) = CPU_BE2(v - 0x100);
|
||||||
|
}
|
||||||
|
// detect a pointer into the incriminating area
|
||||||
|
a = 0;
|
||||||
|
if (v >> 12 == 0x0603f000 >> 12 && !(v & 3))
|
||||||
|
a = v;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// tweak for Mars Check Program: copies 32K longwords (128KB) from a 64KB buffer
|
||||||
|
// in ROM or DRAM to SDRAM with DMA in 4-longword mode, overwriting an SDRAM comm
|
||||||
|
// area in turn. This crashes the test on emulators without CPU cache emulation.
|
||||||
|
// This may be a bug in Mars Check, since it's only checking for the 64KB result.
|
||||||
|
// Patch the DMA transfers so that they transfer only 64KB.
|
||||||
|
if (PicoIn.quirks & PQUIRK_MARSCHECK_HACK) {
|
||||||
|
int i;
|
||||||
|
unsigned a = 0;
|
||||||
|
for (i = 0; i < Pico.romsize; i += 4) {
|
||||||
|
unsigned v = CPU_BE2(*(u32 *) (Pico.rom + i));
|
||||||
|
if (a == 0xffffff8c && v == 0x5ee1) { // patch if 4-long xfer written to CHCR
|
||||||
|
printf("auto-patching @%06x: %08x->%08x\n", i, v, v & ~0x800);
|
||||||
|
*(u32 *) (Pico.rom + i) = CPU_BE2(v & ~0x800); // change to half-sized xfer
|
||||||
|
}
|
||||||
|
a = v;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void PicoCartDetectMS(void)
|
static void PicoCartDetectMS(void)
|
||||||
|
|
|
@ -52,6 +52,30 @@ hw = pico
|
||||||
check_str = 0x100, "IMA IKUNO"
|
check_str = 0x100, "IMA IKUNO"
|
||||||
hw = pico
|
hw = pico
|
||||||
|
|
||||||
|
# X-Men proto
|
||||||
|
[X-Men (prototype) - 32X]
|
||||||
|
check_str = 0x120, "32X SAMPLE PROGRAM"
|
||||||
|
check_str = 0x32b74c, "Bishop Level"
|
||||||
|
prop = force_6btn
|
||||||
|
|
||||||
|
# WWF Raw
|
||||||
|
[WWF Raw - 32X]
|
||||||
|
check_str = 0x100, "SEGA 32X"
|
||||||
|
check_str = 0x150, "WWF RAW"
|
||||||
|
prop = wwfraw_hack # reads back data written to high ROM adresses from cache
|
||||||
|
|
||||||
|
# Blackthorne
|
||||||
|
[Blackthorne - 32X]
|
||||||
|
check_str = 0x100, "SEGA 32X"
|
||||||
|
check_str = 0x120, "BLACKTHORNE"
|
||||||
|
prop = blackthorne_hack # reads back data overwritten by 2nd CPU from cache
|
||||||
|
|
||||||
|
# Mars check program
|
||||||
|
[Mars Check - 32X]
|
||||||
|
check_str = 0x100, "SEGA"
|
||||||
|
check_str = 0x150, "MARS CHECK PROGRAM"
|
||||||
|
prop = marscheck_hack # reads back data overwritten by DMA from cache
|
||||||
|
|
||||||
# sram emulation triggers some protection for this one
|
# sram emulation triggers some protection for this one
|
||||||
[Puggsy]
|
[Puggsy]
|
||||||
check_str = 0x120, "PUGGSY"
|
check_str = 0x120, "PUGGSY"
|
||||||
|
@ -71,12 +95,6 @@ prop = filled_sram
|
||||||
check_str = 0x150, " HardBall III"
|
check_str = 0x150, " HardBall III"
|
||||||
sram_range = 0x200000,0x20ffff
|
sram_range = 0x200000,0x20ffff
|
||||||
|
|
||||||
# X-Men proto
|
|
||||||
[X-Men (prototype)]
|
|
||||||
check_str = 0x150, "32X SAMPLE PROGRAM"
|
|
||||||
check_str = 0x32b74c, "Bishop Level"
|
|
||||||
prop = force_6btn
|
|
||||||
|
|
||||||
# The SSF2 mapper
|
# The SSF2 mapper
|
||||||
[Mega Everdrive]
|
[Mega Everdrive]
|
||||||
check_str = 0x100, "SEGA SSF"
|
check_str = 0x100, "SEGA SSF"
|
||||||
|
|
|
@ -89,7 +89,10 @@ extern void *p32x_bios_g, *p32x_bios_m, *p32x_bios_s;
|
||||||
#define PHWS_SMS 2
|
#define PHWS_SMS 2
|
||||||
#define PHWS_SG 3
|
#define PHWS_SG 3
|
||||||
|
|
||||||
#define PQUIRK_FORCE_6BTN (1<<0)
|
#define PQUIRK_FORCE_6BTN (1<<0)
|
||||||
|
#define PQUIRK_BLACKTHORNE_HACK (1<<1)
|
||||||
|
#define PQUIRK_WWFRAW_HACK (1<<2)
|
||||||
|
#define PQUIRK_MARSCHECK_HACK (1<<3)
|
||||||
|
|
||||||
// the emulator is configured and some status is reported
|
// the emulator is configured and some status is reported
|
||||||
// through this global state (not saved in savestates)
|
// through this global state (not saved in savestates)
|
||||||
|
|
|
@ -1017,6 +1017,7 @@ u32 REGPARM(3) p32x_sh2_poll_memory8(u32 a, u32 d, SH2 *sh2);
|
||||||
u32 REGPARM(3) p32x_sh2_poll_memory16(u32 a, u32 d, SH2 *sh2);
|
u32 REGPARM(3) p32x_sh2_poll_memory16(u32 a, u32 d, SH2 *sh2);
|
||||||
u32 REGPARM(3) p32x_sh2_poll_memory32(u32 a, u32 d, SH2 *sh2);
|
u32 REGPARM(3) p32x_sh2_poll_memory32(u32 a, u32 d, SH2 *sh2);
|
||||||
void *p32x_sh2_get_mem_ptr(u32 a, u32 *mask, SH2 *sh2);
|
void *p32x_sh2_get_mem_ptr(u32 a, u32 *mask, SH2 *sh2);
|
||||||
|
int p32x_sh2_mem_is_rom(u32 a, SH2 *sh2);
|
||||||
void p32x_sh2_poll_detect(u32 a, SH2 *sh2, u32 flags, int maxcnt);
|
void p32x_sh2_poll_detect(u32 a, SH2 *sh2, u32 flags, int maxcnt);
|
||||||
void p32x_sh2_poll_event(SH2 *sh2, u32 flags, u32 m68k_cycles);
|
void p32x_sh2_poll_event(SH2 *sh2, u32 flags, u32 m68k_cycles);
|
||||||
int p32x_sh2_memcpy(u32 dst, u32 src, int count, int size, SH2 *sh2);
|
int p32x_sh2_memcpy(u32 dst, u32 src, int count, int size, SH2 *sh2);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue