refactor + some instructions + stack implementation

This commit is contained in:
Jairinho 2022-02-23 16:20:07 -03:00
parent 3feed8e5c0
commit e31a6a3b64
No known key found for this signature in database
GPG Key ID: 954589B18A21D5B6
5 changed files with 117 additions and 14 deletions

View File

@ -1,13 +1,23 @@
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 {
V [16]uint8 // general registers
I uint16 // address register
SP uint16 // stack pointer
PC uint16 // program counter
Memory [4096]uint8 // 4KB of system RAM
Stack []uint8 // 32 bytes of stack. starting at 0x0EA0
Screen []uint8 // 256 bytes of display buffer. starting at 0x0F00
V [16]uint8 // general registers
I uint16 // address register
SP uint16 // stack pointer
PC uint16 // program counter
Memory [MemorySize]uint8 // 4KB of system RAM
Timer struct {
Delay uint8 // delay timer
Sound uint8 // sound timer
@ -23,13 +33,11 @@ func NewEmulator() *Emulator {
func (emulator *Emulator) Reset() {
emulator.V = [16]uint8{}
emulator.I = 0x00
emulator.SP = 0x00
emulator.PC = 0x0200
emulator.Memory = [4096]uint8{}
emulator.Stack = emulator.Memory[0x0EA0:]
emulator.Screen = emulator.Memory[0x0F00:]
emulator.I = 0
emulator.SP = StackAddress
emulator.PC = ProgramAddress
emulator.Memory = [MemorySize]uint8{}
emulator.Timer.Delay = 0
emulator.Timer.Sound = 0
copy(emulator.Memory[0x0200:], emulator.ROM)
copy(emulator.Memory[ProgramAddress:], emulator.ROM)
}

43
chip8/instructions.go Normal file
View 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
}
}

View File

@ -0,0 +1 @@
package chip8_test

20
chip8/stack.go Normal file
View 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
View 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)
}