From 677e1113cbdf6761080257842b6f247f7d70e764 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Iv=C3=A1n=20Izaguirre?= Date: Mon, 15 Jan 2024 21:09:02 +0100 Subject: [PATCH] MultiROM card by davidm in applefritter --- cardBuilder.go | 1 + cardMultiRom.go | 111 ++++++++++++++++++ .../MultiRom(SP boot)-Prog aid-28C256.BIN | Bin 0 -> 32768 bytes 3 files changed, 112 insertions(+) create mode 100644 cardMultiRom.go create mode 100644 resources/MultiRom(SP boot)-Prog aid-28C256.BIN diff --git a/cardBuilder.go b/cardBuilder.go index 68eed5c..41a4702 100644 --- a/cardBuilder.go +++ b/cardBuilder.go @@ -41,6 +41,7 @@ func getCardFactory() map[string]*cardBuilder { cardFactory["softswitchlogger"] = newCardLoggerBuilder() cardFactory["memexp"] = newCardMemoryExpansionBuilder() cardFactory["mouse"] = newCardMouseBuilder() + cardFactory["multirom"] = newMultiRomCardBuilder() cardFactory["parallel"] = newCardParallelPrinterBuilder() cardFactory["saturn"] = newCardSaturnBuilder() cardFactory["smartport"] = newCardSmartPortStorageBuilder() diff --git a/cardMultiRom.go b/cardMultiRom.go new file mode 100644 index 0000000..08b9b6a --- /dev/null +++ b/cardMultiRom.go @@ -0,0 +1,111 @@ +package izapple2 + +/* + MultiROM card for Apple II + +See: https://www.applefritter.com/content/multiple-image-rom-card + + +------- +28C256 (Also for 27256 on Rev 1.1 cards) +------- +0000-07FF - CPM boot (User 2) Bank 3 +0800-0FFF - Freeze (User 3) Bank 2 +1000-37FF - IntBasic including programmers aid BankBasic 0 +3800-3FFF - Monitor Bank 6 +4000-47FF - Lockbuster (User 1) Bank 4 +4800-4FFF - Dead boot diagnostic Bank 5 +5000-77FF - Applesoft BankBasic 1 +7800-7FFF - Autostart Bank 7 + + +*/ + +// MultiRomCard represents a Multiple Image ROM Card +type MultiRomCard struct { + cardBase + rom []uint8 + basicBank int + f8Bank int +} + +func newMultiRomCardBuilder() *cardBuilder { + return &cardBuilder{ + name: "MultiROM", + description: "Multiple Image ROM card.", + defaultParams: &[]paramSpec{ + {"rom", "ROM file to load", "/MultiRom(SP boot)-Prog aid-28C256.BIN"}, + {"basic", "Bank for D000 to F7FF", "1"}, + {"bank", "Bank for F8", "7"}}, + buildFunc: func(params map[string]string) (Card, error) { + var c MultiRomCard + var err error + c.basicBank, err = paramsGetInt(params, "basic") + if err != nil { + return nil, err + } + c.f8Bank, err = paramsGetInt(params, "bank") + if err != nil { + return nil, err + } + + romFile := paramsGetPath(params, "rom") + data, _, err := LoadResource(romFile) + if err != nil { + return nil, err + } + + c.rom = data + return &c, nil + }, + } +} + +func (c *MultiRomCard) assign(a *Apple2, slot int) { + c.cardBase.assign(a, slot) + a.mmu.inhibitROM(c) +} + +func (c *MultiRomCard) translateAddress(address uint16) uint16 { + var baseAddress uint16 + // Basic part + if address < 0xf800 { + switch c.basicBank { + case 0: + baseAddress = 0x1000 + default: + baseAddress = 0x5000 + } + return address - 0xd000 + baseAddress + } + + // F8 part + + switch c.f8Bank { + case 2: + baseAddress = 0x0800 + case 3: + baseAddress = 0x0000 + case 4: + baseAddress = 0x4000 + case 5: + baseAddress = 0x4800 + case 6: + baseAddress = 0x3800 + default: + baseAddress = 0x7800 + } + return address - 0xf800 + baseAddress +} + +func (c *MultiRomCard) peek(address uint16) uint8 { + return c.rom[c.translateAddress(address)] +} + +func (c *MultiRomCard) poke(address uint16, value uint8) { + // Nothing +} + +func (c *MultiRomCard) setBase(base uint16) { + // Nothing +} diff --git a/resources/MultiRom(SP boot)-Prog aid-28C256.BIN b/resources/MultiRom(SP boot)-Prog aid-28C256.BIN new file mode 100644 index 0000000000000000000000000000000000000000..44b0375672267720e61b96762b4e58a910989e30 GIT binary patch literal 32768 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