diff --git a/acornMemory.go b/acornMemory.go index 937ccb5..3b79f02 100644 --- a/acornMemory.go +++ b/acornMemory.go @@ -83,7 +83,7 @@ func (m *acornMemory) loadRom(filename string) { func (m *acornMemory) getString(address uint16, terminator uint8) string { str := "" for { - ch := m.Peek(address) + ch := m.Peek(address) & 0x7f //fmt.Printf("{%04x: %02x\n", address, ch) if ch == terminator { break diff --git a/firmware.cfg b/asm/firmware.cfg similarity index 100% rename from firmware.cfg rename to asm/firmware.cfg diff --git a/firmware.lst b/asm/firmware.lst similarity index 51% rename from firmware.lst rename to asm/firmware.lst index fdbcda0..5758013 100644 --- a/firmware.lst +++ b/asm/firmware.lst @@ -1,20 +1,22 @@ ca65 V2.18 - Ubuntu 2.18-1 -Main file : firmware.s -Current file: firmware.s +Main file : asm/firmware.s +Current file: asm/firmware.s 000000r 1 ; build: -000000r 1 ; cl65 -l firmware.lst firmware.s --config firmware.cfg +000000r 1 ; cl65 -l asm/firmware.lst asm/firmware.s --config asm/firmware.cfg -o firmware +000000r 1 ; Review constants.go when this code is changed 000000r 1 000000r 1 000000r 1 ; constants -000000r 1 .export ENTRY := $8000 +000000r 1 .export LANGUAGE_ENTRY := $8000 +000000r 1 .export SERVICE_ENTRY := $8003 000000r 1 000000r 1 000000r 1 ; boot code 000000r 1 .org $0000 000000 1 BOOT: -000000 1 A9 01 LDA #$1 -000002 1 4C 00 80 JMP ENTRY +000000 1 A9 01 lda #$1 +000002 1 4C 00 80 jmp LANGUAGE_ENTRY 000005 1 000005 1 000005 1 ; init ram vectors @@ -51,44 +53,74 @@ Current file: firmware.s 000232 1 1E FB IND2V: .addr epIND2 000234 1 1F FB IND3V: .addr epIND3 000236 1 -000236 1 -000236 1 ; bbz host entry points -000236 1 xx xx xx xx .res $fb00 - * +000236 1 ; support code +000236 1 xx xx xx xx .res $f000 - * 00023A 1 xx xx xx xx 00023E 1 xx xx xx xx +00F000 1 .org $f000 +00F000 1 +00F000 1 ; Send cli command to ROM and check the result +00F000 1 ; Expects A=4, X=F, Y=0, the command to be pointed by $f2 +00F000 1 CLITOROM: +00F000 1 20 03 80 jsr SERVICE_ENTRY +00F003 1 AA tax +00F004 1 F0 0E beq CLAIMED +00F006 1 00 brk ; "254-Bad command" error +00F007 1 FE .byte $fe +00F008 1 C2 41 44 20 .asciiz "Bad command" +00F00C 1 43 4F 4D 4D +00F010 1 41 4E 44 00 +00F014 1 60 CLAIMED: rts +00F015 1 +00F015 1 +00F015 1 ; area to store an error message +00F015 1 xx xx xx xx .res $fa00 - * +00F019 1 xx xx xx xx +00F01D 1 xx xx xx xx +00FA00 1 .org $fa00 +00FA00 1 00 errorArea: brk +00FA01 1 00 errorCode: .byte 0 +00FA02 1 C8 45 4C 4C errorMessage: .asciiz "Hello world" +00FA06 1 4F 20 57 4F +00FA0A 1 52 4C 44 00 +00FA0E 1 +00FA0E 1 ; bbz host entry points +00FA0E 1 xx xx xx xx .res $fb00 - * +00FA12 1 xx xx xx xx +00FA16 1 xx xx xx xx 00FB00 1 .org $fb00 -00FB00 1 60 epUPT: rts ; 0xfb00 -00FB01 1 60 epEVNT: rts ; 0xfb01 -00FB02 1 60 epFSC: rts ; 0xfb02 -00FB03 1 60 epFIND: rts ; 0xfb03 -00FB04 1 60 epGBPB: rts ; 0xfb04 -00FB05 1 60 epBPUT: rts ; 0xfb05 -00FB06 1 60 epBGET: rts ; 0xfb06 -00FB07 1 60 epARGS: rts ; 0xfb07 -00FB08 1 60 epFILE: rts ; 0xfb08 -00FB09 1 60 epRDCH: rts ; 0xfb09 -00FB0A 1 60 epWRCH: rts ; 0xfb0a -00FB0B 1 60 epWORD: rts ; 0xfb0b -00FB0C 1 60 epBYTE: rts ; 0xfb0c -00FB0D 1 60 epCLI: rts ; 0xfb0d -00FB0E 1 60 epIRQ2: rts ; 0xfb0e -00FB0F 1 60 epIRQ1: rts ; 0xfb0f -00FB10 1 60 epBRK: rts ; 0xfb10 -00FB11 1 60 epUSER: rts ; 0xfb11 -00FB12 1 60 epSYSBRK: rts ; 0xfb12 -00FB13 1 60 epRDRM: rts ; 0xfb13 -00FB14 1 60 epVDUCH: rts ; 0xfb14 -00FB15 1 60 epGSINIT: rts ; 0xfb16 -00FB16 1 60 epGSREAD: rts ; 0xfb17 -00FB17 1 60 epNET: rts ; 0xfb18 -00FB18 1 60 epVDU: rts ; 0xfb19 -00FB19 1 60 epKEY: rts ; 0xfb1a -00FB1A 1 60 epINS: rts ; 0xfb1b -00FB1B 1 60 epREM: rts ; 0xfb1c -00FB1C 1 60 epCNP: rts ; 0xfb1d -00FB1D 1 60 epIND1: rts ; 0xfb1e -00FB1E 1 60 epIND2: rts ; 0xfb1f -00FB1F 1 60 epIND3: rts ; 0xfb20 +00FB00 1 60 epUPT: rts ; 0xfb00 +00FB01 1 60 epEVNT: rts ; 0xfb01 +00FB02 1 60 epFSC: rts ; 0xfb02 +00FB03 1 60 epFIND: rts ; 0xfb03 +00FB04 1 60 epGBPB: rts ; 0xfb04 +00FB05 1 60 epBPUT: rts ; 0xfb05 +00FB06 1 60 epBGET: rts ; 0xfb06 +00FB07 1 60 epARGS: rts ; 0xfb07 +00FB08 1 60 epFILE: rts ; 0xfb08 +00FB09 1 60 epRDCH: rts ; 0xfb09 +00FB0A 1 60 epWRCH: rts ; 0xfb0a +00FB0B 1 60 epWORD: rts ; 0xfb0b +00FB0C 1 60 epBYTE: rts ; 0xfb0c +00FB0D 1 60 epCLI: rts ; 0xfb0d +00FB0E 1 60 epIRQ2: rts ; 0xfb0e +00FB0F 1 60 epIRQ1: rts ; 0xfb0f +00FB10 1 60 epBRK: rts ; 0xfb10 +00FB11 1 60 epUSER: rts ; 0xfb11 +00FB12 1 60 epSYSBRK: rts ; 0xfb12 +00FB13 1 60 epRDRM: rts ; 0xfb13 +00FB14 1 60 epVDUCH: rts ; 0xfb14 +00FB15 1 60 epGSINIT: rts ; 0xfb16 +00FB16 1 60 epGSREAD: rts ; 0xfb17 +00FB17 1 60 epNET: rts ; 0xfb18 +00FB18 1 60 epVDU: rts ; 0xfb19 +00FB19 1 60 epKEY: rts ; 0xfb1a +00FB1A 1 60 epINS: rts ; 0xfb1b +00FB1B 1 60 epREM: rts ; 0xfb1c +00FB1C 1 60 epCNP: rts ; 0xfb1d +00FB1D 1 60 epIND1: rts ; 0xfb1e +00FB1E 1 60 epIND2: rts ; 0xfb1f +00FB1F 1 60 epIND3: rts ; 0xfb20 00FB20 1 00FB20 1 00FB20 1 ; MOS function calls @@ -122,7 +154,7 @@ Current file: firmware.s 00FFFA 1 00FFFA 1 00FFFA 1 ; 6502 vectors -00FFFA 1 00 00 .addr $0000 ; NMI address -00FFFC 1 00 80 .addr ENTRY ; RESET address -00FFFE 1 12 FB .addr epSYSBRK ; IRQ address +00FFFA 1 00 00 .addr $0000 ; NMI address +00FFFC 1 00 80 .addr LANGUAGE_ENTRY ; RESET address +00FFFE 1 12 FB .addr epSYSBRK ; IRQ address 00FFFE 1 diff --git a/firmware.c65 b/asm/firmware.s similarity index 52% rename from firmware.c65 rename to asm/firmware.s index 9752bbe..4a8958b 100644 --- a/firmware.c65 +++ b/asm/firmware.s @@ -1,16 +1,18 @@ ; build: -; cl65 -l firmware.lst firmware.s --config firmware.cfg +; cl65 -l asm/firmware.lst asm/firmware.s --config asm/firmware.cfg -o firmware +; Review constants.go when this code is changed ; constants - .export ENTRY := $8000 + .export LANGUAGE_ENTRY := $8000 + .export SERVICE_ENTRY := $8003 ; boot code .org $0000 BOOT: - LDA #$1 - JMP ENTRY + lda #$1 + jmp LANGUAGE_ENTRY ; init ram vectors @@ -45,42 +47,64 @@ IND1V: .addr epIND1 IND2V: .addr epIND2 IND3V: .addr epIND3 +; support code + .res $f000 - * + .org $f000 + +; Send cli command to ROM and check the result +; Expects A=4, X=F, Y=0, the command to be pointed by $f2 +CLITOROM: + jsr SERVICE_ENTRY + tax + beq CLAIMED + brk ; "254-Bad command" error + .byte $fe + .asciiz "Bad command" +CLAIMED: rts + + +; area to store an error message + .res $fa00 - * + .org $fa00 +errorArea: brk +errorCode: .byte 0 +errorMessage: .asciiz "Hello world" ; bbz host entry points .res $fb00 - * .org $fb00 -epUPT: rts ; 0xfb00 -epEVNT: rts ; 0xfb01 -epFSC: rts ; 0xfb02 -epFIND: rts ; 0xfb03 -epGBPB: rts ; 0xfb04 -epBPUT: rts ; 0xfb05 -epBGET: rts ; 0xfb06 -epARGS: rts ; 0xfb07 -epFILE: rts ; 0xfb08 -epRDCH: rts ; 0xfb09 -epWRCH: rts ; 0xfb0a -epWORD: rts ; 0xfb0b -epBYTE: rts ; 0xfb0c -epCLI: rts ; 0xfb0d -epIRQ2: rts ; 0xfb0e -epIRQ1: rts ; 0xfb0f -epBRK: rts ; 0xfb10 -epUSER: rts ; 0xfb11 -epSYSBRK: rts ; 0xfb12 -epRDRM: rts ; 0xfb13 -epVDUCH: rts ; 0xfb14 -epGSINIT: rts ; 0xfb16 -epGSREAD: rts ; 0xfb17 -epNET: rts ; 0xfb18 -epVDU: rts ; 0xfb19 -epKEY: rts ; 0xfb1a -epINS: rts ; 0xfb1b -epREM: rts ; 0xfb1c -epCNP: rts ; 0xfb1d -epIND1: rts ; 0xfb1e -epIND2: rts ; 0xfb1f -epIND3: rts ; 0xfb20 +epUPT: rts ; 0xfb00 +epEVNT: rts ; 0xfb01 +epFSC: rts ; 0xfb02 +epFIND: rts ; 0xfb03 +epGBPB: rts ; 0xfb04 +epBPUT: rts ; 0xfb05 +epBGET: rts ; 0xfb06 +epARGS: rts ; 0xfb07 +epFILE: rts ; 0xfb08 +epRDCH: rts ; 0xfb09 +epWRCH: rts ; 0xfb0a +epWORD: rts ; 0xfb0b +epBYTE: rts ; 0xfb0c +epCLI: rts ; 0xfb0d +epIRQ2: rts ; 0xfb0e +epIRQ1: rts ; 0xfb0f +epBRK: rts ; 0xfb10 +epUSER: rts ; 0xfb11 +epSYSBRK: rts ; 0xfb12 +epRDRM: rts ; 0xfb13 +epVDUCH: rts ; 0xfb14 +epGSINIT: rts ; 0xfb16 +epGSREAD: rts ; 0xfb17 +epNET: rts ; 0xfb18 +epVDU: rts ; 0xfb19 +epKEY: rts ; 0xfb1a +epINS: rts ; 0xfb1b +epREM: rts ; 0xfb1c +epCNP: rts ; 0xfb1d +epIND1: rts ; 0xfb1e +epIND2: rts ; 0xfb1f +epIND3: rts ; 0xfb20 ; MOS function calls @@ -112,6 +136,6 @@ OSCLI: jmp (CLIV) ; OSCLI pass string to command line inte ; 6502 vectors - .addr $0000 ; NMI address - .addr ENTRY ; RESET address - .addr epSYSBRK ; IRQ address + .addr $0000 ; NMI address + .addr LANGUAGE_ENTRY ; RESET address + .addr epSYSBRK ; IRQ address diff --git a/bbz.go b/bbz.go index 4e26dbd..152e50a 100644 --- a/bbz.go +++ b/bbz.go @@ -52,7 +52,14 @@ func RunMOSEnvironment(romFilename string, firmFilename string, cpuLog bool, api env.cpu.ExecuteInstruction() pc, sp := env.cpu.GetPCAndSP() - if pc >= entryPoints && pc <= epEntryPointsLast { + + if pc == romStartAddress { + a, _, _, _ := env.cpu.GetAXYP() + env.log(fmt.Sprintf("LANGUAGE(A=%02x)", a)) + } else if pc == romServiceEntry { + a, x, _, _ := env.cpu.GetAXYP() + env.log(fmt.Sprintf("SERVICE(CMD=%02x, SLOT=%02x)", a, x)) + } else if pc >= entryPoints && pc <= epEntryPointsLast { a, x, y, p := env.cpu.GetAXYP() // Intercept MOS API calls. @@ -207,6 +214,8 @@ func RunMOSEnvironment(romFilename string, firmFilename string, cpuLog bool, api brkv := env.mem.peekWord(vectorBRK) env.cpu.SetPC(brkv) + // TODO: multiple ROMS: service call 6 before the jump to vectorBRK + env.log(fmt.Sprintf("BREAK(ERR=%02x, '%s')", faultNumber, faultString)) default: diff --git a/constants.go b/constants.go index 733deb2..4f47600 100644 --- a/constants.go +++ b/constants.go @@ -17,6 +17,7 @@ Memory map, pages: */ const ( + zpStr uint16 = 0x00f2 // OSCLI command line zpAccumulator uint16 = 0x00fc zpErrorPointer uint16 = 0x00fd @@ -30,6 +31,9 @@ const ( romCopyrightOffsetPointer uint16 = 0x8007 romTitleString uint16 = 0x8009 + // Support code on the firmware. Check firmware.lst when changing firmware.s + procCLITOROM uint16 = 0xf000 + // Scratch area for errors in page 0xfa errorArea uint16 = 0xfa00 errorMessageMaxLength int = 100 diff --git a/firmware b/firmware index 6e3368d..7db6c30 100644 Binary files a/firmware and b/firmware differ diff --git a/osCLI.go b/osCLI.go index 4a86c27..06a3439 100644 --- a/osCLI.go +++ b/osCLI.go @@ -67,6 +67,8 @@ func execOSCLI(env *environment) { case "*HELP": msg = "bbz - Acorn MOS for 6502 adaptation layer, https://github.com/ivanizag/bbz" + // TODO: multiple ROMS: service call 9 after the MOS message + case "*.": fallthrough case "*CAT": @@ -117,7 +119,17 @@ func execOSCLI(env *environment) { execOSBYTE(env) default: - env.raiseError(254, "Bad command") + romType := env.mem.Peek(romTypeByte) + if (romType & 0x80) != 0 { + // The ROM has a service entry. Let's try. + env.mem.pokeWord(zpStr, xy) + cmd := uint8(4) // Unrecognized command + romSlot := uint8(0xf) // The only supported slot + env.cpu.SetAXYP(cmd, romSlot, 1, p) + env.cpu.SetPC(procCLITOROM) + } else { + env.raiseError(254, "Bad command") + } } if msg != "" {