mirror of
https://github.com/Candygoblen123/SwiftNES.git
synced 2024-11-24 18:06:47 -06:00
test snake game
This commit is contained in:
parent
c441014511
commit
5bdfebdf13
@ -1,3 +1,6 @@
|
|||||||
|
import Foundation
|
||||||
|
import SDL
|
||||||
|
|
||||||
enum AddressingMode {
|
enum AddressingMode {
|
||||||
case Immediate
|
case Immediate
|
||||||
case ZeroPage
|
case ZeroPage
|
||||||
@ -61,7 +64,6 @@ class CPU {
|
|||||||
return base &+ UInt16(register_y)
|
return base &+ UInt16(register_y)
|
||||||
case .Indirect_X:
|
case .Indirect_X:
|
||||||
let base = memRead(programCounter)
|
let base = memRead(programCounter)
|
||||||
|
|
||||||
let ptr = UInt8(base) &+ register_x
|
let ptr = UInt8(base) &+ register_x
|
||||||
let lo = memRead(UInt16(ptr))
|
let lo = memRead(UInt16(ptr))
|
||||||
let hi = memRead(UInt16(ptr &+ 1))
|
let hi = memRead(UInt16(ptr &+ 1))
|
||||||
@ -101,184 +103,189 @@ class CPU {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func run() {
|
func run() {
|
||||||
run {
|
run {}
|
||||||
|
}
|
||||||
|
|
||||||
|
func run(callback: @escaping () -> ()) {
|
||||||
|
let opcodes = OPCODES_MAP
|
||||||
|
Timer.scheduledTimer(withTimeInterval: 0.00007, repeats: true) { [self] timer in
|
||||||
|
processOpcodes(callback: callback, opcodes: opcodes, timer: timer)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func run(callback: () -> ()) {
|
func processOpcodes(callback: () -> (), opcodes: [UInt8: OpCode], timer: Timer) {
|
||||||
let opcodes = OPCODES_MAP
|
callback()
|
||||||
|
let code = memRead(programCounter)
|
||||||
|
programCounter += 1
|
||||||
|
|
||||||
while true {
|
let programCounterState = programCounter
|
||||||
callback()
|
guard let opcode = opcodes[code] else {fatalError("OpCode \(code) not recgonized!")}
|
||||||
let code = memRead(programCounter)
|
// print(programCounter, opcode.mnemonic)
|
||||||
programCounter += 1
|
|
||||||
|
|
||||||
let programCounterState = programCounter
|
switch code {
|
||||||
guard let opcode = opcodes[code] else {fatalError("OpCode \(code) not recgonized!")}
|
/// LDA
|
||||||
|
case 0xa9, 0xa5, 0xb5, 0xad, 0xbd, 0xb9, 0xa1, 0xb1:
|
||||||
switch code {
|
lda(opcode.mode)
|
||||||
/// LDA
|
/// STA
|
||||||
case 0xa9, 0xa5, 0xb5, 0xad, 0xbd, 0xb9, 0xa1, 0xb1:
|
case 0x85, 0x95, 0x8d, 0x9d, 0x99, 0x81, 0x91:
|
||||||
lda(opcode.mode)
|
sta(opcode.mode)
|
||||||
/// STA
|
case 0xd8:
|
||||||
case 0x85, 0x95, 0x8d, 0x9d, 0x99, 0x81, 0x91:
|
status.remove(.decimalMode)
|
||||||
sta(opcode.mode)
|
case 0x58:
|
||||||
case 0xd8:
|
status.remove(.interruptDisable)
|
||||||
status.remove(.decimalMode)
|
case 0xb8:
|
||||||
case 0x58:
|
status.remove(.overflow)
|
||||||
status.remove(.interruptDisable)
|
case 0x18:
|
||||||
case 0xb8:
|
clearCarryFlag()
|
||||||
status.remove(.overflow)
|
case 0x38:
|
||||||
case 0x18:
|
setCarryFlag()
|
||||||
clearCarryFlag()
|
case 0x78:
|
||||||
case 0x38:
|
status.insert(.interruptDisable)
|
||||||
setCarryFlag()
|
case 0xf8:
|
||||||
case 0x78:
|
status.insert(.decimalMode)
|
||||||
status.insert(.interruptDisable)
|
case 0x48:
|
||||||
case 0xf8:
|
stackPush(register_a)
|
||||||
status.insert(.decimalMode)
|
case 0x68:
|
||||||
case 0x48:
|
pla()
|
||||||
stackPush(register_a)
|
case 0x08:
|
||||||
case 0x68:
|
php()
|
||||||
pla()
|
case 0x28:
|
||||||
case 0x08:
|
plp()
|
||||||
php()
|
case 0x69, 0x65, 0x75, 0x6d, 0x7d, 0x79, 0x61, 0x71:
|
||||||
case 0x28:
|
adc(opcode.mode)
|
||||||
plp()
|
case 0xe9, 0xe5, 0xf5, 0xed, 0xfd, 0xf9, 0xe1, 0xf1:
|
||||||
case 0x69, 0x65, 0x75, 0x6d, 0x7d, 0x79, 0x61, 0x71:
|
sbc(opcode.mode)
|
||||||
adc(opcode.mode)
|
case 0x29, 0x25, 0x35, 0x2d, 0x3d, 0x39, 0x21, 0x31:
|
||||||
case 0xe9, 0xe5, 0xf5, 0xed, 0xfd, 0xf9, 0xe1, 0xf1:
|
and(opcode.mode)
|
||||||
sbc(opcode.mode)
|
case 0x49, 0x45, 0x55, 0x4d, 0x5d, 0x59, 0x41, 0x51:
|
||||||
case 0x29, 0x25, 0x35, 0x2d, 0x3d, 0x39, 0x21, 0x31:
|
eor(opcode.mode)
|
||||||
and(opcode.mode)
|
case 0x09, 0x05, 0x15, 0x0d, 0x1d, 0x19, 0x01, 0x11:
|
||||||
case 0x49, 0x45, 0x55, 0x4d, 0x5d, 0x59, 0x41, 0x51:
|
ora(opcode.mode)
|
||||||
eor(opcode.mode)
|
case 0x4a:
|
||||||
case 0x09, 0x05, 0x15, 0x0d, 0x1d, 0x19, 0x01, 0x11:
|
lsrAccumulator()
|
||||||
ora(opcode.mode)
|
case 0x46, 0x56, 0x4e, 0x5e:
|
||||||
case 0x4a:
|
_ = lsr(opcode.mode)
|
||||||
lsrAccumulator()
|
case 0x0a:
|
||||||
case 0x46, 0x56, 0x4e, 0x5e:
|
aslAccumulator()
|
||||||
_ = lsr(opcode.mode)
|
case 0x06, 0x16, 0x0e, 0x1e:
|
||||||
case 0x0a:
|
_ = asl(opcode.mode)
|
||||||
aslAccumulator()
|
case 0x2a:
|
||||||
case 0x06, 0x16, 0x0e, 0x1e:
|
rolAccumulator()
|
||||||
_ = asl(opcode.mode)
|
case 0x26, 0x36, 0x2e, 0x3e:
|
||||||
case 0x2a:
|
_ = rol(opcode.mode)
|
||||||
rolAccumulator()
|
case 0x6a:
|
||||||
case 0x26, 0x36, 0x2e, 0x3e:
|
rorAccumulator()
|
||||||
_ = rol(opcode.mode)
|
case 0x66, 0x76, 0x6e, 0x7e:
|
||||||
case 0x6a:
|
_ = ror(opcode.mode)
|
||||||
rorAccumulator()
|
case 0xe6, 0xf6, 0xee, 0xfe:
|
||||||
case 0x66, 0x76, 0x6e, 0x7e:
|
_ = inc(opcode.mode)
|
||||||
_ = ror(opcode.mode)
|
case 0xc8:
|
||||||
case 0xe6, 0xf6, 0xee, 0xfe:
|
iny()
|
||||||
_ = inc(opcode.mode)
|
case 0xc6, 0xd6, 0xce, 0xde:
|
||||||
case 0xc8:
|
_ = dec(opcode.mode)
|
||||||
iny()
|
case 0xca:
|
||||||
case 0xc6, 0xd6, 0xce, 0xde:
|
dex()
|
||||||
_ = dec(opcode.mode)
|
case 0x88:
|
||||||
case 0xca:
|
dey()
|
||||||
dex()
|
case 0xc9, 0xc5, 0xd5, 0xcd, 0xdd, 0xd9, 0xc1, 0xd1:
|
||||||
case 0x88:
|
compare(mode: opcode.mode, compare_with: register_a)
|
||||||
dey()
|
case 0xc0, 0xc4, 0xcc:
|
||||||
case 0xc9, 0xc5, 0xd5, 0xcd, 0xdd, 0xd9, 0xc1, 0xd1:
|
compare(mode: opcode.mode, compare_with: register_y)
|
||||||
compare(mode: opcode.mode, compare_with: register_a)
|
case 0xe0, 0xe4, 0xec:
|
||||||
case 0xc0, 0xc4, 0xcc:
|
compare(mode: opcode.mode, compare_with: register_x)
|
||||||
compare(mode: opcode.mode, compare_with: register_y)
|
case 0x4c:
|
||||||
case 0xe0, 0xe4, 0xec:
|
let memAddr = memReadU16(programCounter)
|
||||||
compare(mode: opcode.mode, compare_with: register_x)
|
programCounter = memAddr
|
||||||
case 0x4c:
|
case 0x6c:
|
||||||
let memAddr = memReadU16(programCounter)
|
let memAddr = memReadU16(programCounter)
|
||||||
programCounter = memAddr
|
//6502 bug mode with with page boundary:
|
||||||
case 0x6c:
|
// if address $3000 contains $40, $30FF contains $80, and $3100 contains $50,
|
||||||
let memAddr = memReadU16(programCounter)
|
// the result of JMP ($30FF) will be a transfer of control to $4080 rather than $5080 as you intended
|
||||||
//6502 bug mode with with page boundary:
|
// i.e. the 6502 took the low byte of the address from $30FF and the high byte from $3000
|
||||||
// if address $3000 contains $40, $30FF contains $80, and $3100 contains $50,
|
let indirectRef: UInt16
|
||||||
// the result of JMP ($30FF) will be a transfer of control to $4080 rather than $5080 as you intended
|
if memAddr & 0x00ff == 0x00ff {
|
||||||
// i.e. the 6502 took the low byte of the address from $30FF and the high byte from $3000
|
let lo = memRead(memAddr)
|
||||||
let indirectRef: UInt16
|
let hi = memRead(memAddr & 0x00ff)
|
||||||
if memAddr & 0x00ff == 0x00ff {
|
indirectRef = UInt16(hi) << 8 | UInt16(lo)
|
||||||
let lo = memRead(memAddr)
|
} else {
|
||||||
let hi = memRead(memAddr & 0x00ff)
|
indirectRef = memReadU16(memAddr)
|
||||||
indirectRef = UInt16(hi) << 8 | UInt16(lo)
|
|
||||||
} else {
|
|
||||||
indirectRef = memReadU16(memAddr)
|
|
||||||
}
|
|
||||||
|
|
||||||
programCounter = indirectRef
|
|
||||||
|
|
||||||
case 0x20:
|
|
||||||
stackPushU16(programCounter + 2 - 1)
|
|
||||||
let targetAddr = memReadU16(programCounter)
|
|
||||||
programCounter = targetAddr
|
|
||||||
case 0x60:
|
|
||||||
programCounter = stackPopU16() + 1
|
|
||||||
case 0x40:
|
|
||||||
status.rawValue = stackPop()
|
|
||||||
status.remove(.break1)
|
|
||||||
status.remove(.break2)
|
|
||||||
|
|
||||||
programCounter = stackPopU16()
|
|
||||||
case 0xd0:
|
|
||||||
branch(!status.contains(.zero))
|
|
||||||
case 0x70:
|
|
||||||
branch(status.contains(.overflow))
|
|
||||||
case 0x50:
|
|
||||||
branch(!status.contains(.overflow))
|
|
||||||
case 0x10:
|
|
||||||
branch(!status.contains(.negative))
|
|
||||||
case 0x30:
|
|
||||||
branch(status.contains(.negative))
|
|
||||||
case 0xf0:
|
|
||||||
branch(status.contains(.zero))
|
|
||||||
case 0xb0:
|
|
||||||
branch(status.contains(.carry))
|
|
||||||
case 0x90:
|
|
||||||
branch(!status.contains(.carry))
|
|
||||||
case 0x24, 0x2c:
|
|
||||||
bit(opcode.mode)
|
|
||||||
case 0x86, 0x96, 0x8e:
|
|
||||||
let addr = getOpperandAddress(opcode.mode)
|
|
||||||
memWrite(addr, data: register_x)
|
|
||||||
case 0x84, 0x94, 0x8c:
|
|
||||||
let addr = getOpperandAddress(opcode.mode)
|
|
||||||
memWrite(addr, data: register_y)
|
|
||||||
case 0xa2, 0xa6, 0xb6, 0xae, 0xbe:
|
|
||||||
ldx(opcode.mode)
|
|
||||||
case 0xa0, 0xa4, 0xb4, 0xac, 0xbc:
|
|
||||||
ldy(opcode.mode)
|
|
||||||
case 0xea:
|
|
||||||
continue
|
|
||||||
case 0xa8:
|
|
||||||
register_y = register_x
|
|
||||||
updateZeroAndNegativeFlags(register_y)
|
|
||||||
case 0xba:
|
|
||||||
register_x = stackPointer
|
|
||||||
updateZeroAndNegativeFlags(register_x)
|
|
||||||
case 0x8a:
|
|
||||||
register_a = register_x
|
|
||||||
updateZeroAndNegativeFlags(register_a)
|
|
||||||
case 0x9a:
|
|
||||||
stackPointer = register_x
|
|
||||||
case 0x98:
|
|
||||||
register_a = register_y
|
|
||||||
updateZeroAndNegativeFlags(register_a)
|
|
||||||
/// TAX
|
|
||||||
case 0xaa:
|
|
||||||
tax()
|
|
||||||
/// INX
|
|
||||||
case 0xe8:
|
|
||||||
inx()
|
|
||||||
/// BRK
|
|
||||||
case 0x00:
|
|
||||||
return
|
|
||||||
default: fatalError("TODO!")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if programCounterState == programCounter {
|
programCounter = indirectRef
|
||||||
programCounter += UInt16(opcode.len - 1)
|
|
||||||
}
|
case 0x20:
|
||||||
|
stackPushU16(programCounter + 2 - 1)
|
||||||
|
let targetAddr = memReadU16(programCounter)
|
||||||
|
programCounter = targetAddr
|
||||||
|
case 0x60:
|
||||||
|
programCounter = stackPopU16() + 1
|
||||||
|
case 0x40:
|
||||||
|
status.rawValue = stackPop()
|
||||||
|
status.remove(.break1)
|
||||||
|
status.remove(.break2)
|
||||||
|
|
||||||
|
programCounter = stackPopU16()
|
||||||
|
case 0xd0:
|
||||||
|
branch(!status.contains(.zero))
|
||||||
|
case 0x70:
|
||||||
|
branch(status.contains(.overflow))
|
||||||
|
case 0x50:
|
||||||
|
branch(!status.contains(.overflow))
|
||||||
|
case 0x10:
|
||||||
|
branch(!status.contains(.negative))
|
||||||
|
case 0x30:
|
||||||
|
branch(status.contains(.negative))
|
||||||
|
case 0xf0:
|
||||||
|
branch(status.contains(.zero))
|
||||||
|
case 0xb0:
|
||||||
|
branch(status.contains(.carry))
|
||||||
|
case 0x90:
|
||||||
|
branch(!status.contains(.carry))
|
||||||
|
case 0x24, 0x2c:
|
||||||
|
bit(opcode.mode)
|
||||||
|
case 0x86, 0x96, 0x8e:
|
||||||
|
let addr = getOpperandAddress(opcode.mode)
|
||||||
|
memWrite(addr, data: register_x)
|
||||||
|
case 0x84, 0x94, 0x8c:
|
||||||
|
let addr = getOpperandAddress(opcode.mode)
|
||||||
|
memWrite(addr, data: register_y)
|
||||||
|
case 0xa2, 0xa6, 0xb6, 0xae, 0xbe:
|
||||||
|
ldx(opcode.mode)
|
||||||
|
case 0xa0, 0xa4, 0xb4, 0xac, 0xbc:
|
||||||
|
ldy(opcode.mode)
|
||||||
|
case 0xea:
|
||||||
|
return
|
||||||
|
case 0xa8:
|
||||||
|
register_y = register_x
|
||||||
|
updateZeroAndNegativeFlags(register_y)
|
||||||
|
case 0xba:
|
||||||
|
register_x = stackPointer
|
||||||
|
updateZeroAndNegativeFlags(register_x)
|
||||||
|
case 0x8a:
|
||||||
|
register_a = register_x
|
||||||
|
updateZeroAndNegativeFlags(register_a)
|
||||||
|
case 0x9a:
|
||||||
|
stackPointer = register_x
|
||||||
|
case 0x98:
|
||||||
|
register_a = register_y
|
||||||
|
updateZeroAndNegativeFlags(register_a)
|
||||||
|
/// TAX
|
||||||
|
case 0xaa:
|
||||||
|
tax()
|
||||||
|
/// INX
|
||||||
|
case 0xe8:
|
||||||
|
inx()
|
||||||
|
/// BRK
|
||||||
|
case 0x00:
|
||||||
|
timer.invalidate()
|
||||||
|
SDL_DestroyWindow(window)
|
||||||
|
SDL_Quit()
|
||||||
|
exit(0)
|
||||||
|
default: fatalError("TODO!")
|
||||||
|
}
|
||||||
|
|
||||||
|
if programCounterState == programCounter {
|
||||||
|
programCounter += UInt16(opcode.len - 1)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -323,7 +330,7 @@ class CPU {
|
|||||||
status.remove(.carry)
|
status.remove(.carry)
|
||||||
}
|
}
|
||||||
|
|
||||||
let result = UInt8(sum)
|
let result = UInt8(truncatingIfNeeded: sum)
|
||||||
|
|
||||||
if (data ^ result) & (result ^ register_a) & 0x80 != 0 {
|
if (data ^ result) & (result ^ register_a) & 0x80 != 0 {
|
||||||
status.insert(.overflow)
|
status.insert(.overflow)
|
||||||
@ -373,7 +380,6 @@ class CPU {
|
|||||||
func branch(_ condition: Bool) {
|
func branch(_ condition: Bool) {
|
||||||
if condition {
|
if condition {
|
||||||
let addr = memRead(programCounter)
|
let addr = memRead(programCounter)
|
||||||
// print(addr)
|
|
||||||
let jump: Int8 = Int8(bitPattern: addr)
|
let jump: Int8 = Int8(bitPattern: addr)
|
||||||
let jump_addr = programCounter &+ 1 &+ UInt16(bitPattern: Int16(jump))
|
let jump_addr = programCounter &+ 1 &+ UInt16(bitPattern: Int16(jump))
|
||||||
|
|
||||||
|
@ -61,8 +61,8 @@ extension CPU {
|
|||||||
func sbc(_ mode: AddressingMode) {
|
func sbc(_ mode: AddressingMode) {
|
||||||
let addr = getOpperandAddress(mode)
|
let addr = getOpperandAddress(mode)
|
||||||
let data = memRead(addr)
|
let data = memRead(addr)
|
||||||
let res = Int8(data) &* -1
|
let res = Int8(bitPattern: data) &* -1
|
||||||
addToRegisterA(UInt8(res &- 1))
|
addToRegisterA(UInt8(bitPattern: res &- 1))
|
||||||
}
|
}
|
||||||
|
|
||||||
func adc(_ mode: AddressingMode) {
|
func adc(_ mode: AddressingMode) {
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
// https://docs.swift.org/swift-book
|
// https://docs.swift.org/swift-book
|
||||||
|
|
||||||
import SDL
|
import SDL
|
||||||
|
import Foundation
|
||||||
|
|
||||||
guard SDL_Init(SDL_INIT_VIDEO) == 0 else {
|
guard SDL_Init(SDL_INIT_VIDEO) == 0 else {
|
||||||
fatalError("SDL could not initialize! SDL_Error: \(String(cString: SDL_GetError()))")
|
fatalError("SDL could not initialize! SDL_Error: \(String(cString: SDL_GetError()))")
|
||||||
@ -17,6 +18,81 @@ let canvas = SDL_CreateRenderer(window, -1, SDL_RENDERER_PRESENTVSYNC.rawValue)
|
|||||||
|
|
||||||
SDL_RenderSetScale(canvas, 10.0, 10.0)
|
SDL_RenderSetScale(canvas, 10.0, 10.0)
|
||||||
|
|
||||||
|
var texture = SDL_CreateTexture(canvas, SDL_PIXELFORMAT_RGB24.rawValue, Int32(SDL_TEXTUREACCESS_TARGET.rawValue), 32, 32)
|
||||||
|
|
||||||
|
var event = SDL_Event()
|
||||||
|
var quit = false
|
||||||
|
|
||||||
|
func handleUserInput(_ cpu: CPU, event: inout SDL_Event) {
|
||||||
|
while SDL_PollEvent(&event) > 0 {
|
||||||
|
if event.type == SDL_QUIT.rawValue {
|
||||||
|
SDL_DestroyWindow(window)
|
||||||
|
SDL_Quit()
|
||||||
|
exit(0)
|
||||||
|
}
|
||||||
|
if event.type == SDL_KEYDOWN.rawValue {
|
||||||
|
switch SDL_KeyCode(UInt32(event.key.keysym.sym)) {
|
||||||
|
case SDLK_ESCAPE:
|
||||||
|
SDL_DestroyWindow(window)
|
||||||
|
SDL_Quit()
|
||||||
|
exit(0)
|
||||||
|
case SDLK_w:
|
||||||
|
cpu.memWrite(0xff, data: 0x77)
|
||||||
|
case SDLK_a:
|
||||||
|
cpu.memWrite(0xff, data: 0x61)
|
||||||
|
case SDLK_s:
|
||||||
|
cpu.memWrite(0xff, data: 0x73)
|
||||||
|
case SDLK_d:
|
||||||
|
cpu.memWrite(0xff, data: 0x64)
|
||||||
|
default:
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func color(_ byte: UInt8) -> SDL_Color {
|
||||||
|
switch byte{
|
||||||
|
case 0:
|
||||||
|
return SDL_Color(r: 0, g: 0, b: 0, a: 255)
|
||||||
|
case 1:
|
||||||
|
return SDL_Color(r: 255, g: 255, b: 255, a: 255)
|
||||||
|
case 2, 9:
|
||||||
|
return SDL_Color(r: 128, g: 128, b: 128, a: 255)
|
||||||
|
case 3, 10:
|
||||||
|
return SDL_Color(r: 255, g: 0, b: 0, a: 255)
|
||||||
|
case 4, 11:
|
||||||
|
return SDL_Color(r: 0, g: 255, b: 0, a: 255)
|
||||||
|
case 5, 12:
|
||||||
|
return SDL_Color(r: 0, g: 0, b: 255, a: 255)
|
||||||
|
case 6, 13:
|
||||||
|
return SDL_Color(r: 255, g: 0, b: 255, a: 255)
|
||||||
|
case 7, 14:
|
||||||
|
return SDL_Color(r: 255, g: 255, b: 0, a: 255)
|
||||||
|
default:
|
||||||
|
return SDL_Color(r: 0, g: 255, b: 255, a: 255)
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func readScreenState(_ cpu: CPU, frame: inout [UInt8]) -> Bool {
|
||||||
|
|
||||||
|
var frame_idx = 0
|
||||||
|
var update = false
|
||||||
|
for i in 0x0200..<0x600 {
|
||||||
|
let color_idx = cpu.memRead(UInt16(i))
|
||||||
|
let color = color(color_idx)
|
||||||
|
let (b1, b2, b3) = (color.r, color.b, color.g)
|
||||||
|
if frame[frame_idx] != b1 || frame[frame_idx + 1] != b2 || frame[frame_idx + 2] != b3 {
|
||||||
|
frame[frame_idx] = b1;
|
||||||
|
frame[frame_idx + 1] = b2;
|
||||||
|
frame[frame_idx + 2] = b3;
|
||||||
|
update = true;
|
||||||
|
}
|
||||||
|
frame_idx += 3
|
||||||
|
}
|
||||||
|
return update
|
||||||
|
}
|
||||||
|
|
||||||
let gameCode: [UInt8] = [
|
let gameCode: [UInt8] = [
|
||||||
0x20, 0x06, 0x06, 0x20, 0x38, 0x06, 0x20, 0x0d, 0x06, 0x20, 0x2a, 0x06, 0x60, 0xa9, 0x02, 0x85,
|
0x20, 0x06, 0x06, 0x20, 0x38, 0x06, 0x20, 0x0d, 0x06, 0x20, 0x2a, 0x06, 0x60, 0xa9, 0x02, 0x85,
|
||||||
@ -41,19 +117,23 @@ let gameCode: [UInt8] = [
|
|||||||
0xea, 0xca, 0xd0, 0xfb, 0x60
|
0xea, 0xca, 0xd0, 0xfb, 0x60
|
||||||
]
|
]
|
||||||
|
|
||||||
print(gameCode[32])
|
|
||||||
|
|
||||||
|
|
||||||
var cpu = CPU()
|
var cpu = CPU()
|
||||||
cpu.load(gameCode)
|
cpu.load(gameCode)
|
||||||
cpu.reset()
|
cpu.reset()
|
||||||
|
|
||||||
cpu.run {
|
var screenState = [UInt8](repeating: 0, count: 32 * 3 * 32)
|
||||||
// TODO:
|
var rng = SystemRandomNumberGenerator()
|
||||||
// read user input and write it to mem[0xFF]
|
|
||||||
// update mem[0xFE] with new Random Number
|
|
||||||
// read mem mapped screen state
|
|
||||||
// render screen state
|
|
||||||
|
|
||||||
|
cpu.run() {
|
||||||
|
handleUserInput(cpu, event: &event)
|
||||||
|
cpu.memWrite(0xfe, data: UInt8.random(in: 1...16, using: &rng))
|
||||||
|
|
||||||
|
if readScreenState(cpu, frame: &screenState) {
|
||||||
|
SDL_UpdateTexture(texture, nil, screenState, 32 * 3)
|
||||||
|
SDL_RenderCopy(canvas, texture, nil, nil)
|
||||||
|
SDL_RenderPresent(canvas)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Infinite loop otherwise the program will exit prematurely
|
||||||
|
RunLoop.main.run()
|
||||||
|
Loading…
Reference in New Issue
Block a user