Files
TeslaRel410/emulator/vpx-device/emu8k_shim.h
T
CydandClaude Fable 5 72da9b2f14 Emulator: parity-safe EMU8000 sample counter -- AWEUTIL runs; wire the
VGL_LABS cockpit test suite as pod-launch 'test' mode

The WC hang, root-caused in three layers (each necessary):
1. WC was rendered-samples + 100ms-capped interpolation; AWEUTIL's poll
   storm (~550k port-ops/s) starved the render thread of awe_lock, so the
   clock crawled ~90x slow. Fixed: free-running host-clock derivation +
   a fairness gate so the render thread can always take the lock.
2. Free-running at true 44.1kHz still failed: trapped port reads cost
   ~30us -- MORE than one 22.7us tick -- so consecutive reads skipped
   counter values, and AWEUTIL's WaitUntilWC (decoded at COM offset
   0x5F42) exits only on EQUALITY with a target tick: skipped value =
   missed target = 1.49s wrap penalty, or forever.
3. Advancing +1 per read still failed: WaitUntilWC reads WC TWICE per
   iteration, so its equality sample saw only every 2nd value -- wrong
   parity = infinite loop. Final semantics: during a poll storm the
   counter advances once per FOUR reads (every value observable by all
   of AWEUTIL's loop shapes; its 8192-unchanged-reads dead-clock bailout
   never trips), and resyncs to true wall time after any 50ms idle gap.
   Result: the full stock TEST.BAT (DIAGNOSE + AWEUTIL /S on both cards)
   completes in seconds.

Also: pod-launch 'test' mode -> vwetest.conf (stock TEST.BAT -> TSTALL),
DOSBox window defaults to 900,600 in test mode (the DOS screen is the
suite's UI), VWE_AWE_LOG gains storm bursts with guest cs:ip + caller and
rare-read tracing (the instrumentation that cracked this).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-16 23:51:52 -05:00

51 lines
2.2 KiB
C

/* Minimal 86Box environment shim for the vendored EMU8000 core (emu8k.cpp).
* Supplies exactly what snd_emu8k.c pulled from 86Box headers:
* - io_sethandler/io_removehandler (implemented in vweawe.cpp on top of
* DOSBox-X IO_Register*Handler, with the 86Box handler signatures)
* - wavetable_pos_global (the render-target sample clock; vweawe.cpp sets
* it per mixer block instead of 86Box's per-frame sound clock)
* - pclog/pclog_ex/fatal logging and the UNUSED() parameter marker
* - emu8k_shim_rom_fopen(): optional AWE32 GM ROM via $VWE_AWE_ROM
*/
#ifndef VWE_EMU8K_SHIM_H
#define VWE_EMU8K_SHIM_H
#include <stdarg.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
/* 86Box io.h handler signatures (priv-pointer style) */
typedef uint8_t (*emu8k_io_inb_t)(uint16_t addr, void *priv);
typedef uint16_t (*emu8k_io_inw_t)(uint16_t addr, void *priv);
typedef uint32_t (*emu8k_io_inl_t)(uint16_t addr, void *priv);
typedef void (*emu8k_io_outb_t)(uint16_t addr, uint8_t val, void *priv);
typedef void (*emu8k_io_outw_t)(uint16_t addr, uint16_t val, void *priv);
typedef void (*emu8k_io_outl_t)(uint16_t addr, uint32_t val, void *priv);
void io_sethandler(uint16_t base, int size,
emu8k_io_inb_t inb, emu8k_io_inw_t inw, emu8k_io_inl_t inl,
emu8k_io_outb_t outb, emu8k_io_outw_t outw,
emu8k_io_outl_t outl, void *priv);
void io_removehandler(uint16_t base, int size,
emu8k_io_inb_t inb, emu8k_io_inw_t inw,
emu8k_io_inl_t inl, emu8k_io_outb_t outb,
emu8k_io_outw_t outw, emu8k_io_outl_t outl, void *priv);
/* render-target sample position for emu8k_update() (86Box sound.h) */
extern int wavetable_pos_global;
FILE *emu8k_shim_rom_fopen(void);
/* the WC sample counter readback: free-running 44100Hz off the host clock,
* exactly like the silicon (guest software busy-waits on it; deriving it
* from render progress made those waits crawl under lock contention) */
uint16_t emu8k_shim_wc_read(void);
#define pclog(...) fprintf(stderr, __VA_ARGS__)
#define pclog_ex(fmt, ap) vfprintf(stderr, fmt, ap)
#define fatal(...) fprintf(stderr, __VA_ARGS__)
#define UNUSED(arg) arg
#endif