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 {
|
||||
case Immediate
|
||||
case ZeroPage
|
||||
@ -61,7 +64,6 @@ class CPU {
|
||||
return base &+ UInt16(register_y)
|
||||
case .Indirect_X:
|
||||
let base = memRead(programCounter)
|
||||
|
||||
let ptr = UInt8(base) &+ register_x
|
||||
let lo = memRead(UInt16(ptr))
|
||||
let hi = memRead(UInt16(ptr &+ 1))
|
||||
@ -101,21 +103,24 @@ class CPU {
|
||||
}
|
||||
|
||||
func run() {
|
||||
run {
|
||||
|
||||
}
|
||||
run {}
|
||||
}
|
||||
|
||||
func run(callback: () -> ()) {
|
||||
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)
|
||||
}
|
||||
}
|
||||
|
||||
while true {
|
||||
func processOpcodes(callback: () -> (), opcodes: [UInt8: OpCode], timer: Timer) {
|
||||
callback()
|
||||
let code = memRead(programCounter)
|
||||
programCounter += 1
|
||||
|
||||
let programCounterState = programCounter
|
||||
guard let opcode = opcodes[code] else {fatalError("OpCode \(code) not recgonized!")}
|
||||
// print(programCounter, opcode.mnemonic)
|
||||
|
||||
switch code {
|
||||
/// LDA
|
||||
@ -249,7 +254,7 @@ class CPU {
|
||||
case 0xa0, 0xa4, 0xb4, 0xac, 0xbc:
|
||||
ldy(opcode.mode)
|
||||
case 0xea:
|
||||
continue
|
||||
return
|
||||
case 0xa8:
|
||||
register_y = register_x
|
||||
updateZeroAndNegativeFlags(register_y)
|
||||
@ -272,7 +277,10 @@ class CPU {
|
||||
inx()
|
||||
/// BRK
|
||||
case 0x00:
|
||||
return
|
||||
timer.invalidate()
|
||||
SDL_DestroyWindow(window)
|
||||
SDL_Quit()
|
||||
exit(0)
|
||||
default: fatalError("TODO!")
|
||||
}
|
||||
|
||||
@ -280,7 +288,6 @@ class CPU {
|
||||
programCounter += UInt16(opcode.len - 1)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func updateZeroAndNegativeFlags(_ result: UInt8) {
|
||||
if result == 0 {
|
||||
@ -323,7 +330,7 @@ class CPU {
|
||||
status.remove(.carry)
|
||||
}
|
||||
|
||||
let result = UInt8(sum)
|
||||
let result = UInt8(truncatingIfNeeded: sum)
|
||||
|
||||
if (data ^ result) & (result ^ register_a) & 0x80 != 0 {
|
||||
status.insert(.overflow)
|
||||
@ -373,7 +380,6 @@ class CPU {
|
||||
func branch(_ condition: Bool) {
|
||||
if condition {
|
||||
let addr = memRead(programCounter)
|
||||
// print(addr)
|
||||
let jump: Int8 = Int8(bitPattern: addr)
|
||||
let jump_addr = programCounter &+ 1 &+ UInt16(bitPattern: Int16(jump))
|
||||
|
||||
|
@ -61,8 +61,8 @@ extension CPU {
|
||||
func sbc(_ mode: AddressingMode) {
|
||||
let addr = getOpperandAddress(mode)
|
||||
let data = memRead(addr)
|
||||
let res = Int8(data) &* -1
|
||||
addToRegisterA(UInt8(res &- 1))
|
||||
let res = Int8(bitPattern: data) &* -1
|
||||
addToRegisterA(UInt8(bitPattern: res &- 1))
|
||||
}
|
||||
|
||||
func adc(_ mode: AddressingMode) {
|
||||
|
@ -2,6 +2,7 @@
|
||||
// https://docs.swift.org/swift-book
|
||||
|
||||
import SDL
|
||||
import Foundation
|
||||
|
||||
guard SDL_Init(SDL_INIT_VIDEO) == 0 else {
|
||||
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)
|
||||
|
||||
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] = [
|
||||
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
|
||||
]
|
||||
|
||||
print(gameCode[32])
|
||||
|
||||
|
||||
var cpu = CPU()
|
||||
cpu.load(gameCode)
|
||||
cpu.reset()
|
||||
|
||||
cpu.run {
|
||||
// TODO:
|
||||
// read user input and write it to mem[0xFF]
|
||||
// update mem[0xFE] with new Random Number
|
||||
// read mem mapped screen state
|
||||
// render screen state
|
||||
var screenState = [UInt8](repeating: 0, count: 32 * 3 * 32)
|
||||
var rng = SystemRandomNumberGenerator()
|
||||
|
||||
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