mirror of
https://github.com/Candygoblen123/SwiftNES.git
synced 2024-11-09 14:36:24 -06:00
Compare commits
2 Commits
f9efe23b0b
...
6974110b22
Author | SHA1 | Date | |
---|---|---|---|
|
6974110b22 | ||
|
ddd8fd6ee6 |
@ -131,7 +131,6 @@ class CPU {
|
|||||||
status = [.interruptDisable, .break2]
|
status = [.interruptDisable, .break2]
|
||||||
|
|
||||||
programCounter = self.memReadU16(0xFFFC)
|
programCounter = self.memReadU16(0xFFFC)
|
||||||
print(programCounter)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//func loadAndRun(_ program: [UInt8]) {
|
//func loadAndRun(_ program: [UInt8]) {
|
||||||
@ -151,16 +150,14 @@ class CPU {
|
|||||||
//}
|
//}
|
||||||
|
|
||||||
func run() {
|
func run() {
|
||||||
run(onCycle: { print(dumpCpuState(self)) }, onComplete: {})
|
run(onCycle: {}, onComplete: {})
|
||||||
}
|
}
|
||||||
|
|
||||||
func run(onCycle: @escaping () -> (), onComplete: @escaping () -> ()) {
|
func run(onCycle: @escaping () -> (), onComplete: @escaping () -> ()) {
|
||||||
let opcodes = OPCODES_MAP
|
let opcodes = OPCODES_MAP
|
||||||
while true {
|
while true {
|
||||||
if bus.pollNMI() != nil {
|
if bus.pollNMI() != nil {
|
||||||
print(programCounter)
|
|
||||||
interrupt(.NMI)
|
interrupt(.NMI)
|
||||||
print(programCounter)
|
|
||||||
}
|
}
|
||||||
processOpcodes(onCycle: onCycle, opcodes: opcodes) {
|
processOpcodes(onCycle: onCycle, opcodes: opcodes) {
|
||||||
onComplete()
|
onComplete()
|
||||||
@ -197,7 +194,6 @@ class CPU {
|
|||||||
|
|
||||||
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
|
||||||
|
@ -28,7 +28,6 @@ class NesPPU {
|
|||||||
func tick(_ cycles: UInt8) -> Bool {
|
func tick(_ cycles: UInt8) -> Bool {
|
||||||
self.cycles += Int(cycles)
|
self.cycles += Int(cycles)
|
||||||
if self.cycles >= 341 {
|
if self.cycles >= 341 {
|
||||||
//print(self.cycles)
|
|
||||||
self.cycles = self.cycles - 341
|
self.cycles = self.cycles - 341
|
||||||
self.scanline += 1
|
self.scanline += 1
|
||||||
|
|
||||||
@ -37,7 +36,6 @@ class NesPPU {
|
|||||||
status.setSpriteZeroHit(false)
|
status.setSpriteZeroHit(false)
|
||||||
if ctrl.generateVblankNMI() {
|
if ctrl.generateVblankNMI() {
|
||||||
nmiInterrupt = 1
|
nmiInterrupt = 1
|
||||||
print("interrupt")
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -116,7 +114,6 @@ class NesPPU {
|
|||||||
|
|
||||||
func writeToData(_ data: UInt8) {
|
func writeToData(_ data: UInt8) {
|
||||||
let addr = addr.get()
|
let addr = addr.get()
|
||||||
print("\(addr): \(data)")
|
|
||||||
switch addr {
|
switch addr {
|
||||||
case 0...0x1fff:
|
case 0...0x1fff:
|
||||||
print("Attempt to write to chr rom space \(addr)!")
|
print("Attempt to write to chr rom space \(addr)!")
|
||||||
|
@ -46,4 +46,28 @@ struct ControlRegister: OptionSet {
|
|||||||
0x1000
|
0x1000
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func spritePatternAddr() -> Int {
|
||||||
|
if !self.contains(.SPRITE_PATTERN_ADDR) {
|
||||||
|
0
|
||||||
|
} else {
|
||||||
|
0x1000
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func spriteSize() -> Int {
|
||||||
|
if !self.contains(.SPRITE_SIZE) {
|
||||||
|
8
|
||||||
|
} else {
|
||||||
|
16
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func masterSlaveSelect() -> Int {
|
||||||
|
if !self.contains(.SPRITE_SIZE) {
|
||||||
|
0
|
||||||
|
} else {
|
||||||
|
1
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,36 +2,117 @@ class Render {
|
|||||||
static func render(_ ppu: NesPPU, frame: Frame) {
|
static func render(_ ppu: NesPPU, frame: Frame) {
|
||||||
let bank = ppu.ctrl.backgroundPatternAddr()
|
let bank = ppu.ctrl.backgroundPatternAddr()
|
||||||
|
|
||||||
for i in 0..<0x03c0 { // For now, just use first nametable
|
for i in 0..<0x03c0 { // FIXME: For now, just use first nametable
|
||||||
let tileAddr = UInt16(ppu.vram[i])
|
let tileAddr = UInt16(ppu.vram[i])
|
||||||
//print(ppu.vram)
|
let tileLoc = (col: i % 32, row: i / 32)
|
||||||
let tileX = i % 32
|
|
||||||
let tileY = i / 32
|
|
||||||
let tile = ppu.chrRom[(bank + Int(tileAddr) * 16)...(bank + Int(tileAddr) * 16 + 15)]
|
let tile = ppu.chrRom[(bank + Int(tileAddr) * 16)...(bank + Int(tileAddr) * 16 + 15)]
|
||||||
|
let bgPalette = getBgPalette(ppu, tileLoc: tileLoc)
|
||||||
|
|
||||||
|
// MARK: Draw Background
|
||||||
|
for y in 0...7 {
|
||||||
|
var upper = tile[tile.startIndex + y]
|
||||||
|
var lower = tile[tile.startIndex + y + 8]
|
||||||
|
|
||||||
|
for x in (0...7).reversed() {
|
||||||
|
let value = (1 & lower) << 1 | (1 & upper)
|
||||||
|
upper = upper >> 1
|
||||||
|
lower = lower >> 1
|
||||||
|
let rgb = switch value {
|
||||||
|
case 0:
|
||||||
|
NESColor.SYSTEM_PALLETE[Int(ppu.paletteTable[0])]
|
||||||
|
case 1:
|
||||||
|
NESColor.SYSTEM_PALLETE[Int(bgPalette[1])]
|
||||||
|
case 2:
|
||||||
|
NESColor.SYSTEM_PALLETE[Int(bgPalette[2])]
|
||||||
|
case 3:
|
||||||
|
NESColor.SYSTEM_PALLETE[Int(bgPalette[3])]
|
||||||
|
default:
|
||||||
|
fatalError("Invalid Pallete Color type")
|
||||||
|
}
|
||||||
|
frame.setPixel((tileLoc.col * 8 + x, tileLoc.row * 8 + y), rgb)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// MARK: Draw Sprites
|
||||||
|
for i in stride(from: 0, to: ppu.oamData.count, by: 4) {
|
||||||
|
let tileIndex = UInt16(ppu.oamData[i + 1])
|
||||||
|
let tileX = Int(ppu.oamData[i + 3])
|
||||||
|
let tileY = Int(ppu.oamData[i])
|
||||||
|
|
||||||
|
let flipVert = ppu.oamData[i + 2] >> 7 & 1 == 1
|
||||||
|
let flipHori = ppu.oamData[i + 2] >> 6 & 1 == 1
|
||||||
|
|
||||||
|
let paletteIndex = ppu.oamData[i + 2] & 0b11
|
||||||
|
let spritePallete = getSpritePalette(ppu, paletteIndex: paletteIndex)
|
||||||
|
|
||||||
|
let bank = ppu.ctrl.spritePatternAddr()
|
||||||
|
let tile = ppu.chrRom[(bank + Int(tileIndex) * 16)...(bank + Int(tileIndex) * 16 + 15)]
|
||||||
|
|
||||||
for y in 0...7 {
|
for y in 0...7 {
|
||||||
var upper = tile[tile.startIndex + y]
|
var upper = tile[tile.startIndex + y]
|
||||||
var lower = tile[tile.startIndex + y + 8]
|
var lower = tile[tile.startIndex + y + 8]
|
||||||
|
|
||||||
for x in (0...7).reversed() {
|
for x in (0...7).reversed() {
|
||||||
let value = (1 & upper) << 1 | (1 & lower)
|
let value = (1 & lower) << 1 | (1 & upper)
|
||||||
upper = upper >> 1
|
upper = upper >> 1
|
||||||
lower = lower >> 1
|
lower = lower >> 1
|
||||||
|
if (value == 0) {
|
||||||
|
continue // skip coloring this pixel, it's transparent
|
||||||
|
}
|
||||||
let rgb = switch value {
|
let rgb = switch value {
|
||||||
case 0:
|
|
||||||
NESColor.SYSTEM_PALLETE[0x01]
|
|
||||||
case 1:
|
case 1:
|
||||||
NESColor.SYSTEM_PALLETE[0x23]
|
NESColor.SYSTEM_PALLETE[Int(spritePallete[1])]
|
||||||
case 2:
|
case 2:
|
||||||
NESColor.SYSTEM_PALLETE[0x28]
|
NESColor.SYSTEM_PALLETE[Int(spritePallete[2])]
|
||||||
case 3:
|
case 3:
|
||||||
NESColor.SYSTEM_PALLETE[0x31]
|
NESColor.SYSTEM_PALLETE[Int(spritePallete[3])]
|
||||||
default:
|
default:
|
||||||
fatalError("Invalid Pallete Color type")
|
fatalError("Invalid Pallete Color type")
|
||||||
}
|
}
|
||||||
frame.setPixel((tileX * 8 + x, tileY * 8 + y), rgb)
|
switch (flipHori, flipVert) {
|
||||||
|
case (false, false):
|
||||||
|
frame.setPixel((tileX + x, tileY + y), rgb)
|
||||||
|
case (true, false):
|
||||||
|
frame.setPixel((tileX + 7 - x, tileY + y), rgb)
|
||||||
|
case (false, true):
|
||||||
|
frame.setPixel((tileX + x, tileY + 7 - y), rgb)
|
||||||
|
case (true, true):
|
||||||
|
frame.setPixel((tileX + 7 - x, tileY + 7 - y), rgb)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static func getBgPalette(_ ppu: NesPPU, tileLoc: (col: Int, row: Int)) -> [UInt8] {
|
||||||
|
let attrTableIndex = tileLoc.row / 4 * 8 + tileLoc.col / 4
|
||||||
|
let attrByte = ppu.vram[0x3c0 + attrTableIndex] // FIXME: still using hardcoded first nametable
|
||||||
|
|
||||||
|
let palleteIndex = switch (tileLoc.col % 4 / 2, tileLoc.row % 4 / 2) {
|
||||||
|
case (0,0):
|
||||||
|
attrByte & 0b11
|
||||||
|
case (1,0):
|
||||||
|
(attrByte >> 2) & 0b11
|
||||||
|
case (0,1):
|
||||||
|
(attrByte >> 4) & 0b11
|
||||||
|
case (1,1):
|
||||||
|
(attrByte >> 6) & 0b11
|
||||||
|
default:
|
||||||
|
fatalError("Invalid titleLoc. This should never happen!")
|
||||||
|
}
|
||||||
|
|
||||||
|
let palleteStartIndex = 1 + Int(palleteIndex) * 4
|
||||||
|
return [ppu.paletteTable[0], ppu.paletteTable[palleteStartIndex], ppu.paletteTable[palleteStartIndex + 1], ppu.paletteTable[palleteStartIndex + 2]]
|
||||||
|
}
|
||||||
|
|
||||||
|
static func getSpritePalette(_ ppu: NesPPU, paletteIndex: UInt8) -> [UInt8] {
|
||||||
|
let start = 0x11 + Int(paletteIndex * 4)
|
||||||
|
return [
|
||||||
|
0,
|
||||||
|
ppu.paletteTable[start],
|
||||||
|
ppu.paletteTable[start + 1],
|
||||||
|
ppu.paletteTable[start + 2]
|
||||||
|
]
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user