aboutsummaryrefslogtreecommitdiff
path: root/cpu
diff options
context:
space:
mode:
authorcrecher <crecher@crecher.net>2026-10-13 01:13:13 +0200
committercrecher <crecher@crecher.net>2026-10-13 01:13:13 +0200
commit99cae5a5a37f41f878a84857361eda47910303ba (patch)
tree31c8665ca991f95e09e93bb2e6ec91d81d2427ff /cpu
parent96ff6d8eda2ba434682909f4ff4ce350d78b2273 (diff)
downloadgones-99cae5a5a37f41f878a84857361eda47910303ba.tar.gz
gones-99cae5a5a37f41f878a84857361eda47910303ba.zip
sprites!!!!!!
Diffstat (limited to 'cpu')
-rw-r--r--cpu/cpu.go5
-rw-r--r--cpu/instructions.go80
-rw-r--r--cpu/opcodes.go15
3 files changed, 100 insertions, 0 deletions
diff --git a/cpu/cpu.go b/cpu/cpu.go
index 113adf0..b8b0a1e 100644
--- a/cpu/cpu.go
+++ b/cpu/cpu.go
@@ -111,6 +111,11 @@ func (c *CPU) interrupt(vector uint16, brk bool) {
c.PC = c.read16(vector)
}
+// burns cycles without running anything, used while dma holds the cpu
+func (c *CPU) Stall(cycles int) {
+ c.Cycles += uint64(cycles)
+}
+
func (c *CPU) Step() int {
if c.Jammed {
c.Cycles++
diff --git a/cpu/instructions.go b/cpu/instructions.go
index b74a2db..b4d4bbe 100644
--- a/cpu/instructions.go
+++ b/cpu/instructions.go
@@ -226,3 +226,83 @@ func jamExec(c *CPU, op operand) {
c.Jammed = true
c.PC--
}
+
+// and with immediate, then carry takes the sign bit
+func ancExec(c *CPU, op operand) {
+ c.A &= c.operandValue(op)
+ c.setZN(c.A)
+ c.setFlag(FlagC, c.A&0x80 != 0)
+}
+
+// and with immediate, then lsr a
+func alrExec(c *CPU, op operand) {
+ v := c.A & c.operandValue(op)
+ c.setFlag(FlagC, v&0x01 != 0)
+ c.A = v >> 1
+ c.setZN(c.A)
+}
+
+// and with immediate, then ror a, but C and V come from bits 6 and 5 of the
+// result (binary mode only, the 2A03 has no decimal mode)
+func arrExec(c *CPU, op operand) {
+ v := c.A & c.operandValue(op)
+ var carryIn uint8
+ if c.flag(FlagC) {
+ carryIn = 0x80
+ }
+ c.A = v>>1 | carryIn
+ c.setZN(c.A)
+ c.setFlag(FlagC, c.A&0x40 != 0)
+ c.setFlag(FlagV, (c.A>>6^c.A>>5)&0x01 != 0)
+}
+
+// x = (a & x) - immediate, like cmp: no borrow in, V untouched
+func axsExec(c *CPU, op operand) {
+ v := c.A & c.X
+ imm := c.operandValue(op)
+ c.setFlag(FlagC, v >= imm)
+ c.X = v - imm
+ c.setZN(c.X)
+}
+
+// memory & sp goes into a, x and sp
+func lasExec(c *CPU, op operand) {
+ v := c.operandValue(op) & c.SP
+ c.A, c.X, c.SP = v, v, v
+ c.setZN(v)
+}
+
+const unstableMagic uint8 = 0xEE
+
+func aneExec(c *CPU, op operand) {
+ c.A = (c.A | unstableMagic) & c.X & c.operandValue(op)
+ c.setZN(c.A)
+}
+
+func lxaExec(c *CPU, op operand) {
+ c.A = (c.A | unstableMagic) & c.operandValue(op)
+ c.X = c.A
+ c.setZN(c.A)
+}
+
+func (c *CPU) storeHighAnd(op operand, v uint8) {
+ baseHi := uint8(op.addr >> 8)
+ if op.pageCrossed {
+ baseHi--
+ }
+ v &= baseHi + 1
+ addr := op.addr
+ if op.pageCrossed {
+ addr = uint16(v)<<8 | addr&0x00FF
+ }
+ c.write(addr, v)
+}
+
+func ahxExec(c *CPU, op operand) { c.storeHighAnd(op, c.A&c.X) }
+func shxExec(c *CPU, op operand) { c.storeHighAnd(op, c.X) }
+func shyExec(c *CPU, op operand) { c.storeHighAnd(op, c.Y) }
+
+func tasExec(c *CPU, op operand) {
+ c.SP = c.A & c.X
+ c.storeHighAnd(op, c.SP)
+}
diff --git a/cpu/opcodes.go b/cpu/opcodes.go
index ea6e1b9..aa8f8a5 100644
--- a/cpu/opcodes.go
+++ b/cpu/opcodes.go
@@ -334,6 +334,21 @@ func init() {
def(0xD2, "JAM", ModeImplied, 2, false, jamExec)
def(0xF2, "JAM", ModeImplied, 2, false, jamExec)
+ def(0x0B, "ANC", ModeImmediate, 2, false, ancExec)
+ def(0x2B, "ANC", ModeImmediate, 2, false, ancExec)
+ def(0x4B, "ALR", ModeImmediate, 2, false, alrExec)
+ def(0x6B, "ARR", ModeImmediate, 2, false, arrExec)
+ def(0x8B, "ANE", ModeImmediate, 2, false, aneExec)
+ def(0xAB, "LXA", ModeImmediate, 2, false, lxaExec)
+ def(0xCB, "AXS", ModeImmediate, 2, false, axsExec)
+ def(0xBB, "LAS", ModeAbsoluteY, 4, true, lasExec)
+
+ def(0x93, "AHX", ModeIndirectY, 6, false, ahxExec)
+ def(0x9F, "AHX", ModeAbsoluteY, 5, false, ahxExec)
+ def(0x9B, "TAS", ModeAbsoluteY, 5, false, tasExec)
+ def(0x9C, "SHY", ModeAbsoluteX, 5, false, shyExec)
+ def(0x9E, "SHX", ModeAbsoluteY, 5, false, shxExec)
+
// illegal / undocumented instructions
def(0xA7, "LAX", ModeZeroPage, 3, false, laxExec)
def(0xB7, "LAX", ModeZeroPageY, 4, false, laxExec)