Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
402 changes: 402 additions & 0 deletions config/regpromote/4D53006E.json

Large diffs are not rendered by default.

6 changes: 6 additions & 0 deletions config/seeds/4D53006E.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
[
{
"start": "0x0019D240",
"note": "Post-race \"Updating Scoreboards\" state callback, reached only through this+0x1C of the race-end state machine at 0x00096C30; refused as an unresolved call target until lifted (forza1-source/src/fz_missing.c translates it by hand meanwhile)."
}
]
10 changes: 10 additions & 0 deletions scripts/recompile.py
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,8 @@ def build_commands(args, xbe: Path, analysis_json: Path):
lift += ["--game-name", args.game_name]
if args.trace_all_entries:
lift.append("--trace-all-entries")
if getattr(args, "regpromote_file", None):
lift += ["--regpromote", str(args.regpromote_file)]
# XDK functions with a name-keyed replacement (tools/recomp/hle.py), used
# whenever tools.xdk_symbols has been run for this XBE.
hle_symbols = xbe.with_name(xbe.stem + "_xdk_symbols.json")
Expand Down Expand Up @@ -330,6 +332,14 @@ def main() -> int:
args.data_sections = [e["pattern"] for e in entries]
print(f"data sections: {', '.join(args.data_sections)} ({sec_file.name})")

# Functions whose guest registers are kept in C locals
# (tools/recomp/regpromote.py): the title's profile's hottest, per title.
args.regpromote_file = None
rp_file = config_file(args, "regpromote", title or "")
if title and rp_file.is_file():
args.regpromote_file = rp_file
print(f"register promotion: {rp_file.name}")

if not args.dry_run and not xbe.is_file():
print(f"error: XBE not found: {xbe}", file=sys.stderr)
return 1
Expand Down
4 changes: 4 additions & 0 deletions src/apu/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -73,3 +73,7 @@ else()
# Linux: platform layer (Win32 primitives on POSIX) + SDL3 audio + libm
target_link_libraries(xbox_apu PRIVATE platform SDL3::SDL3 m)
endif()
if(WIN32)
add_compile_definitions(_USE_MATH_DEFINES)
endif()

2 changes: 1 addition & 1 deletion src/apu/apu_fault.c
Original file line number Diff line number Diff line change
Expand Up @@ -92,8 +92,8 @@ static void say_undecoded(const char *what, recomp_fault *f, uint32_t va)
fprintf(stderr, "[%s] undecoded access at 0x%08X, host insn %s\n", what, va, insn);
fflush(stderr);
}
#endif

#endif
/* ---- the three range handlers -------------------------------------------- */

static int pcrtc_fault(recomp_fault *f, uint32_t va)
Expand Down
19 changes: 18 additions & 1 deletion src/apu/apu_mmio_hook.c
Original file line number Diff line number Diff line change
Expand Up @@ -422,8 +422,25 @@ int nv2a_intr_handle_write(PCONTEXT ctx, uintptr_t host_addr,
uint64_t written;
int size;

if (!mmio_decode_write_value(ctx, &written, &size))
const uint8_t *ip = (const uint8_t *)ctx->Rip;
if (ip[0] == 0x83 && ((ip[1] >> 3) & 7) == 1 && (ip[1] >> 6) != 3) {
int modrm_len = decode_modrm_len(ip + 1, 0);
uint32_t imm = (uint32_t)(int32_t)(int8_t)ip[1 + modrm_len];
uint32_t result = *(const volatile uint32_t *)host_addr | imm;
uint8_t parity = (uint8_t)result;
parity ^= parity >> 4;
parity ^= parity >> 2;
parity ^= parity >> 1;
ctx->EFlags = (ctx->EFlags & ~0x8C5u) |
((result & 0x80000000u) ? 0x80u : 0) |
(result == 0 ? 0x40u : 0) |
((parity & 1) == 0 ? 0x4u : 0);
ctx->Rip += 2 + modrm_len;
written = result;
size = 4;
} else if (!mmio_decode_write_value(ctx, &written, &size)) {
return 0;
}

if (nv2a_offset == NV2A_PCRTC_INTR_0_OFF) {
uint32_t remaining = *pcrtc & ~(uint32_t)written;
Expand Down
6 changes: 6 additions & 0 deletions src/d3d/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -146,4 +146,10 @@ else()
# -Wno-missing-field-initializers: Vulkan's `{ VK_STRUCTURE_TYPE_... }` idiom.
target_compile_options(xbox_d3d8 PRIVATE -Wall -Wextra -Wno-unused-parameter
-Wno-missing-field-initializers -O2)
if(WIN32)
# The clang driver on Windows: CodeView debug info, so the PDB the
# title links (/DEBUG) names static functions in a sampled profile
# too, as /Zi does for MSVC. No effect on the generated code.
target_compile_options(xbox_d3d8 PRIVATE -g -gcodeview)
endif()
endif()
19 changes: 14 additions & 5 deletions src/d3d/d3d8_clear.c
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ static struct {
int tried, failed;
RhiShader *vs, *ps;
RhiBuffer *cb;
RhiBlendState *blend[2]; /* [writes colour] */
RhiBlendState *blend[16]; /* [RHI_WRITE_* mask], made when first asked */
RhiDepthState *depth[4]; /* [writes depth | writes stencil << 1] */
RhiRasterState *raster;
} g;
Expand Down Expand Up @@ -99,9 +99,9 @@ static int create(void)
bd.cpu_access = RHI_CPU_WRITE;
if (!(g.cb = rhi_buffer_create(&bd, NULL))) { fail("CreateBuffer"); return 0; }

for (i = 0; i < 2; i++) {
for (i = 0; i < 16; i += 15) {
memset(&bl, 0, sizeof bl);
bl.write_mask = i ? RHI_WRITE_ALL : 0;
bl.write_mask = (uint32_t)i;
if (!(g.blend[i] = rhi_blend_state_create(&bl))) { fail("CreateBlendState"); return 0; }
}
for (i = 0; i < 4; i++) {
Expand Down Expand Up @@ -131,13 +131,14 @@ static int create(void)
}

int d3d8_clear_rects(RhiView *rtv, RhiView *dsv, UINT width, UINT height,
const RhiRect *rects, UINT count, int color, int depth, int stencil,
const RhiRect *rects, UINT count, int color_mask, int depth, int stencil,
const float rgba[4], float z, uint8_t stencil_value)
{
RhiOutputState saved;
RhiViewport vp;
float blend_factor[4] = { 1, 1, 1, 1 };
UINT i;
int color = color_mask & RHI_WRITE_ALL;

if (!width || !height || (!color && !depth && !stencil))
return 0;
Expand Down Expand Up @@ -167,7 +168,15 @@ int d3d8_clear_rects(RhiView *rtv, RhiView *dsv, UINT width, UINT height,
rhi_set_shader(RHI_STAGE_PIXEL, g.ps);
rhi_set_uniform_buffers(RHI_STAGE_VERTEX, 7, 1, &g.cb);
rhi_set_uniform_buffers(RHI_STAGE_PIXEL, 7, 1, &g.cb);
rhi_set_blend_state(g.blend[color ? 1 : 0], blend_factor, 0xFFFFFFFF);
if (!g.blend[color]) {
RhiBlendDesc bl;
memset(&bl, 0, sizeof bl);
bl.write_mask = (uint32_t)color;
g.blend[color] = rhi_blend_state_create(&bl);
if (!g.blend[color])
color = RHI_WRITE_ALL; /* the whole colour, as before */
}
rhi_set_blend_state(g.blend[color], blend_factor, 0xFFFFFFFF);
rhi_set_depth_state(g.depth[(depth ? 1 : 0) | (stencil ? 2 : 0)], stencil_value);
rhi_set_raster_state(g.raster);

Expand Down
Loading