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
|
||||
|
||||
// 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)
|
||||
{
|
||||
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)) {
|
||||
a += offs;
|
||||
// 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) {
|
||||
case 0: *val = (s8)p32x_sh2_read8(a, sh2s); break; // 8
|
||||
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:
|
||||
#if PROPAGATE_CONSTANTS
|
||||
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)
|
||||
u = FETCH32(opd->imm);
|
||||
else
|
||||
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);
|
||||
}
|
||||
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] |= d & 0x80;
|
||||
|
||||
if ((d ^ old) & 1)
|
||||
if ((old ^ d) & 1)
|
||||
p32x_pwm_schedule_sh2(sh2);
|
||||
if ((old ^ d) & 2)
|
||||
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,
|
||||
// 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.
|
||||
if ((a1 & 0x3e0000) == 0x3e0000)
|
||||
if ((a1 & 0x3e0000) == 0x3e0000 && (PicoIn.quirks & PQUIRK_WWFRAW_HACK))
|
||||
((u16 *)sh2->p_rom)[a1 / 2] = d;
|
||||
else
|
||||
sh2_write16_unmapped(a, d, sh2);
|
||||
|
@ -1951,6 +1951,16 @@ void *p32x_sh2_get_mem_ptr(u32 a, u32 *mask, SH2 *sh2)
|
|||
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)
|
||||
{
|
||||
u32 mask;
|
||||
|
|
|
@ -137,15 +137,7 @@ static void dmac_memcpy(struct dma_chan *chan, SH2 *sh2)
|
|||
|
||||
if (!up || chan->tcr < 4)
|
||||
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
|
||||
// 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?
|
||||
|
|
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;
|
||||
else if (strcmp(p, "filled_sram") == 0)
|
||||
*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)
|
||||
PicoIn.quirks |= PQUIRK_FORCE_6BTN;
|
||||
else {
|
||||
|
@ -1335,6 +1341,45 @@ static void PicoCartDetect(const char *carthw_cfg)
|
|||
// Unusual region 'code'
|
||||
if (rom_strcmp(0x1f0, "EUROPE") == 0 || rom_strcmp(0x1f0, "Europe") == 0)
|
||||
*(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)
|
||||
|
|
|
@ -52,6 +52,30 @@ hw = pico
|
|||
check_str = 0x100, "IMA IKUNO"
|
||||
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
|
||||
[Puggsy]
|
||||
check_str = 0x120, "PUGGSY"
|
||||
|
@ -71,12 +95,6 @@ prop = filled_sram
|
|||
check_str = 0x150, " HardBall III"
|
||||
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
|
||||
[Mega Everdrive]
|
||||
check_str = 0x100, "SEGA SSF"
|
||||
|
|
|
@ -90,6 +90,9 @@ extern void *p32x_bios_g, *p32x_bios_m, *p32x_bios_s;
|
|||
#define PHWS_SG 3
|
||||
|
||||
#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
|
||||
// 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_memory32(u32 a, u32 d, 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_event(SH2 *sh2, u32 flags, u32 m68k_cycles);
|
||||
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