ph00524: add emulator
This commit is contained in:
parent
7c663f42ca
commit
be255f2e6f
8 changed files with 605 additions and 0 deletions
98
modules/ph00524/emu/arbiters.go
Normal file
98
modules/ph00524/emu/arbiters.go
Normal file
|
|
@ -0,0 +1,98 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"log"
|
||||
|
||||
"github.com/koron-go/z80"
|
||||
)
|
||||
|
||||
// ioPeripheral is a z80.IO device at a given address.
|
||||
type ioPeripheral struct {
|
||||
start uint8
|
||||
length uint8
|
||||
peripheral z80.IO
|
||||
}
|
||||
|
||||
// ioArbiter is a collection of I/O devices at addresses. It implements z80.IO
|
||||
// itself, dispatching to the appropriate device as needed.
|
||||
type ioArbiter struct {
|
||||
peripherals []*ioPeripheral
|
||||
}
|
||||
|
||||
func (i *ioArbiter) get(addr uint8) *ioPeripheral {
|
||||
for _, periph := range i.peripherals {
|
||||
if addr < periph.start {
|
||||
continue
|
||||
}
|
||||
if addr > periph.start+periph.length {
|
||||
continue
|
||||
}
|
||||
return periph
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (i *ioArbiter) In(addr uint8) uint8 {
|
||||
p := i.get(addr)
|
||||
if p == nil {
|
||||
log.Fatalf("Unhandled I/O In at %02x", addr)
|
||||
return 0
|
||||
}
|
||||
return p.peripheral.In(addr - p.start)
|
||||
}
|
||||
func (i *ioArbiter) Out(addr uint8, value uint8) {
|
||||
p := i.get(addr)
|
||||
if p == nil {
|
||||
log.Fatalf("Unhandled I/O Out at %02x", addr)
|
||||
return
|
||||
}
|
||||
p.peripheral.Out(addr-p.start, value)
|
||||
}
|
||||
|
||||
// memory is a continuous memory region at a given address, optionally marked
|
||||
// read only.
|
||||
type memory struct {
|
||||
start uint16
|
||||
data []uint8
|
||||
readonly bool
|
||||
}
|
||||
|
||||
// memoryArbiter implements Z80.Memory and dispatches accesses to subordinate
|
||||
// memory instances.
|
||||
type memoryArbiter struct {
|
||||
memories []memory
|
||||
}
|
||||
|
||||
func (m *memoryArbiter) get(addr uint16) *memory {
|
||||
for _, mem := range m.memories {
|
||||
if addr < mem.start {
|
||||
continue
|
||||
}
|
||||
if addr >= mem.start+uint16(len(mem.data)) {
|
||||
continue
|
||||
}
|
||||
return &mem
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *memoryArbiter) Get(addr uint16) uint8 {
|
||||
mem := m.get(addr)
|
||||
if mem == nil {
|
||||
log.Fatalf("Unhandled memory Get at %04x", addr)
|
||||
return 0
|
||||
}
|
||||
return mem.data[addr-mem.start]
|
||||
}
|
||||
|
||||
func (m *memoryArbiter) Set(addr uint16, value uint8) {
|
||||
mem := m.get(addr)
|
||||
if mem == nil {
|
||||
log.Fatalf("Unhandled memory Set at %04x", addr)
|
||||
return
|
||||
}
|
||||
if mem.readonly {
|
||||
log.Fatalf("Read-only memory Set at %04x", addr)
|
||||
}
|
||||
mem.data[addr-mem.start] = value
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue