mirror of
https://github.com/Candygoblen123/SwiftNES.git
synced 2024-11-22 09:46:24 -06:00
create Rom.swift and bus.swift
This commit is contained in:
parent
88d6a22bad
commit
915bff96a1
37
Sources/Bus.swift
Normal file
37
Sources/Bus.swift
Normal 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)")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -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
50
Sources/Rom.swift
Normal 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)
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user