chipper

package module
v0.0.0-...-919880a Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Mar 8, 2025 License: BSD-3-Clause Imports: 13 Imported by: 0

README

CI status License Go Report Card

chipper

Chipper is a CHIP-8 emulator written in Go.

In this repo you'll also find a Vue app which embeds the emulator via WASM, allowing you to play CHIP-8 games, directly from the browser!

Roadmap

This is mostly for myself, just a set of TO-DOs for improving the code now that chipper hit MVP.

  • flesh out README
  • finish writing tests for the entire instruction set
  • improve the Web UI with keymap information
  • improve the Web UI with keymap configuration
  • move state management to Pinia
  • filter out some ROMs that won't show by default in a production build

Documentation

Index

Constants

View Source
const (
	ColorClear = iota
	ColorSet
)
View Source
const (
	ProgramCounterSize = 2     // Size in bytes.
	RegisterCount      = 16    // V0-VF.
	StartAddress       = 0x200 // starting address of PC.
	NumKeys            = 16
	InstructionSize    = 2 // each instruction is 2 bytes wide.
)

Variables

This section is empty.

Functions

func ColorEq

func ColorEq(c1, c2 color.Color) bool

func DumpEmu

func DumpEmu(emu *Emulator)

func Each

func Each(d Display, fn func(int, int) error) error

func NewRAM

func NewRAM(size int) ([]byte, error)

func ToAddr3

func ToAddr3(p []int) (uint16, error)

func ToByte

func ToByte(p []int) (byte, error)

Types

type ArgCountError

type ArgCountError struct {
	// contains filtered or unexported fields
}

func (ArgCountError) Error

func (e ArgCountError) Error() string

type DebugDisplay

type DebugDisplay struct {
	// contains filtered or unexported fields
}

func NewDebugDisplay

func NewDebugDisplay(w, h int) (*DebugDisplay, error)

func (*DebugDisplay) At

func (d *DebugDisplay) At(x, y int) color.Color

func (*DebugDisplay) Bounds

func (d *DebugDisplay) Bounds() image.Rectangle

func (*DebugDisplay) ColorClear

func (d *DebugDisplay) ColorClear() color.Color

func (*DebugDisplay) ColorModel

func (d *DebugDisplay) ColorModel() color.Model

func (*DebugDisplay) ColorSet

func (d *DebugDisplay) ColorSet() color.Color

func (*DebugDisplay) Set

func (d *DebugDisplay) Set(x, y int, c color.Color)

func (*DebugDisplay) String

func (d *DebugDisplay) String() string

type Direction

type Direction int
const (
	Up Direction = iota
	Down
)

type Display

type Display interface {
	fmt.Stringer
	draw.Image
	ColorClear() color.Color
	ColorSet() color.Color
}

type Emulator

type Emulator struct {
	PC              uint16
	V               [RegisterCount]byte
	DelayTimer      byte
	SoundTimer      byte
	Index           uint16
	Keys            KeyInputSource
	Stack           *Stack
	RAM             []byte
	Display         Display
	LastInstruction Instruction
	// contains filtered or unexported fields
}

func NewEmulator

func NewEmulator(stackSize, ramSize int, display Display, keys KeyInputSource) (*Emulator, error)

func (*Emulator) Close

func (emu *Emulator) Close()

func (*Emulator) Execute

func (emu *Emulator) Execute(instr Instruction) error

func (*Emulator) Fetch

func (emu *Emulator) Fetch(numBytes int) ([]byte, error)

Fetch will read the instruction pointed at by the PC. It will do a bounds check.

func (*Emulator) Load

func (emu *Emulator) Load(r io.Reader) error

Load will read the ROM from the passed in io.Reader and load the sprites.

func (*Emulator) SetLogger

func (emu *Emulator) SetLogger(l *log.Logger)

func (*Emulator) Tick

func (emu *Emulator) Tick() error

Tick is the core Fetch-Decode-Execute loop of the emulator.

type Instruction

type Instruction struct {
	Op       Opcode
	Operands []int
}

func Decode

func Decode(p []byte) (Instruction, error)

func (Instruction) String

func (instr Instruction) String() string

type InstructionNotImplementedError

type InstructionNotImplementedError struct {
	// contains filtered or unexported fields
}

func (InstructionNotImplementedError) Error

type KeyInputSource

type KeyInputSource interface {
	Get(key int) bool
	Set(key int, v bool)
	WaitUntilKeypress() <-chan int
}

type Opcode

type Opcode string
const (
	Unknown                   Opcode = "Unknown"
	Nop                       Opcode = "Nop"
	ExecNNN                   Opcode = "ExecNNN"
	Clear                     Opcode = "Clear"
	ReturnFromSub             Opcode = "ReturnFromSub"
	JumpNNN                   Opcode = "JumpNNN"
	CallSub                   Opcode = "CallSub"
	SkipIfXEqNN               Opcode = "SkipIfXEqNN"
	SkipIfXNotEqNN            Opcode = "SkipIfXNotEqNN"
	SkipIfXEqY                Opcode = "SkipIfXEqY"
	StoreNNInX                Opcode = "StoreNNInX"
	AddNNToX                  Opcode = "AddNNToX"
	StoreYinX                 Opcode = "StoreYinX"
	SetXToXORY                Opcode = "SetXToXORY"
	SetXToXANDY               Opcode = "SetXToXANDY"
	SetXToXXORY               Opcode = "SetXToXXORY"
	AddYToX                   Opcode = "AddYToX"
	SubYFromX                 Opcode = "SubYFromX"
	StoreYShiftedRightInX     Opcode = "StoreYShiftedRightInX"
	SetXToYMinusX             Opcode = "SetXToYMinusX"
	StoreYShiftedLeftInX      Opcode = "StoreYShiftedLeftInX"
	SkipIfXNotEqY             Opcode = "SkipIfXNotEqY"
	StoreMemAddrNNNInRegI     Opcode = "StoreMemAddrNNNInRegI"
	JumpToAddrNNNPlusV0       Opcode = "JumpToAddrNNNPlusV0"
	SetXToRandomNumWithMaskNN Opcode = "SetXToRandomNumWithMaskNN"
	DrawSpriteInXY            Opcode = "DrawSpriteInXY"
	SkipIfKeyInXIsPressed     Opcode = "SkipIfKeyInXIsPressed"
	SkipIfKeyInXNotPressed    Opcode = "SkipIfKeyInXNotPressed"
	StoreValDTInX             Opcode = "StoreValDTInX"
	WaitForKeyAndStoreInX     Opcode = "WaitForKeyAndStoreInX"
	SetDTToX                  Opcode = "SetDTToX"
	SetSTToX                  Opcode = "SetSTToX"
	AddXToI                   Opcode = "AddXToI"
	SetIToMemAddrOfSpriteInX  Opcode = "SetIToMemAddrOfSpriteInX"
	StoreBCDOfXInI            Opcode = "StoreBCDOfXInI"
	Store0ToXInI              Opcode = "Store0ToXInI"
	Fill0ToXWithValueInAddrI  Opcode = "Fill0ToXWithValueInAddrI"
)

func DetermineOpcode

func DetermineOpcode(digits []int) Opcode

DetermineOpcode will return the appropriate Opcode given the digits passed in. It expects digits to have length 4.

type Stack

type Stack struct {
	// contains filtered or unexported fields
}

Stack is LIFO data structure, it provides a Push/Pop API. @TODO: consider adding support for ShiftLeft and ShiftRight.

func NewStack

func NewStack(size int) (*Stack, error)

NewStack will return a stack of size N, with the data already allocated.

func (*Stack) Pop

func (s *Stack) Pop() (uint16, error)

Pop an element of the stack, will error if the stack is empty.

func (*Stack) Push

func (s *Stack) Push(val uint16) error

Push an element onto the stack, will error if the stack is full.

func (Stack) String

func (s Stack) String() string

type StubKeyInputSource

type StubKeyInputSource struct{}

func (*StubKeyInputSource) Get

func (stub *StubKeyInputSource) Get(_ int) bool

func (*StubKeyInputSource) Set

func (stub *StubKeyInputSource) Set(_ int, _ bool)

func (*StubKeyInputSource) WaitUntilKeypress

func (stub *StubKeyInputSource) WaitUntilKeypress() <-chan int

Directories

Path Synopsis
cmd
dumprom command
emu command
webui command

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL