mirror of
https://github.com/ivanizag/izapple2.git
synced 2025-02-10 03:30:56 +00:00
135 lines
3.5 KiB
Go
135 lines
3.5 KiB
Go
package izapple2
|
|
|
|
import "fmt"
|
|
|
|
/*
|
|
Ralle Palaveev's ProDOS-Romcard3
|
|
|
|
See:
|
|
https://github.com/rallepaqlaveev/ProDOS-Romcard3
|
|
|
|
Note that this card disables the C800-CFFF range only on writes to CFFF, not as most other cards that disable on reads and writes.
|
|
|
|
*/
|
|
|
|
// CardProDOSRomCard3 is a Memory Expansion card
|
|
type CardProDOSRomCard3 struct {
|
|
cardBase
|
|
bank uint16
|
|
data []uint8
|
|
nvram bool
|
|
secondROMPage bool
|
|
}
|
|
|
|
func newCardProDOSRomCard3Builder() *cardBuilder {
|
|
return &cardBuilder{
|
|
name: "ProDOS ROM Card 3",
|
|
description: "A bootable 4 MB ROM card by Ralle Palaveev",
|
|
defaultParams: &[]paramSpec{
|
|
{"image", "ROM image with the ProDOS volume", "https://github.com/rallepalaveev/ProDOS-Romcard3/raw/main/ProDOS-ROMCARD3_4MB_A2D.v1.4_v37.po"},
|
|
},
|
|
buildFunc: func(params map[string]string) (Card, error) {
|
|
image := paramsGetPath(params, "image")
|
|
if image == "" {
|
|
return nil, fmt.Errorf("image required for the ProDOS ROM drive")
|
|
}
|
|
|
|
data, _, err := LoadResource(image)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
if len(data) != 4*1024*1024 {
|
|
return nil, fmt.Errorf("NVRAM image must be 4MB")
|
|
}
|
|
|
|
var c CardProDOSRomCard3
|
|
c.data = data
|
|
c.loadRom(data[0x200:0x300], cardRomSimple)
|
|
c.romC8xx = &c
|
|
return &c, nil
|
|
},
|
|
}
|
|
}
|
|
|
|
//lint:ignore U1000 this is used to write debug code
|
|
func newCardProDOSNVRAMDriveBuilder() *cardBuilder {
|
|
return &cardBuilder{
|
|
name: "ProDOS 4MB NVRAM DRive",
|
|
description: "A bootable 4 MB NVRAM card by Ralle Palaveev, WIP",
|
|
defaultParams: &[]paramSpec{
|
|
{"image", "ROM image with the ProDOS volume", ""},
|
|
},
|
|
buildFunc: func(params map[string]string) (Card, error) {
|
|
image := paramsGetPath(params, "image")
|
|
if image == "" {
|
|
return nil, fmt.Errorf("image required for the ProDOS ROM drive")
|
|
}
|
|
|
|
data, _, err := LoadResource(image)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
if len(data) != 4*1024*1024 && len(data) != 512*1024 {
|
|
return nil, fmt.Errorf("NVRAM image must be 512KB or 4MB")
|
|
}
|
|
|
|
var c CardProDOSRomCard3
|
|
c.data = data
|
|
c.loadRom(data[0x200:0x400], cardRomSimple)
|
|
c.romC8xx = &c
|
|
c.nvram = true
|
|
return &c, nil
|
|
},
|
|
}
|
|
}
|
|
|
|
func (c *CardProDOSRomCard3) assign(a *Apple2, slot int) {
|
|
|
|
// Set pointer position
|
|
c.addCardSoftSwitchW(0, func(value uint8) {
|
|
c.bank = uint16(value) | c.bank&0xff00
|
|
}, "BANKLO")
|
|
c.addCardSoftSwitchW(1, func(value uint8) {
|
|
c.bank = uint16(value)<<8 | c.bank&0xff
|
|
}, "BANKHI")
|
|
|
|
if c.nvram {
|
|
c.addCardSoftSwitchW(2, func(value uint8) {
|
|
if c.secondROMPage {
|
|
c.romCsxx.setPage(0)
|
|
} else {
|
|
c.romCsxx.setPage(1)
|
|
}
|
|
}, "?????")
|
|
}
|
|
|
|
c.cardBase.assign(a, slot)
|
|
}
|
|
|
|
func (c *CardProDOSRomCard3) translateAddress(address uint16) int {
|
|
// An address from 0xC800 to 0xCFFF is mapped to the corresponding bank of the ROM
|
|
// There are 0x800 (2048) banks with 0x0800 (2048) bytes each
|
|
offset := address - 0xC800
|
|
pageAddress := int(c.bank&0x7FF) * 0x0800
|
|
|
|
// fmt.Printf("CardProDOSRomCard3.translateAddress: address=%04X, bank=%04X, offset=%04X, pageAddress=%08X\n", address, c.bank, offset, pageAddress)
|
|
|
|
return pageAddress + int(offset)
|
|
}
|
|
|
|
func (c *CardProDOSRomCard3) peek(address uint16) uint8 {
|
|
if address&0xff == 0 {
|
|
fmt.Printf("CardProDOSRomCard3.peek: address=%04X\n", address)
|
|
}
|
|
return c.data[c.translateAddress(address)]
|
|
}
|
|
|
|
func (c *CardProDOSRomCard3) poke(address uint16, value uint8) {
|
|
fmt.Printf("CardProDOSRomCard3.poke: address=%04X, value=%02X\n", address, value)
|
|
if c.nvram && address != 0xcfff {
|
|
c.data[c.translateAddress(address)] = value
|
|
}
|
|
}
|