Move slots and Status SmartPort call
This commit is contained in:
parent
986172516f
commit
79a584fb95
16
README.md
16
README.md
|
@ -56,6 +56,18 @@ Portable emulator of an Apple II+ or //e. Written in Go.
|
||||||
- Pause (thanks a2geek)
|
- Pause (thanks a2geek)
|
||||||
- ProDOS MLI calls tracing
|
- ProDOS MLI calls tracing
|
||||||
|
|
||||||
|
By default the following configuration is launched:
|
||||||
|
|
||||||
|
- Enhanced Apple //e with 65c02 processor
|
||||||
|
- RAMworks card with 80 column, RGB (with Video7 modes) and 8Gb RAM is aux slot
|
||||||
|
- Memory Expansion card with 1Gb in slot 1
|
||||||
|
- VidHD card (SHR support) in slot 2
|
||||||
|
- FASTChip Accelerator card in slot 3
|
||||||
|
- ThunderClock Plus card in slot 4
|
||||||
|
- SmartPort card with 1 device in slot 5 (if an image is provided with -disk35)
|
||||||
|
- DiskII controller card in slot 6
|
||||||
|
- SmartPort card with 1 device in slot 7 (if an image is provided with -hd)
|
||||||
|
|
||||||
## Running the emulator
|
## Running the emulator
|
||||||
|
|
||||||
No installation required. [Download](https://github.com/ivanizag/apple2/releases) the single file executable `apple2xxx_xxx` for linux or Mac, SDL2 graphics or console. Build from source to get the latest features.
|
No installation required. [Download](https://github.com/ivanizag/apple2/releases) the single file executable `apple2xxx_xxx` for linux or Mac, SDL2 graphics or console. Build from source to get the latest features.
|
||||||
|
@ -174,7 +186,7 @@ Only valid on SDL mode
|
||||||
-languageCardSlot int
|
-languageCardSlot int
|
||||||
slot for the 16kb language card. -1 for none
|
slot for the 16kb language card. -1 for none
|
||||||
-memoryExpSlot int
|
-memoryExpSlot int
|
||||||
slot for the Memory Expansion card with 1GB. -1 for none (default 4)
|
slot for the Memory Expansion card with 1GB. -1 for none (default 1)
|
||||||
-mhz float
|
-mhz float
|
||||||
cpu speed in Mhz, use 0 for full speed. Use F5 to toggle. (default 1.0227142857142857)
|
cpu speed in Mhz, use 0 for full speed. Use F5 to toggle. (default 1.0227142857142857)
|
||||||
-model string
|
-model string
|
||||||
|
@ -194,7 +206,7 @@ Only valid on SDL mode
|
||||||
-saturnCardSlot int
|
-saturnCardSlot int
|
||||||
slot for the 256kb Saturn card. -1 for none (default -1)
|
slot for the 256kb Saturn card. -1 for none (default -1)
|
||||||
-thunderClockCardSlot int
|
-thunderClockCardSlot int
|
||||||
slot for the ThunderClock Plus card. -1 for none (default 5)
|
slot for the ThunderClock Plus card. -1 for none (default 4)
|
||||||
-traceCpu
|
-traceCpu
|
||||||
dump to the console the CPU execution. Use F11 to toggle.
|
dump to the console the CPU execution. Use F11 to toggle.
|
||||||
-traceHD
|
-traceHD
|
||||||
|
|
|
@ -71,7 +71,7 @@ func MainApple() *Apple2 {
|
||||||
"slot for the FASTChip accelerator card, -1 for none")
|
"slot for the FASTChip accelerator card, -1 for none")
|
||||||
memoryExpansionCardSlot := flag.Int(
|
memoryExpansionCardSlot := flag.Int(
|
||||||
"memoryExpSlot",
|
"memoryExpSlot",
|
||||||
4,
|
1,
|
||||||
"slot for the Memory Expansion card with 1GB. -1 for none")
|
"slot for the Memory Expansion card with 1GB. -1 for none")
|
||||||
ramWorksKb := flag.Int(
|
ramWorksKb := flag.Int(
|
||||||
"ramworks",
|
"ramworks",
|
||||||
|
@ -79,7 +79,7 @@ func MainApple() *Apple2 {
|
||||||
"memory to use with RAMWorks card, 0 for no card, max is 16384")
|
"memory to use with RAMWorks card, 0 for no card, max is 16384")
|
||||||
thunderClockCardSlot := flag.Int(
|
thunderClockCardSlot := flag.Int(
|
||||||
"thunderClockCardSlot",
|
"thunderClockCardSlot",
|
||||||
5,
|
4,
|
||||||
"slot for the ThunderClock Plus card. -1 for none")
|
"slot for the ThunderClock Plus card. -1 for none")
|
||||||
mono := flag.Bool(
|
mono := flag.Bool(
|
||||||
"mono",
|
"mono",
|
||||||
|
@ -247,10 +247,6 @@ func MainApple() *Apple2 {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
if *fastChipCardSlot == 5 {
|
|
||||||
// Don't use fastChipCard if the slot 5 is already in use
|
|
||||||
*fastChipCardSlot = 0
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if *fastChipCardSlot >= 0 {
|
if *fastChipCardSlot >= 0 {
|
||||||
|
|
|
@ -9,6 +9,7 @@ See:
|
||||||
Beneath Prodos, section 6-6, 7-13 and 5-8. (http://www.apple-iigs.info/doc/fichiers/beneathprodos.pdf)
|
Beneath Prodos, section 6-6, 7-13 and 5-8. (http://www.apple-iigs.info/doc/fichiers/beneathprodos.pdf)
|
||||||
Apple IIc Technical Reference, 2nd Edition. Chapter 8. https://ia800207.us.archive.org/19/items/AppleIIcTechnicalReference2ndEd/Apple%20IIc%20Technical%20Reference%202nd%20ed.pdf
|
Apple IIc Technical Reference, 2nd Edition. Chapter 8. https://ia800207.us.archive.org/19/items/AppleIIcTechnicalReference2ndEd/Apple%20IIc%20Technical%20Reference%202nd%20ed.pdf
|
||||||
https://prodos8.com/docs/technote/21/
|
https://prodos8.com/docs/technote/21/
|
||||||
|
https://prodos8.com/docs/technote/20/
|
||||||
|
|
||||||
|
|
||||||
*/
|
*/
|
||||||
|
@ -29,8 +30,7 @@ func buildHardDiskRom(slot int) []uint8 {
|
||||||
0xa9, 0x20, // LDA #$20
|
0xa9, 0x20, // LDA #$20
|
||||||
0xa9, 0x00, // LDA #$00
|
0xa9, 0x00, // LDA #$00
|
||||||
0xa9, 0x03, // LDA #$03
|
0xa9, 0x03, // LDA #$03
|
||||||
0xa9, 0x3c, // LDA #$3c
|
0xa9, 0x00, // LDA #$00
|
||||||
// Alternate: 0xa9, 0x00, // LDA #$00 ; Not a Smartport device, but won't boot on ii+ ROM
|
|
||||||
|
|
||||||
// Boot code: SS will load block 0 in address $0800. The jump there.
|
// Boot code: SS will load block 0 in address $0800. The jump there.
|
||||||
// Note: after execution the first block expects $42 to $47 to have
|
// Note: after execution the first block expects $42 to $47 to have
|
||||||
|
@ -50,6 +50,12 @@ func buildHardDiskRom(slot int) []uint8 {
|
||||||
0x4c, 0x01, 0x08, // JMP $801 ; Jump to loaded boot sector
|
0x4c, 0x01, 0x08, // JMP $801 ; Jump to loaded boot sector
|
||||||
})
|
})
|
||||||
|
|
||||||
|
if slot == 7 {
|
||||||
|
// It should be 0 for SmartPort, but with 0 it's not bootable with the II+ ROM
|
||||||
|
// See http://www.1000bit.it/support/manuali/apple/technotes/udsk/tn.udsk.2.html
|
||||||
|
data[0x07] = 0x3c
|
||||||
|
}
|
||||||
|
|
||||||
// Entrypoints and Smartport body
|
// Entrypoints and Smartport body
|
||||||
copy(data[0x40:], []uint8{
|
copy(data[0x40:], []uint8{
|
||||||
0x4c, 0x80, 0xc0 + uint8(slot), // JMP $cs80 ; Prodos Entrypoint
|
0x4c, 0x80, 0xc0 + uint8(slot), // JMP $cs80 ; Prodos Entrypoint
|
||||||
|
@ -115,12 +121,12 @@ func (c *cardHardDisk) assign(a *Apple2, slot int) {
|
||||||
address := uint16(a.mmu.Peek(0x44)) + uint16(a.mmu.Peek(0x45))<<8
|
address := uint16(a.mmu.Peek(0x44)) + uint16(a.mmu.Peek(0x45))<<8
|
||||||
block := uint16(a.mmu.Peek(0x46)) + uint16(a.mmu.Peek(0x47))<<8
|
block := uint16(a.mmu.Peek(0x46)) + uint16(a.mmu.Peek(0x47))<<8
|
||||||
if c.trace {
|
if c.trace {
|
||||||
fmt.Printf("[CardHardDisk] Prodos command %v on unit $%x, block %v to $%x.\n", command, unit, block, address)
|
fmt.Printf("[CardHardDisk] Prodos command %v on slot %v, unit $%x, block %v to $%x.\n", command, slot, unit, block, address)
|
||||||
}
|
}
|
||||||
|
|
||||||
switch command {
|
switch command {
|
||||||
case proDosDeviceCommandStatus:
|
case proDosDeviceCommandStatus:
|
||||||
return proDosDeviceNoError
|
return c.status(unit, address)
|
||||||
case proDosDeviceCommandRead:
|
case proDosDeviceCommandRead:
|
||||||
return c.readBlock(block, address)
|
return c.readBlock(block, address)
|
||||||
case proDosDeviceCommandWrite:
|
case proDosDeviceCommandWrite:
|
||||||
|
@ -147,12 +153,12 @@ func (c *cardHardDisk) assign(a *Apple2, slot int) {
|
||||||
address := uint16(a.mmu.Peek(paramsAddress+2)) + uint16(a.mmu.Peek(paramsAddress+3))<<8
|
address := uint16(a.mmu.Peek(paramsAddress+2)) + uint16(a.mmu.Peek(paramsAddress+3))<<8
|
||||||
block := uint16(a.mmu.Peek(paramsAddress+4)) + uint16(a.mmu.Peek(paramsAddress+5))<<8
|
block := uint16(a.mmu.Peek(paramsAddress+4)) + uint16(a.mmu.Peek(paramsAddress+5))<<8
|
||||||
if c.trace {
|
if c.trace {
|
||||||
fmt.Printf("[CardHardDisk] Smart port command %v on unit $%x, block %v to $%x.\n", command, unit, block, address)
|
fmt.Printf("[CardHardDisk] Smart port command %v on slot %v, unit $%x, block %v to $%x.\n", command, slot, unit, block, address)
|
||||||
}
|
}
|
||||||
|
|
||||||
switch command {
|
switch command {
|
||||||
case proDosDeviceCommandStatus:
|
case proDosDeviceCommandStatus:
|
||||||
return proDosDeviceNoError
|
return c.status(unit, address)
|
||||||
case proDosDeviceCommandRead:
|
case proDosDeviceCommandRead:
|
||||||
return c.readBlock(block, address)
|
return c.readBlock(block, address)
|
||||||
case proDosDeviceCommandWrite:
|
case proDosDeviceCommandWrite:
|
||||||
|
@ -218,6 +224,24 @@ func (c *cardHardDisk) writeBlock(block uint16, source uint16) uint8 {
|
||||||
return proDosDeviceNoError
|
return proDosDeviceNoError
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *cardHardDisk) status(unit uint8, dest uint16) uint8 {
|
||||||
|
if c.trace {
|
||||||
|
fmt.Printf("[CardHardDisk] Status for %v into $%x.\n", unit, dest)
|
||||||
|
}
|
||||||
|
|
||||||
|
// See http://www.1000bit.it/support/manuali/apple/technotes/smpt/tn.smpt.2.html
|
||||||
|
c.a.mmu.Poke(dest+0, 0x02) // One device
|
||||||
|
c.a.mmu.Poke(dest+1, 0xff) // No interrupt
|
||||||
|
c.a.mmu.Poke(dest+2, 0x00)
|
||||||
|
c.a.mmu.Poke(dest+3, 0x00) // Unknown manufacturer
|
||||||
|
c.a.mmu.Poke(dest+4, 0x01)
|
||||||
|
c.a.mmu.Poke(dest+5, 0x00) // Versión 1.0 final
|
||||||
|
c.a.mmu.Poke(dest+6, 0x00)
|
||||||
|
c.a.mmu.Poke(dest+7, 0x00) // Reserved
|
||||||
|
|
||||||
|
return proDosDeviceNoError
|
||||||
|
}
|
||||||
|
|
||||||
func (c *cardHardDisk) addDisk(disk *blockDisk) {
|
func (c *cardHardDisk) addDisk(disk *blockDisk) {
|
||||||
c.disk = disk
|
c.disk = disk
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue