create Rom.swift and bus.swift

This commit is contained in:
Andrew Glaze 2024-07-19 22:52:46 -04:00
parent 88d6a22bad
commit 915bff96a1
3 changed files with 100 additions and 5 deletions

37
Sources/Bus.swift Normal file
View File

@ -0,0 +1,37 @@
class Bus {
var cpuVram: [UInt8] = .init(repeating: 0, count: 2048)
fileprivate let RAM : UInt16 = 0x0000
fileprivate let RAM_MIRRORS_END: UInt16 = 0x1FFF
fileprivate let PPU_REGISTERS: UInt16 = 0x2000
fileprivate let PPU_REGISTERS_MIRRORS_END: UInt16 = 0x3FFF
}
extension Bus: Memory {
func memRead(_ addr: UInt16) -> UInt8 {
switch addr {
case RAM...RAM_MIRRORS_END:
let mirrorDownAddr = addr & 0b00000111_11111111
return self.cpuVram[Int(mirrorDownAddr)]
case PPU_REGISTERS...PPU_REGISTERS_MIRRORS_END:
let mirrorDownAddr = addr & 0b00100000_00000111;
fatalError("PPU not implemented yet")
default:
print("Ignoring mem access at \(addr)")
return 0
}
}
func memWrite(_ addr: UInt16, data: UInt8) {
switch addr {
case RAM...RAM_MIRRORS_END:
let mirrorDownAddr = addr & 0b11111111111
self.cpuVram[Int(mirrorDownAddr)] = data
case PPU_REGISTERS...PPU_REGISTERS_MIRRORS_END:
let mirrorDownAddr = addr & 0b00100000_00000111
fatalError("PPU is not implemented yet!")
default:
print("Ignorming mem-write at \(addr)")
}
}
}

View File

@ -37,7 +37,7 @@ class CPU {
var stackPointer: UInt8 = STACK_RESET var stackPointer: UInt8 = STACK_RESET
var status: CPUFlags = [.interruptDisable, .break2] var status: CPUFlags = [.interruptDisable, .break2]
var programCounter: UInt16 = 0 var programCounter: UInt16 = 0
private var memory = [UInt8](repeating: 0, count: 0xFFFF) var bus = Bus()
func getOpperandAddress(_ mode: AddressingMode) -> UInt16 { func getOpperandAddress(_ mode: AddressingMode) -> UInt16 {
@ -98,7 +98,7 @@ class CPU {
} }
func load(_ program: [UInt8]) { func load(_ program: [UInt8]) {
memory[0x0600 ..< (0x0600 + program.count)] = program[0..<program.count] //memory[0x0600 ..< (0x0600 + program.count)] = program[0..<program.count]
memWriteU16(0xFFFC, data: 0x0600) memWriteU16(0xFFFC, data: 0x0600)
} }
@ -108,7 +108,7 @@ class CPU {
func run(onCycle: @escaping () -> (), onComplete: @escaping () -> ()) { func run(onCycle: @escaping () -> (), onComplete: @escaping () -> ()) {
let opcodes = OPCODES_MAP let opcodes = OPCODES_MAP
Timer.scheduledTimer(withTimeInterval: 0.00007, repeats: true) { [self] timer in _ = Timer.scheduledTimer(withTimeInterval: 0.00007, repeats: true) { [self] timer in
processOpcodes(onCycle: onCycle, opcodes: opcodes, timer: timer) { processOpcodes(onCycle: onCycle, opcodes: opcodes, timer: timer) {
onComplete() onComplete()
} }
@ -390,11 +390,19 @@ class CPU {
extension CPU: Memory { extension CPU: Memory {
func memRead(_ addr: UInt16) -> UInt8 { func memRead(_ addr: UInt16) -> UInt8 {
memory[Int(addr)] return bus.memRead(addr)
} }
func memWrite(_ addr: UInt16, data: UInt8) { func memWrite(_ addr: UInt16, data: UInt8) {
memory[Int(addr)] = data bus.memWrite(addr, data: data)
}
func memReadU16(_ addr: UInt16) -> UInt16 {
return bus.memReadU16(addr)
}
func memWriteU16(_ addr: UInt16, data: UInt16) {
bus.memWriteU16(addr, data: data)
} }
} }

50
Sources/Rom.swift Normal file
View File

@ -0,0 +1,50 @@
struct Rom {
fileprivate let PRG_ROM_PAGE_SIZE = 16384
fileprivate let CHR_ROM_PAGE_SIZE = 8192
var program: [UInt8]
var character: [UInt8]
var mapper: UInt8
var screenMirror: Mirroring
init(_ raw: [UInt8]) throws {
guard raw[0...4] == [0x4E, 0x45, 0x53, 0x1A] else { throw HeaderParseError.notINES("File is not in iNES file format.") }
mapper = (raw[7] & 0b1111_0000) | (raw[6] >> 4)
let inesVer = (raw[7] >> 2) & 0b11
guard inesVer == 0 else { throw HeaderParseError.iNes2("iNES2.0 format not supported.") }
let fourScreen = raw[6] & 0b1000 != 0
let vertMirroring = raw[6] & 0b1 != 0
screenMirror = switch (fourScreen, vertMirroring) {
case (true, _):
Mirroring.fourScreen
case (false, true):
Mirroring.vertical
case (false, false):
Mirroring.horizontal
}
let programSize = Int(raw[4]) * PRG_ROM_PAGE_SIZE
let characterSize = Int(raw[5]) * CHR_ROM_PAGE_SIZE
let skipTrainer = raw[6] & 0b100 != 0
let programStart = 16 + (skipTrainer ? 512 : 0)
let characterStart = programStart + programSize
program = Array(raw[programStart...(programStart + programSize)])
character = Array(raw[characterStart...(characterStart + characterSize)])
}
}
enum Mirroring {
case vertical
case horizontal
case fourScreen
}
enum HeaderParseError: Error {
case notINES(String)
case iNes2(String)
}