From 93b1f85be5cd652beb4004f31469974514f79aa6 Mon Sep 17 00:00:00 2001 From: Raphael Amorim Date: Fri, 5 Jun 2026 09:24:45 +0200 Subject: [PATCH] drop unicode chars --- cdrom.jam | 16 ++++++++-------- cpu.jam | 18 +++++++++--------- cue.jam | 16 ++++++++-------- disc.jam | 10 +++++----- dma.jam | 18 +++++++++--------- gpu.jam | 20 ++++++++++---------- gte.jam | 34 +++++++++++++++++----------------- main.jam | 12 ++++++------ mcd.jam | 12 ++++++------ mdec.jam | 14 +++++++------- sdl.jam | 6 +++--- sio1.jam | 2 +- spu.jam | 16 ++++++++-------- tests.jam | 50 +++++++++++++++++++++++++------------------------- 14 files changed, 122 insertions(+), 122 deletions(-) diff --git a/cdrom.jam b/cdrom.jam index b8a7ab7..c99a296 100644 --- a/cdrom.jam +++ b/cdrom.jam @@ -11,7 +11,7 @@ // bank read 0x800 status (busy/parm-empty/resp-empty/...) // bank read 0x801 pop one byte from the response FIFO // bank read 0x802 pop one byte from the data FIFO (sector buffer) -// bank read 0x803 index 0/2 → IER, index 1/3 → IFR | 0xE0 +// bank read 0x803 index 0/2 -> IER, index 1/3 -> IFR | 0xE0 // // bank 0 write 0x801 command byte (triggers state machine) // bank 0 write 0x802 push parameter byte @@ -148,7 +148,7 @@ pub const Cdrom = struct { xaLh: [2]i32, xaRh: [2]i32, // Last resampled OUTPUT sample per channel — the `ls` seed for the next - // sector's XA→44.1kHz rate conversion. + // sector's XA->44.1kHz rate conversion. xaPrevL: i32, xaPrevR: i32, // Parameter / response FIFOs. Each is a 32-byte ring with u8 @@ -369,8 +369,8 @@ pub const Cdrom = struct { self.busy = 0; // Response-1 prechecks, before dispatch: - // (1) disc-required commands with no disc → INT5(11h,80h), - // (3) wrong parameter count → INT5(03h,20h), unknown command → + // (1) disc-required commands with no disc -> INT5(11h,80h), + // (3) wrong parameter count -> INT5(03h,20h), unknown command -> // INT5(03h,40h). (Version checks are omitted — jam models a // single CD-ROM revision.) `pcnt` = parameters queued for this cmd. const pcnt: u32 = ((self.paramW as u32) - (self.paramR as u32)) & 0xFF; @@ -447,7 +447,7 @@ pub const Cdrom = struct { const f: u32 = self.popParam(); // Validate the MSF before accepting: // BCD-valid nibbles, seconds < 0x60, frame < 0x75. Invalid - // MSF → INT5(stat, 0x10) instead of an INT3 success. + // MSF -> INT5(stat, 0x10) instead of an INT3 success. const bcdOk: bool = ((m & 0x0F) <= 9) && ((m >> 4) <= 9) && ((s & 0x0F) <= 9) && ((s >> 4) <= 9) && ((f & 0x0F) <= 9) && ((f >> 4) <= 9); @@ -612,7 +612,7 @@ pub const Cdrom = struct { self.errorOut(CD_STAT_SPINDLE, CD_ERR_INVALID_SUBFUNC); return; } - // GetTD: look up the track's absolute LBA → + // GetTD: look up the track's absolute LBA -> // MM:SS; INT5 if past the last track (TS_FAR = 0xFFFFFFFF here). const track: u32 = (bcd & 0x0F) + ((bcd >> 4) & 0x0F) * 10; const f: u32 = discTrackLba(disc, track); @@ -723,7 +723,7 @@ pub const Cdrom = struct { } if (cmd == CDL_SEEKL) { // Query the seek TARGET (pendingLba) - // FIRST; TS_FAR → INVALID_SUBFUNC, TS_AUDIO → SEEK_FAILED, and + // FIRST; TS_FAR -> INVALID_SUBFUNC, TS_AUDIO -> SEEK_FAILED, and // the seek is NOT committed on error. On success commit and // set seek precision = 1. const tsl: u32 = discQuery(disc, self.pendingLba); @@ -980,7 +980,7 @@ pub const Cdrom = struct { // f18khz sector) to the SPU's 44100 Hz output rate before pushing. The // SPU CD FIFO is drained one entry per 44100 Hz output sample, so // pushing native-rate samples 1:1 plays XA ~17% too fast and overruns - // the FIFO (most samples dropped → warble). The resampler is + // the FIFO (most samples dropped -> warble). The resampler is // conceptually a 7×-upsample — // whose `(k+1)/8` integer-divides to 0, making it a sample-and-hold of // the previous source sample — then decimate by m=f18khz?3:6, yielding diff --git a/cpu.jam b/cpu.jam index 190e67c..421a49d 100644 --- a/cpu.jam +++ b/cpu.jam @@ -376,7 +376,7 @@ pub fn iRegimm(c: mut Cpu, opc: u32, regs: *mut[] u32) { } // REGIMM default: branch type is decided by bit 16 - // (= rt & 1). Even-numbered rt → BLTZ semantics, odd → BGEZ. + // (= rt & 1). Even-numbered rt -> BLTZ semantics, odd -> BGEZ. // (An earlier version only matched 0x00/0x10 for BLTZ and treated // 0x02 / 0x12 as BGEZ, which was wrong.) var take: bool = false; @@ -650,8 +650,8 @@ pub fn iMtlo(c: mut Cpu, opc: u32, regs: *mut[] u32) { c.lo = s; } -// MULT — signed 32×32 → 64. Sign-flip the operands to positive, do an -// unsigned 32×32 → 64 with Jam's native u64, then sign-flip the result. +// MULT — signed 32×32 -> 64. Sign-flip the operands to positive, do an +// unsigned 32×32 -> 64 with Jam's native u64, then sign-flip the result. pub fn umul64(a: u32, b: u32) u64 { return (a as u64) * (b as u64); } @@ -839,10 +839,10 @@ pub fn iRfe(c: mut Cpu, regs: *mut[] u32, cop0: *mut[] u32) { // register-move; otherwise it's a math operation whose body lives in // `gteExec`. // -// rs = 0x00 MFC2 data register → CPU register (delayed load) -// rs = 0x02 CFC2 control register → CPU register (delayed load) -// rs = 0x04 MTC2 CPU register → data register -// rs = 0x06 CTC2 CPU register → control register +// rs = 0x00 MFC2 data register -> CPU register (delayed load) +// rs = 0x02 CFC2 control register -> CPU register (delayed load) +// rs = 0x04 MTC2 CPU register -> data register +// rs = 0x06 CTC2 CPU register -> control register // rs >= 0x10 COP2 imm — math op (RTPS, NCLIP, NCDS, ...) pub fn iCop2Unimpl(c: mut Cpu, opc: u32, bus: Bus, regs: *mut[] u32, cop0: *mut[] u32) { @@ -960,7 +960,7 @@ pub fn dispatchSpecial(c: mut Cpu, opc: u32, bus: Bus, pub fn dispatchCop0(c: mut Cpu, opc: u32, regs: *mut[] u32, cop0: *mut[] u32) { // Dispatch purely on rs (the CO/CT/MFC/MTC selector); the // R3000 fn field is ignored for RFE since TLB ops don't exist on - // PSX. rs=0x10 → RFE regardless of fn. + // PSX. rs=0x10 -> RFE regardless of fn. const rs: u32 = opRs(opc); if (rs == 0x00) { iMfc0(c, opc, regs, cop0); return; } if (rs == 0x04) { iMtc0(c, opc, regs, cop0); return; } @@ -999,7 +999,7 @@ pub fn dispatch(c: mut Cpu, opc: u32, bus: Bus, if (p == 0x10) { const sr10: u32 = cop0Read(cop0, C0_SR); if ((sr10 & 0x10000000) == 0 && (sr10 & 0x02) != 0) { - // User mode without CU0 → coprocessor unusable. + // User mode without CU0 -> coprocessor unusable. commitLoad(c, regs); raiseException(c, cop0, CAUSE_CPU); return; diff --git a/cue.jam b/cue.jam index 11a9d51..3b1d2b2 100644 --- a/cue.jam +++ b/cue.jam @@ -61,8 +61,8 @@ pub const CueTrack = struct { pub const Cue = struct { // Vec instead of raw `*mut[] T` so each backing buffer auto-drops - // when the enclosing Box(Cue) is destroyed (Box.drop → @dropInPlace - // → field walk → Vec.drop). Cue's own `cfn drop` is the iterate-and- + // when the enclosing Box(Cue) is destroyed (Box.drop -> @dropInPlace + // -> field walk -> Vec.drop). Cue's own `cfn drop` is the iterate-and- // close-files cleanup that Vec can't synthesize for a File handle. files: Vec(CueFile), tracks: Vec(CueTrack), @@ -208,9 +208,9 @@ pub fn kwId(buf: *mut[] u8) u32 { // Vecs are filled-with-zero so the existing index-based writes by // cueParse (`c.files.ptr[fi].sectors = ...`) land on valid slots — // matches the old memset-after-malloc semantics. When the owning Bus -// goes out of scope, Box(Disc).drop → @dropInPlace → Disc.cuePtr Box -// drop → @dropInPlace on Cue → Cue's cfn drop closes open files → -// Cue's field-walk drops each Vec → libc free. +// goes out of scope, Box(Disc).drop -> @dropInPlace -> Disc.cuePtr Box +// drop -> @dropInPlace on Cue -> Cue's cfn drop closes open files -> +// Cue's field-walk drops each Vec -> libc free. // Close every open per-cue-file handle and zero the counters so the // same Box(Cue) can be repopulated by a fresh cueParse. The Vec backings // stay live — only the user-visible "we have N tracks/files loaded" @@ -507,7 +507,7 @@ pub fn cueParse(raw: *mut[] u8, path: []u8) i32 { return 0; } -// FILE "path" BINARY → push a CueFile, open + size it. +// FILE "path" BINARY -> push a CueFile, open + size it. pub fn cueParseFile(raw: *mut[] u8) { var c: *mut[] Cue = raw as *mut[] Cue; skipWs(raw); @@ -553,7 +553,7 @@ pub fn cueParseFile(raw: *mut[] u8) { // nameBuf auto-drops on function-scope exit. } -// TRACK NN MODE → push a CueTrack tagged with the current file. +// TRACK NN MODE -> push a CueTrack tagged with the current file. pub fn cueParseTrack(raw: *mut[] u8) { var c: *mut[] Cue = raw as *mut[] Cue; skipWs(raw); @@ -580,7 +580,7 @@ pub fn cueParseTrack(raw: *mut[] u8) { c[0].trackCount = ti + 1; } -// INDEX NN MM:SS:FF → record the MSF into the most-recent track. +// INDEX NN MM:SS:FF -> record the MSF into the most-recent track. pub fn cueParseIndex(raw: *mut[] u8) { var c: *mut[] Cue = raw as *mut[] Cue; if (c[0].trackCount == 0) { return; } diff --git a/disc.jam b/disc.jam index d07a130..07a9643 100644 --- a/disc.jam +++ b/disc.jam @@ -12,8 +12,8 @@ // single Mode2/2352 data track. // // LBA convention follows the PSX BIOS: -// LBA = 150 → start of track 1 data (00:02:00 on the disc) -// LBA = 150 + N → Nth sector of the data track in the .bin file +// LBA = 150 -> start of track 1 data (00:02:00 on the disc) +// LBA = 150 + N -> Nth sector of the data track in the .bin file // We subtract the 150-sector lead-in when seeking inside the .bin — // real discs prefix the data with 2 seconds (150 sectors) of pregap // that's not part of the image file. @@ -37,9 +37,9 @@ pub const Disc = struct { pad2: u8, // Always-allocated Box(Cue). For non-cue discs it sits empty // (fileCount=0). For cue discs, cueParse writes into it in place. - // Auto-drop chain: Box(Disc).drop → @dropInPlace → field walk → - // Box(Cue).drop → @dropInPlace on Cue → Cue.cfn drop closes files - // → field walk drops each Vec backing. Holding the Box here (vs a + // Auto-drop chain: Box(Disc).drop -> @dropInPlace -> field walk -> + // Box(Cue).drop -> @dropInPlace on Cue -> Cue.cfn drop closes files + // -> field walk drops each Vec backing. Holding the Box here (vs a // raw `*mut[] u8`) is what makes the cleanup chain self-sufficient. cuePtr: Box(Cue), }; diff --git a/dma.jam b/dma.jam index 17a521a..dc7f48c 100644 --- a/dma.jam +++ b/dma.jam @@ -132,8 +132,8 @@ pub fn dmaRead32(d: *mut[] u32, off: u32) u32 { // = DICR bytes. The old `dmaRead32(off) & mask` returned 0 for any offset not // 0x70/0x74 (dmaRead32's default) — so a `lbu`/`lhu` of the DICR enable bits // at 0x1F8010F5/F6 read 0, and Brave Fencer's per-frame DICR-enable RMW then -// wrote the per-channel IRQ enables back as 0 → DMA-completion IRQs stopped -// firing → the FMV's STR clock callback never ran → black screen. (3rd +// wrote the per-channel IRQ enables back as 0 -> DMA-completion IRQs stopped +// firing -> the FMV's STR clock callback never ran -> black screen. (3rd // trace-diff divergence, instr 368,822,179; the write side already handled // these sub-offsets, only the read side was broken.) pub fn dmaRead16(d: *mut[] u32, off: u32) u32 { @@ -279,7 +279,7 @@ pub fn dmaDoGpuRequest(d: *mut[] u32, bus: Bus) { i = i + 1; } } else { - // GPU→RAM (C0 transfer): drain GPUREAD per word into RAM. + // GPU->RAM (C0 transfer): drain GPUREAD per word into RAM. // Each word reads GPUREAD at 0x1F801810, which // pulls from VRAM via the active C0 state machine. // Our previous stub wrote zeros, which broke @@ -317,7 +317,7 @@ pub fn dmaDoGpuLinked(d: *mut[] u32, bus: Bus) { } } -// DMA0: RAM → MDEC input port. Each word from RAM is sent to the MDEC +// DMA0: RAM -> MDEC input port. Each word from RAM is sent to the MDEC // data port (0x1F801820), which buffers it as command parameters or // command body. When all words for the active MDEC command are // delivered, MDEC's internal state machine runs the decode and fills @@ -340,7 +340,7 @@ pub fn dmaDoMdecIn(d: *mut[] u32, bus: Bus) { d[23] = size; } -// DMA1: MDEC output port → RAM. +// DMA1: MDEC output port -> RAM. pub fn dmaDoMdecOut(d: *mut[] u32, bus: Bus) { if (!chcrBusy(d, 1)) { return; } const size: u32 = bcrSize(d, 1) * bcrBlocks(d, 1); @@ -359,7 +359,7 @@ pub fn dmaDoMdecOut(d: *mut[] u32, bus: Bus) { d[24] = size; } -// CD-ROM → RAM transfer. Each "word" in BCR.size is 4 bytes from the +// CD-ROM -> RAM transfer. Each "word" in BCR.size is 4 bytes from the // data FIFO at 0x1F801802. Streaming goes through // cdromReadData(), popping one byte at a time and packing into a // little-endian word. After the transfer, ack via the d[26] flag so @@ -444,7 +444,7 @@ pub fn dmaDoSpu(d: *mut[] u32, bus: Bus) { d[chBase(4) + F_MADR] = addr; // The SPU transfer completes instantly, FULLY clears CHCR // (BUSY off), and raises the ch4 completion IRQ on the NEXT dmaUpdate - // (spu_irq_delay is set then immediately zeroed → IC_DMA ~1 instr later). + // (spu_irq_delay is set then immediately zeroed -> IC_DMA ~1 instr later). // The old jam model kept BUSY for `words*8` cycles (d[F_SPU_REMAIN]) and // only THEN raised the IRQ — an in-flight-DMA nicety for ps1-tests // (testDMAWriteTiming), but it DEFERRED the completion IC_DMA by the whole @@ -454,7 +454,7 @@ pub fn dmaDoSpu(d: *mut[] u32, bus: Bus) { // its DMA-IRQ handler — which is what advances the FMV's STR frame clock // (0x800d24d0) — and the video stayed black. // The fix: clear CHCR now + raise the ch4 done flag immediately so - // dmaUpdate folds it into DICR.DMA4FL → IC_DMA on the next instruction. + // dmaUpdate folds it into DICR.DMA4FL -> IC_DMA on the next instruction. d[chBase(4) + F_CHCR] = 0; d[chBase(4) + F_BCR] = 0; d[27] = 1; @@ -510,7 +510,7 @@ pub fn dmaTickSpu(d: *mut[] u32, delta: u32) { // zeroed before the !delay test = immediate). Brave Fencer's FMV chains the // next MDEC frame-decode off this IRQ; jam's old immediate fire landed it // before the handler was ready, so the decode pipeline never re-fed the -// MDEC → black video. +// MDEC -> black video. pub fn dmaUpdate(d: *mut[] u32, ic: *mut[] u32, cop0: *mut[] u32) { if (d[23] != 0) { d[23] = d[23] - 1; diff --git a/gpu.jam b/gpu.jam index 331bd42..d4f00e7 100644 --- a/gpu.jam +++ b/gpu.jam @@ -2,7 +2,7 @@ // // Implements the GP0/GP1 command machinery and the polygon, line, // rectangle, fill, and CPU↔VRAM blit commands. Triangles are -// point-sampled with texture + gouraud support (gpuRasterPoly → +// point-sampled with texture + gouraud support (gpuRasterPoly -> // gpuRasterTri); together with the GTE this renders real game geometry. // // State buffer layout (80 u32 entries): @@ -19,7 +19,7 @@ // [34..37] OWNED BY main.jam's frame loop, NOT the GPU: [34]=last CPU-clocked // SPU sample, [35]=SPU sample accumulator, [36]=scanline, // [37]=f32 GPU-cycle accumulator (type-punned). Do NOT reuse here. -// [38..43] C0 (VRAM→CPU) state: xcnt, ycnt, xsiz, ysiz, tsiz, addr +// [38..43] C0 (VRAM->CPU) state: xcnt, ycnt, xsiz, ysiz, tsiz, addr // [44] gp1_10h_req // [45] gpuread // [46] gpustat @@ -98,7 +98,7 @@ pub fn gpuRead32(g: *mut[] u32, vram: *mut[] u8, off: u32) u32 { if (off == 0x00) { var data: u32 = 0; if (g[42] != 0) { - // C0 (VRAM→CPU) transfer in progress — drain two pixels. + // C0 (VRAM->CPU) transfer in progress — drain two pixels. data = vramPackTwo(g, vram); g[42] = g[42] - 2; } @@ -177,7 +177,7 @@ pub fn gpuWrite8(g: *mut[] u32, vram: *mut[] u8, off: u32, val: u32) { // GP0 dispatch — state machine: RECV_CMD latches a new command word // into buf[0], RECV_ARGS appends additional words, RECV_DATA streams -// pixels for CPU→VRAM. +// pixels for CPU->VRAM. pub fn gpuGp0(g: *mut[] u32, vram: *mut[] u8, val: u32) { const st: u32 = g[19]; if (st == GP_RECV_CMD) { @@ -393,7 +393,7 @@ pub fn gpuVramToVram(g: *mut[] u32, vram: *mut[] u8) { g[19] = GP_RECV_CMD; } -// 0xA0 CPU→VRAM transfer. Header is 3 words (cmd, dest XY, size XY) +// 0xA0 CPU->VRAM transfer. Header is 3 words (cmd, dest XY, size XY) // then `size` 16-bit words come over GP0 packed two per u32. pub fn gpuCpuToVram(g: *mut[] u32, vram: *mut[] u8) { if (g[19] == GP_RECV_CMD) { @@ -442,7 +442,7 @@ pub fn gpuCpuToVram(g: *mut[] u32, vram: *mut[] u8) { } } -// 0xC0 VRAM→CPU transfer. Sets up the source rectangle; the data comes +// 0xC0 VRAM->CPU transfer. Sets up the source rectangle; the data comes // out via gpuRead32 / vramPackTwo over subsequent reads. pub fn gpuVramToCpu(g: *mut[] u32, vram: *mut[] u8) { if (g[19] == GP_RECV_CMD) { @@ -645,7 +645,7 @@ pub fn gpuRasterPoly(g: *mut[] u32, vram: *mut[] u8) { // read from). Without this, FMVs that draw the decoded frame // as a texture-mapped polygon then composite it with a // textured rect end up sampling the wrong VRAM region for the - // rect — texel 0 on every pixel → black FMV. + // rect — texel 0 on every pixel -> black FMV. g[60] = tpx; g[61] = tpy; g[62] = depth; @@ -682,8 +682,8 @@ pub fn gpuRasterPoly(g: *mut[] u32, vram: *mut[] u8) { // propagate the polygon's tpage into the derived globals so a // following textured RECTANGLE (which carries clut but no // tpage) inherits this state instead of stale values. Without - // it, the rect samples the wrong VRAM region → texel 0 → - // texel-0 skip → entire FMV frame is black. + // it, the rect samples the wrong VRAM region -> texel 0 -> + // texel-0 skip -> entire FMV frame is black. g[60] = tpx; g[61] = tpy; g[62] = depth; @@ -859,7 +859,7 @@ pub fn gpuRasterTri(g: *mut[] u32, vram: *mut[] u8, } color = gpuModulate(texel, modc); } - // Texel bit 15 → blend per transparency mode. + // Texel bit 15 -> blend per transparency mode. // For untextured polys, transparency applies // unconditionally when isTransp is set. if (isTransp && (texel & 0x8000) != 0) { diff --git a/gte.jam b/gte.jam index 625da09..2786d77 100644 --- a/gte.jam +++ b/gte.jam @@ -110,10 +110,10 @@ pub fn gteAlloc() Vec(u32) { return Vec(u32).filled(0, GTE_REGS); } // // Several COP2 data registers have side effects on read/write: // -// 15 SXYP read → mirror of SXY2; write → push SXY FIFO -// 28 IRGB write → unpack 15-bit RGB into IR1..IR3; read → repack -// 29 ORGB read → repack IR1..IR3 to 15-bit; write → ignored (RO) -// 30 LZCS write → also compute LZCR (leading sign-bit count) +// 15 SXYP read -> mirror of SXY2; write -> push SXY FIFO +// 28 IRGB write -> unpack 15-bit RGB into IR1..IR3; read -> repack +// 29 ORGB read -> repack IR1..IR3 to 15-bit; write -> ignored (RO) +// 30 LZCS write -> also compute LZCR (leading sign-bit count) // 31 LZCR read-only // Sign-extend a 16-bit value held in a u32 to full 32 bits. Several GTE // registers are stored as int16_t, so reading them back via MFC2/CFC2 @@ -166,7 +166,7 @@ pub fn gteDataWrite(g: *mut[] u32, idx: u32, val: u32) { } if (i == 28) { // IRGB — unpack 5-bit channels into IR1/IR2/IR3 (<< 7 to map - // 0..0x1F → 0..0xF80). + // 0..0x1F -> 0..0xF80). const packed: u32 = val & 0x7FFF; g[28] = packed; g[9] = (packed & 0x1F) << 7; @@ -218,7 +218,7 @@ pub fn gteCtrlRead(g: *mut[] u32, idx: u32) u32 { } // 16-bit signed control registers, sign-extended on read: the three // matrix m33 entries - // (rt/l/lr → idx 4/12/20), H (26), DQA (27), ZSF3 (29), ZSF4 (30). + // (rt/l/lr -> idx 4/12/20), H (26), DQA (27), ZSF3 (29), ZSF4 (30). if (i == 4 || i == 12 || i == 20 || i == 26 || i == 27 || i == 29 || i == 30) { return gteSext16(g[32 + i]); @@ -247,7 +247,7 @@ pub fn gteExec(g: *mut[] u32, opc: u32) { // register 31 (LZCR) + bits — wait, use g spare slot g[70+]. g[70] = g[70] + 1; // total GTE ops if (op < 0x40) { g[80 + op] = g[80 + op] + 1; } - // Decode sf (bit 19 → 12 or 0) and lm (bit 10) once per dispatch + // Decode sf (bit 19 -> 12 or 0) and lm (bit 10) once per dispatch // so RTPS/RTPT/MVMVA all see the same flags. const sf: u32 = ((opc >> 19) & 1) * 12; const lm: u32 = (opc >> 10) & 1; @@ -697,7 +697,7 @@ pub fn satIrLm(v: i64, lm: u32) i64 { // is the component (1/2/3) selecting the per-channel bit. gteExec clears // FLAG at the top of each op; gteCtrlRead synthesizes the bit-31 summary. -// IR1..IR3 saturation → bit 24/23/22. +// IR1..IR3 saturation -> bit 24/23/22. pub fn gteClampIr(g: *mut[] u32, i: u32, v: i64, lm: u32) i64 { var lo: i64 = -32768; if (lm != 0) { lo = 0; } @@ -715,35 +715,35 @@ pub fn gteIrTriple(g: *mut[] u32, m1: i64, m2: i64, m3: i64, lm: u32) { g[11] = (gteClampIr(g, 3, m3, lm) as u64 & 0xFFFF) as u32; } -// IR0 clamp 0..0x1000 → bit 12. +// IR0 clamp 0..0x1000 -> bit 12. pub fn gteClampIr0(g: *mut[] u32, v: i64) i64 { if (v < 0) { g[32 + C_FLAG] = g[32 + C_FLAG] | 0x1000; return 0; } if (v > 0x1000) { g[32 + C_FLAG] = g[32 + C_FLAG] | 0x1000; return 0x1000; } return v; } -// SZ3 saturation 0..0xFFFF → bit 18. +// SZ3 saturation 0..0xFFFF -> bit 18. pub fn gteClampSz3(g: *mut[] u32, v: i64) u32 { if (v < 0) { g[32 + C_FLAG] = g[32 + C_FLAG] | 0x40000; return 0; } if (v > 0xFFFF) { g[32 + C_FLAG] = g[32 + C_FLAG] | 0x40000; return 0xFFFF; } return (v as u64 & 0xFFFF) as u32; } -// SX/SY saturation -0x400..0x3FF → bit 14/13. +// SX/SY saturation -0x400..0x3FF -> bit 14/13. pub fn gteClampSxy(g: *mut[] u32, i: u32, v: i64) u32 { if (v < -1024) { g[32 + C_FLAG] = g[32 + C_FLAG] | (0x4000 >> (i - 1)); return 0xFFFFFC00; } if (v > 1023) { g[32 + C_FLAG] = g[32 + C_FLAG] | (0x4000 >> (i - 1)); return 0x3FF; } return ((v + 0x100000000) as u64 & 0xFFFF) as u32; } -// RGB channel clamp 0..0xFF → bit 21/20/19. +// RGB channel clamp 0..0xFF -> bit 21/20/19. pub fn gteClampRgb(g: *mut[] u32, i: u32, v: i64) u32 { if (v < 0) { g[32 + C_FLAG] = g[32 + C_FLAG] | (0x200000 >> (i - 1)); return 0; } if (v > 255) { g[32 + C_FLAG] = g[32 + C_FLAG] | (0x200000 >> (i - 1)); return 255; } return (v as u64 & 0xFF) as u32; } -// MAC0 overflow → bit 15 (neg) / 16 (pos); value is NOT clamped, only +// MAC0 overflow -> bit 15 (neg) / 16 (pos); value is NOT clamped, only // flagged. pub fn gteClampMac0(g: *mut[] u32, v: i64) i64 { const lim: i64 = (1 as i64) << 31; @@ -814,7 +814,7 @@ pub fn satSz3(v: i64) u32 { pub fn satSxy(v: i64) u32 { if (v < -1024) { return 0xFFFFFC00; } if (v > 1023) { return 0x3FF; } - // i64 → u32 via the low 32 bits, masked. + // i64 -> u32 via the low 32 bits, masked. const lo: u32 = ((v + 0x100000000) as u64 & 0xFFFF) as u32; return lo; } @@ -1024,8 +1024,8 @@ pub fn gteOp(g: *mut[] u32, sf: u32, lm: u32) { // NCDS — Normal Color Depth Single. Computes per-vertex lit color with // far-color (fog) depth interpolation, using the light matrix to // transform the input vertex normal. The pipeline: -// 1. L * V → MAC, IR (vertex normal in light space) -// 2. BK + LC*IR → MAC, IR (background + reflected light) +// 1. L * V -> MAC, IR (vertex normal in light space) +// 2. BK + LC*IR -> MAC, IR (background + reflected light) // 3. ir' = clamp((FC<<12) - (C<<4)*IR), with lm=0 // 4. MAC = (C<<4)*IR + IR0*ir' (interpolate to far-colour) // 5. IR = clamp(MAC, lm) @@ -1066,7 +1066,7 @@ pub fn gteNcds(g: *mut[] u32, vidx: u32, sf: u32, lm: u32) { const ll32: i64 = s16ToI64((g[32 + 11] >> 16) & 0xFFFF); const ll33: i64 = s16ToI64(g[32 + 12] & 0xFFFF); - // Stage 1: L * V → MAC, IR. gteClampMac applies `>> sf`, so for + // Stage 1: L * V -> MAC, IR. gteClampMac applies `>> sf`, so for // sf=12 (the BIOS default) we shift down by 12 before clamping into // the IR range; otherwise IR saturates at 0x7FFF and the downstream // stages clip every channel to white. diff --git a/main.jam b/main.jam index 0ebc048..994b9d0 100644 --- a/main.jam +++ b/main.jam @@ -288,8 +288,8 @@ fn runOneFrame(c: mut Cpu, bus: Bus, regs: *mut[] u32, cop0: *mut[] u32, const before: u64 = c.cycles; step(c, bus, regs, cop0); const delta: u32 = (c.cycles - before) as u32; - // Per-instruction device order: cdrom → gpu → pad → timer → dma. - // (Was timer→dma→cdrom→…→gpu; the order decides which IRQ bit lands + // Per-instruction device order: cdrom -> gpu -> pad -> timer -> dma. + // (Was timer->dma->cdrom->…->gpu; the order decides which IRQ bit lands // in I_STAT first each step, and the GPU hblank/vblank events must // fire BEFORE the sysclk timer +2.) @@ -326,7 +326,7 @@ fn runOneFrame(c: mut Cpu, bus: Bus, regs: *mut[] u32, cop0: *mut[] u32, frameDone = true; } } else if (prevHb && !currHb) { - // HBlank-end edge → wrap the scanline accumulator + // HBlank-end edge -> wrap the scanline accumulator // (acc -= 3413). bus.timer.hblankEnd(); acc = acc - GPU_CYCLES_SCANL; @@ -341,8 +341,8 @@ fn runOneFrame(c: mut Cpu, bus: Bus, regs: *mut[] u32, cop0: *mut[] u32, // jam-only extras: neither of these belongs in the per-instruction // device update above. Kept at the end (least perturbation to the - // device order above) and flagged as divergences — SIO1 → - // peripherals task, SPU CPU-clock → SPU task (revisit once the + // device order above) and flagged as divergences — SIO1 -> + // peripherals task, SPU CPU-clock -> SPU task (revisit once the // deterministic CPU surface settles). bus.sio1.update(bus.irq.ptr, cop0, delta); spuAcc = spuAcc + delta; @@ -385,7 +385,7 @@ fn runOneFrame(c: mut Cpu, bus: Bus, regs: *mut[] u32, cop0: *mut[] u32, } // Dump the full 1024x512 VRAM as a binary PPM (P6 / 24-bit RGB) at -// `path`. BGR555 → RGB888 expansion is done inline so the output is +// `path`. BGR555 -> RGB888 expansion is done inline so the output is // viewable with any image viewer. Used as an end-of-run diagnostic so // we can confirm what the BIOS/game actually rendered without staring // at the SDL window. diff --git a/mcd.jam b/mcd.jam index c4d4784..713e10b 100644 --- a/mcd.jam +++ b/mcd.jam @@ -8,14 +8,14 @@ // // State machine (MCD_STATE_*): // -// TX_HIZ → 0xFF on first read (line high-Z) -// TX_FLG → flag byte (0x08 = "first access since power-on") -// TX_ID1 / TX_ID2 → 0x5A / 0x5D identification bytes -// R_* → READ subprotocol: take MSB/LSB → addr<<7, then +// TX_HIZ -> 0xFF on first read (line high-Z) +// TX_FLG -> flag byte (0x08 = "first access since power-on") +// TX_ID1 / TX_ID2 -> 0x5A / 0x5D identification bytes +// R_* -> READ subprotocol: take MSB/LSB -> addr<<7, then // ACK + 128 data bytes + checksum + 'G' end marker -// W_* → WRITE subprotocol: take MSB/LSB + 128 data bytes +// W_* -> WRITE subprotocol: take MSB/LSB + 128 data bytes // + checksum, then ACK + 'G' end marker -// S_* → STATUS subprotocol (rarely used) +// S_* -> STATUS subprotocol (rarely used) // // We model a single-slot card with an in-memory 128 KB buffer; the // buffer is kept as a separate heap allocation (Bus.mcdRam) so callers diff --git a/mdec.jam b/mdec.jam index c5f24b3..f688441 100644 --- a/mdec.jam +++ b/mdec.jam @@ -5,13 +5,13 @@ // chip. The game's flow per frame: // // 1. CdlReadS streams compressed sectors into RAM. -// 2. DMA channel 0 copies input → MDEC's input FIFO (0x1F801820). -// 3. MDEC runs RLE-decode → inverse-quantisation → iDCT → YUV→RGB. -// 4. DMA channel 1 reads decoded RGB → RAM. +// 2. DMA channel 0 copies input -> MDEC's input FIFO (0x1F801820). +// 3. MDEC runs RLE-decode -> inverse-quantisation -> iDCT -> YUV->RGB. +// 4. DMA channel 1 reads decoded RGB -> RAM. // 5. GPU display VRAM blit of the decoded frame. // // Without MDEC, step 4 hands the game zeros / never fires the DMA-done -// IRQ → game stalls on its FMV-wait loop. +// IRQ -> game stalls on its FMV-wait loop. // // Layout: state is a flat struct of typed fields. Input/output buffers // stay heap-allocated separately (256KB + 1MB) so we avoid per-command @@ -195,7 +195,7 @@ pub const Mdec = struct { return idx; } - // YUV → RGB + // YUV -> RGB pub fn yuvToRgb(self: mut Self, output: *mut[] u8, outBase: u32, xx: u32, yy: u32) { const depth: u32 = self.outputDepth; @@ -210,7 +210,7 @@ pub const Mdec = struct { const rRaw: i32 = self.crBlk[cri] as i32; const bRaw: i32 = self.cbBlk[cri] as i32; - // YUV→RGB coefficients (float): g = -0.3437*b + -0.7143*r; + // YUV->RGB coefficients (float): g = -0.3437*b + -0.7143*r; // r = 1.402*r; b = 1.772*b. const rf: f64 = rRaw as f64; const bf: f64 = bRaw as f64; @@ -281,7 +281,7 @@ pub const Mdec = struct { var idx: u32 = 0; // word index into input buffer var outBytes: u32 = 0; - // Each macroblock: Cr, Cb, Y0, Y1, Y2, Y3 → 16×16 RGB. + // Each macroblock: Cr, Cb, Y0, Y1, Y2, Y3 -> 16×16 RGB. while (idx * 2 < inputBytes) { const outBase: u32 = outBytes; idx = self.rlDecodeBlock(input, idx, diff --git a/sdl.jam b/sdl.jam index 52a0efd..1d87b63 100644 --- a/sdl.jam +++ b/sdl.jam @@ -154,7 +154,7 @@ fn disableAppNap() { var reason: []u8 = "jamstation emulation running"; const nsstr: u64 = objc_msgSend(objc_getClass(nmStr.ptr), sel_registerName(selStr.ptr), reason.ptr as u64, 0); - // NSActivityUserInitiated (0x00FFFFFF) → App Nap disabled while held. + // NSActivityUserInitiated (0x00FFFFFF) -> App Nap disabled while held. var selBegin: []u8 = "beginActivityWithOptions:reason:"; const token: u64 = objc_msgSend(pi, sel_registerName(selBegin.ptr), 0x00FFFFFF, nsstr); @@ -361,7 +361,7 @@ pub export fn psone_audio_cb(userdata: u64, stream: *mut[] u8, len: i32) { var ring: *mut[] u8 = userdata as *mut[] u8; const want: u32 = len as u32; var i: u32 = 0; - // Not yet primed (startup or post-underrun rebuffer) → silence. + // Not yet primed (startup or post-underrun rebuffer) -> silence. if (getU32Le(ring, 8) == 0) { while (i < want) { stream[i] = 0; i = i + 1; } return; @@ -468,7 +468,7 @@ pub fn sdlBlit(s: Sdl, pixels: *mut[] u8, const lo: u32 = pixels[sb] as u32; const hi: u32 = pixels[sb + 1] as u32; const px: u32 = lo | (hi << 8); - // BGR555 → 8888 (5→8 by left-shift + replicate high + // BGR555 -> 8888 (5->8 by left-shift + replicate high // bits; cheap "x<<3 | x>>2" expansion). const r5: u32 = px & 0x1F; const g5: u32 = (px >> 5) & 0x1F; diff --git a/sio1.jam b/sio1.jam index 82d3319..d55eeb6 100644 --- a/sio1.jam +++ b/sio1.jam @@ -29,7 +29,7 @@ // 1 DTR_LVL DTR output level // 2 RX_EN receive enable // 3 SO_LVL TX manual output level (loopback) -// 4 ACK_IRQ write 1 → clear STAT[3,4,5,9]; self-clears +// 4 ACK_IRQ write 1 -> clear STAT[3,4,5,9]; self-clears // 5 RTS_LVL RTS output level // 6 RESET master reset // 7 reserved diff --git a/spu.jam b/spu.jam index 67fcf7a..b236091 100644 --- a/spu.jam +++ b/spu.jam @@ -131,7 +131,7 @@ const D_S1: u32 = 0x18; const D_S2: u32 = 0x1C; const D_S3: u32 = 0x20; const D_BFLAGS: u32 = 0x24; -const D_BUF0: u32 = 0x28; // 28 × i16 → 56 bytes through 0x60 +const D_BUF0: u32 = 0x28; // 28 × i16 -> 56 bytes through 0x60 const D_H0: u32 = 0x60; const D_H1: u32 = 0x64; const D_LVOL: u32 = 0x68; // kept as i32 (volumel); a float would also work @@ -150,7 +150,7 @@ const D_ENVCTL: u32 = 0x98; // Global runtime offsets (added to GLOBAL_BASE). const G_TADDR: u32 = 0x00; -const G_TFIFO: u32 = 0x04; // 32 × u16 = 64 bytes → through 0x44 +const G_TFIFO: u32 = 0x04; // 32 × u16 = 64 bytes -> through 0x44 const G_TFIFO_IDX: u32 = 0x44; const G_EVEN_CYC: u32 = 0x48; const G_REVBADDR: u32 = 0x4C; @@ -158,7 +158,7 @@ const G_LRSL: u32 = 0x50; const G_LRSR: u32 = 0x54; // CD-audio FIFO head/tail. 32-bit ring indices that mod-mask down to // CD_FIFO_MASK for the slot. Producer-only writes head; consumer-only -// writes tail. Equal head == tail → empty. +// writes tail. Equal head == tail -> empty. const G_CD_HEAD: u32 = 0x60; const G_CD_TAIL: u32 = 0x64; // Final mixed-output FIFO head/tail. Producer = spuGetSample. @@ -281,7 +281,7 @@ pub fn spuRamAlloc() Vec(u8) { return Vec(u8).filled(0, SPU_RAM_SIZE); } pub fn spuPushCdSample(s: *mut[] u8, leftI16: u32, rightI16: u32) { const head: u32 = getU32(s, GLOBAL_BASE + G_CD_HEAD); const tail: u32 = getU32(s, GLOBAL_BASE + G_CD_TAIL); - if ((head - tail) >= CD_FIFO_CAP) { return; } // full → drop + if ((head - tail) >= CD_FIFO_CAP) { return; } // full -> drop const slot: u32 = CD_FIFO_BASE + ((head & CD_FIFO_MASK) << 2); setU16(s, slot, leftI16 & 0xFFFF); setU16(s, slot + 2, rightI16 & 0xFFFF); @@ -384,7 +384,7 @@ pub fn spuGetReverbSample(s: *mut[] u8, ram: *mut[] u8, const lin: i32 = mulVol(inL, vlin); const rin: i32 = mulVol(inR, vrin); - // Same-side reflection (L→L, R→R). + // Same-side reflection (L->L, R->R). const sLsamePrev: i32 = spuReadReverb(s, ram, mlsame - 2); const sRsamePrev: i32 = spuReadReverb(s, ram, mrsame - 2); const sLsameNow: i32 = sat16i32(lin @@ -398,7 +398,7 @@ pub fn spuGetReverbSample(s: *mut[] u8, ram: *mut[] u8, spuWriteReverb(s, ram, mlsame, sLsameNow); spuWriteReverb(s, ram, mrsame, sRsameNow); - // Cross-side reflection (L→R, R→L). + // Cross-side reflection (L->R, R->L). const sLdiffPrev: i32 = spuReadReverb(s, ram, mldiff - 2); const sRdiffPrev: i32 = spuReadReverb(s, ram, mrdiff - 2); const sLdiffNow: i32 = sat16i32(lin @@ -711,7 +711,7 @@ pub fn spuHandleAdsr(s: *mut[] u8, v: u32) { // so the envelope level the game POLLS at voice reg 0xC (ENVCVOL) is // deterministic and matches hardware — instead of advancing on the // wall-clock audio thread (which desyncs from the CPU and made Brave Fencer -// read a wrong envelope level, looping the intro resource-load → black FMV). +// read a wrong envelope level, looping the intro resource-load -> black FMV). // The audio thread no longer steps the envelope (removed from spuGetSample). pub fn spuStepAdsrCpu(s: *mut[] u8) { var v: u32 = 0; @@ -1097,7 +1097,7 @@ pub fn spuGetSample(s: *mut[] u8, ram: *mut[] u8, pub fn spuPushOutSample(s: *mut[] u8, packed: u32) { const head: u32 = getU32(s, GLOBAL_BASE + G_OUT_HEAD); const tail: u32 = getU32(s, GLOBAL_BASE + G_OUT_TAIL); - if ((head - tail) >= OUT_FIFO_CAP) { return; } // full → drop + if ((head - tail) >= OUT_FIFO_CAP) { return; } // full -> drop const slot: u32 = OUT_FIFO_BASE + ((head & OUT_FIFO_MASK) << 2); setU32(s, slot, packed); setU32(s, GLOBAL_BASE + G_OUT_HEAD, head + 1); diff --git a/tests.jam b/tests.jam index c14d644..acf592a 100644 --- a/tests.jam +++ b/tests.jam @@ -376,19 +376,19 @@ fn tGteRtpsIr() u32 { fn tGteIrSext() u32 { var g: Vec(u32) = gteAlloc(); gteDataWrite(g.ptr, 9, 0x0000FFFF); // IR1 = -1 (16-bit) - const v: u32 = gteDataRead(g.ptr, 9); // MFC2 sign-extends → -1 + const v: u32 = gteDataRead(g.ptr, 9); // MFC2 sign-extends -> -1 return v; } fn tGteDivide() u32 { var g: Vec(u32) = gteAlloc(); - const q: u32 = gteDivide(g.ptr, 0x800, 0x1000); // 2048/4096 → 0x8000 + const q: u32 = gteDivide(g.ptr, 0x800, 0x1000); // 2048/4096 -> 0x8000 return q; } fn tGteDivideOvf() u32 { var g: Vec(u32) = gteAlloc(); - const q: u32 = gteDivide(g.ptr, 0x2000, 0x1000); // n >= 2d → saturates + const q: u32 = gteDivide(g.ptr, 0x2000, 0x1000); // n >= 2d -> saturates return q; } @@ -398,14 +398,14 @@ fn tGteDivideOvf() u32 { fn tGteSqrFlag() u32 { var g: Vec(u32) = gteAlloc(); gteDataWrite(g.ptr, 9, 0x7FFF); // IR1 = 32767 - gteExec(g.ptr, 0x4A080028); // SQR, sf=12 → MAC1=262143, IR1 saturates + gteExec(g.ptr, 0x4A080028); // SQR, sf=12 -> MAC1=262143, IR1 saturates const f: u32 = gteCtrlRead(g.ptr, 31); // bit 24 (IR1 sat) + bit 31 summary return f; } fn tGteDivideFlag() u32 { var g: Vec(u32) = gteAlloc(); - const q: u32 = gteDivide(g.ptr, 0x2000, 0x1000); // n>=2d → bit 17 (divide ovf) + const q: u32 = gteDivide(g.ptr, 0x2000, 0x1000); // n>=2d -> bit 17 (divide ovf) const f: u32 = gteCtrlRead(g.ptr, 31); // bit 17 + bit 31 summary return f; } @@ -413,14 +413,14 @@ fn tGteDivideFlag() u32 { fn tGteNoFlag() u32 { var g: Vec(u32) = gteAlloc(); gteDataWrite(g.ptr, 9, 100); // IR1 = 100 - gteExec(g.ptr, 0x4A080028); // SQR sf=12 → MAC1=2, no saturation + gteExec(g.ptr, 0x4A080028); // SQR sf=12 -> MAC1=2, no saturation const f: u32 = gteCtrlRead(g.ptr, 31); // FLAG must be clean return f; } // RTPS IR3 via gte_clamp_ir_z: with sf=0, MAC3 = 4096*256 = 0x100000. // clamp_ir_z keys FLAG bit 22 off macRaw3>>12 = 256 (in IR range) so it -// stays clear, even though the returned IR3 clamps 0x100000 → 0x7FFF. The +// stays clear, even though the returned IR3 clamps 0x100000 -> 0x7FFF. The // old plain IR clamp keyed bit 22 off the unshifted 0x100000 and wrongly // set it (FLAG = 0x400000; bit 22 is excluded from the bit-31 summary). fn tGteRtpsClampIrZ() u32 { @@ -452,42 +452,42 @@ fn tGteMvmvaNestedOvf() u32 { // IRGB/ORGB (reg 28) repacks IR1/2/3 (>>7, clamped 0..0x1F) into 15-bit RGB. // IR is stored zero-extended in the low 16 bits and must be sign-extended // before the >>7, so a negative IR clamps to 0 (DuckStation -// gte.cpp:343). The old `(g[9] as i32)` bit-cast read IR1=-1 as +65535 → 0x1F; +// gte.cpp:343). The old `(g[9] as i32)` bit-cast read IR1=-1 as +65535 -> 0x1F; // with all three IR = -1 the packed result must be 0, not 0x7FFF. fn tGteIrgbNeg() u32 { var g: Vec(u32) = gteAlloc(); gteDataWrite(g.ptr, 9, 0x0000FFFF); // IR1 = -1 gteDataWrite(g.ptr, 10, 0x0000FFFF); // IR2 = -1 gteDataWrite(g.ptr, 11, 0x0000FFFF); // IR3 = -1 - return gteDataRead(g.ptr, 28); // each channel clamps to 0 → 0 + return gteDataRead(g.ptr, 28); // each channel clamps to 0 -> 0 } -// Positive packing still works after the sign-extension fix: IR1=3968→31, -// IR2=128→1, IR3=0 ⇒ 0x1F | (1<<5) | 0 = 0x3F. +// Positive packing still works after the sign-extension fix: IR1=3968->31, +// IR2=128->1, IR3=0 ⇒ 0x1F | (1<<5) | 0 = 0x3F. fn tGteIrgbPos() u32 { var g: Vec(u32) = gteAlloc(); - gteDataWrite(g.ptr, 9, 0x0F80); // IR1 = 3968 → >>7 = 31 - gteDataWrite(g.ptr, 10, 0x0080); // IR2 = 128 → >>7 = 1 + gteDataWrite(g.ptr, 9, 0x0F80); // IR1 = 3968 -> >>7 = 31 + gteDataWrite(g.ptr, 10, 0x0080); // IR2 = 128 -> >>7 = 1 gteDataWrite(g.ptr, 11, 0x0000); // IR3 = 0 return gteDataRead(g.ptr, 28); } // RTPT runs the depth-cue (DQ) tail only on the LAST vertex. -// Construct V0/V1 with a small Z (→ large divide → the DQ's +// Construct V0/V1 with a small Z (-> large divide -> the DQ's // IR0 = clamp(DQA*div>>12) saturates, setting FLAG bit 12) and V2 with a large -// Z (→ small divide → no IR0 saturation). Bit 12 (IR0 sat) is set ONLY by the +// Z (-> small divide -> no IR0 saturation). Bit 12 (IR0 sat) is set ONLY by the // DQ tail's gte_clamp_ir0 and is excluded from the bit-31 summary, so it // cleanly isolates whether intermediate vertices wrongly ran the DQ. With the -// fix only V2's DQ runs → bit 12 clear. (Pre-fix: V0/V1 saturate it → 0x1000.) +// fix only V2's DQ runs -> bit 12 clear. (Pre-fix: V0/V1 saturate it -> 0x1000.) fn tGteRtptDqGate() u32 { var g: Vec(u32) = gteAlloc(); gteSetIdentity(g.ptr); gteCtrlWrite(g.ptr, 26, 2); // H = 2 gteCtrlWrite(g.ptr, 27, 0x1000); // DQA = 4096 gteCtrlWrite(g.ptr, 28, 0); // DQB = 0 - gteDataWrite(g.ptr, 0, 0); gteDataWrite(g.ptr, 1, 16); // V0.z = 16 → div 0x2000, IR0 sat + gteDataWrite(g.ptr, 0, 0); gteDataWrite(g.ptr, 1, 16); // V0.z = 16 -> div 0x2000, IR0 sat gteDataWrite(g.ptr, 2, 0); gteDataWrite(g.ptr, 3, 16); // V1.z = 16 - gteDataWrite(g.ptr, 4, 0); gteDataWrite(g.ptr, 5, 0x1000); // V2.z = 4096 → div 32, no sat + gteDataWrite(g.ptr, 4, 0); gteDataWrite(g.ptr, 5, 0x1000); // V2.z = 4096 -> div 32, no sat gteExec(g.ptr, 0x4A000030); // RTPT, sf=0 return gteCtrlRead(g.ptr, 31) & 0x1000; // FLAG bit 12 = IR0 saturation (DQ tail only) } @@ -499,7 +499,7 @@ fn tGteRtptDqGate() u32 { // read 0x200000 (R). The old inline clampU8 set none of these (returned 0). fn tGteNcdsRgbSat() u32 { var g: Vec(u32) = gteAlloc(); - gteCtrlWrite(g.ptr, 21, 0x00010000); // RFC large → ir1f saturates high + gteCtrlWrite(g.ptr, 21, 0x00010000); // RFC large -> ir1f saturates high gteDataWrite(g.ptr, 8, 0x7FFF); // IR0 = max gteExec(g.ptr, 0x4A000013); // NCDS, sf=0 return gteCtrlRead(g.ptr, 31) & 0x00380000; // RGB-saturation FLAG bits 19/20/21 @@ -517,7 +517,7 @@ fn tGteDqaWidth() u32 { gteCtrlWrite(g.ptr, 27, 0x00010001); // DQA: low16=1 (s16), high bits set gteCtrlWrite(g.ptr, 28, 0); // DQB = 0 gteDataWrite(g.ptr, 0, 0); - gteDataWrite(g.ptr, 1, 0x1000); // V0.z = 4096 → SZ3 = 4096 + gteDataWrite(g.ptr, 1, 0x1000); // V0.z = 4096 -> SZ3 = 4096 gteExec(g.ptr, 0x4A000001); // RTPS, sf=0 return gteDataRead(g.ptr, 8); // IR0 = clamp((DQA_s16 * div) >> 12) = 16 } @@ -675,11 +675,11 @@ tfn emuDiscBootsExec() { // These deltas drive device timing (CDROM/DMA/timers) at the right rate. // gteOpCycles selects the GTE op cycle count from the low 6 bits. -fn tGteCycRtps() u32 { return gteOpCycles(0x4A000001); } // RTPS → 15 -fn tGteCycNcdt() u32 { return gteOpCycles(0x4A000016); } // NCDT → 44 -fn tGteCycRtpt() u32 { return gteOpCycles(0x4A000030); } // RTPT → 23 -fn tGteCycNcct() u32 { return gteOpCycles(0x4A00003F); } // NCCT → 39 -fn tGteCycDflt() u32 { return gteOpCycles(0x4A000000); } // non-math → 2 +fn tGteCycRtps() u32 { return gteOpCycles(0x4A000001); } // RTPS -> 15 +fn tGteCycNcdt() u32 { return gteOpCycles(0x4A000016); } // NCDT -> 44 +fn tGteCycRtpt() u32 { return gteOpCycles(0x4A000030); } // RTPT -> 23 +fn tGteCycNcct() u32 { return gteOpCycles(0x4A00003F); } // NCCT -> 39 +fn tGteCycDflt() u32 { return gteOpCycles(0x4A000000); } // non-math -> 2 // A plain instruction fetched from cached RAM costs 2 (0 fetch + 2 base). fn tCycRam() u32 { -- 2.51.2