test snake game

This commit is contained in:
Candygoblen123 2024-05-17 14:15:10 -04:00
parent c441014511
commit 5bdfebdf13
No known key found for this signature in database
GPG Key ID: 577DA64EBEF10385
3 changed files with 270 additions and 184 deletions

View File

@ -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,21 +103,24 @@ class CPU {
} }
func run() { func run() {
run { run {}
}
} }
func run(callback: () -> ()) { func run(callback: @escaping () -> ()) {
let opcodes = OPCODES_MAP let opcodes = OPCODES_MAP
Timer.scheduledTimer(withTimeInterval: 0.00007, repeats: true) { [self] timer in
processOpcodes(callback: callback, opcodes: opcodes, timer: timer)
}
}
while true { func processOpcodes(callback: () -> (), opcodes: [UInt8: OpCode], timer: Timer) {
callback() callback()
let code = memRead(programCounter) let code = memRead(programCounter)
programCounter += 1 programCounter += 1
let programCounterState = programCounter let programCounterState = programCounter
guard let opcode = opcodes[code] else {fatalError("OpCode \(code) not recgonized!")} guard let opcode = opcodes[code] else {fatalError("OpCode \(code) not recgonized!")}
// print(programCounter, opcode.mnemonic)
switch code { switch code {
/// LDA /// LDA
@ -249,7 +254,7 @@ class CPU {
case 0xa0, 0xa4, 0xb4, 0xac, 0xbc: case 0xa0, 0xa4, 0xb4, 0xac, 0xbc:
ldy(opcode.mode) ldy(opcode.mode)
case 0xea: case 0xea:
continue return
case 0xa8: case 0xa8:
register_y = register_x register_y = register_x
updateZeroAndNegativeFlags(register_y) updateZeroAndNegativeFlags(register_y)
@ -272,7 +277,10 @@ class CPU {
inx() inx()
/// BRK /// BRK
case 0x00: case 0x00:
return timer.invalidate()
SDL_DestroyWindow(window)
SDL_Quit()
exit(0)
default: fatalError("TODO!") default: fatalError("TODO!")
} }
@ -280,7 +288,6 @@ class CPU {
programCounter += UInt16(opcode.len - 1) programCounter += UInt16(opcode.len - 1)
} }
} }
}
func updateZeroAndNegativeFlags(_ result: UInt8) { func updateZeroAndNegativeFlags(_ result: UInt8) {
if result == 0 { if result == 0 {
@ -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))

View File

@ -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) {

View File

@ -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()