Documentation ¶
Overview ¶
Package rcs contains the common components used to create retro-computing systems.
Index ¶
- Constants
- Variables
- func Add(in0, in1 uint8, carry bool) (out uint8, c, h, v bool)
- func B(v int) string
- func B16(v uint16) string
- func B8(v uint8) string
- func BitPlane4(v uint8, n int) uint8
- func FitInWindow(winW int32, winH int32, screen *Screen)
- func FormatStmt(s Stmt, options FormatOptions) string
- func FromBCD(v uint8) uint8
- func LoadROMs(dir string, roms []ROM) (map[string][]byte, error)
- func NewScanLinesH(r *sdl.Renderer, w int32, h int32, size int32) (*sdl.Texture, error)
- func NewScanLinesV(r *sdl.Renderer, w int32, h int32, size int32) (*sdl.Texture, error)
- func Parity(v uint8) bool
- func ParseBits(s string) uint8
- func SliceBits(value uint8, lo int, hi int) uint8
- func Sub(in0, in1 uint8, borrow bool) (out uint8, fc, fh, fv bool)
- func ToBCD(v uint8) uint8
- func X(v int) string
- func X16(v uint16) string
- func X8(v uint8) string
- type CPU
- type CPUDisassembler
- type CharDecoder
- type CodeFormatter
- type CodeReader
- type Component
- type Decoder
- type Disassembler
- type Encoder
- type FlagRW
- type FormatOptions
- type Load
- type Load8
- type Loader
- type Mach
- type MachCmd
- type MachEvent
- type Memory
- func (m *Memory) Bank() int
- func (m *Memory) Map(startAddr int, m1 *Memory)
- func (m *Memory) MapLoad(addr int, load Load8)
- func (m *Memory) MapNil(addr int)
- func (m *Memory) MapRAM(addr int, ram []uint8)
- func (m *Memory) MapRO(addr int, b *uint8)
- func (m *Memory) MapROM(addr int, rom []uint8)
- func (m *Memory) MapRW(addr int, b *uint8)
- func (m *Memory) MapStore(addr int, store Store8)
- func (m *Memory) MapWO(addr int, b *uint8)
- func (m *Memory) Read(addr int) uint8
- func (m *Memory) ReadLE(addr int) int
- func (m *Memory) SetBank(bank int)
- func (m *Memory) Unmap(addr int)
- func (m *Memory) Unwatch(addr int)
- func (m *Memory) WatchRO(addr int)
- func (m *Memory) WatchRW(addr int)
- func (m *Memory) WatchWO(addr int)
- func (m *Memory) Write(addr int, val uint8)
- func (m *Memory) WriteLE(addr int, val int)
- func (m *Memory) WriteN(addr int, values ...uint8)
- type MemoryEvent
- type Pointer
- type Proc
- type ROM
- type SDLContext
- type Saver
- type Screen
- type Status
- type Stmt
- type StmtEval
- type Store
- type Store8
- type Synth
- type TileSheet
- type Voice
Examples ¶
Constants ¶
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
const MaxGameControllers = 4
Variables ¶
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 ¶
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 BitPlane4 ¶
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 FormatStmt ¶
func FormatStmt(s Stmt, options FormatOptions) string
func FromBCD ¶
FromBCD converts a binary-coded decimal to an integer value.
Example ¶
v := FromBCD(0x42) fmt.Println(v)
Output: 42
func LoadROMs ¶
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 NewScanLinesV ¶
func ParseBits ¶
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 ¶
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 ¶
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.
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 ¶
CharDecoder converts a byte value to a unicode character and indicates if this character is considered to be printable.
type CodeFormatter ¶
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 Decoder ¶
type Decoder struct { Err error // contains filtered or unexported fields }
func NewDecoder ¶
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 ¶
type FormatOptions ¶
type FormatOptions struct {
BytesFormat string
}
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 }
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 ¶
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 ¶
Bank returns the number of the selected bank. Banks are numbered starting with zero.
func (*Memory) Map ¶
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 ¶
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) MapRAM ¶
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 ¶
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 ¶
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 ¶
MapRW adds a read and write to the given 8-bit value at addr. Any existing mappings are replaced.
func (*Memory) MapStore ¶
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 ¶
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) ReadLE ¶
ReadLE returns the 16-bit value at addr and addr+1 stored in little endian byte order.
func (*Memory) WatchRO ¶
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 ¶
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 ¶
WatchWO creates a write watch on the address. When a value is written to that address, a MemoryEvent is sent to the Callback function.
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 ¶
NewPointer creates pointer at address zero on the provided memory.
func (*Pointer) Fetch ¶
Fetch returns the byte at current position as an 8-bit value and advances the pointer by one.
func (*Pointer) FetchLE ¶
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 ¶
Peek returns the byte at the current position as an 8-bit value. The pointer is not moved.
type ROM ¶
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)
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 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.
Directories ¶
Path | Synopsis |
---|---|
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. |