diff --git a/README.md b/README.md index 74ca20b3..a522176e 100644 --- a/README.md +++ b/README.md @@ -255,7 +255,6 @@ The available cards are: diskiiseq: Disk II interface card emulating the Woz state machine fastchip: Accelerator card for Apple IIe (limited support) fujinet: SmartPort interface card hosting the Fujinet - inout: Card to test I/O language: Language card with 16 extra KB for the Apple ][ and ][+ memexp: Memory expansion card mouse: Mouse card implementation, does not emulate a real card, only the firmware behaviour diff --git a/cardBase.go b/cardBase.go index baab0abb..50d8469b 100644 --- a/cardBase.go +++ b/cardBase.go @@ -54,8 +54,9 @@ type cardRomLayout int const ( cardRomSimple cardRomLayout = iota // The ROM is on the slot area, there can be more than one page - cardRomUpper // The ROM is on the full C800 area. The slot area copies C8xx + cardRomUpperStart // The ROM is on the full C800 area. The slot area copies C8xx cardRomUpperHalfEnd // The ROM is on half of the C800 areas. The slot area copies CBxx + cardRomUpperEnd // The ROM is on the full C800 area. The slot area copies CFxx cardRomFull // The ROM is on the full Cxxx area, with pages for each slot position ) @@ -88,14 +89,14 @@ func (c *cardBase) loadRom(data []uint8, layout cardRomLayout) error { } else { return fmt.Errorf("invalid ROM size for simple layout") } - case cardRomUpper: + case cardRomUpperStart: if len(data) == 0x800 { // The file has C800 to CFFF // The 256 bytes in Cx00 are copied from the first page in C800 c.romCsxx = newMemoryRangeROM(0, data, "Slot ROM") c.romC8xx = newMemoryRangeROM(0xc800, data, "Slot C8 ROM") } else { - return fmt.Errorf("invalid ROM size for upper layout") + return fmt.Errorf("invalid ROM size for upper start layout") } case cardRomUpperHalfEnd: if len(data) == 0x400 { @@ -107,6 +108,15 @@ func (c *cardBase) loadRom(data []uint8, layout cardRomLayout) error { } else { return fmt.Errorf("invalid ROM size for upper half end layout") } + case cardRomUpperEnd: + if len(data) == 0x800 { + // The file has C800 to CFFF for ROM + // The 256 bytes in Cx00 are copied from the last page in C800-CFFF + c.romCsxx = newMemoryRangeROM(0, data[0x700:], "Slot ROM") + c.romC8xx = newMemoryRangeROM(0xc800, data, "Slot C8 ROM") + } else { + return fmt.Errorf("invalid ROM size for upper end layout") + } case cardRomFull: if len(data) == 0x1000 { // The file covers the full Cxxx range. Only showing the page diff --git a/cardBuilder.go b/cardBuilder.go index 611da413..7bfb1a6f 100644 --- a/cardBuilder.go +++ b/cardBuilder.go @@ -20,6 +20,7 @@ type cardBuilder struct { description string defaultParams *[]paramSpec requiresIIe bool + hide bool buildFunc func(params map[string]string) (Card, error) } @@ -57,6 +58,7 @@ func getCardFactory() map[string]*cardBuilder { cardFactory["prodosromdrive"] = newCardProDOSRomDriveBuilder() cardFactory["prodosromcard3"] = newCardProDOSRomCard3Builder() // cardFactory["prodosnvramdrive"] = newCardProDOSNVRAMDriveBuilder() + cardFactory["profile"] = newCardProfileBuilder() cardFactory["saturn"] = newCardSaturnBuilder() cardFactory["smartport"] = newCardSmartPortStorageBuilder() cardFactory["swyftcard"] = newCardSwyftBuilder() diff --git a/cardInOut.go b/cardInOut.go index 122b3688..e103e596 100644 --- a/cardInOut.go +++ b/cardInOut.go @@ -28,6 +28,7 @@ func newCardInOutBuilder() *cardBuilder { return &cardBuilder{ name: "InOut test card", description: "Card to test I/O", + hide: true, buildFunc: func(params map[string]string) (Card, error) { return &CardInOut{}, nil }, diff --git a/cardProfile.go b/cardProfile.go new file mode 100644 index 00000000..dc45750d --- /dev/null +++ b/cardProfile.go @@ -0,0 +1,87 @@ +package izapple2 + +import ( + "fmt" +) + +/* +Profile card for Apple II Interface. + +The firmware source code for 5MB is available at: https://bitsavers.org/pdf/apple/disk/profile/appleII_interface/AII_Profile_Boot_Prom_198402.pdf +See also: + https://bitsavers.org/pdf/apple/disk/profile/072-0116_Profile_Level_II_Service_Manual_Oct84.pdf + https://bitsavers.org/pdf/apple/disk/profile/Profile_Communication_Protocol.pdf + https://mirrors.apple2.org.za/Apple%20II%20Documentation%20Project/Interface%20Cards/Hard%20Disk%20Drive%20Controllers/Apple%20II%20ProFile%20Interface%20Card/ + +Softswitches: + W0: WR_PORT, write to Z8 RAM (byte at a time) + R1: RD_PORT, read from Z8 RAM (byte at a time) + R2: BUSY, Z8 not ready + bit 0 off is drive present and connected to card + bit 6 is parity error + bit 7 on is ready and online + W2: RSTAT? + W3: CLR PARITY, clear any previous parity error + +*/ + +// CardProfile represents the Apple II Profile interface card +type CardProfile struct { + cardBase +} + +func newCardProfileBuilder() *cardBuilder { + return &cardBuilder{ + name: "Apple II Profile interface card", + description: "Profile interface card - not implemented", + hide: true, + defaultParams: &[]paramSpec{ + {"rom", "ROM file to load", "/Apple II Interface 341-0271-A ROM 2716 for 5MB Profile.bin"}, + //{"rom", "ROM file to load", "/Apple II Interface 341-0299-B ROM 2716 for 10MB Profile.bin"}, + }, + buildFunc: func(params map[string]string) (Card, error) { + var c CardProfile + romFile := paramsGetPath(params, "rom") + err := c.loadRomFromResource(romFile, cardRomUpperEnd) + if err != nil { + return nil, err + } + return &c, nil + }, + } +} + +func (c *CardProfile) assign(a *Apple2, slot int) { + + // WR_PORT, write to Z8 RAM (byte at a time) + c.addCardSoftSwitchW(0, func(value uint8) { + fmt.Printf("[cardProfile] WR_PORT: Write to Z8 RAM, value 0x%02x\n", value) + }, "PROFILE_WR_PORT") + + // RD_PORT, read from Z8 RAM (byte at a time) + c.addCardSoftSwitchR(1, func() uint8 { + fmt.Printf("[cardProfile] RD_PORT: Read from Z8 RAM\n") + return 0x00 // Return dummy data for now + }, "PROFILE_RD_PORT") + + // BUSY, Z8 not ready + c.addCardSoftSwitchR(2, func() uint8 { + fmt.Printf("[cardProfile] BUSY: Z8 status check\n") + // Return 0x80 (bit 7 on) to indicate ready and online + // bit 0 off indicates drive present + return 0x80 + }, "PROFILE_BUSY") + + // RSTAT? + c.addCardSoftSwitchW(2, func(value uint8) { + fmt.Printf("[cardProfile] RSTAT: Write status, value 0x%02x\n", value) + }, "PROFILE_RSTAT") + + // CLR PARITY, clear any previous parity error + c.addCardSoftSwitchW(3, func(value uint8) { + fmt.Printf("[cardProfile] CLR_PARITY: Clear parity error, value 0x%02x\n", value) + }, "PROFILE_CLR_PARITY") + + // Call base assignment to setup ROM and other card functionality + c.cardBase.assign(a, slot) +} diff --git a/cardThunderClockPlus.go b/cardThunderClockPlus.go index 2368e3fd..5220eb30 100644 --- a/cardThunderClockPlus.go +++ b/cardThunderClockPlus.go @@ -33,7 +33,7 @@ func newCardThunderClockPlusBuilder() *cardBuilder { description: "Clock card", buildFunc: func(params map[string]string) (Card, error) { var c CardThunderClockPlus - err := c.loadRomFromResource("/ThunderclockPlusROM.bin", cardRomUpper) + err := c.loadRomFromResource("/ThunderclockPlusROM.bin", cardRomUpperStart) if err != nil { return nil, err } diff --git a/configuration.go b/configuration.go index 3c8d7b70..3c1db1b4 100644 --- a/configuration.go +++ b/configuration.go @@ -271,7 +271,9 @@ func setupFlags(models *configurationModels, configuration *configuration) error fmt.Fprintf(out, "\nThe available cards are:\n") for _, card := range availableCards() { builder := getCardFactory()[card] - fmt.Fprintf(out, " %s: %s\n", card, builder.description) + if !builder.hide { + fmt.Fprintf(out, " %s: %s\n", card, builder.description) + } } fmt.Fprintf(out, "\nThe available tracers are:\n") diff --git a/doc/usage.txt b/doc/usage.txt index 13e120a5..e00281c0 100644 --- a/doc/usage.txt +++ b/doc/usage.txt @@ -72,7 +72,6 @@ The available cards are: diskiiseq: Disk II interface card emulating the Woz state machine fastchip: Accelerator card for Apple IIe (limited support) fujinet: SmartPort interface card hosting the Fujinet - inout: Card to test I/O language: Language card with 16 extra KB for the Apple ][ and ][+ memexp: Memory expansion card mouse: Mouse card implementation, does not emulate a real card, only the firmware behaviour diff --git a/resources/Apple II Interface 341-0271-A ROM 2716 for 5MB Profile.bin b/resources/Apple II Interface 341-0271-A ROM 2716 for 5MB Profile.bin new file mode 100644 index 00000000..caf48034 Binary files /dev/null and b/resources/Apple II Interface 341-0271-A ROM 2716 for 5MB Profile.bin differ diff --git a/resources/Apple II Interface 341-0299-B ROM 2716 for 10MB Profile.bin b/resources/Apple II Interface 341-0299-B ROM 2716 for 10MB Profile.bin new file mode 100644 index 00000000..36e22ccc Binary files /dev/null and b/resources/Apple II Interface 341-0299-B ROM 2716 for 10MB Profile.bin differ diff --git a/setup.go b/setup.go index ead2bd5c..1a649a3a 100644 --- a/setup.go +++ b/setup.go @@ -240,9 +240,10 @@ func loadMultiPageRom(a *Apple2, filenames []string) error { } var diskAliases = map[string]string{ - "dos33": "/dos33.dsk", - "prodos": "/ProDOS_2_4_3.po", - "cpm": "/cpm_2.20B_56K.po", + "dos33": "/dos33.dsk", + "prodos": "/ProDOS_2_4_3.po", + "cpm": "/cpm_2.20B_56K.po", + "cardcat": "/Card Cat 1.7.dsk", } func applyDiskAliases(filename string) string {