mirror of
https://github.com/ivanizag/izapple2.git
synced 2025-01-23 20:30:28 +00:00
Dan ][ Controller card
This commit is contained in:
parent
f0f8d6448e
commit
18c0779064
@ -29,7 +29,10 @@ Portable emulator of an Apple II+ or //e. Written in Go.
|
||||
- No Slot Clock based on the DS1216
|
||||
- Videx Videoterm 80 column card with the Videx Soft Video Switch (Apple ][+ only)
|
||||
- SwyftCard (Apple //e only)
|
||||
- Brain Board
|
||||
- Brain Board II
|
||||
- MultiROM card
|
||||
- Dan ][ Controller card
|
||||
- Useful cards not emulating a real card
|
||||
- Bootable SmartPort / ProDOS card with the following smartport devices:
|
||||
- Block device (hard disks)
|
||||
|
@ -37,7 +37,7 @@ func (a *Apple2) Start(paused bool) {
|
||||
for i := 0; i < cpuSpinLoops; i++ {
|
||||
// Conditional tracing
|
||||
//pc, _ := a.cpu.GetPCAndSP()
|
||||
//a.cpu.SetTrace(pc >= 0x7f0 && pc < 0x0820)
|
||||
//a.cpu.SetTrace(pc >= 0xc75e && pc < 0xc800)
|
||||
|
||||
// Execution
|
||||
a.cpu.ExecuteInstruction()
|
||||
|
20
cardBase.go
20
cardBase.go
@ -10,6 +10,8 @@ type Card interface {
|
||||
assign(a *Apple2, slot int)
|
||||
reset()
|
||||
|
||||
setName(name string)
|
||||
setDebug(debug bool)
|
||||
GetName() string
|
||||
GetInfo() map[string]string
|
||||
}
|
||||
@ -17,7 +19,8 @@ type Card interface {
|
||||
type cardBase struct {
|
||||
a *Apple2
|
||||
name string
|
||||
romCsxx memoryHandler
|
||||
trace bool
|
||||
romCsxx *memoryRangeROM
|
||||
romC8xx memoryHandler
|
||||
romCxxx memoryHandler
|
||||
|
||||
@ -28,6 +31,10 @@ type cardBase struct {
|
||||
_sswName [16]string
|
||||
}
|
||||
|
||||
func (c *cardBase) setName(name string) {
|
||||
c.name = name
|
||||
}
|
||||
|
||||
func (c *cardBase) GetName() string {
|
||||
return c.name
|
||||
}
|
||||
@ -36,6 +43,10 @@ func (c *cardBase) GetInfo() map[string]string {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *cardBase) setDebug(debug bool) {
|
||||
c.trace = debug
|
||||
}
|
||||
|
||||
func (c *cardBase) reset() {
|
||||
// nothing
|
||||
}
|
||||
@ -143,3 +154,10 @@ func (c *cardBase) addCardSoftSwitches(sss softSwitches, name string) {
|
||||
}, fmt.Sprintf("%v%XW", name, address))
|
||||
}
|
||||
}
|
||||
|
||||
func (c *cardBase) tracef(format string, args ...interface{}) {
|
||||
if c.trace {
|
||||
prefixedFormat := fmt.Sprintf("[%s] %v", c.name, format)
|
||||
fmt.Printf(prefixedFormat, args...)
|
||||
}
|
||||
}
|
||||
|
@ -25,6 +25,7 @@ type cardBuilder struct {
|
||||
const noCardName = "empty"
|
||||
|
||||
var commonParams = []paramSpec{
|
||||
{"debug", "Enable debug messages", "false"},
|
||||
{"tracess", "Trace softswitches", "false"},
|
||||
}
|
||||
|
||||
@ -37,7 +38,7 @@ func getCardFactory() map[string]*cardBuilder {
|
||||
cardFactory = make(map[string]*cardBuilder)
|
||||
cardFactory["brainboard"] = newCardBrainBoardBuilder()
|
||||
cardFactory["brainboard2"] = newCardBrainBoardIIBuilder()
|
||||
//cardFactory["dan2sd"] = newCardDan2ControllerBuilder()
|
||||
cardFactory["dan2sd"] = newCardDan2ControllerBuilder()
|
||||
cardFactory["diskii"] = newCardDisk2Builder()
|
||||
cardFactory["diskiiseq"] = newCardDisk2SequencerBuilder()
|
||||
cardFactory["fastchip"] = newCardFastChipBuilder()
|
||||
@ -117,14 +118,12 @@ func setupCard(a *Apple2, slot int, paramString string) (Card, error) {
|
||||
a.io.traceSlot(slot)
|
||||
}
|
||||
|
||||
cardBase, ok := card.(*cardBase)
|
||||
if err == nil && ok {
|
||||
cardBase.name = builder.name
|
||||
}
|
||||
debug := paramsGetBool(finalParams, "debug")
|
||||
|
||||
card.setName(builder.name)
|
||||
card.setDebug(debug)
|
||||
card.assign(a, slot)
|
||||
a.cards[slot] = card
|
||||
|
||||
return card, err
|
||||
}
|
||||
|
||||
|
389
cardDan2Controller.go
Normal file
389
cardDan2Controller.go
Normal file
@ -0,0 +1,389 @@
|
||||
package izapple2
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
)
|
||||
|
||||
/*
|
||||
Apple II DAN ][ CONTROLLER CARD.]
|
||||
|
||||
See:
|
||||
https://github.com/profdc9/Apple2Card
|
||||
https://www.applefritter.com/content/dan-sd-card-disk-controller
|
||||
|
||||
*/
|
||||
|
||||
// CardDan2Controller represents a Dan ][ controller card
|
||||
type CardDan2Controller struct {
|
||||
cardBase
|
||||
|
||||
commandBuffer []uint8
|
||||
responseBuffer []uint8
|
||||
|
||||
receivingWiteBuffer bool
|
||||
writeBuffer []uint8
|
||||
commitWrite func([]uint8) error
|
||||
|
||||
portB uint8
|
||||
portC uint8
|
||||
|
||||
slotA *cardDan2ControllerSlot
|
||||
slotB *cardDan2ControllerSlot
|
||||
}
|
||||
|
||||
type cardDan2ControllerSlot struct {
|
||||
path string
|
||||
fileNo uint8
|
||||
fileName string
|
||||
}
|
||||
|
||||
func newCardDan2ControllerBuilder() *cardBuilder {
|
||||
return &cardBuilder{
|
||||
name: "Dan ][ Controller card",
|
||||
description: "Apple II Peripheral Card that Interfaces to a ATMEGA328P for SD card storage.",
|
||||
defaultParams: &[]paramSpec{
|
||||
{"slot1", "Image in slot 1. File for raw device, folder for fs mode using files as BLKDEV0x.PO", ""},
|
||||
{"slot1file", "Device selected in slot 1: 0 for raw device, 1 to 9 for file number", "0"},
|
||||
{"slot2", "Image in slot 2. File for raw device, folder for fs mode using files as BLKDEV0x.PO", ""},
|
||||
{"slot2file", "Device selected in slot 2: 0 for raw device, 1 to 9 for file number", "0"},
|
||||
},
|
||||
buildFunc: func(params map[string]string) (Card, error) {
|
||||
var c CardDan2Controller
|
||||
c.responseBuffer = make([]uint8, 0, 1000)
|
||||
|
||||
c.slotA = &cardDan2ControllerSlot{}
|
||||
c.slotA.path = params["slot1"]
|
||||
num, _ := paramsGetInt(params, "slot1file")
|
||||
c.slotA.fileNo = uint8(num)
|
||||
c.slotA.initializeDrive()
|
||||
|
||||
c.slotB = &cardDan2ControllerSlot{}
|
||||
c.slotB.path = params["slot2"]
|
||||
num, _ = paramsGetInt(params, "slot2file")
|
||||
c.slotB.fileNo = uint8(num)
|
||||
c.slotB.initializeDrive()
|
||||
|
||||
err := c.loadRomFromResource("<internal>/Apple2CardFirmware.bin")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &c, nil
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func (c *CardDan2Controller) assign(a *Apple2, slot int) {
|
||||
c.addCardSoftSwitches(func(address uint8, data uint8, write bool) uint8 {
|
||||
address &= 0x03 // only A0 and A1 are connected
|
||||
if write {
|
||||
c.write(address, data)
|
||||
return 0
|
||||
} else {
|
||||
return c.read(address)
|
||||
}
|
||||
}, "DAN2CONTROLLER")
|
||||
|
||||
c.cardBase.assign(a, slot)
|
||||
}
|
||||
|
||||
func (c *CardDan2Controller) write(address uint8, data uint8) {
|
||||
switch address {
|
||||
case 0: // Port A
|
||||
if c.receivingWiteBuffer {
|
||||
c.writeBuffer = append(c.writeBuffer, data)
|
||||
if len(c.writeBuffer) == 512 {
|
||||
c.commitWrite(c.writeBuffer)
|
||||
}
|
||||
} else if c.commandBuffer == nil {
|
||||
if data == 0xac {
|
||||
c.commandBuffer = make([]uint8, 0)
|
||||
}
|
||||
} else {
|
||||
c.commandBuffer = append(c.commandBuffer, data)
|
||||
c.processCommand()
|
||||
}
|
||||
case 3: // Control
|
||||
if data&0x80 == 0 {
|
||||
bit := (data >> 1) & 0x08
|
||||
if data&1 == 0 {
|
||||
// Reset bit
|
||||
c.portC &^= uint8(1) << bit
|
||||
} else {
|
||||
// Set bit
|
||||
c.portC |= uint8(1) << bit
|
||||
}
|
||||
c.romCsxx.setPage((c.portC & 0x07) | ((c.portB << 4) & 0xf0))
|
||||
} else {
|
||||
if data != 0xfa {
|
||||
c.tracef("Not supported status %v, it must be 0xfa\n", data)
|
||||
}
|
||||
/* Sets the 8255 with status 0xfa, 1111_1010:
|
||||
1: set mode
|
||||
11: port A mode 2
|
||||
1: port A input
|
||||
1: port C(upper) input
|
||||
0: port B mode 0
|
||||
1: port B input
|
||||
0: port C(lower) output
|
||||
*/
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (c *CardDan2Controller) read(address uint8) uint8 {
|
||||
switch address {
|
||||
case 0: // Port A
|
||||
if len(c.responseBuffer) > 0 {
|
||||
value := c.responseBuffer[0]
|
||||
c.responseBuffer = c.responseBuffer[1:]
|
||||
return value
|
||||
}
|
||||
return 0
|
||||
case 2: // Port C
|
||||
portC := uint8(0x80) // bit 7-nOBF is always 1, the output buffer is never full
|
||||
if len(c.responseBuffer) > 0 {
|
||||
portC |= 0x20 // bit 5-niBF is 1 if the input buffer has data
|
||||
}
|
||||
return portC
|
||||
}
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
func (s *cardDan2ControllerSlot) blockPosition(unit uint8, block uint16) int64 {
|
||||
if s.fileNo == 0 {
|
||||
// Raw device
|
||||
return 512 * (int64(block) + (int64(unit&0x0f) << 12))
|
||||
} else {
|
||||
// File device
|
||||
return 512 * int64(block)
|
||||
}
|
||||
}
|
||||
|
||||
func (s *cardDan2ControllerSlot) status(unit uint8) error {
|
||||
file, err := os.OpenFile(s.fileName, os.O_RDWR, 0)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer file.Close()
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *cardDan2ControllerSlot) readBlock(unit uint8, block uint16) ([]uint8, error) {
|
||||
file, err := os.OpenFile(s.fileName, os.O_RDWR, 0)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer file.Close()
|
||||
|
||||
position := s.blockPosition(unit, block)
|
||||
buffer := make([]uint8, 512)
|
||||
_, err = file.ReadAt(buffer, position)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return buffer, nil
|
||||
}
|
||||
|
||||
func (s *cardDan2ControllerSlot) writeBlock(unit uint8, block uint16, data []uint8) error {
|
||||
file, err := os.OpenFile(s.fileName, os.O_RDWR, 0)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer file.Close()
|
||||
|
||||
position := s.blockPosition(unit, block)
|
||||
_, err = file.WriteAt(data, position)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *cardDan2ControllerSlot) initializeDrive() {
|
||||
if s.fileNo == 255 {
|
||||
s.fileNo = 0 // Wide raw not supported, changed to raw
|
||||
}
|
||||
if s.fileNo == 0 {
|
||||
// Raw device
|
||||
s.fileName = s.path
|
||||
} else {
|
||||
s.fileName = filepath.Join(s.path, fmt.Sprintf("BLKDEV%02X.PO", s.fileNo))
|
||||
}
|
||||
}
|
||||
|
||||
func (c *CardDan2Controller) selectSlot(unit uint8) *cardDan2ControllerSlot {
|
||||
if unit&0x80 == 0 {
|
||||
return c.slotA
|
||||
} else {
|
||||
return c.slotB
|
||||
}
|
||||
}
|
||||
|
||||
func (c *CardDan2Controller) processCommand() {
|
||||
// See : Apple2Arduino.ino::do_command()
|
||||
command := c.commandBuffer[0]
|
||||
switch command {
|
||||
case 0, 3: // Status and format
|
||||
if len(c.commandBuffer) == 6 {
|
||||
unit, _, _ := c.getUnitBufBlk()
|
||||
slot := c.selectSlot(unit)
|
||||
err := slot.status(unit)
|
||||
if err != nil {
|
||||
c.tracef("Error status : %v\n", err)
|
||||
c.sendResponseCode(0x28)
|
||||
} else {
|
||||
c.sendResponseCode(0x00)
|
||||
}
|
||||
|
||||
if command == 0 {
|
||||
c.tracef("0-Status unit $%02x\n", unit)
|
||||
} else {
|
||||
c.tracef("3-Format unit $%02x\n", unit)
|
||||
}
|
||||
c.commandBuffer = nil
|
||||
}
|
||||
|
||||
case 1: // Read block
|
||||
if len(c.commandBuffer) == 6 {
|
||||
unit, buffer, block := c.getUnitBufBlk()
|
||||
c.tracef("1-Read unit $%02x, buffer $%x, block %v\n", unit, buffer, block)
|
||||
|
||||
slot := c.selectSlot(unit)
|
||||
data, err := slot.readBlock(unit, block)
|
||||
if err != nil {
|
||||
c.tracef("Error reading block : %v\n", err)
|
||||
c.sendResponseCode(0x28)
|
||||
} else {
|
||||
c.sendResponse(data...)
|
||||
}
|
||||
c.commandBuffer = nil
|
||||
}
|
||||
|
||||
case 2: // Write block
|
||||
if len(c.commandBuffer) == 6 {
|
||||
unit, buffer, block := c.getUnitBufBlk()
|
||||
c.tracef("2-Write unit $%02x, buffer $%x, block %v\n", unit, buffer, block)
|
||||
|
||||
c.receivingWiteBuffer = true
|
||||
c.writeBuffer = make([]uint8, 0, 512)
|
||||
c.commitWrite = func(data []uint8) error {
|
||||
slot := c.selectSlot(unit)
|
||||
err := slot.writeBlock(unit, block, c.writeBuffer)
|
||||
if err != nil {
|
||||
c.tracef("Error writing block : %v\n", err)
|
||||
}
|
||||
c.receivingWiteBuffer = false
|
||||
c.writeBuffer = nil
|
||||
c.commitWrite = nil
|
||||
return nil
|
||||
}
|
||||
c.sendResponseCode(0x00)
|
||||
|
||||
c.commandBuffer = nil
|
||||
}
|
||||
|
||||
case 5: // Get volume
|
||||
if len(c.commandBuffer) == 6 {
|
||||
c.tracef("5-Get Volume\n")
|
||||
|
||||
c.sendResponse(c.slotA.fileNo, c.slotB.fileNo)
|
||||
c.commandBuffer = nil
|
||||
}
|
||||
|
||||
case 4, 6, 7: // Set volume
|
||||
if len(c.commandBuffer) == 6 {
|
||||
_, _, block := c.getUnitBufBlk()
|
||||
c.slotA.fileNo = uint8(block & 0xff)
|
||||
c.slotA.initializeDrive()
|
||||
c.slotA.fileNo = uint8((block >> 8) & 0xff)
|
||||
c.slotA.initializeDrive()
|
||||
|
||||
c.tracef("%v-Set Volume %v and %v\n",
|
||||
command, c.slotA.fileNo, c.slotA.fileNo)
|
||||
|
||||
if command == 4 {
|
||||
c.responseBuffer = append(c.responseBuffer, 0x00) // Success code
|
||||
} else {
|
||||
c.sendResponse()
|
||||
// command 6 writes eeprom, not emulated
|
||||
}
|
||||
c.commandBuffer = nil
|
||||
}
|
||||
|
||||
case 13 + 128, 32 + 128: // Read bootblock
|
||||
if len(c.commandBuffer) == 6 {
|
||||
c.tracef("ac-Read bootblock\n")
|
||||
c.sendResponse(PROGMEM[:]...)
|
||||
c.commandBuffer = nil
|
||||
}
|
||||
|
||||
default: // Unknown command
|
||||
c.tracef("Unknown command %v\n", command)
|
||||
c.sendResponseCode(0x27)
|
||||
}
|
||||
}
|
||||
|
||||
func (c *CardDan2Controller) sendResponseCode(code uint8) {
|
||||
c.responseBuffer = append(c.responseBuffer, code)
|
||||
}
|
||||
|
||||
func (c *CardDan2Controller) sendResponse(response ...uint8) {
|
||||
c.responseBuffer = append(c.responseBuffer, 0x00) // Success code
|
||||
c.responseBuffer = append(c.responseBuffer, response...)
|
||||
rest := 512 - len(response)
|
||||
if rest > 0 {
|
||||
c.responseBuffer = append(c.responseBuffer, make([]uint8, rest)...)
|
||||
}
|
||||
}
|
||||
|
||||
func (c *CardDan2Controller) getUnitBufBlk() (uint8, uint16, uint16) {
|
||||
return c.commandBuffer[1],
|
||||
uint16(c.commandBuffer[2]) + uint16(c.commandBuffer[3])<<8,
|
||||
uint16(c.commandBuffer[4]) + uint16(c.commandBuffer[5])<<8
|
||||
}
|
||||
|
||||
var PROGMEM = [512]uint8{
|
||||
0xea, 0xa9, 0x20, 0x85, 0xf0, 0xa9, 0x60, 0x85, 0xf3, 0xa5, 0x43, 0x4a,
|
||||
0x4a, 0x4a, 0x4a, 0x29, 0x07, 0x09, 0xc0, 0x85, 0xf2, 0xa0, 0x00, 0x84,
|
||||
0xf1, 0x88, 0xb1, 0xf1, 0x85, 0xf1, 0x20, 0x93, 0xfe, 0x20, 0x89, 0xfe,
|
||||
0x20, 0x58, 0xfc, 0x20, 0xa2, 0x09, 0xa9, 0x00, 0x85, 0x25, 0x20, 0x22,
|
||||
0xfc, 0xa5, 0x25, 0x85, 0xf5, 0x85, 0xf6, 0x20, 0x90, 0x09, 0xa9, 0x00,
|
||||
0x85, 0x24, 0xa5, 0x25, 0x20, 0xe3, 0xfd, 0xe6, 0x24, 0x20, 0x7a, 0x09,
|
||||
0x20, 0x04, 0x09, 0xa9, 0x14, 0x85, 0x24, 0xa5, 0x25, 0x20, 0xe3, 0xfd,
|
||||
0xe6, 0x24, 0xa5, 0x43, 0x09, 0x80, 0x85, 0x43, 0x20, 0x7a, 0x09, 0x20,
|
||||
0x04, 0x09, 0xa5, 0x43, 0x29, 0x7f, 0x85, 0x43, 0xe6, 0x25, 0xa5, 0x25,
|
||||
0xc9, 0x10, 0x90, 0xbe, 0xa9, 0x00, 0x85, 0x24, 0xa9, 0x12, 0x85, 0x25,
|
||||
0x20, 0x22, 0xfc, 0xa2, 0x14, 0x20, 0x66, 0x09, 0x20, 0x61, 0x09, 0xa9,
|
||||
0x0a, 0x85, 0x24, 0xa5, 0xf7, 0x20, 0xf8, 0x08, 0xa9, 0x14, 0x85, 0x24,
|
||||
0x20, 0x5c, 0x09, 0xa9, 0x1e, 0x85, 0x24, 0xa5, 0xf8, 0x20, 0xf8, 0x08,
|
||||
0xa9, 0x0a, 0x85, 0x24, 0x20, 0xca, 0x08, 0x85, 0xf5, 0x20, 0xf8, 0x08,
|
||||
0xa9, 0x1e, 0x85, 0x24, 0x20, 0xca, 0x08, 0x85, 0xf6, 0x20, 0xf8, 0x08,
|
||||
0x20, 0x8c, 0x09, 0x4c, 0xb7, 0x09, 0xa5, 0xf7, 0x85, 0xf5, 0xa5, 0xf8,
|
||||
0x85, 0xf6, 0x20, 0x90, 0x09, 0x68, 0x68, 0x4c, 0xb7, 0x09, 0x20, 0x0c,
|
||||
0xfd, 0xc9, 0x9b, 0xf0, 0xe9, 0xc9, 0xa1, 0xf0, 0x20, 0xc9, 0xe1, 0x90,
|
||||
0x03, 0x38, 0xe9, 0x20, 0xc9, 0xc1, 0x90, 0x04, 0xc9, 0xc7, 0x90, 0x0b,
|
||||
0xc9, 0xb0, 0x90, 0xe2, 0xc9, 0xba, 0xb0, 0xde, 0x29, 0x0f, 0x60, 0x38,
|
||||
0xe9, 0x07, 0x29, 0x0f, 0x60, 0xa9, 0xff, 0x60, 0xc9, 0xff, 0xf0, 0x03,
|
||||
0x4c, 0xe3, 0xfd, 0xa9, 0xa1, 0x4c, 0xed, 0xfd, 0xa2, 0x00, 0xb0, 0x25,
|
||||
0xad, 0x05, 0x10, 0x30, 0x20, 0xad, 0x04, 0x10, 0x29, 0xf0, 0xc9, 0xf0,
|
||||
0xd0, 0x17, 0xad, 0x04, 0x10, 0x29, 0x0f, 0xf0, 0x10, 0x85, 0xf9, 0xbd,
|
||||
0x05, 0x10, 0x09, 0x80, 0x20, 0xed, 0xfd, 0xe8, 0xe4, 0xf9, 0xd0, 0xf3,
|
||||
0x60, 0x4c, 0x66, 0x09, 0xbc, 0xce, 0xcf, 0xa0, 0xd6, 0xcf, 0xcc, 0xd5,
|
||||
0xcd, 0xc5, 0xbe, 0x00, 0xc3, 0xc1, 0xd2, 0xc4, 0xa0, 0xb1, 0xba, 0x00,
|
||||
0xc4, 0xc1, 0xce, 0xa0, 0xdd, 0xdb, 0xa0, 0xd6, 0xcf, 0xcc, 0xd5, 0xcd,
|
||||
0xc5, 0xa0, 0xd3, 0xc5, 0xcc, 0xc5, 0xc3, 0xd4, 0xcf, 0xd2, 0x8d, 0x00,
|
||||
0xa9, 0xb2, 0x8d, 0x41, 0x09, 0xa2, 0x0c, 0x4c, 0x66, 0x09, 0xbd, 0x30,
|
||||
0x09, 0xf0, 0x0e, 0x20, 0xed, 0xfd, 0xe8, 0xd0, 0xf5, 0xa9, 0x00, 0x85,
|
||||
0x44, 0xa9, 0x10, 0x85, 0x45, 0x60, 0xa9, 0x01, 0x85, 0x42, 0x20, 0x71,
|
||||
0x09, 0xa9, 0x02, 0x85, 0x46, 0xa9, 0x00, 0x85, 0x47, 0x4c, 0xf0, 0x00,
|
||||
0xa9, 0x07, 0xd0, 0x02, 0xa9, 0x06, 0x85, 0x42, 0x20, 0x71, 0x09, 0xa5,
|
||||
0xf5, 0x85, 0x46, 0xa5, 0xf6, 0x85, 0x47, 0x4c, 0xf0, 0x00, 0xa9, 0x05,
|
||||
0x85, 0x42, 0x20, 0x71, 0x09, 0x20, 0xf0, 0x00, 0xad, 0x00, 0x10, 0x85,
|
||||
0xf7, 0xad, 0x01, 0x10, 0x85, 0xf8, 0x60, 0xa9, 0x00, 0x85, 0xf1, 0x6c,
|
||||
0xf1, 0x00,
|
||||
}
|
26
cardDan2Controller_test.go
Normal file
26
cardDan2Controller_test.go
Normal file
@ -0,0 +1,26 @@
|
||||
package izapple2
|
||||
|
||||
import (
|
||||
"strings"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestDan2Controller(t *testing.T) {
|
||||
overrides := newConfiguration()
|
||||
overrides.set(confS7, "dan2sd,slot1=resources/ProDOS_2_4_3.po")
|
||||
|
||||
at, err := makeApple2Tester("2enh", overrides)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
at.terminateCondition = buildTerminateConditionText(at, "NEW VOL", true, 10_000_000)
|
||||
|
||||
at.run()
|
||||
|
||||
text := at.getText()
|
||||
if !strings.Contains(text, "NEW VOL") {
|
||||
t.Errorf("Expected Bitsy Bye screen, got '%s'", text)
|
||||
}
|
||||
|
||||
}
|
@ -55,6 +55,10 @@ func TestPlusDOS33Boots(t *testing.T) {
|
||||
testBoots(t, "2plus", "<internal>/dos33.dsk", 100_000_000, "DOS VERSION 3.3", "\n]", false)
|
||||
}
|
||||
|
||||
func TestProdDOSBoots(t *testing.T) {
|
||||
testBoots(t, "2enh", "<internal>/ProDOS_2_4_3.po", 100_000_000, "BITSY BYE", "NEW VOL", false)
|
||||
}
|
||||
|
||||
func TestCPM65Boots(t *testing.T) {
|
||||
testBoots(t, "2enh", "<internal>/cpm65.po", 5_000_000, "CP/M-65 for the Apple II", "\nA>", true)
|
||||
}
|
||||
|
BIN
resources/Apple2CardFirmware.bin
Normal file
BIN
resources/Apple2CardFirmware.bin
Normal file
Binary file not shown.
BIN
resources/ProDOS_2_4_3.po
Normal file
BIN
resources/ProDOS_2_4_3.po
Normal file
Binary file not shown.
Loading…
x
Reference in New Issue
Block a user