Class: PSX::SPU
- Inherits:
-
Object
- Object
- PSX::SPU
- Defined in:
- lib/psx/spu.rb
Overview
SPU stub — enough to satisfy programs that probe SPUCNT/SPUSTAT and to round-trip data through SPU RAM via FIFO and DMA channel 4.
No audio synthesis. Voice/reverb/etc. registers read back as zero.
Constant Summary collapse
- RAM_SIZE =
512 * 1024
- SPU_TRANSFER_ADDR =
IO offsets relative to 0x1F801000
0xDA6- SPU_FIFO =
0xDA8- SPUCNT =
0xDAA- SPUDTC =
0xDAC- SPUSTAT =
0xDAE- MODE_STOP =
SPUCNT bits 4-5 = transfer mode
0- MODE_MANUAL =
1- MODE_DMA_W =
2- MODE_DMA_R =
3
Instance Method Summary collapse
-
#dma_read_word ⇒ Object
Used by DMA channel 4.
- #dma_write_word(word) ⇒ Object
-
#initialize ⇒ SPU
constructor
A new instance of SPU.
- #read16(offset) ⇒ Object
- #write16(offset, value) ⇒ Object
Constructor Details
Instance Method Details
#dma_read_word ⇒ Object
Used by DMA channel 4. Returns one 32-bit word read from SPU RAM at the current transfer pointer, advancing it.
75 76 77 78 79 80 81 82 |
# File 'lib/psx/spu.rb', line 75 def dma_read_word word = 0 4.times do |i| word |= @ram.getbyte(@current_addr) << (i * 8) @current_addr = (@current_addr + 1) & (RAM_SIZE - 1) end word end |
#dma_write_word(word) ⇒ Object
84 85 86 87 88 89 |
# File 'lib/psx/spu.rb', line 84 def dma_write_word(word) 4.times do |i| @ram.setbyte(@current_addr, (word >> (i * 8)) & 0xFF) @current_addr = (@current_addr + 1) & (RAM_SIZE - 1) end end |
#read16(offset) ⇒ Object
34 35 36 37 38 39 40 41 42 |
# File 'lib/psx/spu.rb', line 34 def read16(offset) case offset when SPU_TRANSFER_ADDR then @transfer_addr >> 3 when SPUCNT then @cnt when SPUDTC then @dtc when SPUSTAT then @stat else 0 end end |
#write16(offset, value) ⇒ Object
44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 |
# File 'lib/psx/spu.rb', line 44 def write16(offset, value) v = value & 0xFFFF case offset when SPU_TRANSFER_ADDR @transfer_addr = (v * 8) & (RAM_SIZE - 1) @current_addr = @transfer_addr when SPU_FIFO if mode == MODE_MANUAL # In ManualWrite mode each FIFO write streams straight to SPU RAM, # advancing the transfer pointer. write_word_to_ram(v) else # In other modes the data is buffered; on the transition to # ManualWrite the buffer drains in order. @fifo << v end when SPUCNT prev_mode = mode @cnt = v # SPUSTAT bits 0-5 mirror SPUCNT bits 0-5 (real hardware applies a # short delay; we apply immediately, which is enough for software # that polls in a loop). @stat = (@stat & ~0x3F) | (@cnt & 0x3F) drain_fifo if mode == MODE_MANUAL && prev_mode != MODE_MANUAL when SPUDTC @dtc = v end end |