refactor + some instructions + stack implementation
This commit is contained in:
parent
3feed8e5c0
commit
e31a6a3b64
|
@ -1,13 +1,23 @@
|
||||||
package chip8
|
package chip8
|
||||||
|
|
||||||
|
const (
|
||||||
|
MemorySize = 4096 // 4KB of memory
|
||||||
|
StackSize = 16
|
||||||
|
InstructionSize = 2
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
ProgramAddress = uint16(0x0200)
|
||||||
|
StackAddress = uint16(0x0EA0)
|
||||||
|
VideoBufferAddress = uint16(0x0F00)
|
||||||
|
)
|
||||||
|
|
||||||
type Emulator struct {
|
type Emulator struct {
|
||||||
V [16]uint8 // general registers
|
V [16]uint8 // general registers
|
||||||
I uint16 // address register
|
I uint16 // address register
|
||||||
SP uint16 // stack pointer
|
SP uint16 // stack pointer
|
||||||
PC uint16 // program counter
|
PC uint16 // program counter
|
||||||
Memory [4096]uint8 // 4KB of system RAM
|
Memory [MemorySize]uint8 // 4KB of system RAM
|
||||||
Stack []uint8 // 32 bytes of stack. starting at 0x0EA0
|
|
||||||
Screen []uint8 // 256 bytes of display buffer. starting at 0x0F00
|
|
||||||
Timer struct {
|
Timer struct {
|
||||||
Delay uint8 // delay timer
|
Delay uint8 // delay timer
|
||||||
Sound uint8 // sound timer
|
Sound uint8 // sound timer
|
||||||
|
@ -23,13 +33,11 @@ func NewEmulator() *Emulator {
|
||||||
|
|
||||||
func (emulator *Emulator) Reset() {
|
func (emulator *Emulator) Reset() {
|
||||||
emulator.V = [16]uint8{}
|
emulator.V = [16]uint8{}
|
||||||
emulator.I = 0x00
|
emulator.I = 0
|
||||||
emulator.SP = 0x00
|
emulator.SP = StackAddress
|
||||||
emulator.PC = 0x0200
|
emulator.PC = ProgramAddress
|
||||||
emulator.Memory = [4096]uint8{}
|
emulator.Memory = [MemorySize]uint8{}
|
||||||
emulator.Stack = emulator.Memory[0x0EA0:]
|
|
||||||
emulator.Screen = emulator.Memory[0x0F00:]
|
|
||||||
emulator.Timer.Delay = 0
|
emulator.Timer.Delay = 0
|
||||||
emulator.Timer.Sound = 0
|
emulator.Timer.Sound = 0
|
||||||
copy(emulator.Memory[0x0200:], emulator.ROM)
|
copy(emulator.Memory[ProgramAddress:], emulator.ROM)
|
||||||
}
|
}
|
||||||
|
|
43
chip8/instructions.go
Normal file
43
chip8/instructions.go
Normal file
|
@ -0,0 +1,43 @@
|
||||||
|
package chip8
|
||||||
|
|
||||||
|
func (emulator *Emulator) ClearScreen() {
|
||||||
|
// TODO: clear the screen buffer
|
||||||
|
emulator.PC += InstructionSize
|
||||||
|
}
|
||||||
|
|
||||||
|
func (emulator *Emulator) Return() {
|
||||||
|
emulator.StackPop()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (emulator *Emulator) Jump(addr uint16) {
|
||||||
|
emulator.PC = addr
|
||||||
|
}
|
||||||
|
|
||||||
|
func (emulator *Emulator) Call(addr uint16) {
|
||||||
|
emulator.StackPush()
|
||||||
|
emulator.PC = addr
|
||||||
|
}
|
||||||
|
|
||||||
|
func (emulator *Emulator) SkipEqual(x uint8, value uint8) {
|
||||||
|
if emulator.V[x] == value {
|
||||||
|
emulator.PC += InstructionSize * 2
|
||||||
|
} else {
|
||||||
|
emulator.PC += InstructionSize
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (emulator *Emulator) SkipNotEqual(x uint8, value uint8) {
|
||||||
|
if emulator.V[x] != value {
|
||||||
|
emulator.PC += InstructionSize * 2
|
||||||
|
} else {
|
||||||
|
emulator.PC += InstructionSize
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (emulator *Emulator) SkipRegistersEqual(x uint8, y uint8) {
|
||||||
|
if emulator.V[x] == emulator.V[y] {
|
||||||
|
emulator.PC += InstructionSize * 2
|
||||||
|
} else {
|
||||||
|
emulator.PC += InstructionSize
|
||||||
|
}
|
||||||
|
}
|
1
chip8/instructions_test.go
Normal file
1
chip8/instructions_test.go
Normal file
|
@ -0,0 +1 @@
|
||||||
|
package chip8_test
|
20
chip8/stack.go
Normal file
20
chip8/stack.go
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
package chip8
|
||||||
|
|
||||||
|
import "encoding/binary"
|
||||||
|
|
||||||
|
func (emulator *Emulator) StackPush() {
|
||||||
|
if emulator.SP == StackAddress+StackSize*2 {
|
||||||
|
panic("chip8: stack overflow")
|
||||||
|
}
|
||||||
|
binary.BigEndian.PutUint16(emulator.Memory[emulator.SP:], emulator.PC)
|
||||||
|
emulator.SP += 2
|
||||||
|
}
|
||||||
|
|
||||||
|
func (emulator *Emulator) StackPop() {
|
||||||
|
if emulator.SP == StackAddress {
|
||||||
|
panic("chip8: nothing to pop from stack")
|
||||||
|
}
|
||||||
|
emulator.SP -= 2
|
||||||
|
emulator.PC = binary.BigEndian.Uint16(emulator.Memory[emulator.SP:])
|
||||||
|
binary.BigEndian.PutUint16(emulator.Memory[emulator.SP:], 0x00) // clean the stack position
|
||||||
|
}
|
31
chip8/stack_test.go
Normal file
31
chip8/stack_test.go
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
package chip8_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
"github.com/tangzero/chip8-emulator/chip8"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestEmulator_StackPush(t *testing.T) {
|
||||||
|
emulator := chip8.NewEmulator()
|
||||||
|
|
||||||
|
emulator.PC = 0xABCD
|
||||||
|
emulator.StackPush()
|
||||||
|
|
||||||
|
assert.Equal(t, uint8(0xAB), emulator.Memory[chip8.StackAddress])
|
||||||
|
assert.Equal(t, uint8(0xCD), emulator.Memory[chip8.StackAddress+1])
|
||||||
|
assert.Equal(t, chip8.StackAddress+2, emulator.SP)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestEmulator_StackPop(t *testing.T) {
|
||||||
|
emulator := chip8.NewEmulator()
|
||||||
|
|
||||||
|
emulator.SP = chip8.StackAddress + 32
|
||||||
|
emulator.Memory[chip8.StackAddress+30] = 0xEE
|
||||||
|
emulator.Memory[chip8.StackAddress+31] = 0xFF
|
||||||
|
emulator.StackPop()
|
||||||
|
|
||||||
|
assert.Equal(t, uint16(0xEEFF), emulator.PC)
|
||||||
|
assert.Equal(t, chip8.StackAddress+30, emulator.SP)
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user