Implements a few more instructions
This commit is contained in:
parent
3c25abc55b
commit
1f4f9278dd
|
@ -44,7 +44,9 @@ class CPU(val memory: Memory) {
|
||||||
Pair(Instruction.BNE, BNE(this)),
|
Pair(Instruction.BNE, BNE(this)),
|
||||||
Pair(Instruction.JMP, JMP(this)),
|
Pair(Instruction.JMP, JMP(this)),
|
||||||
Pair(Instruction.JSR, JSR(this)),
|
Pair(Instruction.JSR, JSR(this)),
|
||||||
Pair(Instruction.RTS, RTS(this))
|
Pair(Instruction.RTS, RTS(this)),
|
||||||
|
Pair(Instruction.SEI, SEI(this)),
|
||||||
|
Pair(Instruction.DEY, DEY(this))
|
||||||
// Pair(Instruction.BPL, BPL(this)),
|
// Pair(Instruction.BPL, BPL(this)),
|
||||||
// Pair(Instruction.BMI, BMI(this)),
|
// Pair(Instruction.BMI, BMI(this)),
|
||||||
// Pair(Instruction.BVC, BVC(this)),
|
// Pair(Instruction.BVC, BVC(this)),
|
||||||
|
@ -59,7 +61,6 @@ class CPU(val memory: Memory) {
|
||||||
// Pair(Instruction.CLC, CLC(this)),
|
// Pair(Instruction.CLC, CLC(this)),
|
||||||
// Pair(Instruction.SEC, SEC(this)),
|
// Pair(Instruction.SEC, SEC(this)),
|
||||||
// Pair(Instruction.CLI, CLI(this)),
|
// Pair(Instruction.CLI, CLI(this)),
|
||||||
// Pair(Instruction.SEI, SEI(this)),
|
|
||||||
// Pair(Instruction.CLV, CLV(this)),
|
// Pair(Instruction.CLV, CLV(this)),
|
||||||
// Pair(Instruction.CLD, CLD(this)),
|
// Pair(Instruction.CLD, CLD(this)),
|
||||||
// Pair(Instruction.SED, SED(this)),
|
// Pair(Instruction.SED, SED(this)),
|
||||||
|
@ -69,7 +70,6 @@ class CPU(val memory: Memory) {
|
||||||
// Pair(Instruction.TXA, TXA(this)),
|
// Pair(Instruction.TXA, TXA(this)),
|
||||||
// Pair(Instruction.TAY, TAY(this)),
|
// Pair(Instruction.TAY, TAY(this)),
|
||||||
// Pair(Instruction.TYA, TYA(this)),
|
// Pair(Instruction.TYA, TYA(this)),
|
||||||
// Pair(Instruction.DEY, DEY(this)),
|
|
||||||
// Pair(Instruction.INY, INY(this)),
|
// Pair(Instruction.INY, INY(this)),
|
||||||
// Pair(Instruction.ROR, ROR(this)),
|
// Pair(Instruction.ROR, ROR(this)),
|
||||||
// Pair(Instruction.ROL, ROL(this)),
|
// Pair(Instruction.ROL, ROL(this)),
|
||||||
|
@ -106,8 +106,8 @@ class CPU(val memory: Memory) {
|
||||||
val function = target.method
|
val function = target.method
|
||||||
target.operation.function()
|
target.operation.function()
|
||||||
} else {
|
} else {
|
||||||
Log.e(TAG, "Address $" + PC.toHexString() + " - unknown opcode " + instruction.toHexString())
|
throw Exception(
|
||||||
stop()
|
"Address $" + PC.toHexString() + " - unknown opcode " + instruction.toHexString())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -131,6 +131,10 @@ class CPU(val memory: Memory) {
|
||||||
setSVFlagsForValue(X)
|
setSVFlagsForValue(X)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun setSZflagsForRegY() {
|
||||||
|
setSVFlagsForValue(Y)
|
||||||
|
}
|
||||||
|
|
||||||
private fun setSVFlagsForValue(value: Int) {
|
private fun setSVFlagsForValue(value: Int) {
|
||||||
if (value != 0) {
|
if (value != 0) {
|
||||||
P = P.and(0xfd)
|
P = P.and(0xfd)
|
||||||
|
|
|
@ -5,6 +5,9 @@ import android.emu6502.instructions.BaseInstruction
|
||||||
import android.emu6502.instructions.Instruction
|
import android.emu6502.instructions.Instruction
|
||||||
|
|
||||||
/** bitwise AND with accumulator */
|
/** bitwise AND with accumulator */
|
||||||
class AND(cpu: CPU)
|
class AND(private val cpu: CPU) : BaseInstruction(Instruction.AND, cpu.instructionList) {
|
||||||
: BaseInstruction(Instruction.AND, cpu.instructionList) {
|
override fun immediate() {
|
||||||
|
cpu.A = cpu.A.and(cpu.popByte())
|
||||||
|
cpu.setSZFlagsForRegA()
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -4,7 +4,7 @@ import android.emu6502.CPU
|
||||||
import android.emu6502.instructions.BaseInstruction
|
import android.emu6502.instructions.BaseInstruction
|
||||||
import android.emu6502.instructions.Instruction
|
import android.emu6502.instructions.Instruction
|
||||||
|
|
||||||
/**DEcrement X */
|
/** DEcrement X */
|
||||||
class DEX(private val cpu: CPU) : BaseInstruction(Instruction.DEX, cpu.instructionList) {
|
class DEX(private val cpu: CPU) : BaseInstruction(Instruction.DEX, cpu.instructionList) {
|
||||||
override fun single() {
|
override fun single() {
|
||||||
cpu.X = (cpu.X - 1).and(0xff)
|
cpu.X = (cpu.X - 1).and(0xff)
|
||||||
|
|
|
@ -0,0 +1,13 @@
|
||||||
|
package android.emu6502.instructions.impl
|
||||||
|
|
||||||
|
import android.emu6502.CPU
|
||||||
|
import android.emu6502.instructions.BaseInstruction
|
||||||
|
import android.emu6502.instructions.Instruction
|
||||||
|
|
||||||
|
/** DEcrement Y */
|
||||||
|
class DEY(private val cpu: CPU) : BaseInstruction(Instruction.DEY, cpu.instructionList) {
|
||||||
|
override fun single() {
|
||||||
|
cpu.Y = (cpu.Y - 1).and(0xff)
|
||||||
|
cpu.setSZflagsForRegY()
|
||||||
|
}
|
||||||
|
}
|
|
@ -10,4 +10,9 @@ class LDA(private val cpu: CPU) : BaseInstruction(Instruction.LDA, cpu.instructi
|
||||||
cpu.A = cpu.popByte()
|
cpu.A = cpu.popByte()
|
||||||
cpu.setSZFlagsForRegA()
|
cpu.setSZFlagsForRegA()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun zeroPage() {
|
||||||
|
cpu.A = cpu.memory.get(cpu.popByte())
|
||||||
|
cpu.setSZFlagsForRegA()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,10 @@
|
||||||
|
package android.emu6502.instructions.impl
|
||||||
|
|
||||||
|
import android.emu6502.CPU
|
||||||
|
import android.emu6502.instructions.BaseInstruction
|
||||||
|
import android.emu6502.instructions.Instruction
|
||||||
|
|
||||||
|
/** SEt Interrupt */
|
||||||
|
class SEI(private val cpu: CPU) : BaseInstruction(Instruction.SEI, cpu.instructionList) {
|
||||||
|
}
|
||||||
|
|
|
@ -10,7 +10,11 @@ class STA(private val memory: Memory, private val cpu: CPU)
|
||||||
: BaseInstruction(Instruction.STA, cpu.instructionList) {
|
: BaseInstruction(Instruction.STA, cpu.instructionList) {
|
||||||
|
|
||||||
override fun absolute() {
|
override fun absolute() {
|
||||||
memory.storeByte(cpu.popWord(), cpu.A);
|
memory.storeByte(cpu.popWord(), cpu.A)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun zeroPage() {
|
||||||
|
memory.storeByte(cpu.popByte(), cpu.A)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -142,4 +142,236 @@ public class CPUTest {
|
||||||
assertThat(cpu.getPC(), equalTo(0x0603));
|
assertThat(cpu.getPC(), equalTo(0x0603));
|
||||||
assertThat(cpu.flags(), equalTo("00110000"));
|
assertThat(cpu.flags(), equalTo("00110000"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test public void testSnake() {
|
||||||
|
List<String> lines = ImmutableList.of(
|
||||||
|
"define appleL $00 ; screen location of apple, low byte",
|
||||||
|
"define appleH $01 ; screen location of apple, high byte",
|
||||||
|
"define snakeHeadL $10 ; screen location of snake head, low byte",
|
||||||
|
"define snakeHeadH $11 ; screen location of snake head, high byte",
|
||||||
|
"define snakeBodyStart $12 ; start of snake body byte pairs",
|
||||||
|
"define snakeDirection $02 ; direction (possible values are below)",
|
||||||
|
"define snakeLength $03 ; snake length, in bytes",
|
||||||
|
"; Directions (each using a separate bit)",
|
||||||
|
"define movingUp 1",
|
||||||
|
"define movingRight 2",
|
||||||
|
"define movingDown 4",
|
||||||
|
"define movingLeft 8",
|
||||||
|
"; ASCII values of keys controlling the snake",
|
||||||
|
"define ASCII_w $77",
|
||||||
|
"define ASCII_a $61",
|
||||||
|
"define ASCII_s $73",
|
||||||
|
"define ASCII_d $64",
|
||||||
|
"; System variables",
|
||||||
|
"define sysRandom $fe",
|
||||||
|
"define sysLastKey $ff",
|
||||||
|
" jsr init",
|
||||||
|
" jsr loop",
|
||||||
|
"init:",
|
||||||
|
" jsr initSnake",
|
||||||
|
" jsr generateApplePosition",
|
||||||
|
" rts",
|
||||||
|
"initSnake:",
|
||||||
|
" lda #movingRight ;start direction",
|
||||||
|
" sta snakeDirection",
|
||||||
|
" lda #4 ;start length (2 segments)",
|
||||||
|
" sta snakeLength",
|
||||||
|
" ",
|
||||||
|
" lda #$11",
|
||||||
|
" sta snakeHeadL",
|
||||||
|
" ",
|
||||||
|
" lda #$10",
|
||||||
|
" sta snakeBodyStart",
|
||||||
|
" ",
|
||||||
|
" lda #$0f",
|
||||||
|
" sta $14 ; body segment 1",
|
||||||
|
" ",
|
||||||
|
" lda #$04",
|
||||||
|
" sta snakeHeadH",
|
||||||
|
" sta $13 ; body segment 1",
|
||||||
|
" sta $15 ; body segment 2",
|
||||||
|
" rts",
|
||||||
|
"generateApplePosition:",
|
||||||
|
" ;load a new random byte into $00",
|
||||||
|
" lda sysRandom",
|
||||||
|
" sta appleL",
|
||||||
|
" ;load a new random number from 2 to 5 into $01",
|
||||||
|
" lda sysRandom",
|
||||||
|
" and #$03 ;mask out lowest 2 bits",
|
||||||
|
" clc",
|
||||||
|
" adc #2",
|
||||||
|
" sta appleH",
|
||||||
|
" rts",
|
||||||
|
"loop:",
|
||||||
|
" jsr readKeys",
|
||||||
|
" jsr checkCollision",
|
||||||
|
" jsr updateSnake",
|
||||||
|
" jsr drawApple",
|
||||||
|
" jsr drawSnake",
|
||||||
|
" jsr spinWheels",
|
||||||
|
" jmp loop",
|
||||||
|
"readKeys:",
|
||||||
|
" lda sysLastKey",
|
||||||
|
" cmp #ASCII_w",
|
||||||
|
" beq upKey",
|
||||||
|
" cmp #ASCII_d",
|
||||||
|
" beq rightKey",
|
||||||
|
" cmp #ASCII_s",
|
||||||
|
" beq downKey",
|
||||||
|
" cmp #ASCII_a",
|
||||||
|
" beq leftKey",
|
||||||
|
" rts",
|
||||||
|
"upKey:",
|
||||||
|
" lda #movingDown",
|
||||||
|
" bit snakeDirection",
|
||||||
|
" bne illegalMove",
|
||||||
|
|
||||||
|
" lda #movingUp",
|
||||||
|
" sta snakeDirection",
|
||||||
|
" rts",
|
||||||
|
"rightKey:",
|
||||||
|
" lda #movingLeft",
|
||||||
|
" bit snakeDirection",
|
||||||
|
" bne illegalMove",
|
||||||
|
" lda #movingRight",
|
||||||
|
" sta snakeDirection",
|
||||||
|
" rts",
|
||||||
|
"downKey:",
|
||||||
|
" lda #movingUp",
|
||||||
|
" bit snakeDirection",
|
||||||
|
" bne illegalMove",
|
||||||
|
" lda #movingDown",
|
||||||
|
" sta snakeDirection",
|
||||||
|
" rts",
|
||||||
|
"leftKey:",
|
||||||
|
" lda #movingRight",
|
||||||
|
" bit snakeDirection",
|
||||||
|
" bne illegalMove",
|
||||||
|
" lda #movingLeft",
|
||||||
|
" sta snakeDirection",
|
||||||
|
" rts",
|
||||||
|
"illegalMove:",
|
||||||
|
" rts",
|
||||||
|
"checkCollision:",
|
||||||
|
" jsr checkAppleCollision",
|
||||||
|
" jsr checkSnakeCollision",
|
||||||
|
" rts",
|
||||||
|
"checkAppleCollision:",
|
||||||
|
" lda appleL",
|
||||||
|
" cmp snakeHeadL",
|
||||||
|
" bne doneCheckingAppleCollision",
|
||||||
|
" lda appleH",
|
||||||
|
" cmp snakeHeadH",
|
||||||
|
" bne doneCheckingAppleCollision",
|
||||||
|
" ;eat apple",
|
||||||
|
" inc snakeLength",
|
||||||
|
" inc snakeLength ;increase length",
|
||||||
|
" jsr generateApplePosition",
|
||||||
|
"doneCheckingAppleCollision:",
|
||||||
|
" rts",
|
||||||
|
"checkSnakeCollision:",
|
||||||
|
" ldx #2 ;start with second segment",
|
||||||
|
"snakeCollisionLoop:",
|
||||||
|
" lda snakeHeadL,x",
|
||||||
|
" cmp snakeHeadL",
|
||||||
|
" bne continueCollisionLoop",
|
||||||
|
"maybeCollided:",
|
||||||
|
" lda snakeHeadH,x",
|
||||||
|
" cmp snakeHeadH",
|
||||||
|
" beq didCollide",
|
||||||
|
"continueCollisionLoop:",
|
||||||
|
" inx",
|
||||||
|
" inx",
|
||||||
|
" cpx snakeLength ;got to last section with no collision",
|
||||||
|
" beq didntCollide",
|
||||||
|
" jmp snakeCollisionLoop",
|
||||||
|
"didCollide:",
|
||||||
|
" jmp gameOver",
|
||||||
|
"didntCollide:",
|
||||||
|
" rts",
|
||||||
|
"updateSnake:",
|
||||||
|
" ldx snakeLength",
|
||||||
|
" dex",
|
||||||
|
" txa",
|
||||||
|
"updateloop:",
|
||||||
|
" lda snakeHeadL,x",
|
||||||
|
" sta snakeBodyStart,x",
|
||||||
|
" dex",
|
||||||
|
" bpl updateloop",
|
||||||
|
" lda snakeDirection",
|
||||||
|
" lsr",
|
||||||
|
" bcs up",
|
||||||
|
" lsr",
|
||||||
|
" bcs right",
|
||||||
|
" lsr",
|
||||||
|
" bcs down",
|
||||||
|
" lsr",
|
||||||
|
" bcs left",
|
||||||
|
"up:",
|
||||||
|
" lda snakeHeadL",
|
||||||
|
" sec",
|
||||||
|
" sbc #$20",
|
||||||
|
" sta snakeHeadL",
|
||||||
|
" bcc upup",
|
||||||
|
" rts",
|
||||||
|
"upup:",
|
||||||
|
" dec snakeHeadH",
|
||||||
|
" lda #$1",
|
||||||
|
" cmp snakeHeadH",
|
||||||
|
" beq collision",
|
||||||
|
" rts",
|
||||||
|
"right:",
|
||||||
|
" inc snakeHeadL",
|
||||||
|
" lda #$1f",
|
||||||
|
" bit snakeHeadL",
|
||||||
|
" beq collision",
|
||||||
|
" rts",
|
||||||
|
"down:",
|
||||||
|
" lda snakeHeadL",
|
||||||
|
" clc",
|
||||||
|
" adc #$20",
|
||||||
|
" sta snakeHeadL",
|
||||||
|
" bcs downdown",
|
||||||
|
" rts",
|
||||||
|
"downdown:",
|
||||||
|
" inc snakeHeadH",
|
||||||
|
" lda #$6",
|
||||||
|
" cmp snakeHeadH",
|
||||||
|
" beq collision",
|
||||||
|
" rts",
|
||||||
|
"left:",
|
||||||
|
" dec snakeHeadL",
|
||||||
|
" lda snakeHeadL",
|
||||||
|
" and #$1f",
|
||||||
|
" cmp #$1f",
|
||||||
|
" beq collision",
|
||||||
|
" rts",
|
||||||
|
"collision:",
|
||||||
|
" jmp gameOver",
|
||||||
|
"drawApple:",
|
||||||
|
" ldy #0",
|
||||||
|
" lda sysRandom",
|
||||||
|
" sta (appleL),y",
|
||||||
|
" rts",
|
||||||
|
"drawSnake:",
|
||||||
|
" ldx #0",
|
||||||
|
" lda #1",
|
||||||
|
" sta (snakeHeadL,x) ; paint head",
|
||||||
|
" ",
|
||||||
|
" ldx snakeLength",
|
||||||
|
" lda #0",
|
||||||
|
" sta (snakeHeadL,x) ; erase end of tail",
|
||||||
|
" rts",
|
||||||
|
"spinWheels:",
|
||||||
|
" ldx #0",
|
||||||
|
"spinloop:",
|
||||||
|
" nop",
|
||||||
|
" nop",
|
||||||
|
" dex",
|
||||||
|
" bne spinloop",
|
||||||
|
" rts",
|
||||||
|
"gameOver:", "\n");
|
||||||
|
assembler.assembleCode(lines);
|
||||||
|
cpu.execute();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue