Class: PSX::Memory
- Inherits:
-
Object
- Object
- PSX::Memory
- Defined in:
- lib/psx/memory.rb
Constant Summary collapse
- RAM_START =
Memory regions (physical addresses)
0x0000_0000- RAM_SIZE =
2 MB (mirrored 4x in 8 MB region)
0x0020_0000- RAM_MIRROR_MASK =
0x001F_FFFF- SCRATCHPAD_START =
0x1F80_0000- SCRATCHPAD_SIZE =
1 KB
0x0000_0400- IO_START =
0x1F80_1000- IO_SIZE =
0x0000_2000- BIOS_START =
0x1FC0_0000- BIOS_SIZE =
512 KB
0x0008_0000- REGION_MASK =
Region masks for KSEG translation
[ 0xFFFF_FFFF, 0xFFFF_FFFF, 0xFFFF_FFFF, 0xFFFF_FFFF, # KUSEG: 0x0000_0000 - 0x7FFF_FFFF 0x7FFF_FFFF, # KSEG0: 0x8000_0000 - 0x9FFF_FFFF (cached) 0x1FFF_FFFF, # KSEG1: 0xA000_0000 - 0xBFFF_FFFF (uncached) 0xFFFF_FFFF, 0xFFFF_FFFF # KSEG2: 0xC000_0000 - 0xFFFF_FFFF ].freeze
Instance Attribute Summary collapse
-
#cache_isolated ⇒ Object
Returns the value of attribute cache_isolated.
-
#cdrom ⇒ Object
Returns the value of attribute cdrom.
-
#dma ⇒ Object
Returns the value of attribute dma.
-
#gpu ⇒ Object
Returns the value of attribute gpu.
-
#sio0 ⇒ Object
Returns the value of attribute sio0.
-
#spu ⇒ Object
Returns the value of attribute spu.
Instance Method Summary collapse
-
#initialize(bios:, ram:, interrupts: nil, dma: nil, timers: nil, cdrom: nil, sio0: nil, spu: nil) ⇒ Memory
constructor
A new instance of Memory.
- #read16(addr) ⇒ Object
- #read32(addr) ⇒ Object
- #read8(addr) ⇒ Object
- #tick_dma ⇒ Object
- #write16(addr, value) ⇒ Object
- #write32(addr, value) ⇒ Object
- #write8(addr, value) ⇒ Object
Constructor Details
#initialize(bios:, ram:, interrupts: nil, dma: nil, timers: nil, cdrom: nil, sio0: nil, spu: nil) ⇒ Memory
Returns a new instance of Memory.
29 30 31 32 33 34 35 36 37 38 39 40 41 |
# File 'lib/psx/memory.rb', line 29 def initialize(bios:, ram:, interrupts: nil, dma: nil, timers: nil, cdrom: nil, sio0: nil, spu: nil) @bios = bios @ram = ram @interrupts = interrupts @dma = dma @timers = timers @cdrom = cdrom @sio0 = sio0 @spu = spu @gpu = nil # Set later when GPU is created @scratchpad = ("\x00" * SCRATCHPAD_SIZE).b # Force binary encoding @cache_isolated = false end |
Instance Attribute Details
#cache_isolated ⇒ Object
Returns the value of attribute cache_isolated.
27 28 29 |
# File 'lib/psx/memory.rb', line 27 def cache_isolated @cache_isolated end |
#cdrom ⇒ Object
Returns the value of attribute cdrom.
27 28 29 |
# File 'lib/psx/memory.rb', line 27 def cdrom @cdrom end |
#dma ⇒ Object
Returns the value of attribute dma.
27 28 29 |
# File 'lib/psx/memory.rb', line 27 def dma @dma end |
#gpu ⇒ Object
Returns the value of attribute gpu.
27 28 29 |
# File 'lib/psx/memory.rb', line 27 def gpu @gpu end |
#sio0 ⇒ Object
Returns the value of attribute sio0.
27 28 29 |
# File 'lib/psx/memory.rb', line 27 def sio0 @sio0 end |
#spu ⇒ Object
Returns the value of attribute spu.
27 28 29 |
# File 'lib/psx/memory.rb', line 27 def spu @spu end |
Instance Method Details
#read16(addr) ⇒ Object
71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 |
# File 'lib/psx/memory.rb', line 71 def read16(addr) phys = addr & REGION_MASK[(addr >> 29) & 0x7] # RAM (most common) return @ram.read16(phys & RAM_MIRROR_MASK) if phys < 0x0080_0000 # BIOS return @bios.read16(phys - BIOS_START) if phys >= 0x1FC0_0000 && phys < 0x1FC8_0000 # Scratchpad if phys >= 0x1F80_0000 && phys < 0x1F80_0400 offset = phys - SCRATCHPAD_START return @scratchpad.getbyte(offset) | (@scratchpad.getbyte(offset + 1) << 8) end # I/O return io_read16(phys - IO_START) if phys >= 0x1F80_1000 && phys < 0x1F80_3000 0 end |
#read32(addr) ⇒ Object
92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 |
# File 'lib/psx/memory.rb', line 92 def read32(addr) # Fast path: translate virtual to physical phys = addr & REGION_MASK[(addr >> 29) & 0x7] # Fast path for RAM (most common case) if phys < 0x0080_0000 return @ram.read32(phys & RAM_MIRROR_MASK) end # Fast path for BIOS if phys >= 0x1FC0_0000 && phys < 0x1FC8_0000 return @bios.read32(phys - BIOS_START) end # Scratchpad if phys >= 0x1F80_0000 && phys < 0x1F80_0400 offset = phys - SCRATCHPAD_START return @scratchpad.getbyte(offset) | (@scratchpad.getbyte(offset + 1) << 8) | (@scratchpad.getbyte(offset + 2) << 16) | (@scratchpad.getbyte(offset + 3) << 24) end # I/O return io_read32(phys - IO_START) if phys >= 0x1F80_1000 && phys < 0x1F80_3000 # Cache control return 0 if phys >= 0xFFFE_0000 && phys < 0xFFFE_0200 # Expansion regions return 0xFFFF_FFFF if phys >= 0x1F00_0000 && phys < 0x1F80_0000 return 0xFFFF_FFFF if phys >= 0x1F80_2000 && phys < 0x1F80_2100 0 end |
#read8(addr) ⇒ Object
47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 |
# File 'lib/psx/memory.rb', line 47 def read8(addr) phys = addr & REGION_MASK[(addr >> 29) & 0x7] # RAM (most common) return @ram.read8(phys & RAM_MIRROR_MASK) if phys < 0x0080_0000 # BIOS return @bios.read8(phys - BIOS_START) if phys >= 0x1FC0_0000 && phys < 0x1FC8_0000 # Scratchpad if phys >= 0x1F80_0000 && phys < 0x1F80_0400 return @scratchpad.getbyte(phys - SCRATCHPAD_START) end # I/O return io_read8(phys - IO_START) if phys >= 0x1F80_1000 && phys < 0x1F80_3000 # Expansion regions return 0xFF if phys >= 0x1F00_0000 && phys < 0x1F80_0000 return 0xFF if phys >= 0x1F80_2000 && phys < 0x1F80_2100 0 end |
#tick_dma ⇒ Object
43 44 45 |
# File 'lib/psx/memory.rb', line 43 def tick_dma @dma&.tick(self, gpu: @gpu) end |
#write16(addr, value) ⇒ Object
155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 |
# File 'lib/psx/memory.rb', line 155 def write16(addr, value) return if @cache_isolated phys = addr & REGION_MASK[(addr >> 29) & 0x7] # RAM (most common) if phys < 0x0080_0000 @ram.write16(phys & RAM_MIRROR_MASK, value) return end # Scratchpad if phys >= 0x1F80_0000 && phys < 0x1F80_0400 offset = phys - SCRATCHPAD_START @scratchpad.setbyte(offset, value & 0xFF) @scratchpad.setbyte(offset + 1, (value >> 8) & 0xFF) return end # I/O if phys >= 0x1F80_1000 && phys < 0x1F80_3000 io_write16(phys - IO_START, value) return end # BIOS (read-only) warn format("Write to BIOS at 0x%08X", addr) if phys >= 0x1FC0_0000 && phys < 0x1FC8_0000 end |
#write32(addr, value) ⇒ Object
184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 |
# File 'lib/psx/memory.rb', line 184 def write32(addr, value) return if @cache_isolated # Fast path: translate virtual to physical phys = addr & REGION_MASK[(addr >> 29) & 0x7] # Fast path for RAM (most common case) if phys < 0x0080_0000 @ram.write32(phys & RAM_MIRROR_MASK, value) return end # Scratchpad if phys >= 0x1F80_0000 && phys < 0x1F80_0400 offset = phys - SCRATCHPAD_START @scratchpad.setbyte(offset, value & 0xFF) @scratchpad.setbyte(offset + 1, (value >> 8) & 0xFF) @scratchpad.setbyte(offset + 2, (value >> 16) & 0xFF) @scratchpad.setbyte(offset + 3, (value >> 24) & 0xFF) return end # I/O if phys >= 0x1F80_1000 && phys < 0x1F80_3000 io_write32(phys - IO_START, value) return end # BIOS (read-only) if phys >= 0x1FC0_0000 && phys < 0x1FC8_0000 warn format("Write to BIOS at 0x%08X", addr) return end # Cache control and expansion regions - ignore writes end |
#write8(addr, value) ⇒ Object
128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 |
# File 'lib/psx/memory.rb', line 128 def write8(addr, value) return if @cache_isolated # Writes go to cache, not memory phys = addr & REGION_MASK[(addr >> 29) & 0x7] # RAM (most common) if phys < 0x0080_0000 @ram.write8(phys & RAM_MIRROR_MASK, value) return end # Scratchpad if phys >= 0x1F80_0000 && phys < 0x1F80_0400 @scratchpad.setbyte(phys - SCRATCHPAD_START, value & 0xFF) return end # I/O if phys >= 0x1F80_1000 && phys < 0x1F80_3000 io_write8(phys - IO_START, value) return end # BIOS (read-only) warn format("Write to BIOS at 0x%08X", addr) if phys >= 0x1FC0_0000 && phys < 0x1FC8_0000 end |