Playing with the Apple II Profile Interface Card

This commit is contained in:
Iván Izaguirre committed 2025-09-13 21:34:48 +02:00
1 parent bef421469f
commit dcb4e3c923
11 files changed
+111 -10

No files matched your search

-1
View File
@@ -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
+13 -3
View File
@@ -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
+2
View File
@@ -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()
+1
View File
@@ -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
},
+87
View File
@@ -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", "<internal>/Apple II Interface 341-0271-A ROM 2716 for 5MB Profile.bin"},
//{"rom", "ROM file to load", "<internal>/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)
}
+1 -1
View File
@@ -33,7 +33,7 @@ func newCardThunderClockPlusBuilder() *cardBuilder {
description: "Clock card",
buildFunc: func(params map[string]string) (Card, error) {
var c CardThunderClockPlus
err := c.loadRomFromResource("<internal>/ThunderclockPlusROM.bin", cardRomUpper)
err := c.loadRomFromResource("<internal>/ThunderclockPlusROM.bin", cardRomUpperStart)
if err != nil {
return nil, err
}
+3 -1
View File
@@ -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")
-1
View File
@@ -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
+4 -3
View File
@@ -240,9 +240,10 @@ func loadMultiPageRom(a *Apple2, filenames []string) error {
}
var diskAliases = map[string]string{
"dos33": "<internal>/dos33.dsk",
"prodos": "<internal>/ProDOS_2_4_3.po",
"cpm": "<internal>/cpm_2.20B_56K.po",
"dos33": "<internal>/dos33.dsk",
"prodos": "<internal>/ProDOS_2_4_3.po",
"cpm": "<internal>/cpm_2.20B_56K.po",
"cardcat": "<internal>/Card Cat 1.7.dsk",
}
func applyDiskAliases(filename string) string {