rcs

package
v0.0.0-...-20a4c11 Latest Latest
Warning

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

Go to latest
Published: Sep 23, 2022 License: MIT Imports: 19 Imported by: 0

Documentation

Overview

Package rcs contains the common components used to create retro-computing systems.

Index

Examples

Constants

View Source
const (
	SampleRate  = 22050
	Channels    = 2
	AudioFormat = sdl.AUDIO_U16LSB
	Buffer      = 5
)

FIXME: This need to be more specific names or moved out of this scope

View Source
const MaxGameControllers = 4

Variables

View Source
var ASCIIDecoder = func(code uint8) (rune, bool) {
	printable := code >= 32 && code < 128
	return rune(code), printable
}

ASCIIDecoder is a pass through of byte values to unicode characters. Values 32 to 128 are considered printable.

Functions

func Add

func Add(in0, in1 uint8, carry bool) (out uint8, c, h, v bool)

Add performs addition on in0 and in1 with a carry and returns the result along with the new values for the carry, half-carry, and overflow flags.

func B

func B(v int) string

func B16

func B16(v uint16) string

func B8

func B8(v uint8) string

func BitPlane4

func BitPlane4(v uint8, n int) uint8

BitPlane4 returns the nth 2-bit value stored in 4-bit planes found in v. If n is 0, returns bits 0 and 4. If n is 1, returns bits 1 and 5, etc.

func FitInWindow

func FitInWindow(winW int32, winH int32, screen *Screen)

func FormatStmt

func FormatStmt(s Stmt, options FormatOptions) string

func FromBCD

func FromBCD(v uint8) uint8

FromBCD converts a binary-coded decimal to an integer value.

Example
v := FromBCD(0x42)
fmt.Println(v)
Output:

42

func LoadROMs

func LoadROMs(dir string, roms []ROM) (map[string][]byte, error)

LoadROMs loads all ROMs in the given slice of definitions. An attempt will be made to load each ROM. Any errors encountered during the attempts are be combined into a single error.

The returned map will contain a byte slice for each ROM identified by its name. ROMS that are given the same name are concatenated together. Extra whitespace found at the beginning or ending of the name or filename are removed and is useful for aligning the ROM definitions in the source code.

func NewScanLinesH

func NewScanLinesH(r *sdl.Renderer, w int32, h int32, size int32) (*sdl.Texture, error)

func NewScanLinesV

func NewScanLinesV(r *sdl.Renderer, w int32, h int32, size int32) (*sdl.Texture, error)

func Parity

func Parity(v uint8) bool

Parity returns true if there are an even number of bits set in the given value.

func ParseBits

func ParseBits(s string) uint8

ParseBits parses the base-2 string value s to a uint8. Panics if s is not a valid number. Use strconv.ParseUint for input which may be malformed.

func SliceBits

func SliceBits(value uint8, lo int, hi int) uint8

SliceBits extracts a sequence of bits in value from bit lo to bit hi, inclusive.

Example
value := ParseBits("00111000")
fmt.Printf("%03b", SliceBits(value, 3, 5))
Output:

111

func Sub

func Sub(in0, in1 uint8, borrow bool) (out uint8, fc, fh, fv bool)

Sub performs subtraction of in1 from in0 with a borrow and returns the result along with the new values for the borrow, half-borrow, and overflow flags.

func ToBCD

func ToBCD(v uint8) uint8

ToBCD converts an integer value to a binary-coded decimal.

Example
v := ToBCD(42)
fmt.Printf("%02x", v)
Output:

42

func X

func X(v int) string

func X16

func X16(v uint16) string

func X8

func X8(v uint8) string

Types

type CPU

type CPU interface {
	Next()           // Execute the next instruction
	PC() int         // Address of the program counter
	SetPC(int)       // Set the address of the program counter
	Offset() int     // The next instruction is at PC() + Offset()
	Memory() *Memory // View of memory
}

CPU is a central processing unit.

The program counter is an integer to accomodate address busses of at least 32-bit. The program counter stored within the actual struct should proablby be the actual size of the bus.

Offset is for CPUs, like the 6502, that increment the program counter before fetching the instruction opcode. In this case, one should be returned. If the program counter is incremented after the fetch, zero should be returned.

type CPUDisassembler

type CPUDisassembler interface {
	NewDisassembler() *Disassembler
}

CPUDisassembler provides a disassembler instance for CPUs that support this method.

type CharDecoder

type CharDecoder func(uint8) (ch rune, printable bool)

CharDecoder converts a byte value to a unicode character and indicates if this character is considered to be printable.

type CodeFormatter

type CodeFormatter func(Stmt) string

CodeFormat formats a statement in a string suitible for display to the end user.

type CodeReader

type CodeReader func(StmtEval)

CodeReader reads the next instruction using provided pointer and fills in the fields found in the Stmt.

type Component

type Component struct {
	Name   string
	Module string
	Parent string
	C      interface{}
}

func NewComponent

func NewComponent(name string, mod string, parent string, c interface{}) Component

type Decoder

type Decoder struct {
	Err error
	// contains filtered or unexported fields
}

func NewDecoder

func NewDecoder(r io.Reader) *Decoder

func (*Decoder) Decode

func (d *Decoder) Decode(v interface{})

type Disassembler

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

func NewDisassembler

func NewDisassembler(mem *Memory, r CodeReader, f CodeFormatter) *Disassembler

func (*Disassembler) Next

func (d *Disassembler) Next() string

func (*Disassembler) NextStmt

func (d *Disassembler) NextStmt() Stmt

func (*Disassembler) PC

func (d *Disassembler) PC() int

func (*Disassembler) SetPC

func (d *Disassembler) SetPC(addr int)

type Encoder

type Encoder struct {
	Err error
	// contains filtered or unexported fields
}

func NewEncoder

func NewEncoder(w io.Writer) *Encoder

func (*Encoder) Encode

func (e *Encoder) Encode(v interface{})

type FlagRW

type FlagRW struct {
	R bool // Read
	W bool // Write
}

type FormatOptions

type FormatOptions struct {
	BytesFormat string
}

type Load

type Load func() int

Load is a function which loads an integer value

type Load8

type Load8 func() uint8

Load8 is a function which loads an unsigned 8-bit value

type Loader

type Loader interface {
	Load(*Decoder)
}

type Mach

type Mach struct {
	Sys             interface{}
	Comps           []Component
	CharDecoders    map[string]CharDecoder
	DefaultEncoding string
	Ctx             SDLContext
	Screen          Screen
	VBlankFunc      func()
	QueueAudio      func() error
	Keyboard        func(*sdl.KeyboardEvent) error
	ButtonHandler   func(*sdl.ControllerButtonEvent) error
	AxisHandler     func(*sdl.ControllerAxisEvent) error

	CPU         map[string]CPU
	Proc        map[string]Proc
	Status      Status
	Callback    func(MachEvent, ...interface{})
	Breakpoints map[string]map[int]struct{}
	Executing   string // name of the CPU that is executing
	At          int    // address of the executing instruction
	// contains filtered or unexported fields
}

func (*Mach) Command

func (m *Mach) Command(cmd MachCmd, args ...interface{})

func (*Mach) Init

func (m *Mach) Init() error

func (*Mach) Run

func (m *Mach) Run() error

type MachCmd

type MachCmd int
const (
	MachExport MachCmd = iota
	MachImport
	MachPause
	MachSnapshot
	MachStart
	MachTrace
	MachTraceAll
	MachQuit
)

type MachEvent

type MachEvent int
const (
	StatusEvent MachEvent = iota
	TraceEvent
	ErrorEvent
)

type Memory

type Memory struct {
	Name     string
	MaxAddr  int               // maximum valid address
	Callback func(MemoryEvent) // function called on watch events
	NBank    int               // number of banks
	// contains filtered or unexported fields
}

Memory represents an address space used to access RAM, ROM, IO ports, and external devices.

To create a memory space with a 16 line address bus and a single bank, use:

mem := rcs.NewMemory(1, 0x10000)

This struct is just a container for the address space and has no actual memory mapped to it yet. Reads or writes to an unmapped address emit a warning through the standard logger.

Single values are mapped for read/write access using the MapRW method. This is useful for mapping ports or registers of a device into the address space. In this example from the Commodore 64, the X coordinate for sprite #0 is mapped to 0xd000 and the Y coordinate is mapped to 0xd001:

mem.MapRW(0xd000, &sprites[0].X)
mem.MapRW(0xd001, &sprites[0].Y)

Use MapRO for a read-only mapping and MapWO for a write-only mapping. In this example from Pac-Man, the value of port IN0 is read through address 0x5000 but interrupts can be enabled or disabled by writing to address 0x5000:

mem.MapRO(0x5000, &portIN0)
mem.MapWO(0x5000, &irqEnable)

A range of addresses can map to the same value with:

for i := 0x50c0; i <= 0x50ff; i++ {
	mem.MapWO(i, &watchdogReset)
}

Large blocks can be mapped by passing in a uint8 slice using MapRAM for read/write access and MapROM for read-only access. The following example maps a 16KB block of ROM to 0x0000 - 0x3fff and a 48KB block of RAM to 0x4000 - 0xffff:

rom := []uint8{ ... 16KB data ... }
ram := make([]uint8, 48*1024, 48*1024)
mem.MapROM(0x0000, rom)
mem.MapRAM(0x4000, ram)

To "overlay" ROM on top of RAM, first use MapRAM and then MapROM which will replace the read mappings while leaving the write mappings untouched. In the following example, reads in the first 16KB come from the ROM but writes go to the RAM:

rom := []uint8{ ... 16KB data ... }
ram := make([]uint8, 64*1024, 64*1024)
mem.MapRAM(0x0000, ram)
mem.MapROM(0x0000, rom)

To use banked memory, create memory with more than one bank:

mem := rcs.NewMemory(2, 0x10000)

All map, read, and write operations are performed on the selected bank which by default is zero. The following example has a ROM overlay in bank 0 and full access to the RAM in bank 1:

rom := []uint8{ ... 16KB data ... }
ram := make([]uint8, 64*1024, 64*1024)

mem.SetBank(0)
mem.MapRAM(0x0000, ram)
mem.MapROM(0x0000, rom)

mem.SetBank(1)
mem.MapRAM(0x0000, ram)

func NewMemory

func NewMemory(banks int, size int) *Memory

NewMemory creates a memory space of uint8 values that are addressable from 0 to size - 1. This function only creates the address space; values must be mapped using the Map methods. To create banked memory, use a value greater than one for the banks argument.

func (*Memory) Bank

func (m *Memory) Bank() int

Bank returns the number of the selected bank. Banks are numbered starting with zero.

func (*Memory) Map

func (m *Memory) Map(startAddr int, m1 *Memory)

Map maps the contents of another memory to this memory at the starting address. This copies the bindings in the other memory at call time; later updates to the map of the other memory will not be seen in this memory.

func (*Memory) MapLoad

func (m *Memory) MapLoad(addr int, load Load8)

MapLoad adds a read mapping to the given function. When this address is read from, the function is invoked to get the value. If there is already a read mapping for this address, it is replaced. Write mappings are not altered.

func (*Memory) MapNil

func (m *Memory) MapNil(addr int)

MapNil creates an empty read and write mapping at the address.

func (*Memory) MapRAM

func (m *Memory) MapRAM(addr int, ram []uint8)

MapRAM adds read/write maps to all of the 8-bit values in ram starting at addr. Any existing read or write maps are replaced.

func (*Memory) MapRO

func (m *Memory) MapRO(addr int, b *uint8)

MapRO adds a read mapping to the given 8-bit value at addr. If there is already a read mapping, it is replaced. Write mappings are not altered.

func (*Memory) MapROM

func (m *Memory) MapROM(addr int, rom []uint8)

MapROM adds read maps to all of the 8-bit values in rom starting at addr. Any existing read maps are replaced but write maps are not altered. If the rom passed in is nil, no mappings are changed.

func (*Memory) MapRW

func (m *Memory) MapRW(addr int, b *uint8)

MapRW adds a read and write to the given 8-bit value at addr. Any existing mappings are replaced.

func (*Memory) MapStore

func (m *Memory) MapStore(addr int, store Store8)

MapStore adds a write mapping to the given function. When this address is written to, the function is invoked with the value to write. If there is already a write mapping for this address, it is replaced. Read mappings are not altered.

func (*Memory) MapWO

func (m *Memory) MapWO(addr int, b *uint8)

MapWO adds a write mapping to the given 8-bit value at addr. If there is already a write mapping, it is replaced. Read mappings are not altered.

func (*Memory) Read

func (m *Memory) Read(addr int) uint8

Read returns the 8-bit value at the given address.

func (*Memory) ReadLE

func (m *Memory) ReadLE(addr int) int

ReadLE returns the 16-bit value at addr and addr+1 stored in little endian byte order.

func (*Memory) SetBank

func (m *Memory) SetBank(bank int)

SetBank changes the selected bank. Banks are numbered starting with zero.

func (*Memory) Unmap

func (m *Memory) Unmap(addr int)

Unmap removes the read and write mappings at the address.

func (*Memory) Unwatch

func (m *Memory) Unwatch(addr int)

Unwatch removes read nad write watches on the address.

func (*Memory) WatchRO

func (m *Memory) WatchRO(addr int)

WatchRO creates a read watch on the address. When a value is read to that address, a MemoryEvent is sent to the Callback function.

func (*Memory) WatchRW

func (m *Memory) WatchRW(addr int)

WatchRW creats a read and write watch on the address. When a value is read from or written to that address, a MemorYEvent is sent to the Callback function.

func (*Memory) WatchWO

func (m *Memory) WatchWO(addr int)

WatchWO creates a write watch on the address. When a value is written to that address, a MemoryEvent is sent to the Callback function.

func (*Memory) Write

func (m *Memory) Write(addr int, val uint8)

Write sets the 8-bit value at the given address.

func (*Memory) WriteLE

func (m *Memory) WriteLE(addr int, val int)

WriteLE puts a 16-bit value at addr and addr+1 stored in little endian byte order.

func (*Memory) WriteN

func (m *Memory) WriteN(addr int, values ...uint8)

WriteN sets multiple 8-bit values starting with the given address.

type MemoryEvent

type MemoryEvent struct {
	Read  bool
	Bank  int
	Addr  int
	Value uint8
}

type Pointer

type Pointer struct {
	Mask int     // Address mask
	Mem  *Memory // Memory view
	// contains filtered or unexported fields
}

Pointer points to a location in memory.

func NewPointer

func NewPointer(mem *Memory) *Pointer

NewPointer creates pointer at address zero on the provided memory.

func (*Pointer) Addr

func (p *Pointer) Addr() int

func (*Pointer) Fetch

func (p *Pointer) Fetch() uint8

Fetch returns the byte at current position as an 8-bit value and advances the pointer by one.

func (*Pointer) FetchLE

func (p *Pointer) FetchLE() int

FetchLE returns the next two bytes as a 16-bit value stored in little endian format and advances the pointer by two.

func (*Pointer) Peek

func (p *Pointer) Peek() uint8

Peek returns the byte at the current position as an 8-bit value. The pointer is not moved.

func (*Pointer) Put

func (p *Pointer) Put(value uint8)

Put sets the value at the current address and advances the pointer by one.

func (*Pointer) PutN

func (p *Pointer) PutN(values ...uint8)

PutN calls Put for each value.

func (*Pointer) SetAddr

func (p *Pointer) SetAddr(addr int)

type Proc

type Proc interface {
	Next()
}

type ROM

type ROM struct {
	Name     string
	File     string
	Checksum string
}

ROM represents a dump of read-only memory data found on disk.

To load in a set of ROMs, define a slice of ROM definitions each with the "name" of the ROM, the filename found on disk, and its SHA1 checksum as a string of hexadecimal values.

roms := []rcs.ROM{
	NewROM("code"  ", "chip1.rom  ", "da39a3ee5e6b4b0d3255bfef95601890afd80709"),
	NewROM("code   ", "chip2.rom  ", "342d21fb707e89a6d407117c810795abcc481c52"),
	NewROM("sprites", "chip3az.rom", "38dc6d5fe1a085f2e885748a00fbe5b7b3b8b1a6"),
}

Then call LoadROMs to return a map of names to byte slices:

data, err := LoadROMs("/path/to/roms", roms)

func NewROM

func NewROM(name string, file string, checksum string) ROM

NewROM creates a new ROM definition.

type SDLContext

type SDLContext struct {
	Window          *sdl.Window
	Renderer        *sdl.Renderer
	AudioSpec       sdl.AudioSpec
	GameControllers [MaxGameControllers]*sdl.GameController
}

SDLContext contains the window for rendering and the audio specs available for use.

type Saver

type Saver interface {
	Save(*Encoder)
}

type Screen

type Screen struct {
	W         int32
	H         int32
	X         int32
	Y         int32
	Scale     int32
	Texture   *sdl.Texture
	ScanLineH bool
	ScanLineV bool
	Draw      func(*sdl.Renderer) error
}

type Status

type Status int
const (
	Pause Status = iota
	Run
	Break
)

func (Status) String

func (s Status) String() string

type Stmt

type Stmt struct {
	Addr    int     // Address of the instruction
	Label   string  // Label for this address, "CHROUT"
	Op      string  // Formated operation, "lda #$40"
	Bytes   []uint8 // Bytes that represent this instruction
	Comment string  // Any notes from the source code
}

Stmt represents a single statement in a disassembly.

type StmtEval

type StmtEval struct {
	Ptr  *Pointer
	Stmt *Stmt
}

type Store

type Store func(int)

Store is a function which stores an integer value

type Store8

type Store8 func(uint8)

Store8 is a function which stores an unsiged 8-bit value

type Synth

type Synth struct {
	Spec sdl.AudioSpec
	V    []*Voice
	// contains filtered or unexported fields
}

func NewSynth

func NewSynth(spec sdl.AudioSpec, voiceN int) (*Synth, error)

func (*Synth) Queue

func (s *Synth) Queue() error

type TileSheet

type TileSheet struct {
	TextureW int32
	TextureH int32
	TileW    int32
	TileH    int32
	Texture  *sdl.Texture
}

func NewColorSheet

func NewColorSheet(r *sdl.Renderer, palettes [][]color.RGBA) (TileSheet, error)

type Voice

type Voice struct {
	Freq     int
	Vol      float64
	Waveform []float64
	// contains filtered or unexported fields
}

func NewVoice

func NewVoice(sampleRate int32) *Voice

func (*Voice) Fill

func (v *Voice) Fill(out []float64, n int)

Directories

Path Synopsis
cbm
Package cbm contains components for Commodore Business Machines.
Package cbm contains components for Commodore Business Machines.
Package m6502 is the MOS Technology 6502 series processor.
Package m6502 is the MOS Technology 6502 series processor.
Package namco contains components for Namco systems.
Package namco contains components for Namco systems.
Package z80 is the Zilog Z80 processor.
Package z80 is the Zilog Z80 processor.

Jump to

Keyboard shortcuts

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