bradford-hamilton-apple-1/internal/vm/vm.go
Bradford Lamson-Scribner cdca8f735d internal/vm: add the first few opcode handlers
Still a little iffy on the code design, although this seems like it
could be a desirable pattern. This way I would have to write an opcode
handler for all the cases and register it to the “op”. That way step
calls are super simple from Appleone’s point of view -> get the operation
and that operation has everything needed to execute on the vm.
2020-05-30 11:03:58 -06:00

61 lines
1.2 KiB
Go

package vm
import (
"fmt"
)
// Appleone represents the virtual Apple 1 computer
type Appleone struct {
cpu *Mos6502 // virtual mos6502 cpu
mem block // available memory (64kiB)
}
// New returns a pointer to an initialized Appleone with a brand spankin new CPU
func New() *Appleone {
return &Appleone{
cpu: newCPU(),
mem: newBlock(),
}
}
func (a *Appleone) load(addr uint16, data []uint8) {
a.mem.load(addr, data)
a.cpu.pc = addr
}
func (a *Appleone) step() {
op, err := opByCode(a.mem[a.cpu.pc])
if err != nil {
fmt.Println("TODO")
}
a.cpu.pc += uint16(op.size)
if err := op.exec(a, op); err != nil {
fmt.Println("TODO")
}
}
func (a *Appleone) pushWordToStack(data byte) {
a.mem[StackBottom+uint16(a.cpu.sp)] = data
a.cpu.sp = uint8((uint16(a.cpu.sp) - 1) & 0xFF)
}
func (a *Appleone) pushDWordToStack(data uint16) {
h := uint8((data >> 8) & 0xFF)
l := uint8(data & 0xFF)
a.pushWordToStack(h)
a.pushWordToStack(l)
}
func (a *Appleone) popStackWord() uint8 {
a.cpu.sp = uint8((uint16(a.cpu.sp) + 1) & 0xFF)
return a.mem[StackBottom+uint16(a.cpu.sp)]
}
func (a *Appleone) popStackDWord() uint16 {
l := a.popStackWord()
h := a.popStackWord()
return (uint16(h) << 8) | uint16(l)
}