[mips] Remove IWRAM stack optimization hack
Converted the hack into another... hopefully better hack. Check for IW/EWRAM addr bit and handle accesses to EWRAM by correcting the base addr and the mirroring range. Assumes that iwram and ewram buffers are at a distance multiple of 64KB for speed (so that lw/sw offsets can be shared). This fixes a variety of games that should have been present in game_config.txt such as Ninja Cop, Star Wars JPB, Medal of Honor, Spongebob, etc. Some of them were just missing regional versions of the cart. It also fixes newer games and homebrew such as GoodBoy Galaxy.
This commit is contained in:
parent
56f00c162e
commit
ef399b9315
7 changed files with 36 additions and 518 deletions
1
cpu.h
1
cpu.h
|
@ -153,7 +153,6 @@ extern u8 *ram_translation_ptr;
|
|||
#define MAX_TRANSLATION_GATES 8
|
||||
|
||||
extern u32 idle_loop_target_pc;
|
||||
extern u32 iwram_stack_optimize;
|
||||
extern u32 translation_gate_targets;
|
||||
extern u32 translation_gate_target_pc[MAX_TRANSLATION_GATES];
|
||||
|
||||
|
|
10
gba_memory.c
10
gba_memory.c
|
@ -2132,10 +2132,7 @@ typedef struct
|
|||
u32 flash_device_id;
|
||||
int save_type;
|
||||
int rtc_enabled;
|
||||
int mirroring_enabled;
|
||||
int use_bios;
|
||||
u32 idle_loop_target_pc;
|
||||
u32 iwram_stack_optimize;
|
||||
u32 translation_gate_target_1;
|
||||
u32 translation_gate_target_2;
|
||||
u32 translation_gate_target_3;
|
||||
|
@ -2173,8 +2170,6 @@ static s32 load_game_config_over(gamepak_info_t *gpinfo)
|
|||
if (gbaover[i].idle_loop_target_pc != 0)
|
||||
idle_loop_target_pc = gbaover[i].idle_loop_target_pc;
|
||||
|
||||
iwram_stack_optimize = gbaover[i].iwram_stack_optimize;
|
||||
|
||||
flash_device_id = gbaover[i].flash_device_id;
|
||||
if (flash_device_id == FLASH_DEVICE_MACRONIX_128KB)
|
||||
flash_bank_cnt = FLASH_SIZE_128KB;
|
||||
|
@ -2269,10 +2264,6 @@ static s32 load_game_config(gamepak_info_t *gpinfo)
|
|||
}
|
||||
}
|
||||
|
||||
if(!strcmp(current_variable, "iwram_stack_optimize") &&
|
||||
!strcmp(current_value, "no\0")) /* \0 for broken toolchain workaround */
|
||||
iwram_stack_optimize = 0;
|
||||
|
||||
if(!strcmp(current_variable, "flash_rom_type") &&
|
||||
!strcmp(current_value, "128KB"))
|
||||
flash_device_id = FLASH_DEVICE_MACRONIX_128KB;
|
||||
|
@ -3254,7 +3245,6 @@ u32 load_gamepak(const struct retro_game_info* info, const char *name)
|
|||
memcpy(gpinfo.gamepak_maker, &gamepak_buffers[0][0xB0], 2);
|
||||
|
||||
idle_loop_target_pc = 0xFFFFFFFF;
|
||||
iwram_stack_optimize = 1;
|
||||
translation_gate_targets = 0;
|
||||
flash_device_id = FLASH_DEVICE_MACRONIX_64KB;
|
||||
flash_bank_cnt = FLASH_SIZE_64KB;
|
||||
|
|
501
gba_over.h
501
gba_over.h
File diff suppressed because it is too large
Load diff
|
@ -92,7 +92,6 @@ int use_libretro_save_method = 0;
|
|||
boot_mode selected_boot_mode = boot_game;
|
||||
|
||||
u32 idle_loop_target_pc = 0xFFFFFFFF;
|
||||
u32 iwram_stack_optimize = 1;
|
||||
u32 translation_gate_target_pc[MAX_TRANSLATION_GATES];
|
||||
u32 translation_gate_targets = 0;
|
||||
|
||||
|
|
|
@ -114,6 +114,7 @@ typedef enum
|
|||
{
|
||||
mips_regimm_bltz = 0x00,
|
||||
mips_regimm_bltzal = 0x10,
|
||||
mips_regimm_bgezal = 0x11,
|
||||
mips_regimm_synci = 0x1F
|
||||
} mips_function_regimm;
|
||||
|
||||
|
@ -399,6 +400,9 @@ typedef enum
|
|||
#define mips_emit_bltzal(rs, offset) \
|
||||
mips_emit_regimm(bltzal, rs, offset) \
|
||||
|
||||
#define mips_emit_bgezal(rs, offset) \
|
||||
mips_emit_regimm(bgezal, rs, offset) \
|
||||
|
||||
#define mips_emit_bltz(rs, offset) \
|
||||
mips_emit_regimm(bltz, rs, offset) \
|
||||
|
||||
|
|
|
@ -260,12 +260,15 @@ u32 arm_to_mips_reg[] =
|
|||
mips_emit_j(mips_absolute_offset(mips_indirect_branch_##type)); \
|
||||
mips_emit_nop() \
|
||||
|
||||
#define block_prologue_size 8
|
||||
#define block_prologue_size 16
|
||||
|
||||
#define generate_block_prologue() \
|
||||
update_trampoline = translation_ptr; \
|
||||
mips_emit_j(mips_absolute_offset(mips_update_gba)); \
|
||||
mips_emit_nop(); \
|
||||
spaccess_trampoline = translation_ptr; \
|
||||
mips_emit_j(mips_absolute_offset(&rom_translation_cache[EWRAM_SPM_OFF])); \
|
||||
mips_emit_nop(); \
|
||||
generate_load_imm(reg_pc, stored_pc) \
|
||||
|
||||
#define check_generate_n_flag (flag_status & 0x08)
|
||||
|
@ -547,7 +550,8 @@ u32 generate_load_rm_sh_##flags_op(u32 rm) \
|
|||
|
||||
#define generate_block_extra_vars() \
|
||||
u32 stored_pc = pc; \
|
||||
u8 *update_trampoline \
|
||||
u8 *update_trampoline; \
|
||||
u8 *spaccess_trampoline; \
|
||||
|
||||
#define generate_block_extra_vars_arm() \
|
||||
generate_block_extra_vars(); \
|
||||
|
@ -1369,9 +1373,16 @@ u32 execute_store_cpsr_body(u32 _cpsr, u32 address)
|
|||
arm_block_memory_offset_##offset_type(); \
|
||||
arm_block_memory_writeback_##access_type(writeback_type); \
|
||||
\
|
||||
if((rn == REG_SP) && iwram_stack_optimize) \
|
||||
if(rn == REG_SP) \
|
||||
{ \
|
||||
/* Assume IWRAM, the most common path by far */ \
|
||||
mips_emit_andi(reg_a1, reg_a2, 0x7FFC); \
|
||||
/* Check the 23rd bit to differenciate IW/EW RAMs */ \
|
||||
mips_emit_srl(reg_temp, reg_a2, 24); \
|
||||
mips_emit_sll(reg_temp, reg_temp, 31); \
|
||||
mips_emit_bgezal(reg_temp, \
|
||||
mips_relative_offset(translation_ptr, spaccess_trampoline)); \
|
||||
/* Delay slot, will be overwritten anyway */ \
|
||||
mips_emit_lui(reg_a0, ((u32)(iwram + 0x8000 + 0x8000) >> 16)); \
|
||||
mips_emit_addu(reg_a1, reg_a1, reg_a0); \
|
||||
offset = (u32)(iwram + 0x8000) & 0xFFFF; \
|
||||
|
@ -1696,9 +1707,16 @@ u32 execute_store_cpsr_body(u32 _cpsr, u32 address)
|
|||
thumb_block_address_preadjust_##pre_op(base_reg); \
|
||||
thumb_block_address_postadjust_##post_op(base_reg); \
|
||||
\
|
||||
if((base_reg == REG_SP) && iwram_stack_optimize) \
|
||||
if(base_reg == REG_SP) \
|
||||
{ \
|
||||
/* Assume IWRAM, the most common path by far */ \
|
||||
mips_emit_andi(reg_a1, reg_a2, 0x7FFC); \
|
||||
/* Check the 23rd bit to differenciate IW/EW RAMs */ \
|
||||
mips_emit_srl(reg_temp, reg_a2, 24); \
|
||||
mips_emit_sll(reg_temp, reg_temp, 31); \
|
||||
mips_emit_bgezal(reg_temp, \
|
||||
mips_relative_offset(translation_ptr, spaccess_trampoline)); \
|
||||
/* Delay slot, will be overwritten anyway */ \
|
||||
mips_emit_lui(reg_a0, ((u32)(iwram + 0x8000 + 0x8000) >> 16)); \
|
||||
mips_emit_addu(reg_a1, reg_a1, reg_a0); \
|
||||
offset = (u32)(iwram + 0x8000) & 0xFFFF; \
|
||||
|
@ -2050,6 +2068,7 @@ static void emit_mem_access_loadop(
|
|||
#endif
|
||||
|
||||
#define SMC_WRITE_OFF (10*16*4) /* 10 handlers (16 insts) */
|
||||
#define EWRAM_SPM_OFF (SMC_WRITE_OFF + 4*2) /* Just a jmp + nop */
|
||||
|
||||
// Describes a "plain" memory are, that is, an area that is just accessed
|
||||
// as normal memory (with some caveats tho).
|
||||
|
@ -2682,6 +2701,12 @@ void init_emitter() {
|
|||
mips_emit_j(((u32)&smc_write) >> 2);
|
||||
mips_emit_nop();
|
||||
|
||||
// Special trampoline for SP-relative ldm/stm (to EWRAM)
|
||||
generate_load_imm(reg_a1, 0x3FFFC);
|
||||
mips_emit_and(reg_a1, reg_a1, reg_a2);
|
||||
mips_emit_lui(reg_a0, ((u32)(ewram + 0x8000) >> 16));
|
||||
generate_function_return_swap_delay();
|
||||
|
||||
// Generate the openload handlers (for accesses to unmapped mem)
|
||||
emit_openload_stub(0, false, 0, &translation_ptr); // ld u8
|
||||
emit_openload_stub(1, true, 0, &translation_ptr); // ld s8
|
||||
|
|
|
@ -554,6 +554,8 @@ defsymbl(execute_arm_translate_internal)
|
|||
.bss
|
||||
.align 6
|
||||
|
||||
# Ensure iwram+0x8000 and ewram addresses have identical 31..16 bits
|
||||
# We place them at 128KB offset to ensure so.
|
||||
defsymbl(iwram)
|
||||
.space 0x10000
|
||||
defsymbl(vram)
|
||||
|
|
Loading…
Add table
Reference in a new issue