143 lines
2.9 KiB
Go
143 lines
2.9 KiB
Go
package cards
|
|
|
|
import (
|
|
"fmt"
|
|
)
|
|
|
|
type LanguageCard struct {
|
|
name string
|
|
rom [12288]byte
|
|
ram [16384]byte
|
|
cm CardManager
|
|
slot byte
|
|
slotbit byte
|
|
bank int // 1 = bank 1, 0 = bank 2
|
|
ramread bool
|
|
ramwrite bool
|
|
readcount int
|
|
}
|
|
|
|
func NewLanguageCard(rom []byte, name string, slot byte, cm CardManager) (*LanguageCard, error) {
|
|
if len(rom) != 12288 {
|
|
return nil, fmt.Errorf("Wrong size ROM: expected 12288, got %d", len(rom))
|
|
}
|
|
lc := &LanguageCard{
|
|
name: name,
|
|
cm: cm,
|
|
slot: slot,
|
|
slotbit: 1 << slot,
|
|
bank: 0,
|
|
ramread: false,
|
|
ramwrite: true,
|
|
readcount: 0,
|
|
}
|
|
copy(lc.rom[:], rom)
|
|
return lc, nil
|
|
}
|
|
|
|
func (lc *LanguageCard) String() string {
|
|
return fmt.Sprintf("%s (slot %d)", lc.name, lc.slot)
|
|
}
|
|
|
|
// Init: language card should always handle D000-FFFF accessess, since
|
|
// it contains either RAM or ROM.
|
|
func (lc *LanguageCard) Init() {
|
|
lc.cm.Handle12k(true, lc.slot)
|
|
}
|
|
|
|
func (lc *LanguageCard) Slot() byte {
|
|
return lc.slot
|
|
}
|
|
|
|
func (lc *LanguageCard) ROMDisabled() {
|
|
// Language card doesn't have a $C(8-F)xx ROM
|
|
}
|
|
|
|
func (lc *LanguageCard) handleAccess(address byte, write bool) {
|
|
if write {
|
|
lc.readcount = 0
|
|
}
|
|
|
|
address &^= 4
|
|
switch address &^ 8 {
|
|
case 0:
|
|
lc.ramread = true
|
|
lc.ramwrite = false
|
|
lc.readcount = 0
|
|
case 1:
|
|
lc.ramread = false
|
|
if lc.readcount > 0 {
|
|
lc.ramwrite = true
|
|
}
|
|
if !write {
|
|
lc.readcount++
|
|
}
|
|
case 2:
|
|
lc.ramread = false
|
|
lc.ramwrite = false
|
|
lc.readcount = 0
|
|
case 3:
|
|
lc.ramread = true
|
|
if lc.readcount > 0 {
|
|
lc.ramwrite = true
|
|
}
|
|
if !write {
|
|
lc.readcount++
|
|
}
|
|
}
|
|
lc.bank = int((address & 8) >> 3)
|
|
// fmt.Printf("ramread: %v, ramwrite: %v, bank: %d, readcount: %d\n", lc.ramread, lc.ramwrite, lc.bank, lc.readcount)
|
|
}
|
|
|
|
func (lc *LanguageCard) Read16(address byte) byte {
|
|
// fmt.Printf("Read to %02xd: ", address)
|
|
lc.handleAccess(address, false)
|
|
return lc.cm.EmptyRead()
|
|
}
|
|
|
|
func (lc *LanguageCard) Write16(address byte, value byte) {
|
|
// fmt.Printf("Write to %02xd: ", address)
|
|
lc.handleAccess(address, true)
|
|
}
|
|
|
|
func (lc *LanguageCard) ramOffset(address uint16) uint16 {
|
|
if address < 0xE000 {
|
|
return address - 0xD000 + 0x1000*uint16(lc.bank)
|
|
}
|
|
return address - 0xE000 + 0x2000
|
|
}
|
|
|
|
func (lc *LanguageCard) Read(address uint16) byte {
|
|
// fmt.Printf("Read from %04x\n", address)
|
|
if address < 0xD000 {
|
|
panic(fmt.Sprintf("%s got read to $%04X (<$D000)", lc.String(), address))
|
|
}
|
|
if lc.ramread {
|
|
return lc.ram[lc.ramOffset(address)]
|
|
}
|
|
return lc.rom[address-0xD000]
|
|
}
|
|
|
|
func (lc *LanguageCard) Write(address uint16, value byte) {
|
|
// fmt.Printf("Write to %04x\n", address)
|
|
if lc.ramwrite {
|
|
lc.ram[lc.ramOffset(address)] = value
|
|
}
|
|
}
|
|
|
|
func (lc *LanguageCard) Read256(address byte) byte {
|
|
return lc.cm.EmptyRead()
|
|
}
|
|
|
|
func (lc *LanguageCard) Write256(address byte, value byte) {
|
|
// Language is ROM: do nothing
|
|
}
|
|
|
|
func (lc *LanguageCard) WantTicker() bool {
|
|
return false
|
|
}
|
|
|
|
func (lc *LanguageCard) Tick() {
|
|
// do nothing
|
|
}
|