widescreen: generalize Capcom 2D background hooks for MMX5

This commit is contained in:
Matthew Stanley
2026-07-10 00:17:17 -07:00
parent db4016b685
commit d9dae48c8e
9 changed files with 213 additions and 65 deletions
+32 -13
View File
@@ -838,6 +838,20 @@ std::string CodeGenerator::translate_instruction(uint32_t addr, uint32_t instr)
}
// overlay variant: addr is different code here — fall through to vanilla.
}
if (config_.ws_cull_screen_x_sites.count(addr)) {
if (opcode == 0x0B) { // sltiu rt,rs,imm
uint32_t rs = get_rs(instr), rt = get_rt(instr);
uint16_t imm = get_imm16_u(instr);
return fmt::format("{} = psx_ws_cull_sltiu({}, {});"
" /* ws explicit screen-x cull */{}",
reg_name(rt), reg_name(rs), imm, comment);
} else if (!config_.overlay_mode) {
fmt::print(stderr, "ERROR: [widescreen.cull] screen_x site 0x{:08X} "
"is not sltiu (opcode 0x{:02X})\n", addr, opcode);
std::exit(1);
}
// Overlay variant: the configured main-EXE PC holds different code.
}
// Widescreen automatic horizontal-FOV cull widening ([widescreen.cull]
// auto_screen_x). ws_auto_cull_func_ is set when this function carries the
// GTE screen-extent reject signature, so a per-vertex width compare here is
@@ -884,7 +898,7 @@ std::string CodeGenerator::translate_instruction(uint32_t addr, uint32_t instr)
// overlay variant: addr is different code here — fall through to vanilla.
}
// Widescreen pure-2D background tile-loop widen ([widescreen.bg2d]). MMX6's
// Widescreen pure-2D background tile-loop widen ([widescreen.bg2d]). The
// per-layer BG renderer draws `count` 16px tile columns from a start column /
// start screen-x derived from the camera scroll. Rewrite those three values
// (via the gpu.c psx_ws_mmx6_bg_* helpers — identity at 4:3 / 512 hi-res) so
@@ -894,11 +908,16 @@ std::string CodeGenerator::translate_instruction(uint32_t addr, uint32_t instr)
if (opcode == 0x09 || opcode == 0x0D) { // addiu / ori (li rt,imm)
uint32_t rt = get_rt(instr);
uint16_t imm = get_imm16_u(instr);
return fmt::format("{} = (uint32_t)psx_ws_mmx6_bg_cols({});{}",
return fmt::format("{} = (uint32_t)psx_ws_bg2d_cols({});{}",
reg_name(rt), (int)imm, comment);
} else if (opcode == 0x0B) { // sltiu rt,rs,imm (loop bound compare)
uint32_t rs = get_rs(instr), rt = get_rt(instr);
uint16_t imm = get_imm16_u(instr);
return fmt::format("{} = ({} < (uint32_t)psx_ws_bg2d_cols({})) ? 1u : 0u;{}",
reg_name(rt), reg_name(rs), (int)imm, comment);
} else if (!config_.overlay_mode) {
fmt::print(stderr, "ERROR: [widescreen.bg2d] count_site 0x{:08X} is not "
"addiu/ori (opcode 0x{:02X})\n", addr, opcode);
"addiu/ori/sltiu (opcode 0x{:02X})\n", addr, opcode);
std::exit(1);
}
}
@@ -906,8 +925,8 @@ std::string CodeGenerator::translate_instruction(uint32_t addr, uint32_t instr)
if (opcode == 0x0C) { // andi rt,rs,imm (start tile-column mask)
uint32_t rs = get_rs(instr), rt = get_rt(instr);
uint16_t imm = get_imm16_u(instr);
return fmt::format("{} = (uint32_t)psx_ws_mmx6_bg_startcol((int)({} & 0x{:X}u));{}",
reg_name(rt), reg_name(rs), imm, comment);
return fmt::format("{} = (uint32_t)psx_ws_bg2d_startcol((int)({} & 0x{:X}u), 0x{:X}u);{}",
reg_name(rt), reg_name(rs), imm, imm, comment);
} else if (!config_.overlay_mode) {
fmt::print(stderr, "ERROR: [widescreen.bg2d] startcol_site 0x{:08X} is not "
"andi (opcode 0x{:02X})\n", addr, opcode);
@@ -917,7 +936,7 @@ std::string CodeGenerator::translate_instruction(uint32_t addr, uint32_t instr)
if (config_.ws_bg2d_startx_site && addr == config_.ws_bg2d_startx_site) {
if (opcode == 0x00 && (instr & 0x3F) == 0x03) { // sra rd,rt,sa (start screen-x)
uint32_t rt = get_rt(instr), rd = get_rd(instr), sh = get_shamt(instr);
return fmt::format("{} = (uint32_t)psx_ws_mmx6_bg_startx((int32_t){} >> {});{}",
return fmt::format("{} = (uint32_t)psx_ws_bg2d_startx((int32_t){} >> {});{}",
reg_name(rd), reg_name(rt), sh, comment);
} else if (!config_.overlay_mode) {
fmt::print(stderr, "ERROR: [widescreen.bg2d] startx_site 0x{:08X} is not "
@@ -932,7 +951,7 @@ std::string CodeGenerator::translate_instruction(uint32_t addr, uint32_t instr)
if (opcode == 0x08 || opcode == 0x09) { // addi / addiu
uint32_t rs = get_rs(instr), rt = get_rt(instr);
int16_t imm = get_imm16(instr);
return fmt::format("{} = (uint32_t)psx_ws_mmx6_bg_stream_left((int32_t){} + ({}));{}",
return fmt::format("{} = (uint32_t)psx_ws_bg2d_stream_left((int32_t){} + ({}));{}",
reg_name(rt), reg_name(rs), imm, comment);
} else if (!config_.overlay_mode) {
fmt::print(stderr, "ERROR: [widescreen.bg2d] stream_left_site 0x{:08X} is not "
@@ -944,7 +963,7 @@ std::string CodeGenerator::translate_instruction(uint32_t addr, uint32_t instr)
if (opcode == 0x08 || opcode == 0x09) { // addi / addiu
uint32_t rs = get_rs(instr), rt = get_rt(instr);
int16_t imm = get_imm16(instr);
return fmt::format("{} = (uint32_t)psx_ws_mmx6_bg_stream_right((int32_t){} + ({}));{}",
return fmt::format("{} = (uint32_t)psx_ws_bg2d_stream_right((int32_t){} + ({}));{}",
reg_name(rt), reg_name(rs), imm, comment);
} else if (!config_.overlay_mode) {
fmt::print(stderr, "ERROR: [widescreen.bg2d] stream_right_site 0x{:08X} is not "
@@ -2498,11 +2517,11 @@ std::string CodeGenerator::generate_file(
ss << "extern int psx_ws_x_margin(void); /* widescreen cull-margin term (gpu.c) */\n";
ss << "extern int psx_ws_cull_sltiu(uint32_t sx, uint32_t imm); /* ws auto screen-x cull (gpu.c) */\n";
ss << "extern int psx_ws_backdrop_x(int x); /* widescreen backdrop screenX squash (gpu.c) */\n";
ss << "extern int psx_ws_mmx6_bg_cols(int base); /* ws 2D bg tile-loop widen: col count (gpu.c) */\n";
ss << "extern int psx_ws_mmx6_bg_startcol(int col); /* ws 2D bg tile-loop widen: start tile col (gpu.c) */\n";
ss << "extern int psx_ws_mmx6_bg_startx(int x); /* ws 2D bg tile-loop widen: start screen-x (gpu.c) */\n";
ss << "extern int psx_ws_mmx6_bg_stream_left(int x); /* ws 2D bg tile-ring streamer: left edge (gpu.c) */\n";
ss << "extern int psx_ws_mmx6_bg_stream_right(int x); /* ws 2D bg tile-ring streamer: right edge (gpu.c) */\n";
ss << "extern int psx_ws_bg2d_cols(int base); /* ws 2D bg tile-loop widen: col count (gpu.c) */\n";
ss << "extern int psx_ws_bg2d_startcol(int col, unsigned mask); /* ws 2D bg tile-loop widen: start tile col (gpu.c) */\n";
ss << "extern int psx_ws_bg2d_startx(int x); /* ws 2D bg tile-loop widen: start screen-x (gpu.c) */\n";
ss << "extern int psx_ws_bg2d_stream_left(int x); /* ws 2D bg tile-ring streamer: left edge (gpu.c) */\n";
ss << "extern int psx_ws_bg2d_stream_right(int x); /* ws 2D bg tile-ring streamer: right edge (gpu.c) */\n";
ss << "extern int psx_ws_mmx6_bg_bufbase(int addr); /* ws 2D bg packet-buffer relocation (gpu.c) */\n";
ss << "extern int psx_ws_mmx6_bg_undercap(int counter);/* ws 2D bg per-frame tile cap (gpu.c) */\n";
ss << "extern int psx_game_option_store(uint32_t addr, int val); /* persisted OPTION restore-at-init (game_options.c) */\n";