Skip to content
Merged
Show file tree
Hide file tree
Changes from 11 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
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -61,3 +61,7 @@ test/lldb_*.py
/test/tools/test_blitter_compare
/test/tools/test_screenshot
test/tools/build/

# Acid-test build outputs
test/acid/acid_run
test/acid/tests/**/*.jag
14 changes: 13 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -857,7 +857,7 @@ test/tools/test_memory_map: test/tools/test_memory_map.c
-o $@ test/tools/test_memory_map.c -ldl
endif

.PHONY: clean test lint coverage benchmark
.PHONY: clean test lint coverage benchmark acid
endif

lint:
Expand Down Expand Up @@ -905,6 +905,18 @@ benchmark:
--warmup $(BENCH_WARMUP) --blitter $(BENCH_BLITTER) \
$(if $(BENCH_STATE),--load-state "$(BENCH_STATE)")

# `make acid` -- builds the core and runs the synthetic acid-test ROMs
# (see test/acid/README.md). Requires the vasm 68K assembler on $PATH;
# if absent, the assemble step is skipped and only the runner harness
# is built (so CI can still validate the harness compiles).
#
# Forces a BENCH_PROFILE=1 + TEST_EXPORTS=1 build of the core so the
# acid runner can dlsym `perf_counters_find` and report a per-test
# delta (halflines, vblank IRQs, blits, inner-loop iters, ...).
acid:
$(MAKE) BENCH_PROFILE=1 TEST_EXPORTS=1 -j$(shell getconf _NPROCESSORS_ONLN 2>/dev/null || echo 4)
$(MAKE) -C test/acid test CORE=$(abspath $(TARGET))

print-%:
@echo '$*=$($*)'

32 changes: 32 additions & 0 deletions docs/emulation-bug-hunt-todos.md
Original file line number Diff line number Diff line change
Expand Up @@ -456,3 +456,35 @@ shipping v2.2.0; capture them so they don't get lost.
/ `const`-correctness audits as a CI step. `clang-tidy` and
`cppcheck` would be good starting points; the codebase already
has a C89 lint, so the infrastructure is there.

## Original `docs/TODO` items still relevant (Shamus / CJ)

The historical `docs/TODO` from the upstream Virtual Jaguar tree
lists several still-open accuracy / feature items. These map onto
the acid-test categories in `test/acid/README.md`; tracking here so
they don't get lost:

- **"Fix VC behavior to match what a real Jaguar does. Still not
sure just what the heck is going on there." [Shamus]** —
acid `timing/`. Active suspect for the Doom 1.5-2x speed
regression (issue #131).
- **"Cycle accuracy for GPU/DSP/OP/Blitter." [Shamus]** —
cross-cutting; informs every category in `test/acid/`, especially
`bus/` (which can't pass without it).
- **"Need to propagate blitter fixes in the A1 <- A2 direction
to the A1 -> A2 direction and the GPU fixes to various
instructions to the DSP." [Shamus]** — acid `blitter/` (A1↔A2
symmetry tests) and `gpu/` + `dsp/` (shared opcode coverage).
- **"Blitter needs fixing." [Shamus]** — acid `blitter/`.
PR #129 fixed a perf-relevant chunk (`ADDARRAY` etc); accuracy
axis still wide open.
- **"Need to emulate bus contention." [Shamus]** — acid `bus/`.
Almost certainly load-bearing for the Doom regression and the
AvP audio dropouts.
- **"Need to fix timing in the OP. As it is now, it gives a false
impression of how much it's capable of." [Shamus]** —
acid `op/`.

The original `docs/TODO` is intentionally left untouched — it's
the authors' historical record and we track our own work via
GitHub issues + this file + `test/acid/`.
18 changes: 17 additions & 1 deletion src/core/jaguar.c
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
#include "jaguar.h"

#include "cdrom.h"
#include "perf_counters.h"
#include "dac.h"
#include "dsp.h"
#include "eeprom.h"
Expand All @@ -33,6 +34,16 @@

static bool frameDone;

/* Frame-pacing instrumentation (no-op unless built with BENCH_PROFILE).
* Lets the acid runner / benchmark detect timing regressions like the
* Doom 2x speed bug -- e.g. expected 525 halflines/frame NTSC, 60 vblank
* IRQs/sec. See test/acid/README.md and src/core/perf_counters.h.
* Counters that fire from other TUs are declared at their use sites
* (PERF_COUNTER backs each name with a file-scope static). */
PERF_COUNTER(timing_halfline_callbacks);
PERF_COUNTER(timing_vblank_irqs);
PERF_COUNTER(timing_jaguar_execute_calls);

// Platform-independent xorshift32 PRNG for deterministic RAM initialization.
// libc rand() produces different sequences on different platforms (glibc vs
// macOS libsystem), which causes cross-platform baseline mismatches.
Expand Down Expand Up @@ -694,7 +705,8 @@ void JaguarInit(void)
// Half line times are, naturally, half of this. :-P
void HalflineCallback(void)
{
uint16_t vc = TOMReadWord(0xF00006, JAGUAR);
uint16_t vc = (PERF_INC(timing_halfline_callbacks),
TOMReadWord(0xF00006, JAGUAR));
uint16_t vp = TOMReadWord(0xF0003E, JAGUAR) + 1;
uint16_t vi = TOMReadWord(0xF0004E, JAGUAR);

Expand All @@ -712,7 +724,10 @@ void HalflineCallback(void)

// Time for Vertical Interrupt?
if ((vc & 0x7FF) == vi && (vc & 0x7FF) > 0)
{
PERF_INC(timing_vblank_irqs);
TOMSetPendingVideoInt();
}

TOMExecHalfline(vc, true);

Expand Down Expand Up @@ -934,6 +949,7 @@ uint8_t * GetRamPtr(void)
* so the DSP runs alongside the 68K and GPU, matching real hardware timing. */
void JaguarExecuteNew(void)
{
PERF_INC(timing_jaguar_execute_calls);
frameDone = false;

do
Expand Down
5 changes: 5 additions & 0 deletions src/jerry/jerry.c
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,9 @@
#include "eeprom.h"
#include "event.h"
#include "jaguar.h"
#include "perf_counters.h"

PERF_COUNTER(timing_jerry_irqs);
#include "joystick.h"
#include "m68000/m68kinterface.h"
#include "memtrack.h"
Expand Down Expand Up @@ -250,6 +253,7 @@ void JERRYPIT1Callback(void)
// Not sure, but I think we don't generate another IRQ if one's already going...
// But this seems to work... :-/
jerryPendingInterrupt |= IRQ2_TIMER1;
PERF_INC(timing_jerry_irqs);
m68k_set_irq(2); // Generate 68K IPL 2
}
}
Expand All @@ -266,6 +270,7 @@ void JERRYPIT2Callback(void)
if (jerryInterruptMask & IRQ2_TIMER2) // CPU Timer 2 IRQ
{
jerryPendingInterrupt |= IRQ2_TIMER2;
PERF_INC(timing_jerry_irqs);
m68k_set_irq(2); // Generate 68K IPL 2
}
}
Expand Down
9 changes: 9 additions & 0 deletions src/tom/tom.c
Original file line number Diff line number Diff line change
Expand Up @@ -262,8 +262,11 @@
#include "jaguar.h"
#include "m68000/m68kinterface.h"
#include "op.h"
#include "perf_counters.h"
#include "settings.h"

PERF_COUNTER(timing_gpu_irqs_to_68k);

// Red Color Values for CrY<->RGB Color Conversion
uint8_t redcv[16][16] = {
// 0 1 2 3 4 5 6 7 8 9 A B C D E F
Expand Down Expand Up @@ -1316,7 +1319,10 @@ void TOMExecPIT(uint32_t cycles)
GPUSetIRQLine(GPUIRQ_TIMER, ASSERT_LINE); // GPUSetIRQLine does the 'IRQ enabled' checking

if (TOMIRQEnabled(IRQ_TIMER))
{
PERF_INC(timing_gpu_irqs_to_68k);
m68k_set_irq(2); // Cause a 68000 IPL 2...
}

TOMResetPIT();
}
Expand All @@ -1329,7 +1335,10 @@ void TOMPITCallback(void)
GPUSetIRQLine(GPUIRQ_TIMER, ASSERT_LINE); // It does the 'IRQ enabled' checking

if (TOMIRQEnabled(IRQ_TIMER))
{
PERF_INC(timing_gpu_irqs_to_68k);
m68k_set_irq(2); // Generate a 68K IPL 2...
}

TOMResetPIT();
}
Expand Down
Loading
Loading