Test boot process for all models

This commit is contained in:
Ivan Izaguirre 2022-02-21 23:05:53 +01:00
parent 9d6393f078
commit cde673a552
6 changed files with 238 additions and 73 deletions

37
apple2Tester.go Normal file
View File

@ -0,0 +1,37 @@
package izapple2
import (
"github.com/ivanizag/izapple2/screen"
)
type apple2Tester struct {
a *Apple2
terminateCondition func(a *Apple2) bool
}
func makeApple2Tester(model string) *apple2Tester {
a := newApple2()
a.setup(0, true) // Full speed
initModel(a, model, defaultInternal, defaultInternal)
a.AddLanguageCard(0)
var at apple2Tester
at.a = a
a.addTracer(&at)
return &at
}
func (at *apple2Tester) inspect() {
if at.terminateCondition(at.a) {
at.a.SendCommand(CommandKill)
}
}
func (at *apple2Tester) run() {
at.a.Run()
}
func (at *apple2Tester) getText() string {
return screen.RenderTextModeString(at.a, false, false, false, at.a.isApple2e)
}

92
apple2_test.go Normal file
View File

@ -0,0 +1,92 @@
package izapple2
import (
"strings"
"testing"
)
func TestPlusBoots(t *testing.T) {
at := makeApple2Tester("2plus")
at.terminateCondition = func(a *Apple2) bool {
return a.cpu.GetCycles() > 200_000
}
at.run()
text := at.getText()
if !strings.Contains(text, "APPLE ][") {
t.Errorf("Expected 'APPLE ][', got '%s'", text)
}
if !strings.Contains(text, "\n]") {
t.Errorf("Expected ] prompt, got '%s'", text)
}
}
func Test2EBoots(t *testing.T) {
at := makeApple2Tester("2e")
at.terminateCondition = func(a *Apple2) bool {
return a.cpu.GetCycles() > 200_000
}
at.run()
text := at.getText()
if !strings.Contains(text, "Apple ][") {
t.Errorf("Expected 'Apple ][', got '%s'", text)
}
if !strings.Contains(text, "\n]") {
t.Errorf("Expected ] prompt, got '%s'", text)
}
}
func Test2EnhancedBoots(t *testing.T) {
at := makeApple2Tester("2enh")
at.terminateCondition = func(a *Apple2) bool {
return a.cpu.GetCycles() > 200_000
}
at.run()
text := at.getText()
if !strings.Contains(text, "Apple //e") {
t.Errorf("Expected 'Apple //e', got '%s'", text)
}
if !strings.Contains(text, "\n]") {
t.Errorf("Expected ] prompt, got '%s'", text)
}
}
func TestBase64Boots(t *testing.T) {
at := makeApple2Tester("base64a")
at.terminateCondition = func(a *Apple2) bool {
return a.cpu.GetCycles() > 1_000_000
}
at.run()
text := at.getText()
if !strings.Contains(text, "BASE 64A") {
t.Errorf("Expected 'BASE 64A', got '%s'", text)
}
if !strings.Contains(text, "\n]") {
t.Errorf("Expected ] prompt, got '%s'", text)
}
}
func TestPlusDOS33Boots(t *testing.T) {
at := makeApple2Tester("2plus")
err := at.a.AddDisk2(6, "<internal>/dos33.dsk", "")
if err != nil {
panic(err)
}
at.terminateCondition = func(a *Apple2) bool {
return a.cpu.GetCycles() > 100_000_000
}
at.run()
text := at.getText()
if !strings.Contains(text, "DOS VERSION 3.3") {
t.Errorf("Expected 'APPLE ][', got '%s'", text)
}
if !strings.Contains(text, "\n]") {
t.Errorf("Expected ] prompt, got '%s'", text)
}
}

View File

@ -189,86 +189,24 @@ func MainApple() *Apple2 {
a.addTracer(newTraceApplecorn(a, false))
}
var charGenMap charColumnMap
initialCharGenPage := 0
initModel(a, *model, *romFile, *charRomFile)
a.cpu.SetTrace(*traceCPU)
// Disable incompatible cards
switch *model {
case "2plus":
setApple2plus(a)
if *romFile == defaultInternal {
*romFile = "<internal>/Apple2_Plus.rom"
}
if *charRomFile == defaultInternal {
*charRomFile = "<internal>/Apple2rev7CharGen.rom"
}
charGenMap = charGenColumnsMap2Plus
*vidHDCardSlot = -1
case "2e":
setApple2e(a)
if *romFile == defaultInternal {
*romFile = "<internal>/Apple2e.rom"
}
if *charRomFile == defaultInternal {
*charRomFile = "<internal>/Apple IIe Video Unenhanced - 342-0133-A - 2732.bin"
}
a.isApple2e = true
charGenMap = charGenColumnsMap2e
*videxCardSlot = -1
case "2enh":
setApple2eEnhanced(a)
if *romFile == defaultInternal {
*romFile = "<internal>/Apple2e_Enhanced.rom"
}
if *charRomFile == defaultInternal {
*charRomFile = "<internal>/Apple IIe Video Enhanced - 342-0265-A - 2732.bin"
}
a.isApple2e = true
charGenMap = charGenColumnsMap2e
*videxCardSlot = -1
case "base64a":
setBase64a(a)
if *romFile == defaultInternal {
err := loadBase64aRom(a)
if err != nil {
panic(err)
}
*romFile = ""
}
if *charRomFile == defaultInternal {
*charRomFile = "<internal>/BASE64A_ROM7_CharGen.BIN"
initialCharGenPage = 1
}
charGenMap = charGenColumnsMapBase64a
*vidHDCardSlot = -1
*videxCardSlot = -1 // The videx firmware crashes the BASE64A, probably by use of ANN0
default:
panic("Model not supported")
}
if a.isApple2e {
// Videx not used on Apple IIe
*videxCardSlot = -1
}
a.cpu.SetTrace(*traceCPU)
// Load ROM if not loaded already
if *romFile != "" {
err := a.LoadRom(*romFile)
if err != nil {
panic(err)
}
}
// Load character generator if it loaded already
cg, err := newCharacterGenerator(*charRomFile, charGenMap, a.isApple2e)
if err != nil {
panic(err)
}
cg.setPage(initialCharGenPage)
a.cg = cg
// Externsion cards
if *languageCardSlot >= 0 {
a.AddLanguageCard(*languageCardSlot)
@ -362,3 +300,73 @@ func MainApple() *Apple2 {
return a
}
func initModel(a *Apple2, model string, romFile string, charRomFile string) {
var charGenMap charColumnMap
initialCharGenPage := 0
switch model {
case "2plus":
setApple2plus(a)
if romFile == defaultInternal {
romFile = "<internal>/Apple2_Plus.rom"
}
if charRomFile == defaultInternal {
charRomFile = "<internal>/Apple2rev7CharGen.rom"
}
charGenMap = charGenColumnsMap2Plus
case "2e":
setApple2e(a)
if romFile == defaultInternal {
romFile = "<internal>/Apple2e.rom"
}
if charRomFile == defaultInternal {
charRomFile = "<internal>/Apple IIe Video Unenhanced - 342-0133-A - 2732.bin"
}
charGenMap = charGenColumnsMap2e
case "2enh":
setApple2eEnhanced(a)
if romFile == defaultInternal {
romFile = "<internal>/Apple2e_Enhanced.rom"
}
if charRomFile == defaultInternal {
charRomFile = "<internal>/Apple IIe Video Enhanced - 342-0265-A - 2732.bin"
}
charGenMap = charGenColumnsMap2e
case "base64a":
setBase64a(a)
if romFile == defaultInternal {
err := loadBase64aRom(a)
if err != nil {
panic(err)
}
romFile = ""
}
if charRomFile == defaultInternal {
charRomFile = "<internal>/BASE64A_ROM7_CharGen.BIN"
initialCharGenPage = 1
}
charGenMap = charGenColumnsMapBase64a
default:
panic("Model not supported")
}
// Load ROM if not loaded already
if romFile != "" {
err := a.LoadRom(romFile)
if err != nil {
panic(err)
}
}
// Load character generator if it loaded already
cg, err := newCharacterGenerator(charRomFile, charGenMap, a.isApple2e)
if err != nil {
panic(err)
}
cg.setPage(initialCharGenPage)
a.cg = cg
}

View File

@ -26,7 +26,7 @@ func RenderTextModeAnsi(vs VideoSource, is80Columns bool, isSecondPage bool, isA
line := ""
for c := 0; c < columns; c++ {
char := text[l*columns+c]
line += textMemoryByteToString(char, isAltText, isApple2e)
line += textMemoryByteToString(char, isAltText, isApple2e, true)
}
content += fmt.Sprintf("# %v #\n", line)
}
@ -49,7 +49,7 @@ $e0-$ff Low Nor Low Nor Low Nor Low Nor
----------------------------------------------------
*/
func textMemoryByteToString(value uint8, isAltCharSet bool, isApple2e bool) string {
func textMemoryByteToString(value uint8, isAltCharSet bool, isApple2e bool, ansi bool) string {
// Normal, inverse or flash
topBits := value >> 6
isInverse := topBits == 0
@ -80,13 +80,13 @@ func textMemoryByteToString(value uint8, isAltCharSet bool, isApple2e bool) stri
value = '_'
}
if isFlash {
if ansi && isFlash {
if value == ' ' {
// Flashing space in Apple is the full box. It can't be done with ANSI codes
value = '_'
}
return fmt.Sprintf("\033[5m%v\033[0m", string(value))
} else if isInverse {
} else if ansi && isInverse {
return fmt.Sprintf("\033[7m%v\033[0m", string(value))
} else {
return string(value)

28
screen/textToString.go Normal file
View File

@ -0,0 +1,28 @@
package screen
import (
"fmt"
)
// RenderTextModeString returns the text mode contents ignoring reverse and flash
func RenderTextModeString(vs VideoSource, is80Columns bool, isSecondPage bool, isAltText bool, isApple2e bool) string {
var text []uint8
if is80Columns {
text = getText80FromMemory(vs, isSecondPage)
} else {
text = getTextFromMemory(vs, isSecondPage, false)
}
columns := len(text) / textLines
content := ""
for l := 0; l < textLines; l++ {
line := ""
for c := 0; c < columns; c++ {
char := text[l*columns+c]
line += textMemoryByteToString(char, isAltText, isApple2e, false)
}
content += fmt.Sprintf("%v\n", line)
}
return content
}

View File

@ -26,7 +26,7 @@ func TestTextMemoryByteToString(t *testing.T) {
}
func charExpectation(t *testing.T, arg uint8, alt bool, expect string) {
s := textMemoryByteToString(arg, alt, alt)
s := textMemoryByteToString(arg, alt, alt, true)
if s != expect {
t.Errorf("For 0x%02x:%v, got %v, expected %v", arg, alt, s, expect)
}