Something went wrong. Try again.
A Playstation One (PS1) emulator fully written in Jam
Something went wrong. Try again.
jamstation irq.jam
3.8 kB · 127 lines
at main
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128// SPDX-License-Identifier: MIT// Copyright (c) 2026 Raphael Amorim
// Two registers live at 0x1F801070..0x1F801077:// 0x00 I_STAT status - set by devices raising IRQs, cleared by// writing 0 to the matching bit// 0x04 I_MASK mask - when (stat & mask) != 0, COP0 CAUSE bit IP2// (= 0x00000400) is asserted, which causes the CPU to// take an external interrupt the next time it samples// pending IRQs at fetch time.//// State buffer (two u32 entries):// [0] I_STAT// [1] I_MASK
const { Vec } = import("std/collections");
pub const IC_VBLANK: u32 = 0x001;pub const IC_GPU: u32 = 0x002;pub const IC_CDROM: u32 = 0x004;pub const IC_DMA: u32 = 0x008;pub const IC_TIMER0: u32 = 0x010;pub const IC_TIMER1: u32 = 0x020;pub const IC_TIMER2: u32 = 0x040;pub const IC_JOY: u32 = 0x080;pub const IC_SIO: u32 = 0x100;pub const IC_SPU: u32 = 0x200;pub const IC_LP_PIO: u32 = 0x400;
const CAUSE_IP2: u32 = 0x00000400;const C0_CAUSE: u32 = 13;
pub fn createIrq() Vec(u32) { return Vec(u32).filled(0, 16);}
pub fn irqReevaluate(ic: *mut[] u32, cop0: *mut[] u32) { const pending: u32 = ic[0] & ic[1]; var cause: u32 = cop0[C0_CAUSE]; if (pending != 0) { cause = cause | CAUSE_IP2; } else { cause = cause & (~CAUSE_IP2); } cop0[C0_CAUSE] = cause;}
pub fn irqRead32(ic: *mut[] u32, off: u32) u32 { match (off) { 0x00 { return ic[0]; } 0x04 { return ic[1]; } _ { return 0; } }}
pub fn irqRead16(ic: *mut[] u32, off: u32) u32 { match (off) { 0x00 { return ic[0] & 0xFFFF; } 0x02 { return (ic[0] >> 16) & 0xFFFF; } 0x04 { return ic[1] & 0xFFFF; } 0x06 { return (ic[1] >> 16) & 0xFFFF; } _ { return 0; } }}
pub fn irqRead8(ic: *mut[] u32, off: u32) u32 { match (off) { 0x00 { return ic[0] & 0xFF; } 0x01 { return (ic[0] >> 8) & 0xFF; } 0x02 { return (ic[0] >> 16) & 0xFF; } 0x03 { return (ic[0] >> 24) & 0xFF; } 0x04 { return ic[1] & 0xFF; } 0x05 { return (ic[1] >> 8) & 0xFF; } 0x06 { return (ic[1] >> 16) & 0xFF; } 0x07 { return (ic[1] >> 24) & 0xFF; } _ { return 0; } }}
pub fn irqWrite32(ic: *mut[] u32, cop0: *mut[] u32, off: u32, val: u32) { match (off) { 0x00 { ic[0] = ic[0] & val; } 0x04 { ic[1] = val; } _ {} } irqReevaluate(ic, cop0);}
pub fn irqWrite16(ic: *mut[] u32, cop0: *mut[] u32, off: u32, val: u32) { const v: u32 = val & 0xFFFF; match (off) { 0x00 { ic[0] = ic[0] & (0xFFFF0000 | v); } 0x02 { ic[0] = ic[0] & (0x0000FFFF | (v << 16)); } 0x04 { ic[1] = (ic[1] & 0xFFFF0000) | v; } 0x06 { ic[1] = (ic[1] & 0x0000FFFF) | (v << 16); } _ {} } irqReevaluate(ic, cop0);}
pub fn irqWrite8(ic: *mut[] u32, cop0: *mut[] u32, off: u32, val: u32) { const v: u32 = val & 0xFF; match (off) { 0x00 { ic[0] = ic[0] & (0xFFFFFF00 | v); } 0x01 { ic[0] = ic[0] & (0xFFFF00FF | (v << 8)); } 0x02 { ic[0] = ic[0] & (0xFF00FFFF | (v << 16)); } 0x03 { ic[0] = ic[0] & (0x00FFFFFF | (v << 24)); } 0x04 { ic[1] = (ic[1] & 0xFFFFFF00) | v; } 0x05 { ic[1] = (ic[1] & 0xFFFF00FF) | (v << 8); } 0x06 { ic[1] = (ic[1] & 0xFF00FFFF) | (v << 16); } 0x07 { ic[1] = (ic[1] & 0x00FFFFFF) | (v << 24); } _ {} } irqReevaluate(ic, cop0);}
pub fn irqRaise(ic: *mut[] u32, cop0: *mut[] u32, lines: u32) { ic[0] = ic[0] | lines; var b: u32 = 0; while (b < 11) { if ((lines & (1 << b)) != 0) { ic[2 + b] = ic[2 + b] + 1; } b = b + 1; } irqReevaluate(ic, cop0);}