mirror of
https://github.com/ivanizag/izapple2.git
synced 2025-01-03 11:30:29 +00:00
Initial support for the Base64A clone. Support for ROM banks
This commit is contained in:
parent
4b655b40b8
commit
68d68eadfc
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
.vscode
|
@ -59,6 +59,11 @@ func MainApple() *Apple2 {
|
|||||||
false,
|
false,
|
||||||
"shows the character map",
|
"shows the character map",
|
||||||
)
|
)
|
||||||
|
base64a := flag.Bool(
|
||||||
|
"base64a",
|
||||||
|
false,
|
||||||
|
"setup a Base64A clone",
|
||||||
|
)
|
||||||
flag.Parse()
|
flag.Parse()
|
||||||
|
|
||||||
if *dumpChars {
|
if *dumpChars {
|
||||||
@ -69,7 +74,11 @@ func MainApple() *Apple2 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
a := NewApple2(*charRomFile, *cpuClock, !*mono, *fastDisk, *panicSS)
|
a := NewApple2(*charRomFile, *cpuClock, !*mono, *fastDisk, *panicSS)
|
||||||
a.LoadRom(*romFile)
|
if *base64a {
|
||||||
|
NewBase64a(a)
|
||||||
|
} else {
|
||||||
|
a.LoadRom(*romFile)
|
||||||
|
}
|
||||||
if *languageCardSlot >= 0 {
|
if *languageCardSlot >= 0 {
|
||||||
a.AddLanguageCard(*languageCardSlot)
|
a.AddLanguageCard(*languageCardSlot)
|
||||||
}
|
}
|
||||||
|
93
base64a.go
Normal file
93
base64a.go
Normal file
@ -0,0 +1,93 @@
|
|||||||
|
package apple2
|
||||||
|
|
||||||
|
import "fmt"
|
||||||
|
|
||||||
|
/*
|
||||||
|
Copam BASE64A adaptation.
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Base64a extends an Apple2
|
||||||
|
type Base64a struct {
|
||||||
|
a *Apple2
|
||||||
|
romBanks [4]*memoryRange
|
||||||
|
romBank uint8
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewBase64a instantiates an apple2
|
||||||
|
func NewBase64a(a *Apple2) *Base64a {
|
||||||
|
|
||||||
|
var b Base64a
|
||||||
|
b.a = a
|
||||||
|
b.loadRom()
|
||||||
|
|
||||||
|
return &b
|
||||||
|
}
|
||||||
|
|
||||||
|
const (
|
||||||
|
// There are 6 ROM chips. Each can have 4Kb or 8Kb. They can fill
|
||||||
|
// 2 or 4 banks with 2kb windows.
|
||||||
|
base64aRomBankSize = 12 * 1024
|
||||||
|
base64aRomBankCount = 4
|
||||||
|
base64aRomWindowSize = 2 * 1024
|
||||||
|
base64aRomChipCount = 6
|
||||||
|
)
|
||||||
|
|
||||||
|
func (b *Base64a) loadRom() {
|
||||||
|
// Load the 6 PROM dumps
|
||||||
|
romBanksBytes := make([][]uint8, base64aRomBankCount)
|
||||||
|
for j := range romBanksBytes {
|
||||||
|
romBanksBytes[j] = make([]uint8, 0, base64aRomBankSize)
|
||||||
|
}
|
||||||
|
|
||||||
|
for i := 0; i < base64aRomChipCount; i++ {
|
||||||
|
filename := fmt.Sprintf("<internal>/BASE64A_%X.BIN", 0xd0+i*0x08)
|
||||||
|
data := loadResource(filename)
|
||||||
|
for j := range romBanksBytes {
|
||||||
|
start := (j * base64aRomWindowSize) % len(data)
|
||||||
|
romBanksBytes[j] = append(romBanksBytes[j], data[start:start+base64aRomWindowSize]...)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for j := range romBanksBytes {
|
||||||
|
b.romBanks[j] = newMemoryRange(0xd000, romBanksBytes[j])
|
||||||
|
}
|
||||||
|
|
||||||
|
// Start with first bank active
|
||||||
|
b.changeRomBank(0)
|
||||||
|
|
||||||
|
// Add rom soft switches. They use the annunciator 0 and 1
|
||||||
|
b.a.io.addSoftSwitchRW(0x58, func(*ioC0Page) uint8 {
|
||||||
|
b.changeRomBank(b.romBank & 2)
|
||||||
|
return 0
|
||||||
|
})
|
||||||
|
b.a.io.addSoftSwitchRW(0x59, func(*ioC0Page) uint8 {
|
||||||
|
b.changeRomBank(b.romBank | 1)
|
||||||
|
return 0
|
||||||
|
})
|
||||||
|
b.a.io.addSoftSwitchRW(0x5A, func(*ioC0Page) uint8 {
|
||||||
|
b.changeRomBank(b.romBank & 1)
|
||||||
|
return 0
|
||||||
|
})
|
||||||
|
b.a.io.addSoftSwitchRW(0x5B, func(*ioC0Page) uint8 {
|
||||||
|
b.changeRomBank(b.romBank | 2)
|
||||||
|
return 0
|
||||||
|
})
|
||||||
|
|
||||||
|
// Other softswitches
|
||||||
|
b.a.io.addSoftSwitchW(0x0C, notImplementedSoftSwitchW) // 80 columns off?
|
||||||
|
b.a.io.addSoftSwitchW(0x0E, notImplementedSoftSwitchW) // Alt char off?
|
||||||
|
|
||||||
|
// Write on the speaker. That is a double access and should do nothing
|
||||||
|
// but works somehow on the BASE64A
|
||||||
|
b.a.io.addSoftSwitchW(0x30, func(io *ioC0Page, value uint8) {
|
||||||
|
getSpeakerSoftSwitch(io)
|
||||||
|
})
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *Base64a) changeRomBank(bank uint8) {
|
||||||
|
b.romBank = bank
|
||||||
|
fmt.Printf("Change to ROM bank #%v\n", b.romBank)
|
||||||
|
b.a.mmu.physicalROM = b.romBanks[b.romBank]
|
||||||
|
b.a.mmu.resetRomPaging() // If rom was not active. This is going to far?
|
||||||
|
}
|
@ -27,7 +27,7 @@ const (
|
|||||||
|
|
||||||
type opcode struct {
|
type opcode struct {
|
||||||
name string
|
name string
|
||||||
bytes uint8
|
bytes uint16
|
||||||
cycles int
|
cycles int
|
||||||
addressMode int
|
addressMode int
|
||||||
action opFunc
|
action opFunc
|
||||||
@ -54,14 +54,14 @@ func (s *State) ExecuteInstruction(log bool) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
line := make([]uint8, opcode.bytes)
|
line := make([]uint8, opcode.bytes)
|
||||||
for i := uint8(0); i < opcode.bytes; i++ {
|
for i := uint16(0); i < opcode.bytes; i++ {
|
||||||
line[i] = s.mem.Peek(pc)
|
line[i] = s.mem.Peek(pc)
|
||||||
pc++
|
pc++
|
||||||
}
|
}
|
||||||
s.reg.setPC(pc)
|
s.reg.setPC(pc)
|
||||||
|
|
||||||
if log {
|
if log {
|
||||||
fmt.Printf("%#04x %-12s: ", pc, lineString(line, opcode))
|
fmt.Printf("%#04x %-12s: ", pc-opcode.bytes, lineString(line, opcode))
|
||||||
}
|
}
|
||||||
opcode.action(s, line, opcode)
|
opcode.action(s, line, opcode)
|
||||||
s.cycles += uint64(opcode.cycles)
|
s.cycles += uint64(opcode.cycles)
|
||||||
|
17
ioC0Page.go
17
ioC0Page.go
@ -65,16 +65,16 @@ func (p *ioC0Page) addSoftSwitchRW(address uint8, ss softSwitchR) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (p *ioC0Page) addSoftSwitchR(address uint8, ss softSwitchR) {
|
func (p *ioC0Page) addSoftSwitchR(address uint8, ss softSwitchR) {
|
||||||
if p.softSwitchesR[address] != nil {
|
//if p.softSwitchesR[address] != nil {
|
||||||
fmt.Printf("Addresss 0x0c%02x is already assigned for read", address)
|
// fmt.Printf("Addresss 0x0c%02x is already assigned for read\n", address)
|
||||||
}
|
//}
|
||||||
p.softSwitchesR[address] = ss
|
p.softSwitchesR[address] = ss
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *ioC0Page) addSoftSwitchW(address uint8, ss softSwitchW) {
|
func (p *ioC0Page) addSoftSwitchW(address uint8, ss softSwitchW) {
|
||||||
if p.softSwitchesW[address] != nil {
|
//if p.softSwitchesW[address] != nil {
|
||||||
fmt.Printf("Addresss 0x0c%02x is already assigned for write", address)
|
// fmt.Printf("Addresss 0x0c%02x is already assigned for write\n", address)
|
||||||
}
|
//}
|
||||||
p.softSwitchesW[address] = ss
|
p.softSwitchesW[address] = ss
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -91,7 +91,6 @@ func (p *ioC0Page) setSpeakerProvider(s SpeakerProvider) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (p *ioC0Page) peek(address uint16) uint8 {
|
func (p *ioC0Page) peek(address uint16) uint8 {
|
||||||
//fmt.Printf("Peek on $%02x\n", address)
|
|
||||||
pageAddress := uint8(address)
|
pageAddress := uint8(address)
|
||||||
ss := p.softSwitchesR[pageAddress]
|
ss := p.softSwitchesR[pageAddress]
|
||||||
if ss == nil {
|
if ss == nil {
|
||||||
@ -100,7 +99,9 @@ func (p *ioC0Page) peek(address uint16) uint8 {
|
|||||||
}
|
}
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
return ss(p)
|
value := ss(p)
|
||||||
|
//fmt.Printf("Peek on $%02x: $%02x\n", address, value)
|
||||||
|
return value
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *ioC0Page) poke(address uint16, value uint8) {
|
func (p *ioC0Page) poke(address uint16, value uint8) {
|
||||||
|
@ -76,6 +76,10 @@ func addApple2SoftSwitches(io *ioC0Page) {
|
|||||||
func notImplementedSoftSwitchR(*ioC0Page) uint8 {
|
func notImplementedSoftSwitchR(*ioC0Page) uint8 {
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func notImplementedSoftSwitchW(*ioC0Page, uint8) {
|
||||||
|
}
|
||||||
|
|
||||||
func getStatusSoftSwitch(ioFlag uint8) softSwitchR {
|
func getStatusSoftSwitch(ioFlag uint8) softSwitchR {
|
||||||
return func(io *ioC0Page) uint8 {
|
return func(io *ioC0Page) uint8 {
|
||||||
return io.softSwitchesData[ioFlag]
|
return io.softSwitchesData[ioFlag]
|
||||||
@ -107,11 +111,15 @@ func getKeySoftSwitch(io *ioC0Page) uint8 {
|
|||||||
io.softSwitchesData[ioDataKeyboard] = key + (1 << 7)
|
io.softSwitchesData[ioDataKeyboard] = key + (1 << 7)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return io.softSwitchesData[ioDataKeyboard]
|
value := io.softSwitchesData[ioDataKeyboard]
|
||||||
|
//fmt.Printf("Key $%02x, %v\n", value, strobed)
|
||||||
|
return value
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func strobeKeyboardSoftSwitch(io *ioC0Page) uint8 {
|
func strobeKeyboardSoftSwitch(io *ioC0Page) uint8 {
|
||||||
result := io.softSwitchesData[ioDataKeyboard]
|
result := io.softSwitchesData[ioDataKeyboard]
|
||||||
|
//fmt.Printf("Strobe $%02x\n", result)
|
||||||
io.softSwitchesData[ioDataKeyboard] &^= 1 << 7
|
io.softSwitchesData[ioDataKeyboard] &^= 1 << 7
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user