mirror of
https://github.com/Candygoblen123/SwiftNES.git
synced 2024-09-19 17:01:01 -05:00
108 lines
2.8 KiB
Swift
108 lines
2.8 KiB
Swift
|
class NesPPU {
|
||
|
public var paletteTable = [UInt8](repeating: 0, count: 32)
|
||
|
public var vram = [UInt8](repeating: 0, count: 2048)
|
||
|
|
||
|
public let mirroring: Mirroring
|
||
|
public var chrRom: [UInt8]
|
||
|
|
||
|
private let addr: AddrRegister = AddrRegister()
|
||
|
private var readBuff: UInt8 = 0
|
||
|
var ctrl = ControlRegister()
|
||
|
let status = StatusRegister()
|
||
|
let scroll = ScrollRegister()
|
||
|
let mask = MaskRegister()
|
||
|
|
||
|
var oamAddr: UInt8 = 0
|
||
|
var oamData = [UInt8](repeating: 0, count: 64 * 4)
|
||
|
|
||
|
init(_ chrRom: [UInt8], _ mirroring: Mirroring) {
|
||
|
self.chrRom = chrRom
|
||
|
self.mirroring = mirroring
|
||
|
}
|
||
|
|
||
|
func writeToPPUAddr(_ value: UInt8) {
|
||
|
addr.update(value)
|
||
|
}
|
||
|
|
||
|
func writeToCtrl(_ value: UInt8) {
|
||
|
ctrl.rawValue = value
|
||
|
}
|
||
|
|
||
|
func incrememtVramAddr() {
|
||
|
addr.increment(ctrl.vramAddrIncrement())
|
||
|
}
|
||
|
|
||
|
func readData() -> UInt8 {
|
||
|
let addr = addr.get()
|
||
|
incrememtVramAddr()
|
||
|
|
||
|
switch addr {
|
||
|
case 0...0x1fff:
|
||
|
let res = readBuff
|
||
|
readBuff = chrRom[Int(addr)]
|
||
|
return res
|
||
|
case 0x2000...0x2fff:
|
||
|
let res = readBuff
|
||
|
readBuff = vram[Int(mirrorVramAddr(addr))]
|
||
|
return res
|
||
|
case 0x3000...0x3eff:
|
||
|
fatalError("addr space 0x3000..0x3eff is not expected to be used, requested = \(addr)")
|
||
|
case 0x3f00...0x3fff:
|
||
|
return self.paletteTable[Int(addr - 0x3f00)]
|
||
|
default:
|
||
|
fatalError("Unexpected access to mirrored space \(addr)")
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func mirrorVramAddr(_ addr: UInt16) -> UInt16 {
|
||
|
let mirroredVram = addr & 0b10111111111111 // mirror down 0x3000-0x3eff to 0x2000 - 0x2eff
|
||
|
let vramIndex = mirroredVram - 0x2000 // to vram array index
|
||
|
let nameTable = vramIndex / 0x400 // to the name index table
|
||
|
return switch (mirroring, nameTable) {
|
||
|
case (.vertical, 2), (.vertical, 3):
|
||
|
vramIndex - 0x800
|
||
|
case (.horizontal, 2):
|
||
|
vramIndex - 0x400
|
||
|
case (.horizontal, 1):
|
||
|
vramIndex - 0x400
|
||
|
case (.horizontal, 3):
|
||
|
vramIndex - 0x800
|
||
|
default:
|
||
|
vramIndex
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func writeToData(_ data: UInt8) {
|
||
|
fatalError("Not Implemented")
|
||
|
}
|
||
|
|
||
|
func readStatus() -> UInt8 {
|
||
|
let data = status.snapshot()
|
||
|
status.resetVblankStatus()
|
||
|
addr.resetLatch()
|
||
|
scroll.resetLatch()
|
||
|
return data
|
||
|
}
|
||
|
|
||
|
func writeToScroll(_ value: UInt8) {
|
||
|
scroll.write(value)
|
||
|
}
|
||
|
|
||
|
func writeToOamAddr(_ value: UInt8) {
|
||
|
oamAddr = value
|
||
|
}
|
||
|
|
||
|
func writeToOamData(_ value: UInt8) {
|
||
|
oamData[Int(oamAddr)] = value
|
||
|
oamAddr = oamAddr &+ 1
|
||
|
}
|
||
|
|
||
|
func readOamData() -> UInt8 {
|
||
|
oamData[Int(oamAddr)]
|
||
|
}
|
||
|
|
||
|
func writeToMask(_ value: UInt8) {
|
||
|
mask.update(value)
|
||
|
}
|
||
|
}
|