Class: PSX::CDROM
- Inherits:
-
Object
- Object
- PSX::CDROM
- Defined in:
- lib/psx/cdrom.rb
Overview
Minimal CD-ROM controller stub.
Enough to convince the BIOS that there’s a CD subsystem present with no disc inserted, so it proceeds to the shell screen. Handles the commands the BIOS issues during boot: GetStat, Init, GetID, Setmode, Test, etc.
We don’t model timing accurately. Responses are queued and delivered one per tick (called from the emulator’s frame loop), respecting that the previous IRQ must be acknowledged and the previous response FIFO drained before the next response shows up.
Constant Summary collapse
- STAT_INDEX_MASK =
Status register (0x1F801800 read) bits
0x03- STAT_ADPCM_BUSY =
0x04- STAT_PARAMETER_FIFO_EMPTY =
0x08- STAT_PARAMETER_FIFO_NOT_FULL =
0x10- STAT_RESPONSE_FIFO_NOT_EMPTY =
0x20- STAT_DATA_FIFO_NOT_EMPTY =
0x40- STAT_BUSY =
0x80- DEFAULT_STAT =
“stat” byte returned in command responses. Bit 4 = shell open (we say closed); bit 0 = error. We default to 0x02 (motor on, no error, no disc seek done) for no-disc.
0x02
Instance Method Summary collapse
-
#initialize(interrupts:) ⇒ CDROM
constructor
A new instance of CDROM.
-
#read8(reg) ⇒ Object
— Bus interface ——————————————————.
- #reset ⇒ Object
-
#tick ⇒ Object
Advance one step in the response queue.
- #write8(reg, value) ⇒ Object
Constructor Details
#initialize(interrupts:) ⇒ CDROM
Returns a new instance of CDROM.
29 30 31 32 |
# File 'lib/psx/cdrom.rb', line 29 def initialize(interrupts:) @interrupts = interrupts reset end |
Instance Method Details
#read8(reg) ⇒ Object
— Bus interface ——————————————————
46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 |
# File 'lib/psx/cdrom.rb', line 46 def read8(reg) case reg & 3 when 0 then status when 1 # Response FIFO v = @response.shift || 0 v & 0xFF when 2 # Data FIFO (no data, just return 0) 0 when 3 case @index when 0, 2 then @irq_enable | 0xE0 when 1, 3 then @irq_flags | 0xE0 end end end |
#reset ⇒ Object
34 35 36 37 38 39 40 41 42 |
# File 'lib/psx/cdrom.rb', line 34 def reset @index = 0 @parameters = [] @response = [] @irq_enable = 0 @irq_flags = 0 # bits 0-2 = pending INT type (0..7) @pending = [] # [[int_type, [bytes...]], ...] @stat = DEFAULT_STAT end |
#tick ⇒ Object
Advance one step in the response queue. Call this periodically (e.g. once per VBlank). One delivery per call: a response only appears once the previous one has been acknowledged.
99 100 101 102 103 104 105 106 107 108 |
# File 'lib/psx/cdrom.rb', line 99 def tick return if @pending.empty? return if @irq_flags != 0 # previous IRQ not yet acknowledged return if !@response.empty? # previous response not yet drained type, data = @pending.shift @response.concat(data) @irq_flags = type & 0x07 @interrupts.request(Interrupts::IRQ_CDROM) if (@irq_enable & @irq_flags) != 0 end |
#write8(reg, value) ⇒ Object
64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 |
# File 'lib/psx/cdrom.rb', line 64 def write8(reg, value) v = value & 0xFF case reg & 3 when 0 @index = v & 3 when 1 case @index when 0 then execute_command(v) # other indices: audio map / right CD audio routing — ignore end when 2 case @index when 0 @parameters.push(v) if @parameters.size < 16 when 1 @irq_enable = v & 0x1F # 2/3 = audio routing — ignore end when 3 case @index when 0 # Request register: bit 7 BFRD enables data buffer read; bit 5 SMEN. # Both unused by our stub. when 1 # Ack IRQ flags and optionally reset parameter FIFO (bit 6). @irq_flags &= ~(v & 0x1F) @parameters.clear if (v & 0x40) != 0 # 2/3 = audio volume apply — ignore end end end |