diff --git a/README.md b/README.md index e64b213..62dde7b 100644 --- a/README.md +++ b/README.md @@ -4,4 +4,5 @@ Current references: - [6502 instruction set](https://www.masswerk.at/6502/6502_instruction_set.html) - [6502 memory test](http://www.willegal.net/appleii/6502mem.htm) - [6502 instructions description with undocumented commands](http://www.zimmers.net/anonftp/pub/cbm/documents/chipdata/64doc) -- [a rust implementation](https://github.com/alexander-akhmetov/mos6502) \ No newline at end of file +- [a rust implementation](https://github.com/alexander-akhmetov/mos6502) +- [MOS hardware manual](http://bytecollector.com/archive/misc/6500-10A_MCS6500hwMan_Jan76.pdf) \ No newline at end of file diff --git a/internal/cpu/cpu.go b/internal/cpu/cpu.go index 8b87463..0fe8f06 100644 --- a/internal/cpu/cpu.go +++ b/internal/cpu/cpu.go @@ -1,5 +1,5 @@ -package cpu - +// Package cpu emulates a Mos6502 cpu +// // A .... Accumulator OPC A operand is AC (implied single byte instruction) // abs .... absolute OPC $LLHH operand is address $HHLL * // abs,X .... absolute, X-indexed OPC $LLHH,X operand is address; effective address is address incremented by X with carry ** @@ -13,9 +13,9 @@ package cpu // zpg .... zeropage OPC $LL operand is zeropage address (hi-byte is zero, address = $00LL) // zpg,X .... zeropage, X-indexed OPC $LL,X operand is zeropage address; effective address is address incremented by X without carry ** // zpg,Y .... zeropage, Y-indexed OPC $LL,Y operand is zeropage address; effective address is address incremented by Y without carry ** - +// // 16-bit address words are little endian, lo(w)-byte first, followed by the hi(gh)-byte. - +// // SR Flags (bit 7 to bit 0): // N .... Negative // V .... Overflow @@ -25,15 +25,16 @@ package cpu // I .... Interrupt (IRQ disable) // Z .... Zero // C .... Carry - +// // Processor Stack: // LIFO, top down, 8 bit range, 0x0100 - 0x01FF +package cpu -// addressingMode is a type alias for a string, used below for defining addressing mode types -type addressingMode int +// addrMode is a type alias for a string, used below for defining addressing modes +type addrMode int const ( - accumulator addressingMode = iota + accumulator addrMode = iota absolute absoluteXIndexed absoluteYIndexed @@ -48,17 +49,39 @@ const ( zeroPageYIndexed ) +// Available cpu flags written as binary integer literals +const ( + flagDefault uint8 = 0B_00110000 + flagNegative uint8 = 0B_10000000 + flagOverflow uint8 = 0B_01000000 + flagB uint8 = 0B_00010000 + flagDecimal uint8 = 0B_00001000 + flagInterrupt uint8 = 0B_00000100 + flagZero uint8 = 0B_00000010 + flagCarry uint8 = 0B_00000001 +) + +// StackBottom represents the bottom address +const StackBottom uint16 = 0x0100 // 256 + // Mos6502 TODO: docs type Mos6502 struct { - pc uint16 // program counter (16 bit) - ac uint8 // accumulator (8 bit) - x uint8 // X register (8 bit) - y uint8 // Y register (8 bit) - sr uint8 // status register [NV-BDIZC] (8 bit) - sp uint8 // stack pointer (8 bit) + sp uint8 // stack pointer + pc uint16 // program counter + a uint8 // accumulator register + x uint8 // X index register + y uint8 // Y index register + p uint8 // processor flags } // New TODO: docs func New() *Mos6502 { - return &Mos6502{} + return &Mos6502{ + sp: 0xFF, + pc: 0, + a: 0, + x: 0, + y: 0, + p: flagDefault, + } } diff --git a/internal/cpu/opcodes.go b/internal/cpu/opcodes.go index 841a58c..f9b9cf8 100644 --- a/internal/cpu/opcodes.go +++ b/internal/cpu/opcodes.go @@ -3,18 +3,18 @@ package cpu // op represents an operation. It includes the name of the op, it's 8 bit hexidecimal // opcode, how many bytes it occupies (it's size), as well as it's addressing mode. type op struct { - name string - opcode uint8 - size uint8 - addressingMode addressingMode + name string + opcode uint8 + size uint8 + addrMode addrMode } -func newOp(name string, opcode, size uint8, addressingMode addressingMode) op { +func newOp(name string, opcode, size uint8, addrMode addrMode) op { return op{ - name: name, - opcode: opcode, - size: size, - addressingMode: addressingMode, + name: name, + opcode: opcode, + size: size, + addrMode: addrMode, } } diff --git a/internal/vm/vm.go b/internal/vm/vm.go new file mode 100644 index 0000000..e719b15 --- /dev/null +++ b/internal/vm/vm.go @@ -0,0 +1,17 @@ +package vm + +import "github.com/bradford-hamilton/apple-1/internal/cpu" + +// Appleone represents the virtual Apple 1 computer +type Appleone struct { + cpu *cpu.Mos6502 // virtual Mos6502 cpu + mem [64 * 1024]byte // available memory (64kiB) +} + +// New returns a pointer to an initialized Appleone with a brand spankin new CPU +func New() *Appleone { + return &Appleone{ + cpu: cpu.New(), + mem: [64 * 1024]byte{}, + } +} diff --git a/pkg/appleone/appleone.go b/pkg/appleone/appleone.go deleted file mode 100644 index 08d1f26..0000000 --- a/pkg/appleone/appleone.go +++ /dev/null @@ -1,13 +0,0 @@ -package appleone - -import "github.com/bradford-hamilton/apple-1/internal/cpu" - -// Appleone represents our virtual Apple 1 computer -type Appleone struct { - cpu *cpu.Mos6502 -} - -// New returns a pointer to an initialized Appleone with a brand spankin new CPU -func New() *Appleone { - return &Appleone{cpu: cpu.New()} -}