adapted to Kick Assembler, some documentation update

This commit is contained in:
FeralChild64 committed 2019-09-07 12:35:21 +02:00
1 parent ae23dbae7b
commit de27124b4f
198 files changed
+3979 -3774

No files matched your search

+2 -2
View File
@@ -2,9 +2,9 @@
# Compilation related files # Compilation related files
temp.s temp.s
temp.map temp.sym
ophis.bin assembler/KickAss*
build/* build/*
# Input to the similarity tool - copyrighted material, we can't check it in! # Input to the similarity tool - copyrighted material, we can't check it in!
-3
View File
@@ -1,3 +0,0 @@
[submodule "Ophis"]
path = Ophis
url = https://github.com/gardners/Ophis.git
+18 -23
View File
@@ -33,15 +33,10 @@ GIT_COMMIT:= $(shell git log -1 --pretty='%h' | tr '[:lower:]' '[:upper:]')
all: build/chargen build/newkern_generic build/newbasic_generic build/newc65 build/newkern_ultimate64 build/newbasic_ultimate64 all: build/chargen build/newkern_generic build/newbasic_generic build/newc65 build/newkern_ultimate64 build/newbasic_ultimate64
Ophis:
git submodule init
git submodule update
clean: clean:
@rm -rf build @rm -rf build
@rm -f temp.s @rm -f temp.s
@rm -f temp.map @rm -f temp.sym
@rm -f ophis.bin
updatebin: build/chargen build/newbasic_generic build/newkern_generic build/newbasic_mega65 build/newkern_mega65 build/newbasic_ultimate64 build/newkern_ultimate64 updatebin: build/chargen build/newbasic_generic build/newkern_generic build/newbasic_mega65 build/newkern_mega65 build/newbasic_ultimate64 build/newkern_ultimate64
cp build/chargen bin/chargen.rom cp build/chargen bin/chargen.rom
@@ -81,23 +76,23 @@ build/chargen: $(TOOL_PNGPREPARE) assets/8x8font.png
# Dependencies # Dependencies
build/basic_generic/OUT.BIN: Ophis $(TOOLS_LIST) $(SRC_BASIC_generic) build/basic/packed_messages.s build/basic_generic/OUT.BIN: $(TOOLS_LIST) $(SRC_BASIC_generic) build/basic/packed_messages.s
build/kernal_generic/OUT.BIN: Ophis $(TOOLS_LIST) $(SRC_KERNAL_generic) build/kernal_generic/OUT.BIN: $(TOOLS_LIST) $(SRC_KERNAL_generic)
build/newrom_generic: build/basic_generic/OUT.BIN build/kernal_generic/OUT.BIN build/newrom_generic: build/basic_generic/OUT.BIN build/kernal_generic/OUT.BIN
build/newkern_generic: build/newrom_generic Makefile build/newkern_generic: build/newrom_generic Makefile
build/newbasic_generic: build/newrom_generic Makefile build/newbasic_generic: build/newrom_generic Makefile
build/basic_mega65/OUT.BIN: Ophis $(TOOLS_LIST) $(SRC_BASIC_mega65) build/basic/packed_messages.s build/basic_mega65/OUT.BIN: $(TOOLS_LIST) $(SRC_BASIC_mega65) build/basic/packed_messages.s
build/kernal_mega65/OUT.BIN: Ophis $(TOOLS_LIST) $(SRC_KERNAL_mega65) build/kernal_mega65/OUT.BIN: $(TOOLS_LIST) $(SRC_KERNAL_mega65)
build/newrom_mega65: build/basic_mega65/OUT.BIN build/kernal_mega65/OUT.BIN build/newrom_mega65: build/basic_mega65/OUT.BIN build/kernal_mega65/OUT.BIN
build/newkern_mega65: build/newrom_mega65 Makefile build/newkern_mega65: build/newrom_mega65 Makefile
build/newbasic_mega65: build/newrom_mega65 Makefile build/newbasic_mega65: build/newrom_mega65 Makefile
build/basic_ultimate64/OUT.BIN: Ophis $(TOOLS_LIST) $(SRC_BASIC_ultimate64) build/basic/packed_messages.s build/basic_ultimate64/OUT.BIN: $(TOOLS_LIST) $(SRC_BASIC_ultimate64) build/basic/packed_messages.s
build/kernal_ultimate64/OUT.BIN: Ophis $(TOOLS_LIST) $(SRC_KERNAL_ultimate64) build/kernal_ultimate64/OUT.BIN: $(TOOLS_LIST) $(SRC_KERNAL_ultimate64)
build/newrom_ultimate64: build/basic_ultimate64/OUT.BIN build/kernal_ultimate64/OUT.BIN build/newrom_ultimate64: build/basic_ultimate64/OUT.BIN build/kernal_ultimate64/OUT.BIN
build/newkern_ultimate64: build/newrom_ultimate64 Makefile build/newkern_ultimate64: build/newrom_ultimate64 Makefile
build/newbasic_ultimate64: build/newrom_ultimate64 Makefile build/newbasic_ultimate64: build/newrom_ultimate64 Makefile
# Rules - BASIC and KERNAL # Rules - BASIC and KERNAL
@@ -107,7 +102,7 @@ build/basic/packed_messages.s: $(TOOL_COMPRESS_TEXT)
$(TOOL_COMPRESS_TEXT) > build/basic/packed_messages.s $(TOOL_COMPRESS_TEXT) > build/basic/packed_messages.s
.PRECIOUS: build/basic_%/OUT.BIN .PRECIOUS: build/basic_%/OUT.BIN
build/basic_%/OUT.BIN: Ophis $(TOOLS_LIST) $(SRC_BASIC_$*) build/basic/packed_messages.s build/basic_%/OUT.BIN: $(TOOLS_LIST) $(SRC_BASIC_$*) build/basic/packed_messages.s
@mkdir -p build/basic_$* @mkdir -p build/basic_$*
@rm -f build/basic_$*/* @rm -f build/basic_$*/*
@for SRC in $(SRC_BASIC_$*); do \ @for SRC in $(SRC_BASIC_$*); do \
@@ -117,7 +112,7 @@ build/basic_%/OUT.BIN: Ophis $(TOOLS_LIST) $(SRC_BASIC_$*) build/basic/packed_me
$(TOOL_PREPROCESS) -d build/basic_$* -l a000 -h e4d2 $(TOOL_PREPROCESS) -d build/basic_$* -l a000 -h e4d2
.PRECIOUS: build/kernal_%/OUT.BIN .PRECIOUS: build/kernal_%/OUT.BIN
build/kernal_%/OUT.BIN: Ophis $(TOOLS_LIST) $(SRC_KERNAL_$*) build/kernal_%/OUT.BIN: $(TOOLS_LIST) $(SRC_KERNAL_$*)
@mkdir -p build/kernal_$* @mkdir -p build/kernal_$*
@rm -f build/kernal_$*/* @rm -f build/kernal_$*/*
@for SRC in $(SRC_KERNAL_$*); do \ @for SRC in $(SRC_KERNAL_$*); do \
Submodule Ophis deleted from 15818e7666.
+2 -1
View File
@@ -1,5 +1,6 @@
# open-roms # open-roms
A project to create unencumbered open-source ROMs for use on selected retro computers
A project to create unencumbered open-source ROMs for use on selected retro computers. For the current status check [this document](STATUS.md)
# Problem Statement and Motivation # Problem Statement and Motivation
+3 -9
View File
@@ -38,16 +38,10 @@ The following ROM features are currently missing:
Status of the various APIs and variables from the original ROMs Status of the various APIs and variables from the original ROMs
## Page 0 ## Low memory locations (pages 0 - 3)
TODO For the current status of the low memory location implementation andd usage check [this file](c64/aliases/,aliases_ram_lowmem.s). NOTE: available vector to certain routine does not mean that this routine is fully implemented!
## Pages 2 & 3
TODO
## BASIC ## BASIC
@@ -107,7 +101,7 @@ NOTE: Even the 'DONE' routines won't support features described as missing in on
| `$FFE7` | `CLALL` | DONE | | | `$FFE7` | `CLALL` | DONE | |
| `$FFEA` | `UDTIM` | DONE | | | `$FFEA` | `UDTIM` | DONE | |
| `$FFED` | `SCREEN` | DONE | | | `$FFED` | `SCREEN` | DONE | |
| `$FFF0` | `PLOT` | DONE | | | `$FFF0` | `PLOT` | PARTIAL | cursor blink not handled |
| `$FFF3` | `IOBASE` | DONE | | | `$FFF3` | `IOBASE` | DONE | |
<br /> <br />
+1
View File
@@ -0,0 +1 @@
Put KickAss.jar and KickAss.cfg into this directory.
+58 -58
View File
@@ -1,63 +1,63 @@
;; Kernal error codes - returned in the A register // Kernal error codes - returned in the A register
;; Described in 'Commodore 64 Programmer's Reference Guide', page 306 // Described in 'Commodore 64 Programmer's Reference Guide', page 306
.alias K_ERR_ROUTINE_TERMINATED $00 .const K_ERR_ROUTINE_TERMINATED = $00
.alias K_ERR_TOO_MANY_OPEN_FILES $01 .const K_ERR_TOO_MANY_OPEN_FILES = $01
.alias K_ERR_FILE_ALREADY_OPEN $02 .const K_ERR_FILE_ALREADY_OPEN = $02
.alias K_ERR_FILE_NOT_OPEN $03 .const K_ERR_FILE_NOT_OPEN = $03
.alias K_ERR_FILE_NOT_FOUND $04 .const K_ERR_FILE_NOT_FOUND = $04
.alias K_ERR_DEVICE_NOT_FOUND $05 .const K_ERR_DEVICE_NOT_FOUND = $05
.alias K_ERR_FILE_NOT_INPUT $06 .const K_ERR_FILE_NOT_INPUT = $06
.alias K_ERR_FILE_NOT_OUTPUT $07 .const K_ERR_FILE_NOT_OUTPUT = $07
.alias K_ERR_FILE_NAME_MISSING $08 .const K_ERR_FILE_NAME_MISSING = $08
.alias K_ERR_ILLEGAL_DEVICE_NUMBER $09 .const K_ERR_ILLEGAL_DEVICE_NUMBER = $09
.alias K_ERR_TOP_MEM_RS232 $F0 .const K_ERR_TOP_MEM_RS232 = $F0
;; Kernal status codes for READST routine (IOSTATUS) // Kernal status codes for READST routine (IOSTATUS)
;; Described in 'Commodore 64 Programmer's Reference Guide', page 292 // Described in 'Commodore 64 Programmer's Reference Guide', page 292
;; For IEC devices // For IEC devices
.alias K_STS_TIMEOUT_WRITE $01 .const K_STS_TIMEOUT_WRITE = $01
.alias K_STS_TIMEOUT_READ $02 .const K_STS_TIMEOUT_READ = $02
.alias K_STS_EOI $40 .const K_STS_EOI = $40
.alias K_STS_DEVICE_NOT_FOUND $80 .const K_STS_DEVICE_NOT_FOUND = $80
;; For tape deck // For tape deck
.alias K_STS_SHORT_BLOCK $04 .const K_STS_SHORT_BLOCK = $04
.alias K_STS_LONG_BLOCK $08 .const K_STS_LONG_BLOCK = $08
.alias K_STS_READ_ERROR $10 .const K_STS_READ_ERROR = $10
.alias K_STS_CHECKSUM_ERROR $20 .const K_STS_CHECKSUM_ERROR = $20
.alias K_STS_END_OF_FILE $40 .const K_STS_END_OF_FILE = $40
.alias K_STS_END_OF_TAPE $80 .const K_STS_END_OF_TAPE = $80
;; BASIC error codes, taken from http://sta.c64.org/cbm64baserr.html // BASIC error codes, taken from http://sta.c64.org/cbm64baserr.html
.alias B_ERR_TOO_MANY_FILES $01 .const B_ERR_TOO_MANY_FILES = $01
.alias B_ERR_FILE_OPEN $02 .const B_ERR_FILE_OPEN = $02
.alias B_ERR_FILE_NOT_OPEN $03 .const B_ERR_FILE_NOT_OPEN = $03
.alias B_ERR_FILE_NOT_FOUND $04 .const B_ERR_FILE_NOT_FOUND = $04
.alias B_ERR_DEVICE_NOT_PRESENT $05 .const B_ERR_DEVICE_NOT_PRESENT = $05
.alias B_ERR_NOT_INPUT_FILE $06 .const B_ERR_NOT_INPUT_FILE = $06
.alias B_ERR_NOT_OUTPUT_FILE $07 .const B_ERR_NOT_OUTPUT_FILE = $07
.alias B_ERR_MISSING_FILENAME $08 .const B_ERR_MISSING_FILENAME = $08
.alias B_ERR_ILLEGAL_DEVICE_NUMBER $09 .const B_ERR_ILLEGAL_DEVICE_NUMBER = $09
.alias B_ERR_NEXT_WITHOUT_FOR $0A .const B_ERR_NEXT_WITHOUT_FOR = $0A
.alias B_ERR_SYNTAX $0B .const B_ERR_SYNTAX = $0B
.alias B_ERR_RETURN_WITHOUT_GOSUB $0C .const B_ERR_RETURN_WITHOUT_GOSUB = $0C
.alias B_ERR_OUT_OF_DATA $0D .const B_ERR_OUT_OF_DATA = $0D
.alias B_ERR_ILLEGAL_QUANTITY $0E .const B_ERR_ILLEGAL_QUANTITY = $0E
.alias B_ERR_OVERFLOW $0F .const B_ERR_OVERFLOW = $0F
.alias B_ERR_OUT_OF_MEMORY $10 .const B_ERR_OUT_OF_MEMORY = $10
.alias B_ERR_UNDEFD_STATEMENT $11 .const B_ERR_UNDEFD_STATEMENT = $11
.alias B_ERR_BAD_SUBSCRIPT $12 .const B_ERR_BAD_SUBSCRIPT = $12
.alias B_ERR_REDIMD_ARRAY $13 .const B_ERR_REDIMD_ARRAY = $13
.alias B_ERR_DIVISION_BY_ZERO $14 .const B_ERR_DIVISION_BY_ZERO = $14
.alias B_ERR_ILLEGAL_DIRECT $15 .const B_ERR_ILLEGAL_DIRECT = $15
.alias B_ERR_TYPE_MISMATCH $16 .const B_ERR_TYPE_MISMATCH = $16
.alias B_ERR_STRING_TOO_LONG $17 .const B_ERR_STRING_TOO_LONG = $17
.alias B_ERR_FILE_DATA $18 .const B_ERR_FILE_DATA = $18
.alias B_ERR_FORMULA_TOO_COMPLEX $19 .const B_ERR_FORMULA_TOO_COMPLEX = $19
.alias B_ERR_CANT_CONTINUE $1A .const B_ERR_CANT_CONTINUE = $1A
.alias B_ERR_UNDEFD_FUNCTION $1B .const B_ERR_UNDEFD_FUNCTION = $1B
.alias B_ERR_VERIFY $1C .const B_ERR_VERIFY = $1C
.alias B_ERR_LOAD $1D .const B_ERR_LOAD = $1D
.alias B_ERR_BREAK $1E .const B_ERR_BREAK = $1E
+124 -124
View File
@@ -1,148 +1,148 @@
;; //
;; Names of hardware registers - slightly modified names from C64 Programmer's Reference Guide // Names of hardware registers - slightly modified names from C64 Programmer's Reference Guide
;; //
;; CPU memory registers // CPU memory registers
.alias CPU_D6510 $00 .label CPU_D6510 = $00
.alias CPU_R6510 $01 .label CPU_R6510 = $01
;; VIC-II registers // VIC-II registers
.alias VIC_SP0X $D000 .label VIC_SP0X = $D000
.alias VIC_SP0Y $D001 .label VIC_SP0Y = $D001
.alias VIC_SP1X $D002 .label VIC_SP1X = $D002
.alias VIC_SP1Y $D003 .label VIC_SP1Y = $D003
.alias VIC_SP2X $D004 .label VIC_SP2X = $D004
.alias VIC_SP2Y $D005 .label VIC_SP2Y = $D005
.alias VIC_SP3X $D006 .label VIC_SP3X = $D006
.alias VIC_SP3Y $D007 .label VIC_SP3Y = $D007
.alias VIC_SP4X $D008 .label VIC_SP4X = $D008
.alias VIC_SP4Y $D009 .label VIC_SP4Y = $D009
.alias VIC_SP5X $D00A .label VIC_SP5X = $D00A
.alias VIC_SP5Y $D00B .label VIC_SP5Y = $D00B
.alias VIC_SP6X $D00C .label VIC_SP6X = $D00C
.alias VIC_SP6Y $D00D .label VIC_SP6Y = $D00D
.alias VIC_SP7X $D00E .label VIC_SP7X = $D00E
.alias VIC_SP7Y $D00F .label VIC_SP7Y = $D00F
.alias VIC_MSIGX $D010 .label VIC_MSIGX = $D010
.alias VIC_SCROLY $D011 .label VIC_SCROLY = $D011
.alias VIC_RASTER $D012 .label VIC_RASTER = $D012
.alias VIC_LPENX $D013 .label VIC_LPENX = $D013
.alias VIC_LPENY $D014 .label VIC_LPENY = $D014
.alias VIC_SPENA $D015 .label VIC_SPENA = $D015
.alias VIC_SCROLX $D016 .label VIC_SCROLX = $D016
.alias VIC_YXPAND $D017 .label VIC_YXPAND = $D017
.alias VIC_YMCSB $D018 .label VIC_YMCSB = $D018
.alias VIC_IRQ $D019 .label VIC_IRQ = $D019
.alias VIC_IRQMSK $D01A .label VIC_IRQMSK = $D01A
.alias VIC_SPBGPR $D01B .label VIC_SPBGPR = $D01B
.alias VIC_SPMC $D01C .label VIC_SPMC = $D01C
.alias VIC_XXPAND $D01D .label VIC_XXPAND = $D01D
.alias VIC_SPSPCL $D01E .label VIC_SPSPCL = $D01E
.alias VIC_SPBGCL $D01F .label VIC_SPBGCL = $D01F
.alias VIC_EXTCOL $D020 .label VIC_EXTCOL = $D020
.alias VIC_BGCOL0 $D021 .label VIC_BGCOL0 = $D021
.alias VIC_BGCOL1 $D022 .label VIC_BGCOL1 = $D022
.alias VIC_BGCOL2 $D023 .label VIC_BGCOL2 = $D023
.alias VIC_BGCOL3 $D024 .label VIC_BGCOL3 = $D024
.alias VIC_SPMC0 $D025 .label VIC_SPMC0 = $D025
.alias VIC_SPMC1 $D026 .label VIC_SPMC1 = $D026
.alias VIC_SP0COL $D027 .label VIC_SP0COL = $D027
.alias VIC_SP1COL $D028 .label VIC_SP1COL = $D028
.alias VIC_SP2COL $D029 .label VIC_SP2COL = $D029
.alias VIC_SP3COL $D02A .label VIC_SP3COL = $D02A
.alias VIC_SP4COL $D02B .label VIC_SP4COL = $D02B
.alias VIC_SP5COL $D02C .label VIC_SP5COL = $D02C
.alias VIC_SP6COL $D02D .label VIC_SP6COL = $D02D
.alias VIC_SP7COL $D02E .label VIC_SP7COL = $D02E
;; SID registers // SID registers
.alias SID_FRELO1 $D400 .label SID_FRELO1 = $D400
.alias SID_FREHI1 $D401 .label SID_FREHI1 = $D401
.alias SID_PWLO1 $D402 .label SID_PWLO1 = $D402
.alias SID_PWHI1 $D403 .label SID_PWHI1 = $D403
.alias SID_VCREG1 $D404 .label SID_VCREG1 = $D404
.alias SID_ATDCY1 $D405 .label SID_ATDCY1 = $D405
.alias SID_SUREL1 $D406 .label SID_SUREL1 = $D406
.alias SID_FRELO2 $D407 .label SID_FRELO2 = $D407
.alias SID_FREHI2 $D408 .label SID_FREHI2 = $D408
.alias SID_PWLO2 $D409 .label SID_PWLO2 = $D409
.alias SID_PWHI2 $D40A .label SID_PWHI2 = $D40A
.alias SID_VCREG2 $D40B .label SID_VCREG2 = $D40B
.alias SID_ATDCY2 $D40C .label SID_ATDCY2 = $D40C
.alias SID_SUREL2 $D40D .label SID_SUREL2 = $D40D
.alias SID_FRELO3 $D40E .label SID_FRELO3 = $D40E
.alias SID_FREHI3 $D40F .label SID_FREHI3 = $D40F
.alias SID_PWLO3 $D410 .label SID_PWLO3 = $D410
.alias SID_PWHI3 $D411 .label SID_PWHI3 = $D411
.alias SID_VCREG3 $D412 .label SID_VCREG3 = $D412
.alias SID_ATDCY3 $D413 .label SID_ATDCY3 = $D413
.alias SID_SUREL3 $D414 .label SID_SUREL3 = $D414
.alias SID_CUTLO $D415 .label SID_CUTLO = $D415
.alias SID_CUTHI $D416 .label SID_CUTHI = $D416
.alias SID_RESON $D417 .label SID_RESON = $D417
.alias SID_SIGVOL $D418 .label SID_SIGVOL = $D418
.alias SID_POTX $D419 .label SID_POTX = $D419
.alias SID_POTY $D41A .label SID_POTY = $D41A
.alias SID_RANDOM $D41B .label SID_RANDOM = $D41B
.alias SID_ENV3 $D41C .label SID_ENV3 = $D41C
;; CIA #1 registers // CIA #1 registers
.alias CIA1_PRA $DC00 .label CIA1_PRA = $DC00
.alias CIA1_PRB $DC01 .label CIA1_PRB = $DC01
.alias CIA1_DDRA $DC02 .label CIA1_DDRA = $DC02
.alias CIA1_DDRB $DC03 .label CIA1_DDRB = $DC03
.alias CIA1_TIMALO $DC04 .label CIA1_TIMALO = $DC04
.alias CIA1_TIMAHI $DC05 .label CIA1_TIMAHI = $DC05
.alias CIA1_TIMBLO $DC06 .label CIA1_TIMBLO = $DC06
.alias CIA1_TIMBHI $DC07 .label CIA1_TIMBHI = $DC07
.alias CIA1_TODTEN $DC08 .label CIA1_TODTEN = $DC08
.alias CIA1_TODSEC $DC09 .label CIA1_TODSEC = $DC09
.alias CIA1_TODMIN $DC0A .label CIA1_TODMIN = $DC0A
.alias CIA1_TODHRS $DC0B .label CIA1_TODHRS = $DC0B
.alias CIA1_SDR $DC0C .label CIA1_SDR = $DC0C
.alias CIA1_ICR $DC0D .label CIA1_ICR = $DC0D
.alias CIA1_CRA $DC0E .label CIA1_CRA = $DC0E
.alias CIA1_CRB $DC0F .label CIA1_CRB = $DC0F
;; CIA #2 registers // CIA #2 registers
.alias CIA2_PRA $DD00 ; VIC bank switching and IEC port .label CIA2_PRA = $DD00 // VIC bank switching and IEC port
.alias CIA2_PRB $DD01 .label CIA2_PRB = $DD01
.alias CIA2_DDRA $DD02 .label CIA2_DDRA = $DD02
.alias CIA2_DDRB $DD03 .label CIA2_DDRB = $DD03
.alias CIA2_TIMALO $DD04 .label CIA2_TIMALO = $DD04
.alias CIA2_TIMAHI $DD05 .label CIA2_TIMAHI = $DD05
.alias CIA2_TIMBLO $DD06 .label CIA2_TIMBLO = $DD06
.alias CIA2_TIMBHI $DD07 .label CIA2_TIMBHI = $DD07
.alias CIA2_TODTEN $DD08 .label CIA2_TODTEN = $DD08
.alias CIA2_TODSEC $DD09 .label CIA2_TODSEC = $DD09
.alias CIA2_TODMIN $DD0A .label CIA2_TODMIN = $DD0A
.alias CIA2_TODHRS $DD0B .label CIA2_TODHRS = $DD0B
.alias CIA2_SDR $DD0C .label CIA2_SDR = $DD0C
.alias CIA2_ICR $DD0D .label CIA2_ICR = $DD0D
.alias CIA2_CRA $DD0E .label CIA2_CRA = $DD0E
.alias CIA2_CRB $DD0F .label CIA2_CRB = $DD0F
;; CIA #2 helper bits - IEC bus // CIA #2 helper bits - IEC bus
.alias BIT_CIA2_PRA_ATN_OUT $08 ; 1 - low (pulled), 0 - high (released) .const BIT_CIA2_PRA_ATN_OUT = $08 // 1 - low (pulled), 0 - high (released)
.alias BIT_CIA2_PRA_CLK_OUT $10 ; 1 - low (pulled), 0 - high (released) .const BIT_CIA2_PRA_CLK_OUT = $10 // 1 - low (pulled), 0 - high (released)
.alias BIT_CIA2_PRA_DAT_OUT $20 ; 1 - low (pulled), 0 - high (released) .const BIT_CIA2_PRA_DAT_OUT = $20 // 1 - low (pulled), 0 - high (released)
.alias BIT_CIA2_PRA_CLK_IN $40 ; 0 - low (pulled), 1 - high (released) .const BIT_CIA2_PRA_CLK_IN = $40 // 0 - low (pulled), 1 - high (released)
.alias BIT_CIA2_PRA_DAT_IN $80 ; 0 - low (pulled), 1 - high (released) .const BIT_CIA2_PRA_DAT_IN = $80 // 0 - low (pulled), 1 - high (released)
+219 -81
View File
@@ -1,98 +1,236 @@
;; //
;; Names of ZP and low memory locations // Names of ZP and low memory locations:
;; (https://www.c64-wiki.com/wiki/Zeropage) // - Compute's Mapping the Commodore 64
;; // - https://www.c64-wiki.com/wiki/Zeropage
// - http://unusedino.de/ec64/technical/project64/memory_maps.html
//
;; $00-$01 - 6502 CPU registers are here // $00-$01 - 6502 CPU registers are here
;; //
;; Page 0 - BASIC area ($02-$8F) // Page 0 - BASIC area ($02-$8F)
;; //
.alias TXTTAB $2B // $02 -- UNUSED -- free for user software
.label ADRAY1 = $03 // $03-$04 -- NOT IMPLEMENTED --
.label ADRAY2 = $05 // $05-$06 -- NOT IMPLEMENTED --
.label CHARAC = $07 // [!] our implementation might be different XXX give more details
.label ENDCHR = $08 // [!] our implementation might be different XXX give more details
.label TRMPOS = $09 // -- NOT IMPLEMENTED --
.label VERCKB = $0A // -- NOT IMPLEMENTED --
.label COUNT = $0B // [!] our implementation might be different XXX give more details
.label DIMFLG = $0C // [!] our implementation might be different XXX give more details
.label VALTYP = $0D // -- NOT IMPLEMENTED --
.label INTFLG = $0E // -- NOT IMPLEMENTED --
.label GARBFL = $0F // [!] our implementation might be different XXX give more details
.label SUBFLG = $10 // -- NOT IMPLEMENTED --
.label INPFLG = $11 // -- NOT IMPLEMENTED --
.label TANSGN = $12 // -- NOT IMPLEMENTED --
.label CHANNL = $13 // -- NOT IMPLEMENTED --
.label LINNUM = $14 // $14-$15 BASIC line number, [!] also used by DOS Wedge
.label TEMPPT = $16 // -- NOT IMPLEMENTED --
.label LASTPT = $17 // $17-$18 -- NOT IMPLEMENTED --
.label TEMPST = $19 // $19-$21 -- NOT IMPLEMENTED --
.label INDEX = $22 // $22-$25 -- NOT IMPLEMENTED -- temporary variables
.label RESHO = $26 // $26-$2A -- NOT IMPLEMENTED --
.label TXTTAB = $2B // $2B-$2C start of BASIC code
.label VARTAB = $2D // $2D-$2E end of BASIC code, start of variables
.label ARYTAB = $2F // $2F-$30 -- NOT IMPLEMENTED --
.label STREND = $31 // $31-$32 -- NOT IMPLEMENTED --
.label FRETOP = $33 // $33-$34 -- NOT IMPLEMENTED --
.label FRESPC = $35 // $35-$36 [!] our implementation might be different XXX give more details
// .label MEMSIZ = $37 // $37-$38 -- NOT IMPLEMENTED -- highest address of BASIC memory XXX remove name conflict
.label CURLIN = $39 // $39-$3A current BASIC line number
.label OLDLIN = $3B // $3B-$3C previous BASIC line number
.label OLDTXT = $3D // $3D-$3E current BASIC line pointer
.label DATLIN = $3F // $3F-$40 -- NOT IMPLEMENTED --
.label DATPTR = $41 // $41-$42 -- NOT IMPLEMENTED --
.label INPPTR = $43 // $43-$44 -- NOT IMPLEMENTED --
.label VARNAM = $45 // $45-$46 -- NOT IMPLEMENTED --
.label VARPNT = $47 // $47-$48 -- NOT IMPLEMENTED --
.label FORPNT = $49 // $49-$4A -- NOT IMPLEMENTED --
.label OPPTR = $4B // $4B-$4C -- NOT IMPLEMENTED --
.label OPMASK = $4D // -- NOT IMPLEMENTED --
.label DEFPNT = $4E // $4E-$4F -- NOT IMPLEMENTED --
.label DSCPNT = $50 // $50-$52 -- NOT IMPLEMENTED --
.label FOUR6 = $53 // -- NOT IMPLEMENTED --
.label JMPER = $54 // $54-$56 -- NOT IMPLEMENTED --
.label TEMPF1 = $57 // $57-$5B BASIC numeric work area
.label TEMPF2 = $5C // $5C-$60 BASIC numeric work area
.label FAC1 = $61 // $61-$66 -- NOT IMPLEMENTED --
.label SGNFLG = $67 // -- NOT IMPLEMENTED --
.label BITS = $68 // -- NOT IMPLEMENTED --
.label FAC2 = $69 // $69-$6E -- NOT IMPLEMENTED -- [!] also used for memory move pointers
.label ARISGN = $6F // -- NOT IMPLEMENTED --
.label FACOV = $70 // -- NOT IMPLEMENTED --
.label FBUFPT = $67 // $71-$72 -- NOT IMPLEMENTED --
.label CHRGET = $73 // $73-$8A -- NOT IMPLEMENTED --
.label TXTPTR = $7A // $7A-$7B current BASIC statement pointer
.label RNDX = $8B // $8B-$8F -- NOT IMPLEMENTED --
;; //
;; Page 0 - Kernal area ($90-$FF) // Page 0 - Kernal area ($90-$FF)
;; //
.alias IOSTATUS $90 .label IOSTATUS = $90
.alias STKEY $91 ; Keys down clears bits. STOP - bit 7, C= - bit 6, SPACE - bit 4, CTRL - bit 2 .label STKEY = $91 // Keys down clears bits. STOP - bit 7, C= - bit 6, SPACE - bit 4, CTRL - bit 2
.label SVXT = $92 // -- NOT IMPLEMENTED --
.label VERCK = $93 // 0 = LOAD, 1 = VERIFY XXX rename to VERCKK
.label C3PO = $94 // flag - is BSOUR content valid
.label BSOUR = $95 // serial bus buffered output byte
.label SYNO = $96 // -- NOT IMPLEMENTED --
.label XSAV = $97 // -- NOT IMPLEMENTED --
.label LDTND = $98 // number of entries in LAT / FAT / SAT tables
.label DFLTN = $99 // default input device
.label DFLTO = $9A // default output device
.label PRTY = $9B // -- NOT IMPLEMENTED --
.label DPSW = $9C // -- NOT IMPLEMENTED --
.label MSGFLG = $9D // bit 6 = error messages, bit 7 = control message
.label PTR1 = $9E // -- NOT IMPLEMENTED --
.label PTR2 = $9F // -- NOT IMPLEMENTED --
.label TIME = $A0 // $A0-$A2, jiffy clock
.label IEC_TMP1 = $A3 // temporary variable for tape and IEC, [!] our usage probably differs in details XXX rename to TSFCNT
.label IEC_TMP2 = $A4 // temporary variable for tape and IEC, [!] our usage probably differs in details XXX rename to TBTCNT
.label CNTDN = $A5 // -- NOT IMPLEMENTED --
.label BUFPNT = $A6 // -- NOT IMPLEMENTED --
.label INBIT = $A7 // -- NOT IMPLEMENTED --
.label BITCI = $A8 // -- NOT IMPLEMENTED --
.label RINONE = $A9 // -- NOT IMPLEMENTED --
.label RIDDATA = $AA // -- NOT IMPLEMENTED --
.label RIPRTY = $AB // -- NOT IMPLEMENTED --
.label SAL = $AC // $AC-$AD -- NOT IMPLEMENTED -- (implemented screen part)
.label EAL = $AE // $AE-$AF -- NOT IMPLEMENTED -- [!] used also byy screen editor
.label CMP0 = $B0 // $B0-$B1, temporary tape storage, [!] here used for BRK instruction address
.label TAPE1 = $B2 // $B2-$B3 tape buffer pointer
.label BITTS = $B4 // -- NOT IMPLEMENTED --
.label NXTBIT = $B5 // -- NOT IMPLEMENTED --
.label RODATA = $B6 // -- NOT IMPLEMENTED --
.label FNLEN = $B7 // current file name length
.label LA = $B8 // current logical_file number
.label SA = $B9 // current secondary address
.label FA = $BA // current device number
.label FNADDR = $BB // $BB-$BC, current file name pointer
.label ROPRTY = $BD // -- NOT IMPLEMENTED --
.label FSBLK = $BE // -- NOT IMPLEMENTED --
.label MYCH = $BF // -- NOT IMPLEMENTED --
.label CAS1 = $C0 // -- NOT IMPLEMENTED --
.label STAL = $C1 // $C1-$C2, LOAD/SAVE start address
.label MEMUS = $C3 // $C3-$C4, temporary address for tape LOAD/SAVE XXX rename to MEMUSS
.label LSTX = $C5 // last keyy matrix position [!] our usage probably differs in details
.label NDX = $C6 // number of chars in keyboard buffer
.label RVS = $C7 // flag, whether to print reversed characters
.label INDX = $C8 // end of logical line (column, 0-79)
.label LXSP = $C9 // $C9-$CA start of input, X/Y position
.label SFDX = $CB // -- NOT IMPLEMENTED --
.label BLNSW = $CC // cursor blink disable flag
.label BLNCT = $CD // cursor blink countdown
.label GDBLN = $CE // cursorb saved character
.label BLNON = $CF // cursor visibilityy flag
.label CRSW = $D0 // whether to input from screen or keyboard
.label PNT = $D1 // $D1-$D2 pointer to the current screen line
.label PNTR = $D3 // current screen X position
.label QTSW = $D4 // quote mode flag
.label LNMX = $D5 // logical line length, [!] our usage probably differs in details
.label TBLX = $D6 // current screen Y position
.label SCHAR = $D7 // ASCII value of the last printed character
.label INSRT = $D8 // insert mode flag/counter
.label LDTB1 = $D9 // $D9-$F2 screen line link table, [!] our usage is different XXX give more details
.label USER = $F3 // $F3-$F4 pointer to current color RAM location
.label KEYTAB = $F5 // $F5-$F6 -- NOT IMPLEMENTED --
.label RIBUF = $F7 // $F7-$F8 -- NOT IMPLEMENTED --
.label ROBUF = $F9 // $F9-$FA -- NOT IMPLEMENTED --
// $FB $FB-$FE -- UNUSED -- free for user software
.label BASZPT = $FF // -- NOT IMPLEMENTED --
.alias VERCK $93 ; 0 = LOAD, 1 = VERIVY //
// Page 1
//
.alias C3PO $94 ; flag - is BSOUR content valid .label STACK = $100 // $100-$1FF, processor stack
.alias BSOUR $95 ; serial bus buffered output byte
.alias LDTND $98 ; number of entries in LAT / FAT / SAT tables //
.alias DFLTN $99 // Pages 2 & 3
.alias DFLTO $9A //
.alias MSGFLG $9D ; bit 6 = error messages, bit 7 = control message .label BUF = $200 // $200-$250, BASIC line editor input buffer (81 bytes)
// [!] XXX document $251-$258 usage
.label LAT = $259 // $259-$262, logical file numbers (table, 10 bytes)
.label FAT = $263 // $263-$26C, device numbers (table, 10 bytes)
.label SAT = $26D // $26D-$276, secondary addresses (table, 10 bytes)
.label KEYD = $277 // $277-$280 keyboard buffer
.label MEMSTR = $281 // $281-$282 XXX rename to LORAM
.label MEMSIZ = $283 // $283-$284, NOTE: Mapping the 64 erroneously has the hex as $282, while the DEC is correct XXX rename to HIRAM
.label TIMOUT = $285 // IEEE-488 timeout
.label COLOR = $286 // current text foreground color
.label GDCOL = $287 // color of character under cursor
.label HIBASE = $288 // high byte of start of screen
.label XMAX = $289 // max keyboard buffer size
.label RPTFLG = $28A // -- NOT IMPLEMENTED --
.label KOUNT = $28B // -- NOT IMPLEMENTED --
.label DELAY = $28C // -- NOT IMPLEMENTED --
.label SHFLAG = $28D // bucky keys (SHIFT/CTRL/C=) flags
.label LSTSHF = $28E // last bucky key flags
.label KEYLOG = $28F // $28F-$290 -- NOT IMPLEMENTED --
.label MODE = $291 // flag, is case switch allowed
.label AUTODN = $292 // -- NOT IMPLEMENTED --
.label M51CRT = $293 // -- NOT IMPLEMENTED -- mock 6551
.label M51CDR = $294 // -- NOT IMPLEMENTED -- mock 6551
.label M51AJB = $295 // $295-$296 -- NOT IMPLEMENTED -- mock 6551
.label RSSTAT = $297 // -- NOT IMPLEMENTED -- mock 6551, RS-232 status
.label BITNUM = $298 // -- NOT IMPLEMENTED --
.label BAUDOF = $299 // $299-$29A -- NOT IMPLEMENTED --
.label RIDBE = $29B // -- NOT IMPLEMENTED --
.label RIDBS = $29C // -- NOT IMPLEMENTED --
.label RODBS = $29D // -- NOT IMPLEMENTED --
.label RODBE = $29E // -- NOT IMPLEMENTED --
.label IRQTMP = $29F // $29F-$2A0 -- NOT IMPLEMENTED --
.label ENABL = $2A1 // -- NOT IMPLEMENTED --
.label TODSNS = $2A2 // -- NOT IMPLEMENTED --
.label TRDTMP = $2A3 // -- NOT IMPLEMENTED --
.label TD1IRQ = $2A4 // -- NOT IMPLEMENTED --
.label TLNIDX = $2A5 // -- NOT IMPLEMENTED --
.label PALNTSC = $2A6 // 0 = NTSC, 1 = PAL XXX rename to TVSFLG
// [!] XXX document $2A7-$2FF usage
.alias TIME $A0 ; $A0-$A2, jiffy clock // BASIC vectors
.label IERROR = $300 // $300-$301 -- NOT IMPLEMENTED --
.label IMAIN = $302 // $302-$303 -- NOT IMPLEMENTED --
.label ICRNCH = $304 // $304-$305 -- NOT IMPLEMENTED --
.label IQPLOP = $306 // $306-$307 -- NOT IMPLEMENTED --
.label IGONE = $308 // $308-$309 -- NOT IMPLEMENTED --
.label IEVAL = $30A // $30A-$30B -- NOT IMPLEMENTED --
.alias IEC_TMP1 $A3 ; temporary variable for tape and IEC .label SAREG = $30C // .A storage, for SYS call
.alias IEC_TMP2 $A4 ; temporary variable for tape and IEC .label SXREG = $30D // .X storage, for SYS call
.label SYREG = $30E // .Y storage, for SYS call
.label SPREG = $30F // .P storage, for SYS call
.alias CMP0 $B0 ; $B0-$B1, temporary tape storage, we use it too for BRK instruction address .label USRPOK = $310 // -- NOT IMPLEMENTED -- JMP instruction
.label USRADD = $311 // $311-$312 -- NOT IMPLEMENTED --
// $313 -- UNUSED -- free for user software
.alias FNLEN $B7 ; current file name length // Kernal vectors - interrupts
.label CINV = $314 // $314-$315
.label CBINV = $316 // $316-$317
.label NMINV = $318 // $318-$319
.alias FNADDR $BB ; $BB-$BC, current file name pointer // Kernal vectors - routines
.label IOPEN = $31A // $31A-$31B
.label ICLOSE = $31C // $31C-$31D
.label ICHKIN = $31E // $31E-$31F
.label ICKOUT = $320 // $320-$321
.label ICLRCH = $322 // $322-$323
.label IBASIN = $324 // $324-$325
.label IBSOUT = $326 // $326-$327
.label ISTOP = $328 // $328-$329
.label IGETIN = $32A // $32A-$32B
.label ICLALL = $32C // $32C-$32D
.label USRCMD = $32E // $32E-$32F
.label ILOAD = $330 // $330-$331
.label ISAVE = $332 // $332-$333
.alias STAL $C1 ; $C1-$C2 LOAD/SAVE start address // $314 $334-$33B -- UNUSED -- free for user software
.alias MEMUS $C3 ; $C3-$C4 temporary address for tape LOAD/SAVE
;; .label TBUFFR = $33C // $33C-$3FB, -- NOT IMPLEMENTED --, tape buffer
;; Other low memory addresses
;;
.alias BUF $200 ; $200-$250 (81 bytes), BASIC line editor input buffer // $3FC $3FC-$3FF -- UNUSED -- free for user software
;; Kernal tables for opened files, 10 entries each
.alias LAT $259 ; logical file numbers
.alias FAT $263 ; device numbers
.alias SAT $26D ; secondary addresses
.alias MEMSTR $281
.alias MEMSIZ $283 ; NOTE: Mapping the 64 erroniously has the hex as $282, while the DEC is correct
.alias TIMOUT $285 ; IEEE-488 timeout
.alias HIBASE $288 ; high byte of start of screen
.alias RSSTAT $297 ; RS-232 status
.alias PALNTSC $2A6 ; 0 = NTSC, 1 = PAL
;; Registers for SYS call
.alias SAREG $30C
.alias SXREG $30D
.alias SYREG $30E
.alias SPREG $30F
.alias USRPOK $310 ; JMP instruction
.alias USRADD $311 ; $311 - $312
;; Kernal vectors - interrupts
.alias CINV $314
.alias CBINV $316
.alias NMINV $318
;; Kernal vectors - routines
.alias IOPEN $31A
.alias ICLOSE $31C
.alias ICHKIN $31E
.alias ICKOUT $320
.alias ICLRCH $322
.alias IBASIN $324
.alias IBSOUT $326
.alias ISTOP $328
.alias IGETIN $32A
.alias ICLALL $32C
.alias USRCMD $32E
.alias ILOAD $330
.alias ISAVE $331
.alias TBUFFR $33C ; $33C-$3FB, tape buffer
+3 -4
View File
@@ -1,5 +1,4 @@
;; BASIC startup vector // BASIC startup vectors
.label IBASIC_COLD_START = $A000
.alias IBASIC_COLD_START $A000 .label IBASIC_WARM_START = $A002
.alias IBASIC_WARM_START $A002
+4 -4
View File
@@ -1,5 +1,5 @@
;; Cartridge ROM locations // Cartridge ROM locations
.alias ICART_COLD_START $8000 ; $8000-$8001, cartridge cold start vector .label ICART_COLD_START = $8000 // $8000-$8001, cartridge cold start vector
.alias ICART_WARM_START $8002 ; $8002-$8003, cartridge warm start vector (RESTORE key) .label ICART_WARM_START = $8002 // $8002-$8003, cartridge warm start vector (RESTORE key)
.alias CART_SIG $8004 ; 5 bytes, signature for cartridge detection .label CART_SIG = $8004 // $8004-$8008, signature for cartridge detection
+40 -40
View File
@@ -1,41 +1,41 @@
;; Kernal jump table // Kernal jump table
.alias JCINT $FF81 .label JCINT = $FF81
.alias JIOINIT $FF84 .label JIOINIT = $FF84
.alias JRAMTAS $FF87 .label JRAMTAS = $FF87
.alias JRESTOR $FF8A .label JRESTOR = $FF8A
.alias JVECTOR $FF8D .label JVECTOR = $FF8D
.alias JSETMSG $FF90 .label JSETMSG = $FF90
.alias JSECOND $FF93 .label JSECOND = $FF93
.alias JTKSA $FF96 .label JTKSA = $FF96
.alias JMEMTOP $FF99 .label JMEMTOP = $FF99
.alias JMEMBOT $FF9C .label JMEMBOT = $FF9C
.alias JSCNKEY $FF9F .label JSCNKEY = $FF9F
.alias JSETTMO $FFA2 .label JSETTMO = $FFA2
.alias JACPTR $FFA5 .label JACPTR = $FFA5
.alias JCIOUT $FFA8 .label JCIOUT = $FFA8
.alias JUNTLK $FFAB .label JUNTLK = $FFAB
.alias JUNLSN $FFAE .label JUNLSN = $FFAE
.alias JLISTEN $FFB1 .label JLISTEN = $FFB1
.alias JTALK $FFB4 .label JTALK = $FFB4
.alias JREADST $FFB7 .label JREADST = $FFB7
.alias JSETFLS $FFBA .label JSETFLS = $FFBA
.alias JSETNAM $FFBD .label JSETNAM = $FFBD
.alias JOPEN $FFC0 .label JOPEN = $FFC0
.alias JCLOSE $FFC3 .label JCLOSE = $FFC3
.alias JCHKIN $FFC6 .label JCHKIN = $FFC6
.alias JCKOUT $FFC9 .label JCKOUT = $FFC9
.alias JCLRCHN $FFCC .label JCLRCHN = $FFCC
.alias JCHRIN $FFCF .label JCHRIN = $FFCF
.alias JCHROUT $FFD2 .label JCHROUT = $FFD2
.alias JLOAD $FFD5 .label JLOAD = $FFD5
.alias JSAVE $FFD8 .label JSAVE = $FFD8
.alias JSETTIM $FFDB .label JSETTIM = $FFDB
.alias JRDTIM $FFDE .label JRDTIM = $FFDE
.alias JSTOP $FFE1 .label JSTOP = $FFE1
.alias JGETIN $FFE4 .label JGETIN = $FFE4
.alias JCLALL $FFE7 .label JCLALL = $FFE7
.alias JUDTIM $FFEA .label JUDTIM = $FFEA
.alias JSCREEN $FFED .label JSCREEN = $FFED
.alias JPLOT $FFF0 .label JPLOT = $FFF0
.alias JIOBASE $FFF3 .label JIOBASE = $FFF3
+115 -113
View File
@@ -1,126 +1,128 @@
; Names of ZP and low memory locations // Names of ZP and low memory locations
; (Only those for now that we feel the need to implement initially) // (Only those for now that we feel the need to implement initially)
; (https://www.c64-wiki.com/wiki/Zeropage) // (https://www.c64-wiki.com/wiki/Zeropage)
.alias tokenise_work1 $7 // XXX get rid of this file, use ,aliases_ram_lowmem.s instead
.alias tokenise_work2 $8
.alias tokenise_work3 $B
.alias tokenise_work4 $F
.alias basic_line_number $14
.alias temp_string_ptr $35
.alias load_or_verify_or_tokenise_work5 $C
.alias basic_work22 $22
.alias basic_work23 $23
.alias basic_work24 $24
.alias basic_work25 $25
;; The various pointers that separate memory regions for BASIC storage .label tokenise_work1 = $7
;; We have multiple names for the ones that mark the boundary of regions. .label tokenise_work2 = $8
.alias basic_start_of_text_ptr $2b .label tokenise_work3 = $B
.alias basic_end_of_text_ptr $2d .label tokenise_work4 = $F
.alias basic_start_of_vars_ptr $2d .label basic_line_number = $14
.alias basic_end_of_vars_ptr $2f .label temp_string_ptr = $35
.alias basic_start_of_arrays_ptr $2f .label load_or_verify_or_tokenise_work5 = $C
.alias basic_end_of_arrays_ptr $31 .label basic_work22 = $22
.alias basic_start_of_free_space_ptr $31 .label basic_work23 = $23
.alias basic_start_of_strings_ptr $33 .label basic_work24 = $24
.alias basic_top_of_memory_ptr $37 .label basic_work25 = $25
.alias basic_current_line_number $39
.alias basic_previous_line_number $3b
.alias basic_current_line_ptr $3d
;; Note that the statement point is in the CHRGET/CHRGOT routine // The various pointers that separate memory regions for BASIC storage
;; in ZP RAM. (Compute's Mapping the 64, p25) // We have multiple names for the ones that mark the boundary of regions.
.alias basic_current_statement_ptr $7a .label basic_start_of_text_ptr = $2b
.label basic_end_of_text_ptr = $2d
.label basic_start_of_vars_ptr = $2d
.label basic_end_of_vars_ptr = $2f
.label basic_start_of_arrays_ptr = $2f
.label basic_end_of_arrays_ptr = $31
.label basic_start_of_free_space_ptr = $31
.label basic_start_of_strings_ptr = $33
.label basic_top_of_memory_ptr = $37
.label basic_current_line_number = $39
.label basic_previous_line_number = $3b
.label basic_current_line_ptr = $3d
.alias basic_numeric_work_area $57 ; $57 - $60 inclusive = 10 bytes // Note that the statement point is in the CHRGET/CHRGOT routine
// in ZP RAM. (Compute's Mapping the 64, p25)
.label basic_current_statement_ptr = $7a
;; Floating point accumulator 1 $61 - $68 .label basic_numeric_work_area = $57 // $57 - $60 inclusive = 10 bytes
.alias basic_fac1_exponent $61
.alias basic_fac1_mantissa $62 ; $62 - $65
.alias basic_fac1_sign $66
.alias basic_fac1_overflow $68
.alias basic_fac1_mantissa_lob $70
.alias basic_fac2_exponent $69 // Floating point accumulator 1 $61 - $68
.alias basic_fac2_mantissa $6A ; $6A - $6D .label basic_fac1_exponent = $61
.alias basic_fac2_sign $6E .label basic_fac1_mantissa = $62 // $62 - $65
.label basic_fac1_sign = $66
.label basic_fac1_overflow = $68
.label basic_fac1_mantissa_lob = $70
;; We also re-use FAC2 for memory move pointers, since .label basic_fac2_exponent = $69
;; we can't be doing calculations while moving memory .label basic_fac2_mantissa = $6A // $6A - $6D
.alias memmove_src $69 .label basic_fac2_sign = $6E
.alias memmove_dst $6b
.alias memmove_size $6d
.alias current_file_num $98 // We also re-use FAC2 for memory move pointers, since
.alias cassette_buffer_bytes_used $A6 // we can't be doing calculations while moving memory
.alias load_or_scroll_temp_pointer $AC .label memmove_src = $69
;; We also use the following for temp colour pointer when scrolling .label memmove_dst = $6b
.alias load_save_verify_end_address $AE .label memmove_size = $6d
.alias cassette_buffer_ptr $B2 .label current_file_num = $98
.alias current_logical_filenum $B8 .label cassette_buffer_bytes_used = $A6
.alias current_secondary_address $B9 .label load_or_scroll_temp_pointer = $AC
.alias current_device_number $BA // We also use the following for temp colour pointer when scrolling
.alias current_filename_ptr $BB .label load_save_verify_end_address = $AE
.alias load_save_start_ptr $C1
.alias load_save_end_ptr $C3
.alias last_key_matrix_position $C5
.alias keys_in_key_buffer $C6
.alias reverse_video_flag $C7
.alias end_of_input_line $C8
.alias start_of_keyboard_input $C9
.alias current_key_index_entry $CB
.alias cursor_blink_disable $CC
.alias cursor_blink_countdown $CD
.alias cursor_saved_character $CE
.alias cursor_is_visible $CF
.alias keyboard_input_ready $D0
.alias current_screen_line_ptr $D1
.alias current_screen_x $D3
.alias quote_mode_flag $D4
.alias logical_line_length $D5
.alias current_screen_y $D6
.alias last_printed_character_ascii $D7
.alias insert_mode $D8
; Bits 0 -3 = bits 8-11 of screen line address
; Bit 7 = line spans multiple physical lines
.alias screen_line_link_table $D9
.alias current_screen_line_colour_ptr $F3
.alias keyboard_decoding_table_ptr $F5
.alias rs232_rx_buffer_ptr $F7
.alias rs232_tx_buffer_ptr $F9
.alias basic_input_buffer BUF .label cassette_buffer_ptr = $B2
.label current_logical_filenum = $B8
.label current_secondary_address = $B9
.label current_device_number = $BA
.label current_filename_ptr = $BB
.label load_save_start_ptr = $C1
.label load_save_end_ptr = $C3
.label last_key_matrix_position = $C5
.label keys_in_key_buffer = $C6
.label reverse_video_flag = $C7
.label end_of_input_line = $C8
.label start_of_keyboard_input = $C9
.label current_key_index_entry = $CB
.label cursor_blink_disable = $CC
.label cursor_blink_countdown = $CD
.label cursor_saved_character = $CE
.label cursor_is_visible = $CF
.label keyboard_input_ready = $D0
.label current_screen_line_ptr = $D1
.label current_screen_x = $D3
.label quote_mode_flag = $D4
.label logical_line_length = $D5
.label current_screen_y = $D6
.label last_printed_character_ascii = $D7
.label insert_mode = $D8
// Bits 0 -3 = bits 8-11 of screen line address
// Bit 7 = line spans multiple physical lines
.label screen_line_link_table = $D9
.label current_screen_line_colour_ptr = $F3
.label keyboard_decoding_table_ptr = $F5
.label rs232_rx_buffer_ptr = $F7
.label rs232_tx_buffer_ptr = $F9
; "Compute's Mapping the 64" book .label basic_input_buffer = BUF
.alias keyboard_buffer $0277
.alias text_colour $0286 ; p55
.alias colour_under_cursor $0287 ; p56
.alias key_buffer_size $0289 ; p57
;; 0 = cursor keys, insert, delete and space repeat, but nothing else // "Compute's Mapping the 64" book
;; 128 = all keys repeat .label keyboard_buffer = $0277
;; 64 = no keys repeat .label text_colour = $0286 // p55
.alias key_repeat_flags $028A ; p58 .label colour_under_cursor = $0287 // p56
;; https://www.c64-wiki.com/wiki/Page_2 .label key_buffer_size = $0289 // p57
.alias key_repeat_counter $028B
.alias key_first_repeat_delay $028C
;; bit 0 = shift, 1 = Vendor Key, 2 = Control
.alias key_bucky_state $028D
.alias key_last_bucky_state $028E
.alias keyboard_decoding_ptr $028F
.alias enable_case_switch $0291
.alias screen_scroll_disable $0292
;; BASIC uses some extra bytes for memory access under ROMs located at $2A7 onwards // 0 = cursor keys, insert, delete and space repeat, but nothing else
;; IRQs are disabled when doing such accesses, and a default NMI handler only increments // 128 = all keys repeat
;; a counter, so that if an NMI occurs, it doesn't crash the machine, but can be captured. // 64 = no keys repeat
.alias missed_nmi_flag $2A7 .label key_repeat_flags = $028A // p58
.alias tiny_nmi_handler $2A8 // https://www.c64-wiki.com/wiki/Page_2
.alias shift_mem_up tiny_nmi_handler+shift_mem_up_routine-tiny_nmi_handler_routine .label key_repeat_counter = $028B
.alias shift_mem_down tiny_nmi_handler+shift_mem_down_routine-tiny_nmi_handler_routine .label key_first_repeat_delay = $028C
.alias peek_under_roms tiny_nmi_handler+peek_under_roms_routine-tiny_nmi_handler_routine // bit 0 = shift, 1 = Vendor Key, 2 = Control
.alias poke_under_roms tiny_nmi_handler+poke_under_roms_routine-tiny_nmi_handler_routine .label key_bucky_state = $028D
.alias memmap_allram tiny_nmi_handler+memmap_allram_routine-tiny_nmi_handler_routine .label key_last_bucky_state = $028E
.alias memmap_normal tiny_nmi_handler+memmap_normal_routine-tiny_nmi_handler_routine .label keyboard_decoding_ptr = $028F
.label enable_case_switch = $0291
.label screen_scroll_disable = $0292
// BASIC uses some extra bytes for memory access under ROMs located at $2A7 onwards
// IRQs are disabled when doing such accesses, and a default NMI handler only increments
// a counter, so that if an NMI occurs, it doesn't crash the machine, but can be captured.
.label missed_nmi_flag = $2A7
.label tiny_nmi_handler = $2A8
.label shift_mem_up = tiny_nmi_handler+shift_mem_up_routine-tiny_nmi_handler_routine
.label shift_mem_down = tiny_nmi_handler+shift_mem_down_routine-tiny_nmi_handler_routine
.label peek_under_roms = tiny_nmi_handler+peek_under_roms_routine-tiny_nmi_handler_routine
.label poke_under_roms = tiny_nmi_handler+poke_under_roms_routine-tiny_nmi_handler_routine
.label memmap_allram = tiny_nmi_handler+memmap_allram_routine-tiny_nmi_handler_routine
.label memmap_normal = tiny_nmi_handler+memmap_normal_routine-tiny_nmi_handler_routine
+5 -4
View File
@@ -1,9 +1,10 @@
;; Target-specific hooks // Target-specific hooks
.macro TARGET_HOOK_BANNER .macro TARGET_HOOK_BANNER() {
.byte " OPEN ROMS, ", $00 .text " OPEN ROMS, "
.byte $00
.macend }
+20 -20
View File
@@ -1,10 +1,10 @@
;; Target-specific hooks // Target-specific hooks
.macro TARGET_HOOK_BANNER .macro TARGET_HOOK_BANNER() {
;; New banner from Retrofan // New banner from Retrofan
.byte $9a, $12, $20, $20, $7f, $a9, $20, $20, $1f, $20, $9a, $20, $20, $20 .byte $9a, $12, $20, $20, $7f, $a9, $20, $20, $1f, $20, $9a, $20, $20, $20
.byte $20, $1f, $20, $9a, $a9, $20, $20, $20, $92, $a1, $1f, $12, $20, $9a, $a9, $20 .byte $20, $1f, $20, $9a, $a9, $20, $20, $20, $92, $a1, $1f, $12, $20, $9a, $a9, $20
.byte $20, $20, $7f, $1f, $20, $20, $9a, $a3, $a3, $a3, $a3, $a3, $a3, $a3, $1f, $20 .byte $20, $20, $7f, $1f, $20, $20, $9a, $a3, $a3, $a3, $a3, $a3, $a3, $a3, $1f, $20
@@ -21,21 +21,21 @@
.byte $20, $20, $1f, $20, $20, $96, $a3, $a3, $a3, $a3, $1f .byte $20, $20, $1f, $20, $20, $96, $a3, $a3, $a3, $a3, $1f
.byte $92, $0D, $0D, $05, $00 .byte $92, $0D, $0D, $05, $00
;; Original Deft-supplied banner // Original Deft-supplied banner
;; .byte $9A,$12,$A3,$A3,$A3,$A3,$A3,$A3,$DF,$9B,$92,$20,$05,$12,$A0,$A0 // .byte $9A,$12,$A3,$A3,$A3,$A3,$A3,$A3,$DF,$9B,$92,$20,$05,$12,$A0,$A0
;; .byte $DF,$9B,$92,$20,$05,$12,$A0,$A0,$DF,$9B,$92,$20,$05,$12,$A0,$A0 // .byte $DF,$9B,$92,$20,$05,$12,$A0,$A0,$DF,$9B,$92,$20,$05,$12,$A0,$A0
;; .byte $DF,$9B,$92,$20,$05,$12,$A0,$A0,$DF,$9A,$92,$20,$05,$20,$20,$20 // .byte $DF,$9B,$92,$20,$05,$12,$A0,$A0,$DF,$9A,$92,$20,$05,$20,$20,$20
;; .byte $4D,$20,$45,$20,$47,$20,$41,$0D,$99,$12,$A3,$A3,$A3,$A3,$A3,$A3 // .byte $4D,$20,$45,$20,$47,$20,$41,$0D,$99,$12,$A3,$A3,$A3,$A3,$A3,$A3
;; .byte $A3,$DF,$92,$7F,$12,$CD,$CD,$DF,$92,$7F,$12,$DF,$05,$92,$20,$20 // .byte $A3,$DF,$92,$7F,$12,$CD,$CD,$DF,$92,$7F,$12,$DF,$05,$92,$20,$20
;; .byte $99,$7F,$12,$DF,$05,$92,$20,$20,$99,$7F,$12,$DF,$92,$7F,$12,$DF // .byte $99,$7F,$12,$DF,$05,$92,$20,$20,$99,$7F,$12,$DF,$92,$7F,$12,$DF
;; .byte $05,$92,$20,$20,$99,$42,$20,$41,$20,$53,$20,$49,$20,$43,$0D,$9E // .byte $05,$92,$20,$20,$99,$42,$20,$41,$20,$53,$20,$49,$20,$43,$0D,$9E
;; .byte $12,$A3,$A3,$A3,$A3,$A3,$A3,$A3,$A3,$DF,$9B,$92,$7F,$12,$DF,$92 // .byte $12,$A3,$A3,$A3,$A3,$A3,$A3,$A3,$A3,$DF,$9B,$92,$7F,$12,$DF,$92
;; .byte $7F,$12,$DF,$92,$7F,$12,$CD,$05,$92,$20,$20,$9B,$7F,$12,$CD,$92 // .byte $7F,$12,$DF,$92,$7F,$12,$CD,$05,$92,$20,$20,$9B,$7F,$12,$CD,$92
;; .byte $7F,$12,$DF,$92,$7F,$12,$CD,$92,$7F,$12,$DF,$9A,$92,$20,$05,$20 // .byte $7F,$12,$DF,$92,$7F,$12,$CD,$92,$7F,$12,$DF,$9A,$92,$20,$05,$20
;; .byte $9A,$2D,$2D,$2D,$2D,$2D,$2D,$2D,$0D,$96,$12,$A3,$A3,$A3,$A3,$A3 // .byte $9A,$2D,$2D,$2D,$2D,$2D,$2D,$2D,$0D,$96,$12,$A3,$A3,$A3,$A3,$A3
;; .byte $A3,$A3,$A3,$A3,$DF,$9A,$92,$7F,$12,$DF,$92,$7F,$9B,$20,$9A,$7F // .byte $A3,$A3,$A3,$A3,$DF,$9A,$92,$7F,$12,$DF,$92,$7F,$9B,$20,$9A,$7F
;; .byte $12,$A0,$A0,$9B,$92,$20,$9A,$7F,$12,$A0,$A0,$9B,$92,$20,$9A,$7F // .byte $12,$A0,$A0,$9B,$92,$20,$9A,$7F,$12,$A0,$A0,$9B,$92,$20,$9A,$7F
;; .byte $12,$DF,$92,$7F,$9B,$20,$9A,$20,$9B,"0.2.0.0",$0D // .byte $12,$DF,$92,$7F,$9B,$20,$9A,$20,$9B,"0.2.0.0",$0D
;; .byte $0D,$05,$92,$00 // .byte $0D,$05,$92,$00
.macend }
@@ -1,9 +1,12 @@
;; Target-specific hooks // Target-specific hooks
.macro TARGET_HOOK_BANNER .macro TARGET_HOOK_BANNER() {
.byte " OPEN ROMS FOR ULTIMATE 64", $0D, $0D, " ", $00 .text " OPEN ROMS FOR ULTIMATE 64"
.byte $0D, $0D
.text " "
.byte $00
.macend }
+2 -1
View File
@@ -1,3 +1,4 @@
;; Compute's Mapping the C64 p88 // Compute's Mapping the C64 p88
.word basic_cold_start .word basic_cold_start
+2 -1
View File
@@ -1,2 +1,3 @@
;; Compute's Mapping the C64 p88 // Compute's Mapping the C64 p88
.word basic_warm_start .word basic_warm_start
+4 -4
View File
@@ -1,6 +1,6 @@
;; Compute's Mapping the 64, p89 // Compute's Mapping the 64, p89
;; 8 character name // 8 character name
;; MEGABAS2 = "MEGA BASIC 2" // MEGABAS2 = "MEGA BASIC 2"
.byte $4D,$45,$47,$41,$42,$41,$53,$32 .byte $4D,$45,$47,$41,$42,$41,$53,$32
+5 -6
View File
@@ -1,19 +1,19 @@
;; Print string at $YYAA // Print string at $YYAA
;; Compute's Mapping the 64 p101 // Compute's Mapping the 64 p101
print_string: print_string:
;; Setup pointer // Setup pointer
sty temp_string_ptr+1 sty temp_string_ptr+1
sta temp_string_ptr+0 sta temp_string_ptr+0
txa txa
pha pha
;; Get offset ready // Get offset ready
ldy #$00 ldy #$00
print_string_loop: print_string_loop:
;; Save Y in X, since X is preserved by chrout, but Y is not // Save Y in X, since X is preserved by chrout, but Y is not
tya tya
tax tax
@@ -28,7 +28,6 @@ print_string_loop:
iny iny
bne print_string_loop bne print_string_loop
print_string_end: print_string_end:
pla pla
+24 -25
View File
@@ -1,31 +1,31 @@
;; BASIC Cold start entry point // BASIC Cold start entry point
;; Compute's Mapping the 64 p211 // Compute's Mapping the 64 p211
basic_cold_start: basic_cold_start:
;; Setup BASIC vectors at $0300 // Setup BASIC vectors at $0300
;; Initialise interpretor // Initialise interpretor
;; Print start up message // Print start up message
;; Print coloured part of the message // Print coloured part of the message
;; ldy #>startup_message // ldy #>startup_message
;; lda #<startup_message // lda #<startup_message
;; jsr print_string // jsr print_string
jsr printf // XXX don't use printf, keep it for debug purposes only
jsr printf
; Used 217 bytes
startup_banner: startup_banner:
`TARGET_HOOK_BANNER TARGET_HOOK_BANNER()
;; Print PAL/NTSC // Print PAL/NTSC
ldx #30 ; NTSC ldx #30 // NTSC
lda PALNTSC lda PALNTSC
beq + beq !+
ldx #31 ; PAL ldx #31 // PAL
* !:
jsr print_packed_message jsr print_packed_message
;; Work out free bytes, and display // Work out free bytes, and display
jsr basic_do_new jsr basic_do_new
lda basic_top_of_memory_ptr+0 lda basic_top_of_memory_ptr+0
sec sec
@@ -39,22 +39,21 @@ startup_banner:
lda #$20 lda #$20
jsr JCHROUT jsr JCHROUT
;; Print the rest of the start up message // Print the rest of the start up message
ldx #34 ldx #34
jsr print_packed_message jsr print_packed_message
;; jump into warm start loop // jump into warm start loop
jmp basic_warm_start jmp basic_warm_start
startup_message: // XXX this is probably not needed anymore
startup_message: // Clear the screen
;; Clear the screen
.byte $93 .byte $93
;; Vertical bars in different colours // Vertical bars in different colours
.byte $1C,$B4 .byte $1C,$B4
.byte $9E,$B5 .byte $9E,$B5
.byte $1E,$A1 .byte $1E,$A1
;; <RVS><WHITE>MEGA<NORMAL>BASIC\r\r // <RVS><WHITE>MEGA<NORMAL>BASIC\r\r
.byte $12,$05,$4D,$45,$47,$41,$92 .byte $12,$05,$4D,$45,$47,$41,$92
.byte $42,$41,$53,$49,$43 .byte $42,$41,$53,$49,$43
.byte $20,$56,$32,$2e,$30,$2e,$30 .byte $20,$56,$32,$2e,$30,$2e,$30
+27 -26
View File
@@ -1,18 +1,19 @@
;; Delete the current BASIC line, which is assumed to have already // Delete the current BASIC line, which is assumed to have already
;; been found with basic_find_line. // been found with basic_find_line.
;; Really only consists of copying memory down. // Really only consists of copying memory down.
;; The only complication is that we have to do the copy with ROMs // The only complication is that we have to do the copy with ROMs
;; banked out. Oh, yes, and we have to update all the links in // banked out. Oh, yes, and we have to update all the links in
;; the following basic lines. // the following basic lines.
basic_delete_line: basic_delete_line:
;; jsr printf // jsr printf
;; .byte "DELETING LINE AT $" // .text "DELETING LINE AT $"
;; .byte $f1,<basic_current_line_ptr,>basic_current_line_ptr // .byte $f1,<basic_current_line_ptr,>basic_current_line_ptr
;; .byte $f0,<basic_current_line_ptr,>basic_current_line_ptr // .byte $f0,<basic_current_line_ptr,>basic_current_line_ptr
;; .byte $0d,0 // .byte $0d,0
;; Get address of next line // Get address of next line
ldx #<basic_current_line_ptr ldx #<basic_current_line_ptr
ldy #0 ldy #0
jsr peek_under_roms jsr peek_under_roms
@@ -21,7 +22,7 @@ basic_delete_line:
jsr peek_under_roms jsr peek_under_roms
sta tokenise_work4 sta tokenise_work4
;; Work out length of this line by looking at the pointer // Work out length of this line by looking at the pointer
lda tokenise_work3 lda tokenise_work3
sec sec
sbc basic_current_line_ptr+0 sbc basic_current_line_ptr+0
@@ -30,31 +31,31 @@ basic_delete_line:
sbc basic_current_line_ptr+1 sbc basic_current_line_ptr+1
sta tokenise_work4 sta tokenise_work4
;; jsr printf // jsr printf
;; .byte "LINE LENGTH IS $" // .text "LINE LENGTH IS $"
;; .byte $f0,<tokenise_work4,>tokenise_work4 // .byte $f0,<tokenise_work4,>tokenise_work4
;; .byte $f0,<tokenise_work3,>tokenise_work3 // .byte $f0,<tokenise_work3,>tokenise_work3
;; .byte $0d,0 // .byte $0d,0
lda tokenise_work4 lda tokenise_work4
sbc #0 sbc #0
cmp #$00 cmp #$00
beq + beq !+
;; Line length is <0 or >255 bytes. // Line length is <0 or >255 bytes.
;; Either way, things are bad, so abort. // Either way, things are bad, so abort.
jmp do_MEMORY_CORRUPT_error jmp do_MEMORY_CORRUPT_error
* !:
;; Length can now be safely assumed to be in the low // Length can now be safely assumed to be in the low
;; byte only, i.e., stored in tokenise_work3 // byte only, i.e., stored in tokenise_work3
lda tokenise_work3 lda tokenise_work3
pha pha
tax tax
;; Shuffle everything down // Shuffle everything down
jsr basic_shift_mem_down_and_relink jsr basic_shift_mem_down_and_relink
;; Now decrease top of BASIC mem // Now decrease top of BASIC mem
pla pla
sta tokenise_work3 sta tokenise_work3
lda basic_end_of_text_ptr+0 lda basic_end_of_text_ptr+0
+13 -16
View File
@@ -1,40 +1,37 @@
;; Compute's Mapping the 64 p93 // Compute's Mapping the 64 p93
basic_do_error: basic_do_error:
;; Save error number // Save error number
txa txa
pha pha
;; Print ? at start // Print ? at start
lda #$0d lda #$0D
jsr JCHROUT jsr JCHROUT
lda #$3f lda #$3F
jsr JCHROUT jsr JCHROUT
;; Print main part of error message // Print main part of error message
pla pla
tax tax
jsr print_packed_message jsr print_packed_message
;; Print ERROR at end // Print ERROR at end
lda #$20 lda #$20
jsr JCHROUT jsr JCHROUT
ldx #33 ldx #33
jsr print_packed_message jsr print_packed_message
;; XXX print IN if not in direct mode // XXX print IN if not in direct mode
;; XXX print line number if not in direct mode // XXX print line number if not in direct mode
lda #$0d lda #$0D
jsr JCHROUT jsr JCHROUT
lda #$0d lda #$0D // XXX do we need this?
jsr JCHROUT jsr JCHROUT
;; Reset stack, and go back to main loop // Reset stack, and go back to main loop
ldx #$fe ldx #$FE
txs txs
jmp basic_main_loop jmp basic_main_loop
+78 -79
View File
@@ -1,13 +1,13 @@
;; Jump back into the BASIC execute line loop // Jump back into the BASIC execute line loop
;; after first checking that we have a colon // after first checking that we have a colon
;; or $00 char // or $00 char
basic_end_of_statement_check: basic_end_of_statement_check:
ldx #<basic_current_statement_ptr ldx #<basic_current_statement_ptr
ldy #0 ldy #0
jsr peek_under_roms jsr peek_under_roms
;; Consume any spaces // Consume any spaces
cmp #$20 cmp #$20
bne no_space_to_skip bne no_space_to_skip
jsr basic_consume_character jsr basic_consume_character
@@ -15,62 +15,62 @@ basic_end_of_statement_check:
no_space_to_skip: no_space_to_skip:
cmp #$00 cmp #$00
beq + beq !+
cmp #$3a cmp #$3a
beq + beq !+
;; not end of statement // not end of statement
clc clc
rts rts
* !:
sec sec
rts rts
basic_execute_statement: basic_execute_statement:
;; Check for RUN/STOP // Check for RUN/STOP
lda STKEY lda STKEY
bmi + bmi !+
jmp basic_do_break jmp basic_do_break
* !:
;; Skip over any white space and : // Skip over any white space and :
ldy #0 ldy #0
ldx #<basic_current_statement_ptr ldx #<basic_current_statement_ptr
jsr peek_under_roms jsr peek_under_roms
jsr basic_end_of_statement_check jsr basic_end_of_statement_check
bcs basic_end_of_line bcs basic_end_of_line
;; jsr printf // jsr printf
;; .byte "LINE PTR = $" // .text "LINE PTR = $"
;; .byte $f1,<basic_current_line_ptr,>basic_current_line_ptr // .byte $f1,<basic_current_line_ptr,>basic_current_line_ptr
;; .byte $f0,<basic_current_line_ptr,>basic_current_line_ptr // .byte $f0,<basic_current_line_ptr,>basic_current_line_ptr
;; .byte ", STATEMENT PTR = $" // .text ", STATEMENT PTR = $"
;; .byte $f1,<basic_current_statement_ptr,>basic_current_statement_ptr // .byte $f1,<basic_current_statement_ptr,>basic_current_statement_ptr
;; .byte $f0,<basic_current_statement_ptr,>basic_current_statement_ptr // .byte $f0,<basic_current_statement_ptr,>basic_current_statement_ptr
;; .byte $d,0 // .byte $d,0
;; Go through the line until its end is reached. // Go through the line until its end is reached.
;; If we reach the end are in direct mode, then // If we reach the end are in direct mode, then
;; go back to reading input, else look for the // go back to reading input, else look for the
;; next line, and advance to that, or else // next line, and advance to that, or else
;; return to READY prompt because we have run out // return to READY prompt because we have run out
;; of program. // of program.
;; Get next char of program text, even if it is hiding under a ROM or the // Get next char of program text, even if it is hiding under a ROM or the
;; IO area. // IO area.
ldx #<basic_current_statement_ptr ldx #<basic_current_statement_ptr
ldy #0 ldy #0
jsr peek_under_roms jsr peek_under_roms
cmp #$00 cmp #$00
beq basic_end_of_line beq basic_end_of_line
;; The checks should be done in order of frequency, so that we are as // The checks should be done in order of frequency, so that we are as
;; fast as possible. // fast as possible.
cmp #$7f cmp #$7f
bcc not_a_token bcc not_a_token
;; It's a token: So get the jump table entry for it, push it on the stack // It's a token: So get the jump table entry for it, push it on the stack
;; and then RTS to start it. // and then RTS to start it.
asl asl
tax tax
lda basic_command_jump_table+1,x lda basic_command_jump_table+1,x
@@ -78,42 +78,42 @@ basic_execute_statement:
lda basic_command_jump_table+0,x lda basic_command_jump_table+0,x
pha pha
;; Now consume the character // Now consume the character
jsr basic_consume_character jsr basic_consume_character
rts rts
not_a_token: not_a_token:
;; Space, which we can also just ignore // Space, which we can also just ignore
cmp #$20 cmp #$20
beq basic_skip_char beq basic_skip_char
;; End of line? // End of line?
cmp #$00 cmp #$00
beq basic_end_of_line beq basic_end_of_line
;; :, i.e., statement separator, which we can simply ignore // :, i.e., statement separator, which we can simply ignore
cmp #$3a cmp #$3a
beq basic_skip_char beq basic_skip_char
;; START wedge support // START wedge support
;; Are we in direct mode? // Are we in direct mode?
;; DOS Wedge is a hacky solution (inelegant, but convenient), // DOS Wedge is a hacky solution (inelegant, but convenient),
;; BASIC programmers should implement communication with drives // BASIC programmers should implement communication with drives
;; the standard way, handling channels properly. Besides, // the standard way, handling channels properly. Besides,
;; current implementation does not support characters under ROM // current implementation does not support characters under ROM
ldx basic_current_line_number+1 ldx basic_current_line_number+1
cpx #$ff cpx #$ff
bne + bne !+
;; We are in direct mode, allow wedge to handle '@' sign // We are in direct mode, allow wedge to handle '@' sign
;; XXX Maybe it should be allowed only as the first command? // XXX Maybe it should be allowed only as the first command?
cmp #$40 cmp #$40
bne + bne !+
jsr basic_consume_character jsr basic_consume_character
jmp wedge_dos jmp wedge_dos
* !:
;; END wedge support // END wedge support
;; If all else fails, it's a syntax error // If all else fails, it's a syntax error
jmp do_SYNTAX_error jmp do_SYNTAX_error
basic_skip_char: basic_skip_char:
@@ -124,14 +124,14 @@ basic_fetch_and_consume_character:
ldy #0 ldy #0
ldx #<basic_current_statement_ptr ldx #<basic_current_statement_ptr
jsr peek_under_roms jsr peek_under_roms
;; FALL THROUGH // FALL THROUGH
basic_consume_character: basic_consume_character:
;; Advance basic text pointer // Advance basic text pointer
inc basic_current_statement_ptr+0 inc basic_current_statement_ptr+0
bne + bne !+
inc basic_current_statement_ptr+1 inc basic_current_statement_ptr+1
* !:
rts rts
basic_unconsume_character: basic_unconsume_character:
@@ -146,46 +146,46 @@ basic_unconsume_character:
basic_end_of_line: basic_end_of_line:
;; XXX - If not in direct mode, then advance to next line, if there is // XXX - If not in direct mode, then advance to next line, if there is
;; one. // one.
;; Are we in direct mode // Are we in direct mode
lda basic_current_line_number+1 lda basic_current_line_number+1
cmp #$ff cmp #$ff
bne basic_not_direct_mode bne basic_not_direct_mode
;; Yes, we were in direct mode, so stop now // Yes, we were in direct mode, so stop now
jmp basic_main_loop jmp basic_main_loop
basic_not_direct_mode: basic_not_direct_mode:
;; Copy line number to previous line number // Copy line number to previous line number
lda basic_current_line_number+0 lda basic_current_line_number+0
sta basic_previous_line_number+0 sta basic_previous_line_number+0
lda basic_current_line_number+1 lda basic_current_line_number+1
sta basic_previous_line_number+1 sta basic_previous_line_number+1
;; Advance the basic line pointer to the next line // Advance the basic line pointer to the next line
jsr basic_follow_link_to_next_line jsr basic_follow_link_to_next_line
;; Are we at the end of the program? // Are we at the end of the program?
lda basic_current_line_ptr+0 lda basic_current_line_ptr+0
ora basic_current_line_ptr+1 ora basic_current_line_ptr+1
bne basic_execute_from_current_line bne basic_execute_from_current_line
;; End of program found // End of program found
jmp basic_main_loop jmp basic_main_loop
basic_execute_from_current_line: basic_execute_from_current_line:
;; Check if pointer is null, if so, we are at the end of // Check if pointer is null, if so, we are at the end of
;; the program. // the program.
ldy #0 ldy #0
ldx #<basic_current_line_ptr ldx #<basic_current_line_ptr
jsr peek_pointer_null_check jsr peek_pointer_null_check
bcs + bcs !+
;; End of program reached // End of program reached
jmp basic_main_loop jmp basic_main_loop
* !:
;; Skip pointer and line number to get address of first statement // Skip pointer and line number to get address of first statement
lda basic_current_line_ptr+0 lda basic_current_line_ptr+0
clc clc
adc #4 adc #4
@@ -194,7 +194,7 @@ basic_execute_from_current_line:
adc #0 adc #0
sta basic_current_statement_ptr+1 sta basic_current_statement_ptr+1
;; Store line number // Store line number
ldx #<basic_current_line_ptr ldx #<basic_current_line_ptr
ldy #2 ldy #2
jsr peek_under_roms jsr peek_under_roms
@@ -206,7 +206,7 @@ basic_execute_from_current_line:
jmp basic_execute_statement jmp basic_execute_statement
basic_command_jump_table: basic_command_jump_table:
;; $80 - $8F // $80 - $8F
.word cmd_end-1 .word cmd_end-1
.word cmd_for-1 .word cmd_for-1
.word cmd_next-1 .word cmd_next-1
@@ -221,10 +221,10 @@ basic_command_jump_table:
.word cmd_if-1 .word cmd_if-1
.word cmd_restore-1 .word cmd_restore-1
.word cmd_gosub-1 .word cmd_gosub-1
.word cmd_return -1 .word cmd_return-1
.word cmd_rem-1 .word cmd_rem-1
;; $90-$9F // $90-$9F
.word cmd_stop-1 .word cmd_stop-1
.word cmd_on-1 .word cmd_on-1
.word cmd_wait-1 .word cmd_wait-1
@@ -242,7 +242,7 @@ basic_command_jump_table:
.word cmd_sys-1 .word cmd_sys-1
.word cmd_open-1 .word cmd_open-1
;; $A0-$AF // $A0-$AF
.word cmd_close-1 .word cmd_close-1
.word cmd_get-1 .word cmd_get-1
.word cmd_new-1 .word cmd_new-1
@@ -260,7 +260,7 @@ basic_command_jump_table:
.word cmd_exponent-1 .word cmd_exponent-1
.word cmd_and-1 .word cmd_and-1
;; $B0-$BF // $B0-$BF
.word cmd_or-1 .word cmd_or-1
.word cmd_greater-1 .word cmd_greater-1
.word cmd_equal-1 .word cmd_equal-1
@@ -278,7 +278,7 @@ basic_command_jump_table:
.word cmd_cos-1 .word cmd_cos-1
.word cmd_sin-1 .word cmd_sin-1
;; $C0-$CF // $C0-$CF
.word cmd_tan-1 .word cmd_tan-1
.word cmd_atn-1 .word cmd_atn-1
.word cmd_peek-1 .word cmd_peek-1
@@ -291,13 +291,13 @@ basic_command_jump_table:
.word cmd_right-1 .word cmd_right-1
.word cmd_mid-1 .word cmd_mid-1
.word cmd_go-1 .word cmd_go-1
;; Undefined tokens // Undefined tokens
.word cmd_unimplemented-1 .word cmd_unimplemented-1
.word cmd_unimplemented-1 .word cmd_unimplemented-1
.word cmd_unimplemented-1 .word cmd_unimplemented-1
.word cmd_unimplemented-1 .word cmd_unimplemented-1
;; $D0-$DF // $D0-$DF
.word cmd_unimplemented-1 .word cmd_unimplemented-1
.word cmd_unimplemented-1 .word cmd_unimplemented-1
.word cmd_unimplemented-1 .word cmd_unimplemented-1
@@ -315,7 +315,7 @@ basic_command_jump_table:
.word cmd_unimplemented-1 .word cmd_unimplemented-1
.word cmd_unimplemented-1 .word cmd_unimplemented-1
;; $E0-$EF // $E0-$EF
.word cmd_unimplemented-1 .word cmd_unimplemented-1
.word cmd_unimplemented-1 .word cmd_unimplemented-1
.word cmd_unimplemented-1 .word cmd_unimplemented-1
@@ -333,7 +333,7 @@ basic_command_jump_table:
.word cmd_unimplemented-1 .word cmd_unimplemented-1
.word cmd_unimplemented-1 .word cmd_unimplemented-1
;; $F0-$FF // $F0-$FF
.word cmd_unimplemented-1 .word cmd_unimplemented-1
.word cmd_unimplemented-1 .word cmd_unimplemented-1
.word cmd_unimplemented-1 .word cmd_unimplemented-1
@@ -350,4 +350,3 @@ basic_command_jump_table:
.word cmd_unimplemented-1 .word cmd_unimplemented-1
.word cmd_unimplemented-1 .word cmd_unimplemented-1
.word cmd_unimplemented-1 .word cmd_unimplemented-1
+13 -13
View File
@@ -1,50 +1,50 @@
;; Find the BASIC line with number basic_line_number // Find the BASIC line with number basic_line_number
basic_find_line: basic_find_line:
;; Get pointer to start of BASIC text // Get pointer to start of BASIC text
lda basic_start_of_text_ptr+0 lda basic_start_of_text_ptr+0
sta basic_current_line_ptr+0 sta basic_current_line_ptr+0
lda basic_start_of_text_ptr+1 lda basic_start_of_text_ptr+1
sta basic_current_line_ptr+1 sta basic_current_line_ptr+1
basic_find_line_loop: basic_find_line_loop:
;; Then search for line number // Then search for line number
;; Line number // Line number
ldy #3 ldy #3
ldx #<basic_current_line_ptr ldx #<basic_current_line_ptr
jsr peek_under_roms jsr peek_under_roms
cmp basic_line_number+1 cmp basic_line_number+1
beq + beq !+
bcs line_num_too_high bcs line_num_too_high
bne not_this_line bne not_this_line
* !:
dey dey
jsr peek_under_roms jsr peek_under_roms
cmp basic_line_number+0 cmp basic_line_number+0
beq + beq !+
bcs line_num_too_high bcs line_num_too_high
bne not_this_line bne not_this_line
* !:
clc clc
rts rts
not_this_line: not_this_line:
;; Not this line, so advance to next line // Not this line, so advance to next line
ldx #<basic_current_line_ptr ldx #<basic_current_line_ptr
jsr peek_pointer_null_check jsr peek_pointer_null_check
bcs more_lines_exist bcs more_lines_exist
;; no more lines exist, return failure // no more lines exist, return failure
line_num_too_high: line_num_too_high:
sec sec
rts rts
more_lines_exist: more_lines_exist:
;; XXX - Add program mangled check here to be triggered // XXX - Add program mangled check here to be triggered
;; if the link goes backwards. // if the link goes backwards.
;; Follow link to next line // Follow link to next line
ldy #0 ldy #0
ldx #<basic_current_line_ptr ldx #<basic_current_line_ptr
jsr peek_under_roms jsr peek_under_roms
+2 -2
View File
@@ -1,5 +1,5 @@
;; Advance basic_current_line_ptr by following the // Advance basic_current_line_ptr by following the
;; link to the next line // link to the next line
basic_find_next_line: basic_find_next_line:
+26 -25
View File
@@ -1,25 +1,26 @@
;; Insert the tokenised line stored at $0200. // Insert the tokenised line stored at $0200.
;; First work out where in the list to put it // First work out where in the list to put it
;; (basic_find_line with the line number can be used to work // (basic_find_line with the line number can be used to work
;; out the insertion point, as it should abort once it finds a // out the insertion point, as it should abort once it finds a
;; line number too high). // line number too high).
;; Then all we have to do is push the rest of the BASIC text up, // Then all we have to do is push the rest of the BASIC text up,
;; and update the pointers in all following basic lines. // and update the pointers in all following basic lines.
basic_insert_line: basic_insert_line:
;; ASSUMES basic_find_line has been called to set the insert point. // ASSUMES basic_find_line has been called to set the insert point.
;; We need to insert space for the link link token, the line number, // We need to insert space for the link link token, the line number,
;; and the zero-terminated line itself. This means 2+2+1 plus length // and the zero-terminated line itself. This means 2+2+1 plus length
;; of tokenised string after the line number // of tokenised string after the line number
;; But first, remember where the pointer will be, so that we can // But first, remember where the pointer will be, so that we can
;; put the line in there after. // put the line in there after.
;; jsr printf // jsr printf
;; .byte "INSERTING LINE AT $" // .text "INSERTING LINE AT $"
;; .byte $f1,<basic_current_line_ptr,>basic_current_line_ptr // .byte $f1,<basic_current_line_ptr,>basic_current_line_ptr
;; .byte $f0,<basic_current_line_ptr,>basic_current_line_ptr // .byte $f0,<basic_current_line_ptr,>basic_current_line_ptr
;; .byte $0d,0 // .byte $0d,0
lda basic_current_line_ptr+0 lda basic_current_line_ptr+0
pha pha
@@ -27,20 +28,20 @@ basic_insert_line:
pha pha
;; Get number of bytes in tokenised line after line number // Get number of bytes in tokenised line after line number
lda tokenise_work2 lda tokenise_work2
sec sec
sbc tokenise_work1 sbc tokenise_work1
;; Add on the four bytes space we need // Add on the four bytes space we need
clc clc
adc #5 adc #5
pha pha
tax tax
;; Make the space // Make the space
jsr basic_shift_mem_up_and_relink jsr basic_shift_mem_up_and_relink
;; Now increase top of BASIC mem // Now increase top of BASIC mem
pla pla
clc clc
adc basic_end_of_text_ptr+0 adc basic_end_of_text_ptr+0
@@ -49,13 +50,13 @@ basic_insert_line:
adc #0 adc #0
sta basic_end_of_text_ptr+1 sta basic_end_of_text_ptr+1
;; Get pointer back // Get pointer back
pla pla
sta basic_current_line_ptr+1 sta basic_current_line_ptr+1
pla pla
sta basic_current_line_ptr+0 sta basic_current_line_ptr+0
;; Write the line number // Write the line number
ldy #2 ldy #2
ldx #<basic_current_line_ptr ldx #<basic_current_line_ptr
lda basic_line_number+0 lda basic_line_number+0
@@ -64,7 +65,7 @@ basic_insert_line:
lda basic_line_number+1 lda basic_line_number+1
jsr poke_under_roms jsr poke_under_roms
;; Now store the line body itself // Now store the line body itself
inc tokenise_work2 inc tokenise_work2
line_store_loop: line_store_loop:
ldx tokenise_work1 ldx tokenise_work1
+50 -51
View File
@@ -1,43 +1,43 @@
basic_main_loop: basic_main_loop:
;; XXX - Check if direct or program mode, and get next line of input // XXX - Check if direct or program mode, and get next line of input
;; the appropriate way. // the appropriate way.
;; XXX - For now, it is hard coded to direct mode // XXX - For now, it is hard coded to direct mode
;; Tell user we are ready // Tell user we are ready
jsr ready_message jsr ready_message
basic_read_next_line: basic_read_next_line:
;; Read a line of input // Read a line of input
ldx #$00 ldx #$00
read_line_loop: read_line_loop:
jsr $ffcf ; KERNAL CHRIN jsr JCHRIN
bcs read_line_loop bcs read_line_loop
cmp #$0d cmp #$0d
beq got_line_of_input beq got_line_of_input
;; Not carriage return, so try to append to line so far // Not carriage return, so try to append to line so far
cpx #80 cpx #80
bcc + bcc !+
;; Report STRING TOO LONG error (Compute's Mapping the 64 p93) // Report STRING TOO LONG error (Compute's Mapping the 64 p93)
ldx #22 ldx #22
jmp basic_do_error jmp basic_do_error
* !:
sta basic_input_buffer,x sta basic_input_buffer,x
inx inx
jmp read_line_loop jmp read_line_loop
got_line_of_input: got_line_of_input:
;; Store length of input buffer ready for tokenising // Store length of input buffer ready for tokenising
stx tokenise_work1 stx tokenise_work1
;; Strip leading spaces from the line // Strip leading spaces from the line
remove_leading_spaces: remove_leading_spaces:
lda $0200 lda $0200
cmp #$20 cmp #$20
bne + bne !+
ldx #1 ldx #1
rsl_l1: lda $0200,x rsl_l1: lda $0200,x
sta $01ff,x sta $01ff,x
@@ -45,40 +45,40 @@ rsl_l1: lda $0200,x
cpx tokenise_work1 cpx tokenise_work1
bne rsl_l1 bne rsl_l1
;; Reduce length of input by one // Reduce length of input by one
dec tokenise_work1 dec tokenise_work1
;; Stop trying to rim if we run out of input // Stop trying to rim if we run out of input
bne remove_leading_spaces bne remove_leading_spaces
* !:
;; Do printing of the new line // Do printing of the new line
lda #$0d lda #$0d
jsr JCHROUT jsr JCHROUT
;; Ignore empty lines // Ignore empty lines
lda tokenise_work1 lda tokenise_work1
beq basic_read_next_line beq basic_read_next_line
;; Else, tokenise the line // Else, tokenise the line
jsr tokenise_line jsr tokenise_line
;; Has the user entered a line of BASIC beginning with a number? // Has the user entered a line of BASIC beginning with a number?
lda $0200 lda $0200
cmp #$30 cmp #$30
bcc not_a_line bcc not_a_line
cmp #$39 cmp #$39
bcs not_a_line bcs not_a_line
;; Yes, the line begins with a number. // Yes, the line begins with a number.
;; Parse the line number and check validity // Parse the line number and check validity
;; injest_number follows tokenise_work1 as the offset into the line, // injest_number follows tokenise_work1 as the offset into the line,
;; so remember the line length somewhere else for now. // so remember the line length somewhere else for now.
lda tokenise_work1 lda tokenise_work1
sta tokenise_work2 sta tokenise_work2
lda #$00 lda #$00
sta tokenise_work1 sta tokenise_work1
;; Try to read line number // Try to read line number
lda #<$0200 lda #<$0200
sta basic_current_statement_ptr+0 sta basic_current_statement_ptr+0
lda #>$0200 lda #>$0200
@@ -86,67 +86,66 @@ rsl_l1: lda $0200,x
jsr basic_parse_line_number jsr basic_parse_line_number
;; Get pointer to next char // Get pointer to next char
lda basic_current_statement_ptr+0 lda basic_current_statement_ptr+0
sta tokenise_work1 sta tokenise_work1
;; Got a valid line number -- so do add/del line // Got a valid line number -- so do add/del line
;; Skip any spaces after the line number // Skip any spaces after the line number
ldx tokenise_work1 ldx tokenise_work1
skip_spaces: skip_spaces:
lda $0200,x lda $0200,x
cmp #$20 cmp #$20
bne + bne !+
inx inx
bne skip_spaces bne skip_spaces
* stx tokenise_work1 !: stx tokenise_work1
;; First, clear all variables, so that we only have to shove BASIC text around. // First, clear all variables, so that we only have to shove BASIC text around.
;; (We could later remove this requirement, and the only effect should be // (We could later remove this requirement, and the only effect should be
;; to slow things down, and that you might have to either CLR if there is no // to slow things down, and that you might have to either CLR if there is no
;; memory free, or else it would auto CLR when you ran out of program space). // memory free, or else it would auto CLR when you ran out of program space).
jsr basic_do_clr jsr basic_do_clr
;; Delete line if present // Delete line if present
jsr basic_find_line jsr basic_find_line
bcs + bcs !+
;; Delete the line, whether we are deleting or // Delete the line, whether we are deleting or
;; replacing the line // replacing the line
jsr basic_delete_line jsr basic_delete_line
* !:
;; Insert new line if non-zero length, i.e., that // Insert new line if non-zero length, i.e., that
;; we are not just deleting the line. // we are not just deleting the line.
lda tokenise_work1 lda tokenise_work1
cmp tokenise_work2 cmp tokenise_work2
beq + beq !+
jsr basic_insert_line jsr basic_insert_line
* !:
;; No READY message after entering or deleting a line of BASIC // No READY message after entering or deleting a line of BASIC
jmp basic_read_next_line jmp basic_read_next_line
not_a_line: not_a_line:
;; Actually interpret the line // Actually interpret the line
;; Setup pointer to the statement // Setup pointer to the statement
lda #<$0200 lda #<$0200
sta basic_current_statement_ptr+0 sta basic_current_statement_ptr+0
lda #>$0200 lda #>$0200
sta basic_current_statement_ptr+1 sta basic_current_statement_ptr+1
;; There is no stored line, so zero that pointer out // There is no stored line, so zero that pointer out
lda #$00 lda #$00
sta basic_current_line_ptr+0 sta basic_current_line_ptr+0
sta basic_current_line_ptr+1 sta basic_current_line_ptr+1
;; Put invalid line number in current line number value, // Put invalid line number in current line number value,
;; so that we know we are in direct mode // so that we know we are in direct mode
;; (Compute's Mapping the 64 p19) // (Compute's Mapping the 64 p19)
lda #$ff lda #$ff
sta basic_current_line_number+1 sta basic_current_line_number+1
jmp basic_execute_statement jmp basic_execute_statement
+8 -8
View File
@@ -3,22 +3,22 @@ basic_parse_line_number:
jsr injest_number jsr injest_number
;; Check if the number is a valid line number // Check if the number is a valid line number
;; i.e., 16 bits, no exponent, no decimal // i.e., 16 bits, no exponent, no decimal
lda basic_fac1_mantissa+2 lda basic_fac1_mantissa+2
ora basic_fac1_mantissa+3 ora basic_fac1_mantissa+3
ora basic_fac1_exponent ora basic_fac1_exponent
beq + beq !+
ml_bad_line_number: ml_bad_line_number:
;; Invalid line number // Invalid line number
jmp do_ILLEGAL_QUANTITY_error jmp do_ILLEGAL_QUANTITY_error
* !:
;; Line number are not allowed to have decimal points in them // Line number are not allowed to have decimal points in them
lda tokenise_work4 lda tokenise_work4
cmp #$ff cmp #$FF
bne ml_bad_line_number bne ml_bad_line_number
;; Got a valid line number. // Got a valid line number.
lda basic_fac1_mantissa+0 lda basic_fac1_mantissa+0
sta basic_line_number+0 sta basic_line_number+0
lda basic_fac1_mantissa+1 lda basic_fac1_mantissa+1
+52 -52
View File
@@ -1,16 +1,16 @@
basic_shift_mem_down_and_relink: basic_shift_mem_down_and_relink:
;; Shift memory down to basic_current_line_pointer // Shift memory down to basic_current_line_pointer
;; from X bytes further along. // from X bytes further along.
;; Destination is basic_current_line_ptr // Destination is basic_current_line_ptr
lda basic_current_line_ptr+0 lda basic_current_line_ptr+0
sta memmove_dst+0 sta memmove_dst+0
lda basic_current_line_ptr+1 lda basic_current_line_ptr+1
sta memmove_dst+1 sta memmove_dst+1
;; Source is that plus X // Source is that plus X
txa txa
pha ; also keep for later pha // also keep for later
clc clc
adc basic_current_line_ptr+0 adc basic_current_line_ptr+0
sta memmove_src+0 sta memmove_src+0
@@ -18,7 +18,7 @@ basic_shift_mem_down_and_relink:
adc #0 adc #0
sta memmove_src+1 sta memmove_src+1
;; Size is distance from source to end of BASIC text. // Size is distance from source to end of BASIC text.
lda basic_end_of_text_ptr+0 lda basic_end_of_text_ptr+0
sec sec
sbc memmove_src+0 sbc memmove_src+0
@@ -27,32 +27,32 @@ basic_shift_mem_down_and_relink:
sbc memmove_src+1 sbc memmove_src+1
sta memmove_size+1 sta memmove_size+1
;; jsr printf // jsr printf
;; .byte "TOP OF BASIC = $" // .text "TOP OF BASIC = $"
;; .byte $f1,<basic_end_of_text_ptr,>basic_end_of_text_ptr // .byte $f1,<basic_end_of_text_ptr,>basic_end_of_text_ptr
;; .byte $f0,<basic_end_of_text_ptr,>basic_end_of_text_ptr // .byte $f0,<basic_end_of_text_ptr,>basic_end_of_text_ptr
;; .byte $0d // .byte $0d
;; .byte "SHIFTING DOWN $" // .text "SHIFTING DOWN $"
;; .byte $f1,<memmove_size,>memmove_size // .byte $f1,<memmove_size,>memmove_size
;; .byte $f0,<memmove_size,>memmove_size // .byte $f0,<memmove_size,>memmove_size
;; .byte " BYTES FROM $" // .text " BYTES FROM $"
;; .byte $f1,<memmove_src,>memmove_src // .byte $f1,<memmove_src,>memmove_src
;; .byte $f0,<memmove_src,>memmove_src // .byte $f0,<memmove_src,>memmove_src
;; .byte " TO $" // .text " TO $"
;; .byte $f1,<memmove_dst,>memmove_dst // .byte $f1,<memmove_dst,>memmove_dst
;; .byte $f0,<memmove_dst,>memmove_dst // .byte $f0,<memmove_dst,>memmove_dst
;; .byte $0d,0 // .byte $0d,0
;; The copy routine that copies under the ROMs is as simple // The copy routine that copies under the ROMs is as simple
;; as possible to be as small as possible, so we have // as possible to be as small as possible, so we have
;; to adjust the pointers and counts so that the simple // to adjust the pointers and counts so that the simple
;; increment and decrement bounds checks work. // increment and decrement bounds checks work.
;; Specifically we want Y pre-set so that the end of the // Specifically we want Y pre-set so that the end of the
;; copy ends when Y = $00. // copy ends when Y = $00.
;; So if copying 1 byte, we want Y=$FF // So if copying 1 byte, we want Y=$FF
;; This means we have to then reduce the source and // This means we have to then reduce the source and
;; target pointers by the same amount // target pointers by the same amount
lda memmove_size+0 lda memmove_size+0
eor #$ff eor #$ff
@@ -75,50 +75,50 @@ basic_shift_mem_down_and_relink:
sbc #0 sbc #0
sta memmove_dst+1 sta memmove_dst+1
;; Increase copy page count so we can post-decrement compare with $00 // Increase copy page count so we can post-decrement compare with $00
inc memmove_size+1 inc memmove_size+1
;; jsr printf // jsr printf
;; .byte "REVISED BOUNDS $" // .text "REVISED BOUNDS $"
;; .byte $f1,<memmove_size,>memmove_size // .byte $f1,<memmove_size,>memmove_size
;; .byte $f0,<memmove_size,>memmove_size // .byte $f0,<memmove_size,>memmove_size
;; .byte " BYTES FROM $" // .text " BYTES FROM $"
;; .byte $f1,<memmove_src,>memmove_src // .byte $f1,<memmove_src,>memmove_src
;; .byte $f0,<memmove_src,>memmove_src // .byte $f0,<memmove_src,>memmove_src
;; .byte " TO $" // .text " TO $"
;; .byte $f1,<memmove_dst,>memmove_dst // .byte $f1,<memmove_dst,>memmove_dst
;; .byte $f0,<memmove_dst,>memmove_dst // .byte $f0,<memmove_dst,>memmove_dst
;; .byte $0d,0 // .byte $0d,0
;; Get Y value ready for the copy // Get Y value ready for the copy
ldy memmove_size+0 ldy memmove_size+0
jsr shift_mem_down jsr shift_mem_down
;; Get length of deletion back // Get length of deletion back
pla pla
sta tokenise_work3 sta tokenise_work3
;; Check if we still have any lines left // Check if we still have any lines left
ldy #0 ldy #0
ldx #<basic_current_line_ptr ldx #<basic_current_line_ptr
jsr peek_pointer_null_check jsr peek_pointer_null_check
bcs relink_down_next_line bcs relink_down_next_line
;; Nope, so just return // Nope, so just return
clc clc
rts rts
relink_down_next_line: relink_down_next_line:
;; inc $d020 // inc $d020
;; jmp relink_down_next_line // jmp relink_down_next_line
;; Subtract tokenise_work3 from the pointer // Subtract tokenise_work3 from the pointer
ldy #0 ldy #0
ldx #<basic_current_line_ptr+0 ldx #<basic_current_line_ptr+0
jsr peek_under_roms jsr peek_under_roms
sec sec
sbc tokenise_Work3 sbc tokenise_work3
sta memmove_src+0 sta memmove_src+0
iny iny
jsr peek_under_roms jsr peek_under_roms
@@ -134,13 +134,13 @@ relink_down_next_line:
jsr poke_under_roms jsr poke_under_roms
relink_down_loop: relink_down_loop:
;; Now advance pointer to the next line, // Now advance pointer to the next line,
lda memmove_src+0 lda memmove_src+0
sta basic_current_line_ptr+0 sta basic_current_line_ptr+0
lda memmove_src+1 lda memmove_src+1
sta basic_current_line_ptr+1 sta basic_current_line_ptr+1
;; Have we run out of lines to patch? // Have we run out of lines to patch?
ldx #<basic_current_line_ptr ldx #<basic_current_line_ptr
jsr peek_pointer_null_check jsr peek_pointer_null_check
bcs relink_down_next_line bcs relink_down_next_line
+61 -61
View File
@@ -1,12 +1,12 @@
basic_shift_mem_up_and_relink: basic_shift_mem_up_and_relink:
;; Shift memory up from basic_current_line_ptr // Shift memory up from basic_current_line_ptr
;; X bytes. // X bytes.
;; NOTE: Pointers need to be reduced by one, due to the way // NOTE: Pointers need to be reduced by one, due to the way
;; the copyroutine works, so we do that here. // the copyroutine works, so we do that here.
;; Work out end point of destination // Work out end point of destination
txa txa
clc clc
adc basic_end_of_text_ptr+0 adc basic_end_of_text_ptr+0
@@ -22,7 +22,7 @@ basic_shift_mem_up_and_relink:
sbc #0 sbc #0
sta memmove_dst+1 sta memmove_dst+1
;; End point of source is just current end of BASIC text // End point of source is just current end of BASIC text
lda basic_end_of_text_ptr+0 lda basic_end_of_text_ptr+0
sec sec
sbc #1 sbc #1
@@ -31,7 +31,7 @@ basic_shift_mem_up_and_relink:
sbc #0 sbc #0
sta memmove_src+1 sta memmove_src+1
;; Work out size of region to copy // Work out size of region to copy
lda basic_end_of_text_ptr+0 lda basic_end_of_text_ptr+0
sec sec
sbc basic_current_line_ptr+0 sbc basic_current_line_ptr+0
@@ -40,25 +40,25 @@ basic_shift_mem_up_and_relink:
sbc basic_current_line_ptr+1 sbc basic_current_line_ptr+1
sta memmove_size+1 sta memmove_size+1
;; jsr printf // jsr printf
;; .byte "TOP OF BASIC = $" // .text "TOP OF BASIC = $"
;; .byte $f1,<basic_end_of_text_ptr,>basic_end_of_text_ptr // .byte $f1,<basic_end_of_text_ptr,>basic_end_of_text_ptr
;; .byte $f0,<basic_end_of_text_ptr,>basic_end_of_text_ptr // .byte $f0,<basic_end_of_text_ptr,>basic_end_of_text_ptr
;; .byte $0d // .byte $0d
;; .byte "SHIFTING UP $" // .text "SHIFTING UP $"
;; .byte $f1,<memmove_size,>memmove_size // .byte $f1,<memmove_size,>memmove_size
;; .byte $f0,<memmove_size,>memmove_size // .byte $f0,<memmove_size,>memmove_size
;; .byte " BYTES FROM $" // .text " BYTES FROM $"
;; .byte $f1,<memmove_src,>memmove_src // .byte $f1,<memmove_src,>memmove_src
;; .byte $f0,<memmove_src,>memmove_src // .byte $f0,<memmove_src,>memmove_src
;; .byte " TO $" // .text " TO $"
;; .byte $f1,<memmove_dst,>memmove_dst // .byte $f1,<memmove_dst,>memmove_dst
;; .byte $f0,<memmove_dst,>memmove_dst // .byte $f0,<memmove_dst,>memmove_dst
;; .byte $0d,0 // .byte $0d,0
;; To make life simple for the copy routine that lives in RAM, // To make life simple for the copy routine that lives in RAM,
;; we have to adjust the end pointers down one page and set Y to the low // we have to adjust the end pointers down one page and set Y to the low
;; byte of the copy size. // byte of the copy size.
lda memmove_src+0 lda memmove_src+0
sec sec
sbc memmove_size+0 sbc memmove_size+0
@@ -75,35 +75,35 @@ basic_shift_mem_up_and_relink:
sbc #0 sbc #0
sta memmove_dst+1 sta memmove_dst+1
;; Now make exit easy, by being able to check for zero on size high byte when done // Now make exit easy, by being able to check for zero on size high byte when done
inc memmove_size+1 inc memmove_size+1
;; Then set Y to the number offset required // Then set Y to the number offset required
ldy memmove_size+0 ldy memmove_size+0
iny iny
stx tokenise_work3 stx tokenise_work3
;; jsr printf // jsr printf
;; .byte "REVISED BOUNDS $" // .text "REVISED BOUNDS $"
;; .byte $f1,<memmove_size,>memmove_size // .byte $f1,<memmove_size,>memmove_size
;; .byte $f0,<memmove_size,>memmove_size // .byte $f0,<memmove_size,>memmove_size
;; .byte " BYTES FROM $" // .text " BYTES FROM $"
;; .byte $f1,<memmove_src,>memmove_src // .byte $f1,<memmove_src,>memmove_src
;; .byte $f0,<memmove_src,>memmove_src // .byte $f0,<memmove_src,>memmove_src
;; .byte " TO $" // .text " TO $"
;; .byte $f1,<memmove_dst,>memmove_dst // .byte $f1,<memmove_dst,>memmove_dst
;; .byte $f0,<memmove_dst,>memmove_dst // .byte $f0,<memmove_dst,>memmove_dst
;; .byte $0d,0 // .byte $0d,0
;; Do the copy // Do the copy
jsr shift_mem_up jsr shift_mem_up
;; Now fix the pointer to the next line // Now fix the pointer to the next line
;; First, we need to point the current BASIC line // First, we need to point the current BASIC line
;; pointer to itself, so that we can add the shift // pointer to itself, so that we can add the shift
;; to make it end up pointing to the next line // to make it end up pointing to the next line
ldy #0 ldy #0
ldx #<basic_current_line_ptr+0 ldx #<basic_current_line_ptr+0
lda basic_current_line_ptr+0 lda basic_current_line_ptr+0
@@ -113,10 +113,10 @@ basic_shift_mem_up_and_relink:
jsr poke_under_roms jsr poke_under_roms
relink_up_next_line: relink_up_next_line:
;; inc $d020 // inc $d020
;; jmp relink_up_next_line // jmp relink_up_next_line
;; Advance pointer by tokenise_word3 bytes // Advance pointer by tokenise_word3 bytes
ldy #0 ldy #0
ldx #<basic_current_line_ptr+0 ldx #<basic_current_line_ptr+0
jsr peek_under_roms jsr peek_under_roms
@@ -132,20 +132,20 @@ relink_up_next_line:
adc #0 adc #0
sta memmove_src+1 sta memmove_src+1
;; jsr printf // jsr printf
;; .byte "LINE ADDR = $" // .text "LINE ADDR = $"
;; .byte $f1,<basic_current_line_ptr,>basic_end_of_text_ptr // .byte $f1,<basic_current_line_ptr,>basic_end_of_text_ptr
;; .byte $f0,<basic_current_line_ptr,>basic_end_of_text_ptr // .byte $f0,<basic_current_line_ptr,>basic_end_of_text_ptr
;; .byte $d," BEFORE = $" // .text $d," BEFORE = $"
;; .byte $f1,<memmove_dst,>memmove_dst // .byte $f1,<memmove_dst,>memmove_dst
;; .byte $f0,<memmove_dst,>memmove_dst // .byte $f0,<memmove_dst,>memmove_dst
;; .byte ", AFTER = $" // .text ", AFTER = $"
;; .byte $f1,<memmove_src,>memmove_src // .byte $f1,<memmove_src,>memmove_src
;; .byte $f0,<memmove_src,>memmove_src // .byte $f0,<memmove_src,>memmove_src
;; .byte $d // .byte $d
;; .byte 0 // .byte 0
;; Write memmove_src back to current line pointer // Write memmove_src back to current line pointer
ldy #0 ldy #0
ldx #<basic_current_line_ptr ldx #<basic_current_line_ptr
lda memmove_src+0 lda memmove_src+0
@@ -156,13 +156,13 @@ relink_up_next_line:
relink_up_loop: relink_up_loop:
;; Now advance pointer to the next line, // Now advance pointer to the next line,
lda memmove_src+0 lda memmove_src+0
sta basic_current_line_ptr+0 sta basic_current_line_ptr+0
lda memmove_src+1 lda memmove_src+1
sta basic_current_line_ptr+1 sta basic_current_line_ptr+1
;; Have we run out of lines to patch? // Have we run out of lines to patch?
ldx #<basic_current_line_ptr ldx #<basic_current_line_ptr
jsr peek_pointer_null_check jsr peek_pointer_null_check
bcs relink_up_next_line bcs relink_up_next_line
+4 -4
View File
@@ -1,12 +1,12 @@
;; Clear screen etc, show READY prompt. // Clear screen etc, show READY prompt.
basic_warm_start: basic_warm_start:
jsr install_ram_routines jsr install_ram_routines
;; If warm start caused by BRK, print it address // If warm start caused by BRK, print it address
lda CMP0 lda CMP0
ora CMP0+1 ora CMP0+1
beq + beq !+
ldx #32 ldx #32
jsr print_packed_message jsr print_packed_message
@@ -18,6 +18,6 @@ basic_warm_start:
lda #$0D lda #$0D
jsr JCHROUT jsr JCHROUT
* !:
jmp basic_main_loop jmp basic_main_loop
+3 -4
View File
@@ -1,4 +1,3 @@
;; Skip the gap between $C000-$DFFF // Skip the gap between $C000-$DFFF
.checkpc $C000
.advance $DFFF,$00 .fill $2000, $00
.checkpc $E000
+13 -12
View File
@@ -1,23 +1,24 @@
cmd_stop: cmd_stop:
basic_do_break: basic_do_break:
jsr printf jsr printf // XXX don't use printf, use packed messages!
.byte "BREAK",0 .text "BREAK"
.byte 0
;; Check for direct mode // Check for direct mode
;; Are we in direct mode // Are we in direct mode
lda basic_current_line_number+1 lda basic_current_line_number+1
cmp #$ff cmp #$FF
beq + beq !+
;; Not direct mode // Not direct mode
jsr printf jsr printf // XXX don't use printf, use packed messages!
.byte " IN ",0 .text " IN "
.byte 0
lda basic_current_line_number+1 lda basic_current_line_number+1
ldx basic_current_line_number+0 ldx basic_current_line_number+0
jsr print_integer jsr print_integer
* !:
lda #$0d lda #$0D
jsr JCHROUT jsr JCHROUT
cmd_end: cmd_end:
jmp basic_main_loop jmp basic_main_loop
+26 -26
View File
@@ -1,9 +1,9 @@
;; LIST basic text. // LIST basic text.
;; XXX - Doesn't currently support line number ranges // XXX - Doesn't currently support line number ranges
cmd_list: cmd_list:
;; Set current line pointer to start of memory // Set current line pointer to start of memory
lda basic_start_of_text_ptr+0 lda basic_start_of_text_ptr+0
sta basic_current_line_ptr+0 sta basic_current_line_ptr+0
lda basic_start_of_text_ptr+1 lda basic_start_of_text_ptr+1
@@ -16,23 +16,23 @@ list_loop:
cmp #$00 cmp #$00
bne list_more_lines bne list_more_lines
;; LIST terminates any running program, // LIST terminates any running program,
;; because it has fiddled with the current line pointer. // because it has fiddled with the current line pointer.
;; (Confirmed by testing on a C64) // (Confirmed by testing on a C64)
jmp basic_main_loop jmp basic_main_loop
list_more_lines: list_more_lines:
lda STKEY lda STKEY
bmi + bmi !+
jmp basic_do_break jmp basic_do_break
* !:
jsr list_single_line jsr list_single_line
;; Now link to the next line // Now link to the next line
jsr basic_find_next_line jsr basic_find_next_line
jmp list_loop jmp list_loop
list_single_line: ; entry point needed by DOS wedge list_single_line: // entry point needed by DOS wedge
;; Print line number // Print line number
ldy #3 ldy #3
jsr peek_under_roms jsr peek_under_roms
pha pha
@@ -44,8 +44,8 @@ list_single_line: ; entry point needed by DOS wedge
lda #$20 lda #$20
jsr JCHROUT jsr JCHROUT
;; Iterate through printing out the line // Iterate through printing out the line
;; contents // contents
lda #0 lda #0
sta quote_mode_flag sta quote_mode_flag
@@ -63,34 +63,34 @@ list_print_loop:
lda #$22 lda #$22
jmp list_is_literal jmp list_is_literal
list_not_quote: list_not_quote:
;; Check quote mode, and display as literal if required // Check quote mode, and display as literal if required
ldx quote_mode_flag ldx quote_mode_flag
bne list_is_literal bne list_is_literal
cmp #$7f cmp #$7f
bcc list_is_literal bcc list_is_literal
;; Display a token // Display a token
;; Save registers // Save registers
tax tax
pha pha
tya tya
pha pha
;; Get pointer to compressed keyword list // Get pointer to compressed keyword list
lda #<packed_keywords lda #<packed_keywords
sta temp_string_ptr+0 sta temp_string_ptr+0
lda #>packed_keywords lda #>packed_keywords
sta temp_string_ptr+1 sta temp_string_ptr+1
;; Subtract $80 from token to get offset in word // Subtract $80 from token to get offset in word
;; list // list
txa txa
and #$7f and #$7f
tax tax
;; Now ask for it to be printed // Now ask for it to be printed
ldy #$ff ldy #$ff
jsr packed_word_search jsr packed_word_search
@@ -100,11 +100,11 @@ list_not_quote:
cmp #$8f cmp #$8f
bne list_not_rem bne list_not_rem
;; REM command locks quote flag on until the end of the line, allowing // REM command locks quote flag on until the end of the line, allowing
;; funny characters in REM statements without problem. // funny characters in REM statements without problem.
inc $0427 inc $0427
sta quote_mode_flag ; Any value other than $00 or $FF will lock quote mode on, so the token value of REM is fine here sta quote_mode_flag // Any value other than $00 or $FF will lock quote mode on, so the token value of REM is fine here
;; FALL THROUGH // FALL THROUGH
list_not_rem: list_not_rem:
iny iny
@@ -116,10 +116,10 @@ list_is_literal:
bne list_print_loop bne list_print_loop
list_end_of_line: list_end_of_line:
;; Clear reverse flag // Clear reverse flag
lda #$92 lda #$92
jsr JCHROUT jsr JCHROUT
;; Print end of line // Print end of line
lda #$0d lda #$0d
jsr JCHROUT jsr JCHROUT
rts rts
+66 -66
View File
@@ -1,64 +1,64 @@
cmd_load: cmd_load:
;; Parse filename // Parse filename
;; (we can tell the KERNAL where it is in memory directly, since the // (we can tell the KERNAL where it is in memory directly, since the
;; KERNAL will be able to peek under ROMs to read it, since it will have // KERNAL will be able to peek under ROMs to read it, since it will have
;; to be able to peek under the ROMs for SAVE and VERIFY). // to be able to peek under the ROMs for SAVE and VERIFY).
;; Parse optional device # // Parse optional device #
;; Parse optional secondary address // Parse optional secondary address
;; XXX - C64 BASIC apparently doesn't clear variables after a LOAD in the // XXX - C64 BASIC apparently doesn't clear variables after a LOAD in the
;; middle of a program. For safety, we do. // middle of a program. For safety, we do.
jsr basic_do_clr jsr basic_do_clr
;; Setup Kernal to print control messages or not // Setup Kernal to print control messages or not
lda #$80 ; display control messages and omit error messages lda #$80 // display control messages and omit error messages
ldx basic_current_line_number+1 ldx basic_current_line_number+1
cpx #$FF cpx #$FF
beq + beq !+
lda #$00 ; direct mode - don't display anything lda #$00 // direct mode - don't display anything
* !:
jsr JSETMSG jsr JSETMSG
;; Set filename and length // Set filename and length
lda #$00 lda #$00
sta FNLEN sta FNLEN
;; Without tape support, LOAD must have a filename // Without tape support, LOAD must have a filename
;; (This also skips any leading spaces) // (This also skips any leading spaces)
jsr basic_end_of_statement_check jsr basic_end_of_statement_check
bcc + bcc !+
jmp do_MISSING_FILENAME_error jmp do_MISSING_FILENAME_error
* !:
jsr basic_fetch_and_consume_character jsr basic_fetch_and_consume_character
cmp #$22 cmp #$22
beq + beq !+
jmp do_SYNTAX_ERROR jmp do_SYNTAX_error
* !:
;; Filename starts here so set pointer // Filename starts here so set pointer
lda basic_current_statement_ptr+0 lda basic_current_statement_ptr+0
sta current_filename_ptr+0 sta current_filename_ptr+0
lda basic_current_statement_ptr+1 lda basic_current_statement_ptr+1
sta current_filename_ptr+1 sta current_filename_ptr+1
;; Now search for end of line or closing quote // Now search for end of line or closing quote
;; so that we know the length of the filename // so that we know the length of the filename
getting_filename: getting_filename:
jsr basic_fetch_and_consume_character jsr basic_fetch_and_consume_character
cmp #$22 cmp #$22
beq got_filename beq got_filename
cmp #$00 cmp #$00
bne + bne !+
jsr basic_unconsume_character jsr basic_unconsume_character
jmp got_filename jmp got_filename
* !:
inc FNLEN inc FNLEN
jmp getting_filename jmp getting_filename
got_filename: got_filename:
;; Now fetch the file number, start from the default one // Now fetch the file number, start from the default one
jsr select_device jsr select_device
stx current_device_number stx current_device_number
jsr injest_comma jsr injest_comma
@@ -66,116 +66,116 @@ got_filename:
jsr basic_parse_line_number jsr basic_parse_line_number
lda basic_line_number+1 lda basic_line_number+1
beq + beq !+
jmp do_ILLEGAL_QUANTITY_error jmp do_ILLEGAL_QUANTITY_error
* !:
lda basic_line_number+0 lda basic_line_number+0
sta current_device_number sta current_device_number
got_devicenumber: got_devicenumber:
;; Now fetch the secondary address // Now fetch the secondary address
lda #$00 lda #$00
sta current_secondary_address sta current_secondary_address
jsr injest_comma jsr injest_comma
bcs got_secondaryaddress bcs got_secondaryaddress
jsr basic_parse_line_number jsr basic_parse_line_number
lda basic_line_number+1 lda basic_line_number+1
bne + bne !+
lda basic_line_number+0 lda basic_line_number+0
sta current_secondary_address sta current_secondary_address
jmp got_secondaryaddress jmp got_secondaryaddress
* !:
;; Second parameter is above 255, this can't be a secondary address // Second parameter is above 255, this can't be a secondary address
;; Use it as load address instead // Use it as load address instead
;; XXX temporary syntax, it would be better to use something // XXX temporary syntax, it would be better to use something
;; XXX like 'LOAD"FILE",8 TO 49152' // XXX like 'LOAD"FILE",8 TO 49152'
ldx basic_line_number+0 ldx basic_line_number+0
ldy basic_line_number+1 ldy basic_line_number+1
bne got_loadaddress bne got_loadaddress
got_secondaryaddress: got_secondaryaddress:
ldx #<$0801 ldx #<$0801 // XXX use start text vector
ldy #>$0801 ldy #>$0801
got_loadaddress: got_loadaddress:
lda #$00 ; LOAD not verify lda #$00 // LOAD not verify
jsr via_ILOAD jsr via_ILOAD
bcc + bcc !+
;; A = KERNAL error code, which also almost match // A = KERNAL error code, which also almost match
;; basic ERROR codes, so we can just copy the // basic ERROR codes, so we can just copy the
;; error code to X, decrement, and handle normally // error code to X, decrement, and handle normally
tax tax
dex dex
jmp do_basic_error jmp do_basic_error
* !:
;; $YYXX is the last loaded address, so store it // $YYXX is the last loaded address, so store it
stx basic_end_of_text_ptr+0 stx basic_end_of_text_ptr+0
sty basic_end_of_text_ptr+1 sty basic_end_of_text_ptr+1
;; Now relink the loaded program, as we cannot trust the line // Now relink the loaded program, as we cannot trust the line
;; links supplied. For example, the VICE virtual drive emulation // links supplied. For example, the VICE virtual drive emulation
;; always supplies $0101 as the address of the next line. // always supplies $0101 as the address of the next line.
jsr basic_relink_program jsr basic_relink_program
;; After LOADing, we either start the program from the beginning, // After LOADing, we either start the program from the beginning,
;; or go back to the READY prompt if LOAD was called from direct mode. // or go back to the READY prompt if LOAD was called from direct mode.
;; Reset to start of program // Reset to start of program
lda basic_start_of_text_ptr+0 lda basic_start_of_text_ptr+0
sta basic_current_line_ptr+0 sta basic_current_line_ptr+0
lda basic_start_of_text_ptr+1 lda basic_start_of_text_ptr+1
sta basic_current_line_ptr+1 sta basic_current_line_ptr+1
;; XXX - should run program if LOAD was used in program mode // XXX - should run program if LOAD was used in program mode
jmp basic_main_loop jmp basic_main_loop
basic_relink_program: basic_relink_program:
;; Start by getting pointer to the first line // Start by getting pointer to the first line
lda basic_start_of_text_ptr+0 lda basic_start_of_text_ptr+0
sta basic_current_line_ptr+0 sta basic_current_line_ptr+0
lda basic_start_of_text_ptr+1 lda basic_start_of_text_ptr+1
sta basic_current_line_ptr+1 sta basic_current_line_ptr+1
basic_relink_loop: basic_relink_loop:
;; Is the pointer to the end of the program // Is the pointer to the end of the program
ldy #1 ldy #1
ldx #<basic_current_line_ptr+0 ldx #<basic_current_line_ptr+0
jsr peek_under_roms jsr peek_under_roms
cmp #$00 cmp #$00
bne + bne !+
;; End of program // End of program
rts rts
* !:
;; Now search forward to find the end of the line // Now search forward to find the end of the line
;; Skip forward pointer and line number // Skip forward pointer and line number
ldy #4 ldy #4
end_of_line_search: end_of_line_search:
ldx #<basic_current_line_ptr+0 ldx #<basic_current_line_ptr+0
jsr peek_under_roms jsr peek_under_roms
cmp #$00 cmp #$00
beq + beq !+
;; Not yet end of line // Not yet end of line
iny iny
bne end_of_line_search bne end_of_line_search
;; line too long // line too long
jmp do_STRING_TOO_LONG_error jmp do_STRING_TOO_LONG_error
* !:
;; Found end of line, so update pointer // Found end of line, so update pointer
;; First, skip over the $00 char // First, skip over the $00 char
iny iny
;; Now overwrite the pointer (carefully) // Now overwrite the pointer (carefully)
;; //
tya tya
clc clc
adc basic_current_line_ptr+0 adc basic_current_line_ptr+0
+21 -23
View File
@@ -2,18 +2,18 @@
cmd_new: cmd_new:
jsr basic_do_new jsr basic_do_new
;; NEW command terminates execution // NEW command terminates execution
;; (Confirmed on a C64) // (Confirmed on a C64)
jmp basic_main_loop jmp basic_main_loop
cmd_clr: cmd_clr:
jsr basic_do_clr jsr basic_do_clr
;; CLR command does not stop execution // CLR command does not stop execution
;; (Cconfirmed on a c64) // (Cconfirmed on a c64)
jmp basic_execute_statement jmp basic_execute_statement
basic_do_new: basic_do_new:
;; Setup pointers to memory storage // Setup pointers to memory storage XXX should depend on text start vector
lda #<$0801 lda #<$0801
sta basic_start_of_text_ptr+0 sta basic_start_of_text_ptr+0
lda #>$0801 lda #>$0801
@@ -22,8 +22,8 @@ basic_do_new:
lda #<$0803 lda #<$0803
sta basic_start_of_vars_ptr+0 sta basic_start_of_vars_ptr+0
;; Zero line pointer // Zero line pointer
;; XXX - We should also zero $0800, i.e., basic_start_of_text_ptr - 1 // XXX - We should also zero $0800, i.e., basic_start_of_text_ptr - 1
ldy #$00 ldy #$00
tya tya
sta (basic_start_of_text_ptr),y sta (basic_start_of_text_ptr),y
@@ -31,32 +31,32 @@ basic_do_new:
sta (basic_start_of_text_ptr),y sta (basic_start_of_text_ptr),y
;; Get top of memory. // Get top of memory.
;; If a cart is present, then it is $7FFF, // If a cart is present, then it is $7FFF,
;; if not, then it is $F7FF, since we support having // if not, then it is $F7FF, since we support having
;; programs and variables under ROM. // programs and variables under ROM.
;; i.e., we support 56KB RAM for BASIC, keeping some space // i.e., we support 56KB RAM for BASIC, keeping some space
;; free for some optimisation structures, e.g., FOR/NEXT loop // free for some optimisation structures, e.g., FOR/NEXT loop
;; records (without them going on the stack), GOSUB stack // records (without them going on the stack), GOSUB stack
;; (same story), expression value cache? // (same story), expression value cache?
sec ; Read, not write value sec // Read, not write value
jsr JMEMTOP jsr JMEMTOP
cpx #$80 cpx #$80
beq + beq !+
lda #>$f7ff lda #>$f7ff
.byte $2c .byte $2C
* lda #>$7FFF !: lda #>$7FFF
sta basic_top_of_memory_ptr+1 sta basic_top_of_memory_ptr+1
sta basic_start_of_strings_ptr+1 sta basic_start_of_strings_ptr+1
lda #<$f7ff lda #<$f7ff
sta basic_top_of_memory_ptr+0 sta basic_top_of_memory_ptr+0
sta basic_start_of_strings_ptr+0 sta basic_start_of_strings_ptr+0
;; FALL THROUGH // FALL THROUGH
basic_do_clr: basic_do_clr:
;; Clear variables, arrays and strings // Clear variables, arrays and strings
lda basic_start_of_vars_ptr+0 lda basic_start_of_vars_ptr+0
sta basic_start_of_arrays_ptr+0 sta basic_start_of_arrays_ptr+0
sta basic_start_of_free_space_ptr+0 sta basic_start_of_free_space_ptr+0
@@ -65,5 +65,3 @@ basic_do_clr:
sta basic_start_of_free_space_ptr+1 sta basic_start_of_free_space_ptr+1
rts rts
+1 -1
View File
@@ -1,4 +1,4 @@
;; REM statement just skips to the next line // REM statement just skips to the next line
cmd_rem: cmd_rem:
jmp basic_end_of_line jmp basic_end_of_line
+7 -7
View File
@@ -1,21 +1,21 @@
cmd_run: cmd_run:
;; RUN clears all variables // RUN clears all variables
jsr basic_do_clr jsr basic_do_clr
cmd_goto: cmd_goto:
;; Reset line pointer to first line of program. // Reset line pointer to first line of program.
lda basic_start_of_text_ptr+0 lda basic_start_of_text_ptr+0
sta basic_current_line_ptr+0 sta basic_current_line_ptr+0
lda basic_start_of_text_ptr+1 lda basic_start_of_text_ptr+1
sta basic_current_line_ptr+1 sta basic_current_line_ptr+1
jsr basic_end_of_statement_check jsr basic_end_of_statement_check
bcs + bcs !+
jsr basic_parse_line_number jsr basic_parse_line_number
jsr basic_find_line jsr basic_find_line
bcc + bcc !+
;; Line doesn't exist, so report error // Line doesn't exist, so report error
jmp do_UNDEFD_STATEMENT_error jmp do_UNDEFD_STATEMENT_error
* !:
;; Run it! // Run it!
jmp basic_execute_from_current_line jmp basic_execute_from_current_line
+8 -8
View File
@@ -1,23 +1,23 @@
cmd_sys: cmd_sys:
jsr basic_end_of_statement_check jsr basic_end_of_statement_check
bcc + bcc !+
;; SYS requires an argument // SYS requires an argument
jmp do_SYNTAX_ERROR jmp do_SYNTAX_error
* !:
jsr basic_parse_line_number jsr basic_parse_line_number
;; setup call // setup call
lda #$4C ;JMP lda #$4C // JMP opcode
sta USRPOK sta USRPOK
lda basic_line_number+0 lda basic_line_number+0
sta USRADD+0 sta USRADD+0
lda basic_line_number+1 lda basic_line_number+1
sta USRADD+1 sta USRADD+1
;; Setup the register values // Setup the register values
lda SPREG lda SPREG
pha pha
ldy SYREG ldy SYREG
@@ -25,7 +25,7 @@ cmd_sys:
lda SAREG lda SAREG
plp plp
;; Call the routine. // Call the routine.
jsr USRPOK jsr USRPOK
jmp basic_execute_statement jmp basic_execute_statement
+7 -7
View File
@@ -1,4 +1,4 @@
;; Default handler for all not-yet-implemented commands // Default handler for all not-yet-implemented commands
cmd_for: cmd_for:
cmd_next: cmd_next:
@@ -13,7 +13,7 @@ cmd_restore:
cmd_gosub: cmd_gosub:
cmd_return: cmd_return:
;; $90-$9F // $90-$9F
cmd_on: cmd_on:
cmd_wait: cmd_wait:
cmd_save: cmd_save:
@@ -26,7 +26,7 @@ cmd_cont:
cmd_cmd: cmd_cmd:
cmd_open: cmd_open:
;; $A0-$AF // $A0-$AF
cmd_close: cmd_close:
cmd_get: cmd_get:
cmd_tab: cmd_tab:
@@ -43,7 +43,7 @@ cmd_div:
cmd_exponent: cmd_exponent:
cmd_and: cmd_and:
;; $B0-$BF // $B0-$BF
cmd_or: cmd_or:
cmd_greater: cmd_greater:
cmd_equal: cmd_equal:
@@ -61,7 +61,7 @@ cmd_exp:
cmd_cos: cmd_cos:
cmd_sin: cmd_sin:
;; $C0-$CF // $C0-$CF
cmd_tan: cmd_tan:
cmd_atn: cmd_atn:
cmd_peek: cmd_peek:
@@ -74,9 +74,9 @@ cmd_left:
cmd_right: cmd_right:
cmd_mid: cmd_mid:
cmd_go: cmd_go:
;; Undefined tokens
// Undefined tokens
cmd_unimplemented: cmd_unimplemented:
jmp do_NOT_IMPLEMENTED_error jmp do_NOT_IMPLEMENTED_error
+55 -54
View File
@@ -1,48 +1,48 @@
;; As many errors are triggered from many places in the BASIC // As many errors are triggered from many places in the BASIC
;; interprettor, it is important to have an efficicent means of // interprettor, it is important to have an efficicent means of
;; calling them. // calling them.
;; LDX #$nn / jmp do_basic_error // LDX #$nn / jmp do_basic_error
;; is the simplest, but takes 5 bytes. // is the simplest, but takes 5 bytes.
;; Having a direct JMP address for each error is preferable, as // Having a direct JMP address for each error is preferable, as
;; it reduces the overhead to 3 bytes, but at the cost of having // it reduces the overhead to 3 bytes, but at the cost of having
;; a jump table of some sort. The .byte $2C method can be used // a jump table of some sort. The .byte $2C method can be used
;; to have a set of addresses that each execute a different // to have a set of addresses that each execute a different
;; LDX #$nn command, reducing the cost of the jump table to 3 // LDX #$nn command, reducing the cost of the jump table to 3
;; bytes per error number. // bytes per error number.
;; But we can do better with a bit of scullduggery and carnal // But we can do better with a bit of scullduggery and carnal
;; knowledge of ZP usage. // knowledge of ZP usage.
;; The INC $nn opcode is $E6. ZP location $E6 is one of the screen // The INC $nn opcode is $E6. ZP location $E6 is one of the screen
;; link addresses. In the original KERNAL, the lower bits of those // link addresses. In the original KERNAL, the lower bits of those
;; addresses have meaning, but in our KERNAL, we ignore them, and just // addresses have meaning, but in our KERNAL, we ignore them, and just
;; have them all zeroes. So.... We can have a sequence of $E6 bytes, // have them all zeroes. So.... We can have a sequence of $E6 bytes,
;; and know exactly how many of them have been executed, by checking // and know exactly how many of them have been executed, by checking
;; the value of $E6. Then all we need to worry about is if an odd // the value of $E6. Then all we need to worry about is if an odd
;; number is required, then we have to have an exit that has a $E6 // number is required, then we have to have an exit that has a $E6
;; opcode with some other address as target, but where the byte value // opcode with some other address as target, but where the byte value
;; of that argument can be safely executed as a CPU instruction. // of that argument can be safely executed as a CPU instruction.
;; NOP = $EA is the obvious choice, as if used as an argument to // NOP = $EA is the obvious choice, as if used as an argument to
;; $E6 will increment location $EA, which is another of the screen // $E6 will increment location $EA, which is another of the screen
;; link addresses. // link addresses.
;; This gives a total overhead of 18 bytes + 1 byte per error // This gives a total overhead of 18 bytes + 1 byte per error
;; message. This compares favourably to the 3 bytes per error // message. This compares favourably to the 3 bytes per error
;; message that the $2C method would result in. // message that the $2C method would result in.
do_NOT_IMPLEMENTED_error: do_NOT_IMPLEMENTED_error:
.byte $E6 .byte $E6
do_MEMORY_CORRUPT_error: do_MEMORY_CORRUPT_error:
.byte $E6 .byte $E6
;; the message "BYTES FREE" // the message "BYTES FREE"
.byte $E6 .byte $E6
;; the word ERROR // the word ERROR
.byte $E6 .byte $E6
;; The word "SAVING" // The word "SAVING"
.byte $E6 .byte $E6
;; The word "VERIFYING" // The word "VERIFYING"
.byte $E6 .byte $E6
;; The word "LOADING" // The word "LOADING"
.byte $E6 .byte $E6
;; The word "READY." // The word "READY."
.byte $E6 .byte $E6
do_LOAD_error: do_LOAD_error:
.byte $E6 .byte $E6
@@ -103,69 +103,70 @@ do_FILE_OPEN_error:
do_TO_MANY_FILES_error: do_TO_MANY_FILES_error:
.byte $EA .byte $EA
;; Now get the error # and restore $E6 to its correct value // Now get the error # and restore $E6 to its correct value
lda $E6 lda $E6
pha pha
and #$80 and #$80
sta $E6 sta $E6
pla pla
;; $E6 has even part // $E6 has even part
asl asl
ora $EA ora $EA
and #$7f and #$7f
tax tax
;; Restore $EA to correct value in case the NOP above is used // Restore $EA to correct value in case the NOP above is used
;; as an argument to the preceeding INC $nn (opcode $E6). // as an argument to the preceeding INC $nn (opcode $E6).
LDA $EA lda $EA
and #$80 and #$80
sta $EA sta $EA
;; FALL THROUGH // FALL THROUGH
;; Error # in X // Error # in X
do_basic_error: do_basic_error:
;; "?" // "?"
txa txa
pha pha
lda #$0d lda #$0d
jsr $ffd2 jsr JCHROUT
lda #$3f lda #$3f
jsr $ffd2 jsr JCHROUT
pla pla
tax tax
;; Error message text // Error message text
jsr print_packed_message jsr print_packed_message
;; A space between error name and word error // A space between error name and word error
lda #$20 lda #$20
jsr $ffd2 jsr $ffd2
;; "ERROR" // "ERROR"
ldx #33 ldx #33
jsr print_packed_message jsr print_packed_message
lda basic_current_line_number+1 lda basic_current_line_number+1
cmp #$ff cmp #$ff
beq + beq !+
;; We were in a program, so show IN <line> // We were in a program, so show IN <line>
jsr printf jsr printf // XXX don't use printf, use packed messages
.byte " IN ",0 .text " IN "
.byte 0
lda basic_current_line_number+1 lda basic_current_line_number+1
ldx basic_current_line_number+0 ldx basic_current_line_number+0
jsr print_integer jsr print_integer
* !:
;; New lines // New lines
lda #$0d lda #$0d
jsr $ffd2 jsr $ffd2
lda #$00 lda #$00
jsr $ffd2 jsr $ffd2
;; XXX - Restore stack depth first? // XXX - Restore stack depth first?
jmp basic_main_loop jmp basic_main_loop
+26 -26
View File
@@ -1,23 +1,23 @@
;; Multiply Floating Point Accumulator by 10 // Multiply Floating Point Accumulator by 10
;; = 8x + 2x // = 8x + 2x
;; Implement by shifting MAC left one bit, // Implement by shifting MAC left one bit,
;; and then keeping that value to add on after // and then keeping that value to add on after
;; shifting two more bits left. // shifting two more bits left.
;; This should be done using basic_fac1_overflow to // This should be done using basic_fac1_overflow to
;; hold the overflow bits, so that the result can // hold the overflow bits, so that the result can
;; be exponent adjusted after, if required. // be exponent adjusted after, if required.
fac1_mul10: fac1_mul10:
lda #$00 lda #$00
sta basic_fac1_overflow sta basic_fac1_overflow
;; Multiply mantissa by 2 // Multiply mantissa by 2
jsr fac1_mantissa_mul2 jsr fac1_mantissa_mul2
;; copy down to BASIC numeric work area at $57 // copy down to BASIC numeric work area at $57
;; (basic_numeric_work_area) // (basic_numeric_work_area)
;; (We copy all 7 bytes off the FAC1, so that we have // (We copy all 7 bytes off the FAC1, so that we have
;; the overflow bits, and the copy is as small as possible) // the overflow bits, and the copy is as small as possible)
ldx #7 ldx #7
f1m10_l1: f1m10_l1:
lda basic_fac1_mantissa,x lda basic_fac1_mantissa,x
@@ -25,11 +25,11 @@ f1m10_l1:
dex dex
bpl f1m10_l1 bpl f1m10_l1
;; Multiply mantissa by 4, so it is now 8x original // Multiply mantissa by 4, so it is now 8x original
jsr fac1_mantissa_mul2 jsr fac1_mantissa_mul2
jsr fac1_mantissa_mul2 jsr fac1_mantissa_mul2
;; Now add stored value of 2x to it, to get the total x10 // Now add stored value of 2x to it, to get the total x10
ldy #3 ldy #3
ldx #0 ldx #0
clc clc
@@ -44,22 +44,22 @@ f1m10_l2:
adc basic_numeric_work_area+7 adc basic_numeric_work_area+7
sta basic_fac1_overflow sta basic_fac1_overflow
;; Now shift right and increase exponent until overflow // Now shift right and increase exponent until overflow
;; bits = $00 // bits = $00
f1m10_l3: f1m10_l3:
lda basic_fac1_overflow lda basic_fac1_overflow
bne + bne !+
;; All done, return // All done, return
clc clc
rts rts
* !:
;; Divide mantissa by two, and increment exponent // Divide mantissa by two, and increment exponent
jsr fac1_mantissa_div2 jsr fac1_mantissa_div2
inc basic_fac1_exponent inc basic_fac1_exponent
lda basic_fac1_exponent lda basic_fac1_exponent
bpl f1m10_l3 bpl f1m10_l3
;; Exponent has bit 7 set, so has wrapped. // Exponent has bit 7 set, so has wrapped.
;; = OVERFLOW ERROR // = OVERFLOW ERROR
jmp do_OVERFLOW_error jmp do_OVERFLOW_error
fac1_mantissa_mul2: fac1_mantissa_mul2:
@@ -67,8 +67,8 @@ fac1_mantissa_mul2:
ldx #0 ldx #0
clc clc
f1m1_l1: f1m1_l1:
;; Multiply mantissa by 2, and store overflow // Multiply mantissa by 2, and store overflow
;; in basic_fac1_bits // in basic_fac1_bits
lda basic_fac1_mantissa,x lda basic_fac1_mantissa,x
rol rol
sta basic_fac1_mantissa,x sta basic_fac1_mantissa,x
@@ -82,7 +82,7 @@ f1m1_l1:
rts rts
fac1_mantissa_div2: fac1_mantissa_div2:
;; Divide mantissa by 2, including using overflow bits // Divide mantissa by 2, including using overflow bits
clc clc
lda basic_fac1_overflow lda basic_fac1_overflow
ror ror
+5 -6
View File
@@ -1,15 +1,15 @@
;; Consummes a comma in a BASIC code, C set for no coma found // Consummes a comma in a BASIC code, C set for no coma found
injest_comma: injest_comma:
jsr basic_fetch_and_consume_character jsr basic_fetch_and_consume_character
cmp #$2C ; comma character cmp #$2C // comma character
beq injest_comma_found beq injest_comma_found
cmp #$20 cmp #$20 // space, can always be skipped
beq injest_comma ; space, can always be skipped beq injest_comma
;; not found // not found
jsr basic_unconsume_character jsr basic_unconsume_character
sec sec
rts rts
@@ -17,4 +17,3 @@ injest_comma:
injest_comma_found: injest_comma_found:
clc clc
rts rts
+50 -51
View File
@@ -1,37 +1,37 @@
;; Parse a number from the input buffer at (basic_current_statement_ptr) // Parse a number from the input buffer at (basic_current_statement_ptr)
;; Result is put into FAC1. // Result is put into FAC1.
;; basic_current_statement_ptr is updated with first position after the number. // basic_current_statement_ptr is updated with first position after the number.
;; XXX - Remember decimal position and exponent, and apply them // XXX - Remember decimal position and exponent, and apply them
;; after to produce normalised floating point number. // after to produce normalised floating point number.
;; XXX - Doesn't use routines to access memory under ROMs etc. // XXX - Doesn't use routines to access memory under ROMs etc.
;; This is important, because this routine operates on numbers in BASIC text. // This is important, because this routine operates on numbers in BASIC text.
ij_not_a_digit: ij_not_a_digit:
;; XXX check for "." or "E" // XXX check for "." or "E"
;; Other chars terminate the accumulation. // Other chars terminate the accumulation.
;; Look for exponentiation marker // Look for exponentiation marker
;; XXX - Implement me! // XXX - Implement me!
;; Probably should have a flag so that we know if we are accumulating // Probably should have a flag so that we know if we are accumulating
;; exponent or mantissa digits // exponent or mantissa digits
;; Look for decimal point // Look for decimal point
cmp #$2e cmp #$2e
bne ij_not_decimal bne ij_not_decimal
lda tokenise_work4 lda tokenise_work4
cmp #$ff cmp #$ff
beq ij_found_decimal beq ij_found_decimal
;; More than one decimal point in a number means we have reached the end of the number // More than one decimal point in a number means we have reached the end of the number
clc clc
rts rts
ij_found_decimal: ij_found_decimal:
;; Found decimal. // Found decimal.
;; Thus start counting digits after the decimal, so that we // Thus start counting digits after the decimal, so that we
;; can do the necessary number of divide by 10s on the final // can do the necessary number of divide by 10s on the final
;; number. // number.
lda #$00 lda #$00
sta tokenise_work4 sta tokenise_work4
@@ -39,31 +39,30 @@ ij_found_decimal:
ij_not_decimal: ij_not_decimal:
clc
CLC rts
RTS
injest_number: injest_number:
;; Clear FAC1 // Clear FAC1
jsr erase_fac1 jsr erase_fac1
;; Clear decimal position flag // Clear decimal position flag
lda #$ff lda #$ff
sta tokenise_work4 sta tokenise_work4
;; Check if leading char is a - sign // Check if leading char is a - sign
;; Note: the - will have been tokenised to $AB // Note: the - will have been tokenised to $AB
;; XXX - implement // XXX - implement
ldy #$00 ldy #$00
lda (basic_current_statement_ptr),y lda (basic_current_statement_ptr),y
cmp #$AB cmp #$AB
bne ij_not_minus bne ij_not_minus
;; Set sign to negative // Set sign to negative
lda #$ff lda #$ff
sta basic_fac1_sign sta basic_fac1_sign
;; Skip over the minus sign // Skip over the minus sign
jsr basic_consume_character jsr basic_consume_character
ij_not_minus: ij_not_minus:
@@ -77,43 +76,43 @@ ij_loop1:
cmp #$3a cmp #$3a
bcs ij_not_a_digit bcs ij_not_a_digit
;; It is a digit // It is a digit
;; Only add digit if we have not overflowed the accuracy of // Only add digit if we have not overflowed the accuracy of
;; the mantissa // the mantissa
lda basic_fac1_exponent lda basic_fac1_exponent
beq ij_accept_precision beq ij_accept_precision
;; We have an extra digit after saturating our precision. // We have an extra digit after saturating our precision.
;; Thus we should ignore the digit, and just multiply the FAC // Thus we should ignore the digit, and just multiply the FAC
;; by 10, but only if we have not seen a decimal point. // by 10, but only if we have not seen a decimal point.
;; If we have seen a decimal point, then we can completely ignore // If we have seen a decimal point, then we can completely ignore
;; the digit, as it is contributing not recordable information // the digit, as it is contributing not recordable information
lda tokenise_work4 lda tokenise_work4
cmp #$ff cmp #$ff
bne ij_seen_decimal_point bne ij_seen_decimal_point
jsr fac1_mul10 jsr fac1_mul10
;; Fall through // Fall through
ij_seen_decimal_point: ij_seen_decimal_point:
jmp ij_consider_next_digit jmp ij_consider_next_digit
ij_accept_precision: ij_accept_precision:
;; We can accept more precision, so multiply the mantissa by 10, so that // We can accept more precision, so multiply the mantissa by 10, so that
;; we can add the new digit in // we can add the new digit in
jsr fac1_mul10 jsr fac1_mul10
lda basic_fac1_exponent lda basic_fac1_exponent
bne ij_consider_next_digit bne ij_consider_next_digit
;; Get digit // Get digit
ldy #$00 ldy #$00
lda (basic_current_statement_ptr),y lda (basic_current_statement_ptr),y
sec sec
sbc #$30 sbc #$30
;; Add to FAC1 mantissa // Add to FAC1 mantissa
clc clc
adc basic_fac1_mantissa+0 adc basic_fac1_mantissa+0
sta basic_fac1_mantissa+0 sta basic_fac1_mantissa+0
@@ -127,16 +126,16 @@ ij_loop2:
dey dey
bne ij_loop2 bne ij_loop2
bcc + bcc !+
;; Carry set, so we have overflowed. // Carry set, so we have overflowed.
;; We should shift everything right one digit, and increase // We should shift everything right one digit, and increase
;; the exponent by one. The non-zero exponent tells us that we // the exponent by one. The non-zero exponent tells us that we
;; can't fit any more precision in. // can't fit any more precision in.
jsr fac1_mantissa_div2 jsr fac1_mantissa_div2
* !:
ij_consider_next_digit: ij_consider_next_digit:
;; Consider next digit // Consider next digit
jsr basic_consume_character jsr basic_consume_character
jmp ij_loop1 jmp ij_loop1
@@ -146,10 +145,10 @@ ij_consider_next_digit:
erase_fac1: erase_fac1:
lda #$00 lda #$00
ldx #8 ldx #8
* !:
sta basic_fac1_exponent,x sta basic_fac1_exponent,x
dex dex
bpl - bpl !-
sta basic_fac1_mantissa_lob sta basic_fac1_mantissa_lob
rts rts
+88 -87
View File
@@ -1,76 +1,77 @@
;; Pack a word using the simple compression scheme. // Pack a word using the simple compression scheme.
;; This has to be the same implementation as in compress_text.c // This has to be the same implementation as in compress_text.c
;; because we compress input lines of BASIC to do the tokenisation. // because we compress input lines of BASIC to do the tokenisation.
;; This allows us to search through the compressed tokens directly // This allows us to search through the compressed tokens directly
;; using the compressed fragment of BASIC, and thus work out the // using the compressed fragment of BASIC, and thus work out the
;; token for a given piece of string. // token for a given piece of string.
;; This also helps ensure that we have an implementation that is totally // This also helps ensure that we have an implementation that is totally
;; different to that of the original C64 BASIC, as well as likely // different to that of the original C64 BASIC, as well as likely
;; saving a bit of space in the ROM, especially once we start implementing // saving a bit of space in the ROM, especially once we start implementing
;; larger keyword vocabs for BASIC 7 or BASIC 10 compatibility, since the // larger keyword vocabs for BASIC 7 or BASIC 10 compatibility, since the
;; compression and decompression machinery is of fixed size. // compression and decompression machinery is of fixed size.
pack_word: pack_word:
;; Inputs: // Inputs:
;; X = offset of string to pack. Address is $0200 + X // X = offset of string to pack. Address is $0200 + X
;; tokenise_work1 = number of bytes to pack // tokenise_work1 = number of bytes to pack
;; tokenise_work2 = packed length of string // tokenise_work2 = packed length of string
;; Outputs: // Outputs:
;; Output is written to $0100 (bottom of stack). // Output is written to $0100 (bottom of stack).
;; Memory modified: // Memory modified:
;; tokenise_work4 = temporary storage // tokenise_work4 = temporary storage
;; tokenise_work3 = flag for whether we have a nybl prepared or not. // tokenise_work3 = flag for whether we have a nybl prepared or not.
;; (This can also be checked on exit, to know whether the last byte // (This can also be checked on exit, to know whether the last byte
;; is incomplete, which is important for searching for abbreviated // is incomplete, which is important for searching for abbreviated
;; key words.) // key words.)
;; Make sure we have a sane request // Make sure we have a sane request
lda tokenise_work1 lda tokenise_work1
bne + bne !+
sec sec
rts rts
* !:
;; Initialise internal variables // Initialise internal variables
lda #$00 lda #$00
sta tokenise_work2 sta tokenise_work2
sta tokenise_work3 sta tokenise_work3
pack_char_loop: pack_char_loop:
;; Get the next char // Get the next char
lda $0200,x lda $0200,x
;; Work out what type of character we have, and thus // Work out what type of character we have, and thus
;; how we need to pack it. // how we need to pack it.
jsr get_packed_char_index jsr get_packed_char_index
cmp #$00 cmp #$00
bne not_exception_char bne not_exception_char
;; Char is an exception char. // Char is an exception char.
;; We need to either finish the previous byte with $xF, // We need to either finish the previous byte with $xF,
;; Or if there is no existing nybl, then we need to output // Or if there is no existing nybl, then we need to output
;; either $FE or $FF, depending on whether this is the last // either $FE or $FF, depending on whether this is the last
;; byte or not // byte or not
lda tokenise_work3 lda tokenise_work3
bne have_nybl_before_exception_char bne have_nybl_before_exception_char
;; No nybl exists before the exception char, so prefix with $FE or $FF // No nybl exists before the exception char, so prefix with $FE or $FF
;; based on whether we are at the end of the input string or not // based on whether we are at the end of the input string or not
inx inx
lda tokenise_work1 lda tokenise_work1
cmp #$01 cmp #$01
beq at_end beq at_end
lda #$FF lda #$FF
.byte $2C .byte $2C
at_end: LDA #$FE at_end:
lda #$FE
dex dex
jsr write_unpacked_char jsr write_unpacked_char
;; Fall through // Fall through
output_exception_byte: output_exception_byte:
lda $0200,x lda $0200,x
@@ -78,18 +79,18 @@ output_exception_byte:
jmp consider_next_char jmp consider_next_char
have_nybl_before_exception_char: have_nybl_before_exception_char:
;; Or existing byte with #$0F, and clear nybl flag // Or existing byte with #$0F, and clear nybl flag
ldy tokenise_work2 ldy tokenise_work2
lda $0100,y lda $0100,y
ora #$0f ora #$0f
sta $0100,y sta $0100,y
inc tokenise_work2 inc tokenise_work2
;; FALL THROUGH // FALL THROUGH
write_literal_and_terminate_if_required: write_literal_and_terminate_if_required:
;; Clear have nybl flag // Clear have nybl flag
lda #$00 lda #$00
sta tokenise_work3 sta tokenise_work3
@@ -99,19 +100,19 @@ write_literal_and_terminate_if_required:
jmp end_string_if_required jmp end_string_if_required
end_string_if_required: end_string_if_required:
;; Check if X points to last char of string to be packed // Check if X points to last char of string to be packed
inx inx
lda tokenise_work1 lda tokenise_work1
cmp #$01 cmp #$01
beq + beq !+
dex dex
jmp consider_next_char jmp consider_next_char
* !:
dex dex
;; Fall through // Fall through
end_string: end_string:
;; Write end of string sequence if required // Write end of string sequence if required
lda #$00 lda #$00
jsr write_unpacked_char jsr write_unpacked_char
rts rts
@@ -124,53 +125,53 @@ write_unpacked_char:
rts rts
not_exception_char: not_exception_char:
;; It wasn't an exception char, so write the symbol out // It wasn't an exception char, so write the symbol out
cmp #$10 cmp #$10
bcs whole_byte_symbol bcs whole_byte_symbol
;; Nybl encoded value: Put in upper half or lower half of a byte? // Nybl encoded value: Put in upper half or lower half of a byte?
ldy tokenise_work3 ldy tokenise_work3
bne store_low_nybl bne store_low_nybl
;; Store in high nybl -- so shift it into the hi nybl // Store in high nybl -- so shift it into the hi nybl
asl asl
asl asl
asl asl
asl asl
ldy tokenise_work2 ldy tokenise_work2
sta $0100,y sta $0100,y
bne stored_nybl ; Must be taken, as A cannot be $00 bne stored_nybl // Must be taken, as A cannot be $00
store_low_nybl: store_low_nybl:
;; Low nybl gets added to high nybl already stored in the byte // Low nybl gets added to high nybl already stored in the byte
ldy tokenise_work2 ldy tokenise_work2
ora $0100,y ora $0100,y
sta $0100,y sta $0100,y
stored_nybl: stored_nybl:
;; Now toggle the nybl flag // Now toggle the nybl flag
lda tokenise_work3 lda tokenise_work3
eor #$ff eor #$ff
sta tokenise_work3 sta tokenise_work3
;; And advance the offset if we filled this byte up // And advance the offset if we filled this byte up
bne consider_next_char ; Taken if byte has a nybl free, i.e., don't advance pointer while half byte remains free bne consider_next_char // Taken if byte has a nybl free, i.e., don't advance pointer while half byte remains free
;; Count the filled up byte // Count the filled up byte
inc tokenise_work2 inc tokenise_work2
;; Add termination byte if required // Add termination byte if required
;; (This re-writes the same byte again, which we don't care about) // (This re-writes the same byte again, which we don't care about)
jmp end_string_if_required jmp end_string_if_required
whole_byte_symbol: whole_byte_symbol:
;; It's a $Fx symbol. // It's a $Fx symbol.
;; But if we have a nybl to flush, then we handle it like // But if we have a nybl to flush, then we handle it like
;; a full exception character // a full exception character
ldy tokenise_work3 ldy tokenise_work3
beq nothing_to_flush beq nothing_to_flush
;; Set low nybl to $F to mark next byte as literal // Set low nybl to $F to mark next byte as literal
ldy tokenise_work2 ldy tokenise_work2
lda $0100,y lda $0100,y
ora #$0f ora #$0f
@@ -180,30 +181,30 @@ whole_byte_symbol:
jmp write_literal_and_terminate_if_required jmp write_literal_and_terminate_if_required
nothing_to_flush: nothing_to_flush:
;; Write the symbol as it is, or the literal // Write the symbol as it is, or the literal
;; if it has been passed to us via fall-through // if it has been passed to us via fall-through
jsr write_unpacked_char jsr write_unpacked_char
jmp end_string_if_required jmp end_string_if_required
consider_next_char: consider_next_char:
;; Pack next char // Pack next char
inx inx
dec tokenise_work1 dec tokenise_work1
beq + beq !+
jmp pack_char_loop jmp pack_char_loop
* !:
;; Add 1 to length if nybl waiting to be flushed // Add 1 to length if nybl waiting to be flushed
;; (but leave flag set so the caller knows if the // (but leave flag set so the caller knows if the
;; bottom nybl might be different if the string were // bottom nybl might be different if the string were
;; longer). // longer).
lda tokenise_work3 lda tokenise_work3
beq + beq !+
inc tokenise_work2 inc tokenise_work2
rts rts
* !:
;; Last byte was full, so we need at $00 on the end // Last byte was full, so we need at $00 on the end
;; (unless a $FE token was written 2 bytes ago) // (unless a $FE token was written 2 bytes ago)
ldy tokenise_work2 ldy tokenise_work2
iny iny
lda #$00 lda #$00
@@ -213,21 +214,21 @@ consider_next_char:
rts rts
get_packed_char_index: get_packed_char_index:
;; Find char in A in the packed char list, and return // Find char in A in the packed char list, and return
;; $1 - $E, $F1 - $FD if the charactar is abbreviable, // $1 - $E, $F1 - $FD if the charactar is abbreviable,
;; or else return $00 if the character has to be stored literally. // or else return $00 if the character has to be stored literally.
;; Y register and A are modified, as are processor flags. // Y register and A are modified, as are processor flags.
ldy #$00 ldy #$00
find_char_loop: find_char_loop:
cmp packed_message_chars,y cmp packed_message_chars,y
bne not_a_match bne not_a_match
enumerate: enumerate:
;; Is it a nybl abbreviable char? // Is it a nybl abbreviable char?
cpy #14 cpy #14
bcs not_nybl_char bcs not_nybl_char
;; Yes, so add 1 and return it // Yes, so add 1 and return it
iny iny
tya tya
rts rts
@@ -235,9 +236,9 @@ enumerate:
not_nybl_char: not_nybl_char:
cpy #27 cpy #27
bcs not_a_match bcs not_a_match
;; It's a $Fx character. // It's a $Fx character.
;; Since the lowest index is $E, and it should be encoded as $F1 // Since the lowest index is $E, and it should be encoded as $F1
;; we need to add $E3 // we need to add $E3
tya tya
clc clc
adc #$E3 adc #$E3
@@ -245,10 +246,10 @@ not_nybl_char:
not_a_match: not_a_match:
iny iny
;; Loop until we find it, or we discover it isn't // Loop until we find it, or we discover it isn't
;; a character with a special encoding // a character with a special encoding
cpy #27 cpy #27
bne find_char_loop bne find_char_loop
;; Not a char that we can pack, so return 0 // Not a char that we can pack, so return 0
lda #$00 lda #$00
rts rts
+3 -3
View File
@@ -1,5 +1,5 @@
;; Return C=1 if a pointer in BASIC memory space is NULL, else C=0 // Return C=1 if a pointer in BASIC memory space is NULL, else C=0
;; X = ZP pointer to check // X = ZP pointer to check
peek_pointer_null_check: peek_pointer_null_check:
ldy #$00 ldy #$00
@@ -11,7 +11,7 @@ peek_pointer_null_check:
cmp #$00 cmp #$00
bne ptr_not_null bne ptr_not_null
;; Pointer is NULL // Pointer is NULL
clc clc
rts rts
ptr_not_null: ptr_not_null:
+23 -22
View File
@@ -1,26 +1,27 @@
;; Works similar to $BDCD in original C64 BASIC // Works similar to $BDCD in original C64 BASIC
;; XXX Should eventually get replaced by a more flexible and optimal routine. // XXX Should eventually get replaced by a more flexible and optimal routine.
;; Temp result gets written to $0100-$0104 // Temp result gets written to $0100-$0104
print_integer: print_integer:
pha pha
txa txa
pha pha
;; Clear temporary output // Clear temporary output
lda #$00 lda #$00
ldy #5 ldy #5
* sta $0100,y !: sta $0100,y
dey dey
bpl - bpl !-
pla pla
ldy #23 ; 8 x 3 - 1 = offset of last digit of 128 ldy #23 // 8 x 3 - 1 = offset of last digit of 128
lo_loop: lo_loop:
cmp #$7f cmp #$7f
bcc bit_clear bcc bit_clear
;; Bit set, so add the digits // Bit set, so add the digits
pha pha
ldx #2 ldx #2
clc clc
@@ -45,16 +46,16 @@ next_lo_bit:
bcc lo_loop bcc lo_loop
;; Now do the same for upper byte // Now do the same for upper byte
pla pla
ldy #39 ; 8 x 5 - 1 = offset of last digit of 32768 ldy #39 // 8 x 5 - 1 = offset of last digit of 32768
hi_loop: hi_loop:
cmp #$7f cmp #$7f
bcc bit_clear_hi bcc bit_clear_hi
;; Bit set, so add the digits // Bit set, so add the digits
pha pha
ldx #4 ldx #4
clc clc
@@ -82,12 +83,12 @@ next_hi_bit:
fix_carry: fix_carry:
;; Deal with any carries // Deal with any carries
ldx #3 ldx #3
carry_fix_loop: carry_fix_loop:
lda $0101,x lda $0101,x
cmp #10 cmp #10
bcc + bcc !+
inc $0100,x inc $0100,x
sec sec
sbc #10 sbc #10
@@ -95,30 +96,30 @@ carry_fix_loop:
jmp carry_fix_loop jmp carry_fix_loop
* dex !: dex
bpl carry_fix_loop bpl carry_fix_loop
post_carry: post_carry:
;; Got digits. // Got digits.
;; Skip leading zeros, and print the resulting number // Skip leading zeros, and print the resulting number
;; Skip leading zeros // Skip leading zeros
ldy #0 ldy #0
* lda $0100,y !: lda $0100,y
bne found_start_of_number bne found_start_of_number
iny iny
cpy #4 cpy #4
bne - bne !-
found_start_of_number: found_start_of_number:
;; Print digits // Print digits
* lda $0100,y !: lda $0100,y
ora #$30 ora #$30
jsr JCHROUT jsr JCHROUT
iny iny
cpy #5 cpy #5
bne - bne !-
rts rts
+56 -55
View File
@@ -1,16 +1,17 @@
;; This routine prints messages that have been packed // This routine prints messages that have been packed
;; using the make_error_tables program. // using the make_error_tables program.
;; The general idea is to save space in the ROM. // The general idea is to save space in the ROM.
// The output of make_error_tables is written to packed_messages.s, and
// contains the following:
//
// packed_message_words - List of nybl packed words.
// packed_message_tokens - List of tokens that get joined to make messages
// packed_message_chars - List of characters in messages sorted by frequency.
;; The output of make_error_tables is written to packed_messages.s, and
;; contains the following:
;;
;; packed_message_words - List of nybl packed words.
;; packed_message_tokens - List of tokens that get joined to make messages
;; packed_message_chars - List of characters in messages sorted by frequency.
print_packed_message: print_packed_message:
;; X = message number // .X = message number
lda #$ff lda #$ff
ldy #$ff ldy #$ff
@@ -20,22 +21,22 @@ packed_message_search:
beq found_message_in_token_stream beq found_message_in_token_stream
lda packed_message_tokens,y lda packed_message_tokens,y
cmp #$ff cmp #$ff
bne + bne !+
dex dex
* !:
cpy #$ff cpy #$ff
bne packed_message_search bne packed_message_search
;; Could not find message // Could not find message
sec sec
rts rts
found_message_in_token_stream: found_message_in_token_stream:
;; Now print each word in the message // Now print each word in the message
tya tya
pha pha
lda packed_message_tokens,y lda packed_message_tokens,y
cmp #$ff cmp #$ff
beq + beq !+
jsr print_packed_word jsr print_packed_word
lda #$20 lda #$20
jsr JCHROUT jsr JCHROUT
@@ -43,50 +44,50 @@ found_message_in_token_stream:
tay tay
iny iny
bne found_message_in_token_stream bne found_message_in_token_stream
* !:
pla pla
;; Rub out space at the end // Rub out space at the end
lda #$14 lda #$14
jsr JCHROUT jsr JCHROUT
rts rts
print_packed_word: print_packed_word:
;; A = the word to print // A = the word to print
tax tax
;; Setup pointer to packed words // Setup pointer to packed words
lda #<packed_message_words lda #<packed_message_words
sta temp_string_ptr+0 sta temp_string_ptr+0
lda #>packed_message_words lda #>packed_message_words
sta temp_string_ptr+1 sta temp_string_ptr+1
;; Find the word in the list // Find the word in the list
ldy #$ff ldy #$ff
packed_word_search: packed_word_search:
iny iny
cpx #$00 cpx #$00
beq found_packed_word beq found_packed_word
;; $x0 is an end of work marker // $x0 is an end of work marker
lda (temp_string_ptr),y lda (temp_string_ptr),y
and #$0f and #$0f
cmp #$00 cmp #$00
bne + bne !+
dex dex
* !:
;; $FE $xx is an end of work marker // $FE $xx is an end of work marker
lda (temp_string_ptr),y lda (temp_string_ptr),y
cmp #$fe cmp #$fe
bne + bne !+
dex dex
iny ; skip next byte iny // skip next byte
* !:
cmp #$ff cmp #$ff
bne + bne !+
iny ; skip next byte iny // skip next byte
* !:
;; Advance to next page if required // Advance to next page if required
cpy #$ff cpy #$ff
bne packed_word_search bne packed_word_search
inc temp_string_ptr+1 inc temp_string_ptr+1
@@ -94,8 +95,8 @@ packed_word_search:
found_packed_word: found_packed_word:
;; Get pointer to start of packed word // Get pointer to start of packed word
;; Make sure we don't wrap on a page boundary // Make sure we don't wrap on a page boundary
tya tya
clc clc
adc temp_string_ptr+0 adc temp_string_ptr+0
@@ -108,10 +109,10 @@ print_packed_string:
ldy #$ff ldy #$ff
next_packed_word_char: next_packed_word_char:
;; Y = offset into packed word data - 1 // .Y = offset into packed word data - 1
iny iny
;; Check for end of word // Check for end of word
lda (temp_string_ptr),y lda (temp_string_ptr),y
cmp #$00 cmp #$00
beq end_of_packed_word beq end_of_packed_word
@@ -122,31 +123,31 @@ next_packed_word_char:
and #$f0 and #$f0
beq end_of_packed_word beq end_of_packed_word
;; Check if it is an uncommon char // Check if it is an uncommon char
lda (temp_string_ptr),y lda (temp_string_ptr),y
and #$f0 and #$f0
cmp #$f0 cmp #$f0
beq is_uncommon_char beq is_uncommon_char
;; Is not an uncommon char, so get char of upper nybl // Is not an uncommon char, so get char of upper nybl
lda (temp_string_ptr),y lda (temp_string_ptr),y
;; Put high nybl into low bits of X // Put high nybl into low bits of X
lsr lsr
lsr lsr
lsr lsr
lsr lsr
tax tax
;; Save Y so it doesn't get clobbered by CHROUT // Save Y so it doesn't get clobbered by CHROUT
tya tya
pha pha
;; X=1-14 = first 14 chars, so subtract one // X=1-14 = first 14 chars, so subtract one
lda packed_message_chars-1,x lda packed_message_chars-1,x
jsr JCHROUT jsr JCHROUT
;; See if there is a char in the low nybl to print // See if there is a char in the low nybl to print
pla pla
tay tay
lda (temp_string_ptr),y lda (temp_string_ptr),y
@@ -156,31 +157,31 @@ next_packed_word_char:
beq no_lo_nybl_char beq no_lo_nybl_char
has_lo_nybl_char: has_lo_nybl_char:
;; We need to print the low nybl char as well // We need to print the low nybl char as well
tax tax
tya tya
pha pha
;; Skip lower nybls of $F or $0 in nybl packed // Skip lower nybls of $F or $0 in nybl packed
;; bytes, as these do not encode characters // bytes, as these do not encode characters
cpx #$f cpx #$f
beq + beq !+
has_nybl: has_nybl:
cpx #0 cpx #0
beq + beq !+
;; X=1-14 = first 14 chars, so subtract one // X=1-14 = first 14 chars, so subtract one
lda packed_message_chars-1,x lda packed_message_chars-1,x
jsr JCHROUT jsr JCHROUT
* !:
pla pla
tay tay
;; FALL THROUGH // FALLTHROUGH
no_lo_nybl_char: no_lo_nybl_char:
;; If current byte has $0F in low nybl, then the next // If current byte has $0F in low nybl, then the next
;; byte is a whole byte. // byte is a whole byte.
lda (temp_string_ptr),y lda (temp_string_ptr),y
and #$0f and #$0f
cmp #$0f cmp #$0f
@@ -190,7 +191,7 @@ ready_for_next_char:
cpy #$ff cpy #$ff
bne next_packed_word_char bne next_packed_word_char
end_of_packed_word: end_of_packed_word:
;; Hit end of packed data // Hit end of packed data
rts rts
last_literal: last_literal:
@@ -202,7 +203,7 @@ next_is_literal_char:
jmp ready_for_next_char jmp ready_for_next_char
unpack_literal_char: unpack_literal_char:
;; Output the literal char, and ready for next char // Output the literal char, and ready for next char
iny iny
tya tya
pha pha
@@ -213,14 +214,14 @@ unpack_literal_char:
rts rts
is_uncommon_char: is_uncommon_char:
;; Lower nybl has offset into low-frequency part of the table // Lower nybl has offset into low-frequency part of the table
lda (temp_string_ptr),y lda (temp_string_ptr),y
and #$0f and #$0f
clc clc
adc #14 adc #14
;; We need to print the low nybl char as well // We need to print the low nybl char as well
tax tax
tya tya
pha pha
+38 -38
View File
@@ -1,17 +1,17 @@
;; printf()-like routine for simplifying debugging // printf()-like routine for simplifying debugging
;; Prints the literal zero-terminated string that follows, // Prints the literal zero-terminated string that follows,
;; which may also include special tokens that allow // which may also include special tokens that allow
;; printing of hex byte and word values stored at the indicated // printing of hex byte and word values stored at the indicated
;; addresses. // addresses.
;; .byte 1,$byte = display byte as hex // .byte 1,$byte = display byte as hex
;; .byte 2,$low,$hi = display word as hex // .byte 2,$low,$hi = display word as hex
;; .byte $f0+n,$low,$hi = display byte at $hi$lo+n as hex // .byte $f0+n,$low,$hi = display byte at $hi$lo+n as hex
printf: printf:
;; Temporary storage is between end of screen at $0400 // Temporary storage is between end of screen at $0400
;; and the sprite pointers at $7f8 // and the sprite pointers at $7f8
sta $7f0 sta $7f0
stx $7f1 stx $7f1
sty $7f2 sty $7f2
@@ -19,14 +19,14 @@ printf:
pla pla
sta $7f3 sta $7f3
;; Set up read routine // Set up read routine
lda #$ad ; LDA $nnnn lda #$ad // LDA $nnnn
sta $7f4 sta $7f4
lda #$60 lda #$60
sta $7f7 ; RTS sta $7f7 // RTS
;; Get PC of caller from the stack, so that // Get PC of caller from the stack, so that
;; we can parse through it // we can parse through it
pla pla
clc clc
adc #$01 adc #$01
@@ -39,8 +39,8 @@ printf_loop:
jsr $7f4 jsr $7f4
cmp #$00 cmp #$00
bne printf_continues bne printf_continues
;; Put return address on stack and restore // Put return address on stack and restore
;; registers // registers
lda $7f6 lda $7f6
pha pha
lda $7f5 lda $7f5
@@ -56,33 +56,33 @@ printf_loop:
printf_continues: printf_continues:
cmp #$01 cmp #$01
bne not_hexbyte bne not_hexbyte
;; Print a hex byte // Print a hex byte
;; Skip the token // Skip the token
jsr printf_advance jsr printf_advance
;; Read the low byte // Read the low byte
jsr $7f4 jsr $7f4
;; Print as hex // Print as hex
jsr printf_printhexbyte jsr printf_printhexbyte
jmp printf_nextchar jmp printf_nextchar
not_hexbyte: not_hexbyte:
cmp #$02 cmp #$02
bne not_hexword bne not_hexword
;; Print a hex word // Print a hex word
;; Skip the token // Skip the token
jsr printf_advance jsr printf_advance
jsr printf_advance jsr printf_advance
;; Read the high byte // Read the high byte
jsr $7f4 jsr $7f4
;; Print as hex // Print as hex
jsr printf_printhexbyte jsr printf_printhexbyte
;; Skip the token // Skip the token
jsr printf_retreat jsr printf_retreat
;; Read the low byte // Read the low byte
jsr $7f4 jsr $7f4
;; Print as hex // Print as hex
jsr printf_printhexbyte jsr printf_printhexbyte
jsr printf_advance jsr printf_advance
jmp printf_nextchar jmp printf_nextchar
@@ -91,11 +91,11 @@ not_hexword:
cmp #$f0 cmp #$f0
bcc not_pointer bcc not_pointer
;; Treat two-byte arg as base address // Treat two-byte arg as base address
;; and lower 4 bits of token as offset from // and lower 4 bits of token as offset from
;; that location. // that location.
;; Get offset // Get offset
and #$0f and #$0f
tay tay
@@ -111,7 +111,7 @@ not_hexword:
jmp printf_nextchar jmp printf_nextchar
not_pointer: not_pointer:
;; Print character // Print character
jsr JCHROUT jsr JCHROUT
printf_nextchar: printf_nextchar:
@@ -120,15 +120,15 @@ printf_nextchar:
jmp printf_loop jmp printf_loop
printf_advance: printf_advance:
;; Advance pointer to next character // Advance pointer to next character
inc $7f5 inc $7f5
bne + bne !+
inc $7f6 inc $7f6
* !:
rts rts
printf_retreat: printf_retreat:
;; Retreat pointer to previous char // Retreat pointer to previous char
lda $7f5 lda $7f5
sec sec
sbc #1 sbc #1
@@ -139,7 +139,7 @@ printf_retreat:
rts rts
printf_printhexbyte: printf_printhexbyte:
;; Print the hex value in .A as two digits, idea by Haubitze // Print the hex value in .A as two digits, idea by Haubitze
sed sed
pha pha
lsr lsr
+2 -2
View File
@@ -1,6 +1,6 @@
ready_message: ready_message:
;; See src/make_error_tables.c for packed message handling // See src/make_error_tables.c for packed message handling
;; information. // information.
ldx #29 ldx #29
jmp print_packed_message jmp print_packed_message
+10 -10
View File
@@ -1,19 +1,19 @@
select_device: select_device:
;; Take last device number, make sure it's a drive - 8 or above. Above 30, // Take last device number, make sure it's a drive - 8 or above. Above 30,
;; although illegal for IEC we also consider a drive, as they exists // although illegal for IEC we also consider a drive, as they exists
;; drivers assigning these numbers to CBM-DOS capable devices - like some // drivers assigning these numbers to CBM-DOS capable devices - like some
;; IEEE-488 carts. // IEEE-488 carts.
;; //
;; If current device is not a drive, set device to 8 (first drive number) // If current device is not a drive, set device to 8 (first drive number)
;; Device number is left in X, for SETFLS Kernal routine // Device number is left in X, for SETFLS Kernal routine
;; Note: if tape support is introduced here, make sure DOS wedge won't get broken // Note: if tape support is introduced here, make sure DOS wedge won't get broken
ldx current_device_number ldx current_device_number
cpx #$08 cpx #$08
bcs + bcs !+
ldx #$08 ldx #$08
* !:
rts rts
+92 -92
View File
@@ -1,18 +1,18 @@
;; Tokenise a line of BASIC // Tokenise a line of BASIC
;; Stored at $0200 // Stored at $0200
;; Length in tokenise_work1 // Length in tokenise_work1
tokenise_line: tokenise_line:
;; We need to consider each offset in the string to see if it matches // We need to consider each offset in the string to see if it matches
;; a token. No BASIC keyword is > 7 bytes, so we need to start with that // a token. No BASIC keyword is > 7 bytes, so we need to start with that
;; length (or remaining length of string) and count our way back down. // length (or remaining length of string) and count our way back down.
;; This means we need separate start and end points to keep track of. // This means we need separate start and end points to keep track of.
;; $0110 = offset into string // $0110 = offset into string
;; $0111 = number of bytes to pack // $0111 = number of bytes to pack
;; $0112 = offset into tokenised output // $0112 = offset into tokenised output
;; $0113 = length of raw string // $0113 = length of raw string
lda #$00 lda #$00
sta $0110 sta $0110
@@ -24,56 +24,56 @@ tokenise_line:
tokenise_char: tokenise_char:
;; Check if we have reached end of the line? // Check if we have reached end of the line?
lda $0110 lda $0110
cmp $0113 cmp $0113
bne + bne !+
;; End of line reached // End of line reached
;; Finished tokenising line // Finished tokenising line
;; Update tokenise_work1 and terminate with null // Update tokenise_work1 and terminate with null
ldx $0112 ldx $0112
lda #$00 lda #$00
sta $0200,x sta $0200,x
stx tokenise_work1 stx tokenise_work1
;; Clear quote mode flag that is also used by KERNAL for screen display // Clear quote mode flag that is also used by KERNAL for screen display
lda #$00 lda #$00
sta quote_mode_flag sta quote_mode_flag
rts rts
* !:
;; More to do // More to do
;; Maximum keyword length // Maximum keyword length
lda #7 lda #7
sta $0111 sta $0111
tokenise_char_loop: tokenise_char_loop:
;; Pack the word from the start (start = X, raw len = tokenise_work1) // Pack the word from the start (start = X, raw len = tokenise_work1)
;; Returns packed length in tokenise_work2 and writes the packed // Returns packed length in tokenise_work2 and writes the packed
;; word at $0100+ // word at $0100+
ldx $0110 ldx $0110
lda $0200,x lda $0200,x
cmp #$22 cmp #$22
bne tk_not_quote bne tk_not_quote
;; Quote // Quote
lda quote_mode_flag lda quote_mode_flag
eor #$ff eor #$ff
sta quote_mode_flag sta quote_mode_flag
jmp tk_literal_char jmp tk_literal_char
tk_not_quote: tk_not_quote:
;; Check for literal characters in various ranges // Check for literal characters in various ranges
;; (This just speeds the tokeniser up, by avoiding the packed token search // (This just speeds the tokeniser up, by avoiding the packed token search
;; for such characters). // for such characters).
;; SPACE and punctuation before +,- and * // SPACE and punctuation before +,- and *
cmp #$2a cmp #$2a
bcc tk_literal_char bcc tk_literal_char
;; Don't try to tokenise digits // Don't try to tokenise digits
cmp #$30 cmp #$30
bcc tk_might_be_keyword bcc tk_might_be_keyword
cmp #$3a cmp #$3a
@@ -81,41 +81,41 @@ tk_not_quote:
jmp tk_literal_char jmp tk_literal_char
tk_might_be_keyword: tk_might_be_keyword:
;; Don't tokenise in quote mode // Don't tokenise in quote mode
lda quote_mode_flag lda quote_mode_flag
bne tk_literal_char bne tk_literal_char
;; Pack string // Pack string
ldx $0110 ldx $0110
lda $0111 lda $0111
sta tokenise_work1 sta tokenise_work1
;; XXX - We should implement an optimisation where we // XXX - We should implement an optimisation where we
;; trim the last symbol of successively, instead of re-packing the word // trim the last symbol of successively, instead of re-packing the word
;; again with one less char each time. // again with one less char each time.
;; XXX - We should limit the word length to the length of interesting chars // XXX - We should limit the word length to the length of interesting chars
;; that are available. // that are available.
jsr pack_word jsr pack_word
lda tokenise_work2 lda tokenise_work2
cmp #$10 cmp #$10
bcc + bcc !+
;; Packed string too long // Packed string too long
jmp do_STRING_TOO_LONG_error jmp do_STRING_TOO_LONG_error
* !:
;; Search for it in keywords // Search for it in keywords
jsr keyword_search jsr keyword_search
;; Did we find a keyword? // Did we find a keyword?
bcc found_token_in_line bcc found_token_in_line
;; Nope, so try shorter // Nope, so try shorter
dec $0111 dec $0111
bne tokenise_char_loop bne tokenise_char_loop
tk_literal_char: tk_literal_char:
;; Is not a token, so copy to output verbatim // Is not a token, so copy to output verbatim
ldx $0110 ldx $0110
ldy $0112 ldy $0112
lda $0200,x lda $0200,x
@@ -123,68 +123,68 @@ tk_literal_char:
inc $0112 inc $0112
inc $0110 inc $0110
;; Tokenise next char // Tokenise next char
jmp tokenise_char jmp tokenise_char
found_token_in_line: found_token_in_line:
;; Got a token, so write it out // Got a token, so write it out
ldx $0112 ldx $0112
sta $0200,x sta $0200,x
inx inx
stx $0112 stx $0112
;; If it is REM, then lock us in quote mode to the end of the line // If it is REM, then lock us in quote mode to the end of the line
cmp #$8f cmp #$8f
bne not_rem bne not_rem
sta quote_mode_flag sta quote_mode_flag
not_rem: not_rem:
;; Now skip over the length of the token // Now skip over the length of the token
lda $0110 lda $0110
clc clc
adc $0111 adc $0111
sta $0110 sta $0110
;; See if there is more of the line left to process // See if there is more of the line left to process
jmp tokenise_char jmp tokenise_char
;; Search for word in keyword list // Search for word in keyword list
;; The packed form is canonical, so we can search for the keyword while // The packed form is canonical, so we can search for the keyword while
;; it remains compressed. This also saves a little time. // it remains compressed. This also saves a little time.
;; Algorithm is simply to find matching first bytes, and then look for // Algorithm is simply to find matching first bytes, and then look for
;; the rest being a match. // the rest being a match.
keyword_search: keyword_search:
;; Search for the compressed keyword stored at $0100 in the list // Search for the compressed keyword stored at $0100 in the list
;; of compressed keywords // of compressed keywords
;; tokenise_work1 = offset in line of input // tokenise_work1 = offset in line of input
;; tokenise_work2 = length of token we are matching // tokenise_work2 = length of token we are matching
;; tokenise_work3 = offset in token list // tokenise_work3 = offset in token list
;; load_or_verify_or_tokenise_work5 = temporary work space // load_or_verify_or_tokenise_work5 = temporary work space
;; X and Y registers used as temporary space. // X and Y registers used as temporary space.
;; returns C=1 if no matching token, else C=0 and A=token // returns C=1 if no matching token, else C=0 and A=token
lda #$00 lda #$00
sta tokenise_work1 sta tokenise_work1
sta tokenise_work3 sta tokenise_work3
next_kw_offset: next_kw_offset:
;; Advance offset in compressed keyword list, to see if a match // Advance offset in compressed keyword list, to see if a match
;; BEGINS here // BEGINS here
;; Get count of bytes to compare // Get count of bytes to compare
lda tokenise_work2 lda tokenise_work2
sta load_or_verify_or_tokenise_work5 sta load_or_verify_or_tokenise_work5
;; Load current position // Load current position
ldy tokenise_work3 ldy tokenise_work3
ldx tokenise_work1 ldx tokenise_work1
;; Advance offset in compressed token list, and stop at the end // Advance offset in compressed token list, and stop at the end
inc tokenise_work3 inc tokenise_work3
lda tokenise_work3 lda tokenise_work3
cmp #packed_keyword_table_len cmp #packed_keyword_table_len
@@ -194,75 +194,75 @@ next_in_match:
lda $0100,x lda $0100,x
cmp packed_keywords,y cmp packed_keywords,y
bne next_kw_offset bne next_kw_offset
;; Advance to next chars in source and target // Advance to next chars in source and target
inx inx
iny iny
dec load_or_verify_or_tokenise_work5 ; Have we compared all bytes yet? dec load_or_verify_or_tokenise_work5 // Have we compared all bytes yet?
bne next_in_match bne next_in_match
;; Keyword matches! // Keyword matches!
;; Now make sure we started on a keyword boundary // Now make sure we started on a keyword boundary
;; (we know we finished on one, because of the structure of the compressed // (we know we finished on one, because of the structure of the compressed
;; keyword data). // keyword data).
;; Offset 0 // Offset 0
;; previous byte is $x0 // previous byte is $x0
;; two byte prior is $FE // two byte prior is $FE
;; Get offset of first byte of this token // Get offset of first byte of this token
ldx tokenise_work3 ldx tokenise_work3
dex ; pointer points one late, so rewind it dex // pointer points one late, so rewind it
;; At start of list? // At start of list?
cpx #$00 cpx #$00
beq word_boundary beq word_boundary
dex dex
;; Previous byte is $x0 end token? // Previous byte is $x0 end token?
lda packed_keywords,x lda packed_keywords,x
and #$0f and #$0f
beq word_boundary beq word_boundary
dex dex
;; Uber-previouss byte is $FE final literal token? // Uber-previouss byte is $FE final literal token?
lda packed_keywords,x lda packed_keywords,x
cmp #$fe cmp #$fe
beq word_boundary beq word_boundary
;; Not a word boundary, so ignore // Not a word boundary, so ignore
jmp next_kw_offset jmp next_kw_offset
word_boundary: word_boundary:
;; Found a token whose offset is in tokenise_work3 // Found a token whose offset is in tokenise_work3
;; Now trace back to the start of the compressed keyword list // Now trace back to the start of the compressed keyword list
;; to work out what keyword number we are, so that we can return // to work out what keyword number we are, so that we can return
;; the token number. // the token number.
ldy #$80 ldy #$80
token_count_loop: token_count_loop:
lda packed_keywords,x lda packed_keywords,x
cmp #$fe cmp #$fe
bne + bne !+
iny iny
* !:
and #$0f and #$0f
cmp #$00 cmp #$00
bne + bne !+
iny iny
* !:
cpx #$00 cpx #$00
beq + beq !+
dex dex
jmp token_count_loop jmp token_count_loop
* !:
tya tya
clc clc
rts rts
done_searching_for_token: done_searching_for_token:
;; No token found // No token found
sec sec
lda #$00 lda #$00
rts rts
+26 -29
View File
@@ -1,19 +1,19 @@
;; IMPORTANT: // IMPORTANT:
;; These routines lengths cannot be changed without changing // These routines lengths cannot be changed without changing
;; the aliases for peek_under_roms, poke_under_roms etc // the aliases for peek_under_roms, poke_under_roms etc
;; in ,aliases.s. // in ,aliases.s.
;; Thus those addresses are expressed using formulae. // Thus those addresses are expressed using formulae.
install_ram_routines: install_ram_routines:
;; Copy routines into place // Copy routines into place
ldx #ram_routines_len-1 ldx #ram_routines_end-ram_routines_start-1
* !:
lda ram_routines_start,x lda ram_routines_start,x
sta tiny_nmi_handler,x sta tiny_nmi_handler,x
dex dex
bpl - bpl !-
;; Point NMI handler to tiny_nmi_handler // Point NMI handler to tiny_nmi_handler
lda #<tiny_nmi_handler lda #<tiny_nmi_handler
sta $FFFE sta $FFFE
lda #>tiny_nmi_handler lda #>tiny_nmi_handler
@@ -23,14 +23,14 @@ install_ram_routines:
ram_routines_start: ram_routines_start:
;; XXX - Routine order must match that of the KERNAL version of the file. // XXX - Routine order must match that of the KERNAL version of the file.
;; (since it has fewer routines) // (since it has fewer routines)
tiny_nmi_handler_routine: tiny_nmi_handler_routine:
inc missed_nmi_flag inc missed_nmi_flag
rti rti
peek_under_roms_routine: peek_under_roms_routine:
php php
; Offset of arg of lda ($00),y // Offset of arg of lda ($00),y
stx peek_under_roms+pa-peek_under_roms_routine+1 stx peek_under_roms+pa-peek_under_roms_routine+1
jsr memmap_allram jsr memmap_allram
pa: lda ($00),y pa: lda ($00),y
@@ -40,7 +40,7 @@ pa: lda ($00),y
poke_under_roms_routine: poke_under_roms_routine:
php php
; Offset of arg of lda ($00),y // Offset of arg of lda ($00),y
stx poke_under_roms+pb-poke_under_roms_routine+1 stx poke_under_roms+pb-poke_under_roms_routine+1
jsr memmap_allram jsr memmap_allram
pb: sta ($00),y pb: sta ($00),y
@@ -64,12 +64,12 @@ memmap_allram_routine:
rts rts
shift_mem_up_routine: shift_mem_up_routine:
;; Move memmove_size bytes from memmove_src to memmove_dst, // Move memmove_size bytes from memmove_src to memmove_dst,
;; where memmove_dst > memmove_src // where memmove_dst > memmove_src
;; This means we have to copy from the back end down. // This means we have to copy from the back end down.
;; This routine assumes the pointers are already pointed // This routine assumes the pointers are already pointed
;; to the end of the areas, and that Y is correctly initialised // to the end of the areas, and that Y is correctly initialised
;; to allow the copy to begin. // to allow the copy to begin.
php php
jsr memmap_allram jsr memmap_allram
smu1: smu1:
@@ -85,12 +85,12 @@ smu1:
jmp memmap_normal jmp memmap_normal
shift_mem_down_routine: shift_mem_down_routine:
;; Move memmove_size bytes from memmove_src to memmove_dst, // Move memmove_size bytes from memmove_src to memmove_dst,
;; where memmove_dst > memmove_src // where memmove_dst > memmove_src
;; This means we have to copy from the back end down. // This means we have to copy from the back end down.
;; This routine assumes the pointers are already pointed // This routine assumes the pointers are already pointed
;; to the end of the areas, and that Y is correctly initialised // to the end of the areas, and that Y is correctly initialised
;; to allow the copy to begin. // to allow the copy to begin.
php php
jsr memmap_allram jsr memmap_allram
smd1: smd1:
@@ -105,7 +105,4 @@ smd1:
plp plp
jmp memmap_normal jmp memmap_normal
ram_routines_end: ram_routines_end:
.alias ram_routines_len ram_routines_end-ram_routines_start
+88 -88
View File
@@ -1,161 +1,161 @@
;; START wedge support // START wedge support
wedge_dos: wedge_dos:
;; Close all the channels, so that wedge has full control // Close all the channels, so that wedge has full control
jsr JCLALL jsr JCLALL
;; Set file parameters, channel 15 is a typical one for commands // Set file parameters, channel 15 is a typical one for commands
jsr select_device ; sets X register jsr select_device // sets .X register
lda #$0F lda #$0F
ldy #$0F ldy #$0F
jsr JSETFLS jsr JSETFLS
;; Now we have to check what the user wants us to do // Now we have to check what the user wants us to do
;; Check if user asked for a status // Check if user asked for a status
ldy #$00 ldy #$00
lda (basic_current_statement_ptr), y lda (basic_current_statement_ptr), y
bne + bne !+
jmp wedge_dos_status ; XXX try to optimize this, perhaps move 'wedge_dos_status' above? jmp wedge_dos_status // XXX try to optimize this, perhaps move 'wedge_dos_status' above?
* !:
;; Check if asked for a directory // Check if asked for a directory
cmp #$24 cmp #$24
bne + bne !+
jmp wedge_dos_directory jmp wedge_dos_directory
* !:
;; Check if asked to change drive number, or if it is a regular command // Check if asked to change drive number, or if it is a regular command
cmp #$30 cmp #$30
bcc wedge_dos_command ; char code before 0 bcc wedge_dos_command // char code before 0
cmp #$3A cmp #$3A
bcs wedge_dos_command ; char code after 9 bcs wedge_dos_command // char code after 9
iny iny
lda (basic_current_statement_ptr), y lda (basic_current_statement_ptr), y
beq wedge_dos_change_drive ; end of buffer beq wedge_dos_change_drive // end of buffer
cmp #$20 cmp #$20
beq wedge_dos_change_drive beq wedge_dos_change_drive
jmp - jmp !-
wedge_dos_command: wedge_dos_command:
;; Provide command name // Provide command name
jsr wedge_dos_setnam jsr wedge_dos_setnam
jsr JSETNAM jsr JSETNAM
jsr JOPEN jsr JOPEN
bcc + bcc !+
jmp wedge_dos_basic_error ; XXX combine with other such jumps jmp wedge_dos_basic_error // XXX combine with other such jumps
* !:
;; Retrieve status, print it if not OK // Retrieve status, print it if not OK
jsr JCLALL jsr JCLALL
jsr wedge_dos_status_get jsr wedge_dos_status_get
lda BUF+0 lda BUF+0
cmp #$30 ; '0' cmp #$30 // '0'
bne wedge_dos_status_print bne wedge_dos_status_print
lda BUF+1 lda BUF+1
cmp #$30 ; '0' cmp #$30 // '0'
bne wedge_dos_status_print bne wedge_dos_status_print
;; Clean-up and exit // Clean-up and exit
jmp wedge_dos_clean_exit jmp wedge_dos_clean_exit
wedge_dos_change_drive: wedge_dos_change_drive:
;; Reuse the line number parser for device number retrieval // Reuse the line number parser for device number retrieval
jsr basic_parse_line_number jsr basic_parse_line_number
lda basic_line_number+1 lda basic_line_number+1
beq + beq !+
jmp do_ILLEGAL_QUANTITY_error jmp do_ILLEGAL_QUANTITY_error
* !:
lda basic_line_number+0 lda basic_line_number+0
cmp #$08 cmp #$08
bpl + bpl !+
bcs + bcs !+
jmp do_ILLEGAL_DEVICE_NUMBER_error jmp do_ILLEGAL_DEVICE_NUMBER_error
* !:
sta current_device_number sta current_device_number
jmp basic_end_of_line jmp basic_end_of_line
wedge_dos_status_get: wedge_dos_status_get:
;; Here the flow is mostly the same as in the example from // Here the flow is mostly the same as in the example from
;; https://codebase64.org/doku.php?id=base:reading_the_error_channel_of_a_disk_drive // https://codebase64.org/doku.php?id=base:reading_the_error_channel_of_a_disk_drive
;; Set remaining file parameters, open the channel // Set remaining file parameters, open the channel
lda #$00 ; empty file name lda #$00 // empty file name
jsr JSETNAM jsr JSETNAM
jsr JOPEN jsr JOPEN
bcc + bcc !+
jmp wedge_dos_basic_error ; XXX combine with other such jumps jmp wedge_dos_basic_error // XXX combine with other such jumps
* !:
;; Set channel for input // Set channel for input
ldx #$0F ldx #$0F
jsr JCHKIN jsr JCHKIN
bcc + bcc !+
jmp wedge_dos_basic_error ; XXX combine with other such jumps jmp wedge_dos_basic_error // XXX combine with other such jumps
* !:
ldy #$00 ldy #$00
* !:
cpy #$50 ; buffer overflow protection cpy #$50 // buffer overflow protection
beq + beq !+
jsr JREADST ; retrieve errors jsr JREADST // retrieve errors
;; XXX error in case of status != EOF // XXX error in case of status != EOF
;; Print out everything retrieved from the drive // Print out everything retrieved from the drive
bne + bne !+
jsr JCHRIN jsr JCHRIN
bcc wedge_dos_x1 bcc wedge_dos_x1
jmp wedge_dos_basic_error ; XXX try to optimize this jmp wedge_dos_basic_error // XXX try to optimize this
wedge_dos_x1: wedge_dos_x1:
sta BUF, y sta BUF, y
iny iny
jmp - jmp !-
* !:
rts rts
wedge_dos_status: wedge_dos_status:
jsr wedge_dos_status_get jsr wedge_dos_status_get
;; FALLTROUGH // FALLTROUGH
wedge_dos_status_print: wedge_dos_status_print:
;; Print buffered status // Print buffered status
ldx #$00 ldx #$00
* !:
dey dey
bmi + bmi !+
lda BUF, x lda BUF, x
jsr JCHROUT jsr JCHROUT
inx inx
bne - bne !-
* !:
;; Clean-up and exit // Clean-up and exit
jmp wedge_dos_clean_exit jmp wedge_dos_clean_exit
wedge_dos_directory: wedge_dos_directory:
;; First change the secondary address to the one suitable for // First change the secondary address to the one suitable for
;; directory loading // directory loading
lda #$00 ; logical device number lda #$00 // logical device number
ldx current_device_number ldx current_device_number
ldy #$60 ldy #$60
jsr JSETFLS jsr JSETFLS
;; Provide file name // Provide file name
jsr wedge_dos_setnam jsr wedge_dos_setnam
;; Open the file // Open the file
jsr JOPEN jsr JOPEN
bcs wedge_dos_basic_error bcs wedge_dos_basic_error
;; Set channel for file reading // Set channel for file reading
ldx #$00 ldx #$00
jsr JCHKIN jsr JCHKIN
bcs wedge_dos_basic_error bcs wedge_dos_basic_error
;; Ignore start address (2 first bytes) - XXX check for errors // Ignore start address (2 first bytes) - XXX check for errors
jsr JCHRIN jsr JCHRIN
bcs wedge_dos_basic_error bcs wedge_dos_basic_error
jsr JCHRIN jsr JCHRIN
@@ -163,37 +163,37 @@ wedge_dos_directory:
wedge_dos_directory_line: wedge_dos_directory_line:
;; Load a single line, reuse BASIC input buffer // Load a single line, reuse BASIC input buffer
ldy #$FF ldy #$FF
* !:
iny iny
jsr JCHRIN jsr JCHRIN
bcs wedge_dos_basic_error bcs wedge_dos_basic_error
sta BUF, y sta BUF, y
cpy #$50 cpy #$50
beq + ; line too long, terminate loading file beq !+ // line too long, terminate loading file
jsr JREADST jsr JREADST
bne + ; end of file bne !+ // end of file
cpy #$04 ; 2 bytes (pointer to next line) + 2 bytes (line number) cpy #$04 // 2 bytes (pointer to next line) + 2 bytes (line number)
bcc - bcc !-
lda BUF, y lda BUF, y
bne - bne !-
;; End of line, but not end of file // End of line, but not end of file
beq wedge_dos_directory_display beq wedge_dos_directory_display
* !:
lda #K_STS_END_OF_FILE lda #K_STS_END_OF_FILE
sta IOSTATUS ; make sure end of file is marked sta IOSTATUS // make sure end of file is marked
;; FALLTROUGH // FALLTROUGH
wedge_dos_directory_display: wedge_dos_directory_display:
cpy #$05 ; protection against malformed directory cpy #$05 // protection against malformed directory
bcc wedge_dos_clean_exit bcc wedge_dos_clean_exit
lda #$00 ; extra protection agains buffer overflow lda #$00 // extra protection agains buffer overflow
sta BUF, y sta BUF, y
;; Display line // Display line
ldx #<BUF ldx #<BUF
stx basic_current_line_ptr+0 stx basic_current_line_ptr+0
ldx #>BUF ldx #>BUF
@@ -201,14 +201,14 @@ wedge_dos_directory_display:
ldx #basic_current_line_ptr ldx #basic_current_line_ptr
jsr list_single_line jsr list_single_line
;; Read & display next line or quit // Read & display next line or quit
lda IOSTATUS lda IOSTATUS
beq wedge_dos_directory_line beq wedge_dos_directory_line
;; FALLTROUGH // FALLTROUGH
wedge_dos_clean_exit: wedge_dos_clean_exit:
jsr JCLALL jsr JCLALL
;; Print new line // Print new line
lda #$0D lda #$0D
jsr JCHROUT jsr JCHROUT
jmp basic_end_of_line jmp basic_end_of_line
@@ -222,17 +222,17 @@ wedge_dos_basic_error:
jmp do_basic_error jmp do_basic_error
wedge_dos_setnam: wedge_dos_setnam:
;; Now determine the length of the 'file' name // Now determine the length of the 'file' name
ldy #$FF ldy #$FF
* !:
iny iny
lda (basic_current_statement_ptr), y lda (basic_current_statement_ptr), y
bne - bne !-
;; Set the name to open // Set the name to open
tya tya
ldx basic_current_statement_ptr+0 ldx basic_current_statement_ptr+0
ldy basic_current_statement_ptr+1 ldy basic_current_statement_ptr+1
jmp JSETNAM jmp JSETNAM
;; END wedge support // END wedge support
+70 -68
View File
@@ -1,73 +1,75 @@
; Names of ZP and low memory locations // Names of ZP and low memory locations
; (Only those of relevance for the KERNAL) // (Only those of relevance for the KERNAL)
; (And only those for now that we feel the need to implement initially) // (And only those for now that we feel the need to implement initially)
; (https://www.c64-wiki.com/wiki/Zeropage) // (https://www.c64-wiki.com/wiki/Zeropage)
.alias kernal_load_or_verify_flag $93 // XXX get rid of this file, use ,aliases_ram_lowmem.s instead
.alias current_file_num $98
.alias input_device_number DFLTN
.alias cassette_buffer_bytes_used $A6
.alias load_or_scroll_temp_pointer $AC
;; We also use the following for temp colour pointer when scrolling
.alias load_save_verify_end_address $AE
.alias cassette_buffer_ptr $B2
.alias current_logical_filenum $B8
.alias current_secondary_address $B9
.alias current_device_number $BA
.alias current_filename_ptr $BB
.alias load_save_end_ptr $C3
.alias last_key_matrix_position $C5
.alias keys_in_key_buffer $C6
.alias reverse_video_flag $C7
.alias end_of_input_line $C8
.alias start_of_keyboard_input $C9
.alias current_key_index_entry $CB
.alias cursor_blink_disable $CC
.alias cursor_blink_countdown $CD
.alias cursor_saved_character $CE
.alias cursor_is_visible $CF
.alias keyboard_input_ready $D0
.alias current_screen_line_ptr $D1
.alias current_screen_x $D3
.alias quote_mode_flag $D4
.alias logical_line_length $D5
.alias current_screen_y $D6
.alias last_printed_character_ascii $D7
.alias insert_mode $D8
; Bits 0 -3 = bits 8-11 of screen line address
; Bit 7 = line spans multiple physical lines
.alias screen_line_link_table $D9
.alias current_screen_line_colour_ptr $F3
.alias keyboard_decoding_table_ptr $F5
.alias rs232_rx_buffer_ptr $F7
.alias rs232_tx_buffer_ptr $F9
; "Compute's Mapping the 64" book .label kernal_load_or_verify_flag = $93
.alias keyboard_buffer $0277 .label current_file_num = $98
.alias text_colour $0286 ; p55 .label input_device_number = DFLTN
.alias colour_under_cursor $0287 ; p56 .label cassette_buffer_bytes_used = $A6
.alias key_buffer_size $0289 ; p57 .label load_or_scroll_temp_pointer = $AC
// We also use the following for temp colour pointer when scrolling
.label load_save_verify_end_address = $AE
.label cassette_buffer_ptr = $B2
.label current_logical_filenum = $B8
.label current_secondary_address = $B9
.label current_device_number = $BA
.label current_filename_ptr = $BB
.label load_save_end_ptr = $C3
.label last_key_matrix_position = $C5
.label keys_in_key_buffer = $C6
.label reverse_video_flag = $C7
.label end_of_input_line = $C8
.label start_of_keyboard_input = $C9
.label current_key_index_entry = $CB
.label cursor_blink_disable = $CC
.label cursor_blink_countdown = $CD
.label cursor_saved_character = $CE
.label cursor_is_visible = $CF
.label keyboard_input_ready = $D0
.label current_screen_line_ptr = $D1
.label current_screen_x = $D3
.label quote_mode_flag = $D4
.label logical_line_length = $D5
.label current_screen_y = $D6
.label last_printed_character_ascii = $D7
.label insert_mode = $D8
// Bits 0 -3 = bits 8-11 of screen line address
// Bit 7 = line spans multiple physical lines
.label screen_line_link_table = $D9
.label current_screen_line_colour_ptr = $F3
.label keyboard_decoding_table_ptr = $F5
.label rs232_rx_buffer_ptr = $F7
.label rs232_tx_buffer_ptr = $F9
;; 0 = cursor keys, insert, delete and space repeat, but nothing else // "Compute's Mapping the 64" book
;; 128 = all keys repeat .label keyboard_buffer = $0277
;; 64 = no keys repeat .label text_colour = $0286 // p55
.alias key_repeat_flags $028A ; p58 .label colour_under_cursor = $0287 // p56
;; https://www.c64-wiki.com/wiki/Page_2 .label key_buffer_size = $0289 // p57
.alias key_repeat_counter $028B
.alias key_first_repeat_delay $028C
;; bit 0 = shift, 1 = Vendor Key, 2 = Control
.alias key_bucky_state $028D
.alias key_last_bucky_state $028E
.alias keyboard_decoding_ptr $028F
.alias enable_case_switch $0291
.alias screen_scroll_disable $0292
;; Under-ROM routines // 0 = cursor keys, insert, delete and space repeat, but nothing else
;; (BASIC also includes them. XXX - We should de-duplicate them in a safe manner) // 128 = all keys repeat
.alias missed_nmi_flag $2A7 // 64 = no keys repeat
.alias tiny_nmi_handler $2A8 .label key_repeat_flags = $028A // p58
.alias peek_under_roms tiny_nmi_handler+peek_under_roms_routine-tiny_nmi_handler_routine // https://www.c64-wiki.com/wiki/Page_2
.alias poke_under_roms tiny_nmi_handler+poke_under_roms_routine-tiny_nmi_handler_routine .label key_repeat_counter = $028B
.alias memmap_allram tiny_nmi_handler+memmap_allram_routine-tiny_nmi_handler_routine .label key_first_repeat_delay = $028C
.alias memmap_normal tiny_nmi_handler+memmap_normal_routine-tiny_nmi_handler_routine // bit 0 = shift, 1 = Vendor Key, 2 = Control
.label key_bucky_state = $028D
.label key_last_bucky_state = $028E
.label keyboard_decoding_ptr = $028F
.label enable_case_switch = $0291
.label screen_scroll_disable = $0292
// Under-ROM routines
// (BASIC also includes them. XXX - We should de-duplicate them in a safe manner)
.label missed_nmi_flag = $2A7
.label tiny_nmi_handler = $2A8
.label peek_under_roms = tiny_nmi_handler+peek_under_roms_routine-tiny_nmi_handler_routine
.label poke_under_roms = tiny_nmi_handler+poke_under_roms_routine-tiny_nmi_handler_routine
.label memmap_allram = tiny_nmi_handler+memmap_allram_routine-tiny_nmi_handler_routine
.label memmap_normal = tiny_nmi_handler+memmap_normal_routine-tiny_nmi_handler_routine
+3 -3
View File
@@ -1,6 +1,6 @@
;; Target-specific hooks // Target-specific hooks
.macro TARGET_HOOK_LOAD .macro TARGET_HOOK_LOAD() {
.macend }
+3 -3
View File
@@ -1,6 +1,6 @@
;; Target-specific hooks // Target-specific hooks
.macro TARGET_HOOK_LOAD .macro TARGET_HOOK_LOAD() {
.macend }
@@ -1,57 +1,57 @@
;; Registers according to Ultimate 64 Command Interface description, // Registers according to Ultimate 64 Command Interface description,
;; https://1541u-documentation.readthedocs.io/en/latest/command%20interface.html // https://1541u-documentation.readthedocs.io/en/latest/command%20interface.html
;; and ultimate_dos_v1.0.pdf and command_interface_v1.0.pdf by Gideon Zweijtzer // and ultimate_dos_v1.0.pdf and command_interface_v1.0.pdf by Gideon Zweijtzer
;; Command interface registers // Command interface registers
.alias U64_CONTROL $DF1C ; write .label U64_CONTROL = $DF1C // write
.alias U64_STATUS $DF1C ; read .label U64_STATUS = $DF1C // read
.alias U64_COMMAND_DATA $DF1D ; write .label U64_COMMAND_DATA = $DF1D // write
.alias U64_IDENTIFICATION $DF1D ; read .label U64_IDENTIFICATION = $DF1D // read
.alias U64_RESPONSE_DATA $DF1E ; read only .label U64_RESPONSE_DATA = $DF1E // read only
.alias U64_STATUS_DATA $DF1F ; read only .label U64_STATUS_DATA = $DF1F // read only
;; Constant for U64_IDENTIFICATION register // Constant for U64_IDENTIFICATION register
.alias U64_MAGIC_ID $C9 .const U64_MAGIC_ID = $C9
;; Constants for U64_CONTROL register // Constants for U64_CONTROL register
.alias U64_CTRL_BIT_PUSH_CMD $01 .const U64_CTRL_BIT_PUSH_CMD = $01
.alias U64_CTRL_BIT_DATA_ACC $02 .const U64_CTRL_BIT_DATA_ACC = $02
.alias U64_CTRL_BIT_ABORT $04 .const U64_CTRL_BIT_ABORT = $04
.alias U64_CTRL_BIT_CLR_ERR $08 .const U64_CTRL_BIT_CLR_ERR = $08
;; Constants for U64_STATUS register // Constants for U64_STATUS register
.alias U64_STAT_BIT_CMD_BUSY $01 .const U64_STAT_BIT_CMD_BUSY = $01
.alias U64_STAT_BIT_DATA_ACC $02 .const U64_STAT_BIT_DATA_ACC = $02
.alias U64_STAT_BIT_ABORT_P $04 .const U64_STAT_BIT_ABORT_P = $04
.alias U64_STAT_BIT_ERROR $08 .const U64_STAT_BIT_ERROR = $08
.alias U64_STAT_MASK_STATE $30 ; two bits! .const U64_STAT_MASK_STATE = $30 // two bits!
.alias U64_STAT_BIT_STAT_AV $40 .const U64_STAT_BIT_STAT_AV = $40
.alias U64_STAT_BIT_DATA_AV $80 .const U64_STAT_BIT_DATA_AV = $80
;; Interface targets // Interface targets
.alias U64_TARGET_DOS1 $01 .const U64_TARGET_DOS1 = $01
.alias U64_TARGET_DOS2 $02 .const U64_TARGET_DOS2 = $02
;; DOS command codes // DOS command codes
.alias U64_DOS_CMD_IDENTIFY $01 .const U64_DOS_CMD_IDENTIFY = $01
.alias U64_DOS_CMD_OPEN_FILE $02 .const U64_DOS_CMD_OPEN_FILE = $02
.alias U64_DOS_CMD_CLOSE_FILE $03 .const U64_DOS_CMD_CLOSE_FILE = $03
.alias U64_DOS_CMD_READ_DATA $04 .const U64_DOS_CMD_READ_DATA = $04
.alias U64_DOS_CMD_WRITE_DATA $05 .const U64_DOS_CMD_WRITE_DATA = $05
.alias U64_DOS_CMD_FILE_SEEK $06 .const U64_DOS_CMD_FILE_SEEK = $06
.alias U64_DOS_CMD_FILE_INFO $07 .const U64_DOS_CMD_FILE_INFO = $07
.alias U64_DOS_CMD_CHANGE_DIR $11 .const U64_DOS_CMD_CHANGE_DIR = $11
.alias U64_DOS_CMD_GET_PATH $12 .const U64_DOS_CMD_GET_PATH = $12
.alias U64_DOS_CMD_OPEN_DIR $13 .const U64_DOS_CMD_OPEN_DIR = $13
.alias U64_DOS_CMD_READ_DIR $14 .const U64_DOS_CMD_READ_DIR = $14
.alias U64_DOS_CMD_COPY_UI_PATH $15 .const U64_DOS_CMD_COPY_UI_PATH = $15
.alias U64_DOS_CMD_LOAD_REU $21 .const U64_DOS_CMD_LOAD_REU = $21
.alias U64_DOS_CMD_SAVE_REU $22 .const U64_DOS_CMD_SAVE_REU = $22
.alias U64_DOS_CMD_ECHO $F0 .const U64_DOS_CMD_ECHO = $F0
;; DOS file opening constants // DOS file opening constants
.alias U64_FA_READ $01 .const U64_FA_READ = $01
.alias U64_FA_WRITE $02 .const U64_FA_WRITE = $02
.alias U64_FA_CREATE_NEW $03 .const U64_FA_CREATE_NEW = $03
.alias U64_FA_CREATE_ALWAYS $04 .const U64_FA_CREATE_ALWAYS = $04
@@ -1,9 +1,9 @@
;; Target-specific hooks // Target-specific hooks
.macro TARGET_HOOK_LOAD .macro TARGET_HOOK_LOAD() {
;; XXX disabled for now - the current file opening API is not // XXX disabled for now - the current file opening API is not
;; really suitable for easy usage from Kernal // really suitable for easy usage from Kernal
;; jsr u64_load // jsr u64_load
.macend }
@@ -1,35 +1,35 @@
;; //
;; LOAD routine hook for fast loading via UltiDOS // LOAD routine hook for fast loading via UltiDOS
;; //
u64_load: u64_load:
;; First check whether the command interface is enabled // First check whether the command interface is enabled
lda U64_IDENTIFICATION lda U64_IDENTIFICATION
cmp #U64_MAGIC_ID cmp #U64_MAGIC_ID
beq + beq !+
u64_load_skip: u64_load_skip:
rts rts
* !:
;; XXX find out which device number softIEC is mapped to // XXX find out which device number softIEC is mapped to
lda current_device_number lda current_device_number
cmp #$20 ; for now use device number 32 cmp #$20 // for now use device number 32
bne u64_load_skip bne u64_load_skip
;; Takeover the flow completely // Takeover the flow completely
pla pla
pla pla
;; Display SEARCHING FOR + filename // Display SEARCHING FOR + filename
jsr lvs_display_searching_for jsr lvs_display_searching_for
;; Whatever the interface was doing - ask to abort it // Whatever the interface was doing - ask to abort it
jsr u64_load_abort jsr u64_load_abort
;; Send a command to open the file // Send a command to open the file
lda #U64_DOS_CMD_OPEN_FILE lda #U64_DOS_CMD_OPEN_FILE
jsr u64_load_send_cmd jsr u64_load_send_cmd
lda #U64_FA_READ lda #U64_FA_READ
@@ -37,16 +37,17 @@ u64_load_skip:
jsr u64_load_send_filename jsr u64_load_send_filename
jsr u64_load_finalize_cmd jsr u64_load_finalize_cmd
;; Check status // Check status
jsr u64_load_check_status jsr u64_load_check_status
bcs lvs_file_not_found_error bcs lvs_file_not_found_error
;; Load first two bytes to determine start address // Load first two bytes to determine start address
;; XXX // XXX
jsr printf jsr printf
.byte "DBG: NOT IMPLEMENTED",$0D,0 .text "DBG: NOT IMPLEMENTED"
.byte $0D,0
jmp lvs_wrap_around_error jmp lvs_wrap_around_error
rts rts
@@ -54,25 +55,25 @@ u64_load_skip:
u64_load_abort: u64_load_abort:
lda #U64_CTRL_BIT_ABORT lda #U64_CTRL_BIT_ABORT
sta U64_CONTROL sta U64_CONTROL
* !:
lda U64_STATUS lda U64_STATUS
bne - bne !-
rts rts
u64_load_send_cmd: u64_load_send_cmd:
ldx #U64_TARGET_DOS2 ldx #U64_TARGET_DOS2
stx U64_COMMAND_DATA ; target stx U64_COMMAND_DATA // target
sta U64_COMMAND_DATA ; command code sta U64_COMMAND_DATA // command code
rts rts
u64_load_send_filename: u64_load_send_filename:
ldy #0 ldy #0
u64_load_send_filename_loop: u64_load_send_filename_loop:
cpy FNLEN cpy FNLEN
bne+ bne !+
rts rts
* !:
ldx #<current_filename_ptr ldx #<current_filename_ptr
jsr peek_under_roms jsr peek_under_roms
iny iny
@@ -81,50 +82,50 @@ u64_load_send_filename_loop:
jmp u64_load_send_filename_loop jmp u64_load_send_filename_loop
u64_load_finalize_cmd: u64_load_finalize_cmd:
;; Push the command for execution // Push the command for execution
lda #U64_CTRL_BIT_PUSH_CMD lda #U64_CTRL_BIT_PUSH_CMD
sta U64_CONTROL sta U64_CONTROL
;; Wait till it is complete // Wait till it is complete
* !:
lda U64_STATUS lda U64_STATUS
and #U64_STAT_BIT_CMD_BUSY and #U64_STAT_BIT_CMD_BUSY
bne - bne !-
rts rts
u64_load_check_status: u64_load_check_status:
;; Wait till status is available // Wait till status is available
lda U64_STATUS lda U64_STATUS
and #U64_STAT_BIT_STAT_AV and #U64_STAT_BIT_STAT_AV
beq u64_load_check_status beq u64_load_check_status
;; Status is ready - check the first character // Status is ready - check the first character
lda U64_STATUS_DATA lda U64_STATUS_DATA
jsr JCHROUT ; XXX for test only jsr JCHROUT // XXX for test only
cmp #$30 ; '0' cmp #$30 // '0'
bne u64_load_check_status_wrong bne u64_load_check_status_wrong
;; Check the second status character // Check the second status character
lda U64_STATUS lda U64_STATUS
and #U64_STAT_BIT_STAT_AV and #U64_STAT_BIT_STAT_AV
beq u64_load_check_status_ok beq u64_load_check_status_ok
lda U64_STATUS_DATA lda U64_STATUS_DATA
jsr JCHROUT ; XXX for test only jsr JCHROUT // XXX for test only
cmp #$30 ; '0' cmp #$30 // '0'
beq u64_load_check_status_ok beq u64_load_check_status_ok
;; FALLTROUGH // FALLTROUGH
u64_load_check_status_wrong: u64_load_check_status_wrong:
sec sec
bcs + bcs !+
u64_load_check_status_ok: u64_load_check_status_ok:
clc clc
* !:
;; Now empty the status queue // Now empty the status queue
lda U64_STATUS lda U64_STATUS
and #U64_STAT_BIT_STAT_AV and #U64_STAT_BIT_STAT_AV
beq + beq !+
lda U64_STATUS_DATA lda U64_STATUS_DATA
jsr JCHROUT ; XXX for test only jsr JCHROUT // XXX for test only
jmp - jmp !-
* !:
rts rts
+9 -10
View File
@@ -1,15 +1,14 @@
;; //
;; Official Kernal routine, described in: // Official Kernal routine, described in:
;; //
;; - [RG64] C64 Programmer's Reference Guide - page 274 // - [RG64] C64 Programmer's Reference Guide - page 274
;; - [CM64] Compute's Mapping the Commodore 64 - page 224/225 // - [CM64] Compute's Mapping the Commodore 64 - page 224/225
;; //
;; CPU registers that has to be preserved (see [RG64]): .Y // CPU registers that has to be preserved (see [RG64]): .Y
;; //
acptr: ACPTR:
jsr kernalstatus_reset jsr kernalstatus_reset
jmp iec_rx_byte jmp iec_rx_byte
+20 -20
View File
@@ -1,41 +1,41 @@
;; We have the following variables: // We have the following variables:
;; cursor_blink_disable // cursor_blink_disable
;; cursor_blink_countdown // cursor_blink_countdown
;; cursor_saved_character // cursor_saved_character
;; cursor_is_visible // cursor_is_visible
;; colour_under_cursor // colour_under_cursor
show_cursor_if_enabled: show_cursor_if_enabled:
lda cursor_blink_disable lda cursor_blink_disable
beq + beq !+
rts rts
* lda cursor_is_visible !: lda cursor_is_visible
beq show_cursor beq show_cursor
rts rts
show_cursor: show_cursor:
;; Set cursor as though it had just finished the off phase, // Set cursor as though it had just finished the off phase,
;; so that the call to blink_cursor paints it // so that the call to blink_cursor paints it
lda #$00 lda #$00
sta cursor_blink_countdown sta cursor_blink_countdown
sta cursor_is_visible sta cursor_is_visible
jsr blink_cursor jsr blink_cursor
;; Then set the timeout to 1 frame, so that the cursor // Then set the timeout to 1 frame, so that the cursor
;; blinks under key repeat conditions, like on the original KERNAL // blinks under key repeat conditions, like on the original KERNAL
lda #$01 lda #$01
sta cursor_blink_countdown sta cursor_blink_countdown
rts rts
blink_cursor: blink_cursor:
;; Is the cursor enabled? // Is the cursor enabled?
lda cursor_blink_disable lda cursor_blink_disable
bne no_blink_cursor bne no_blink_cursor
;; Do we need to redraw things? // Do we need to redraw things?
dec cursor_blink_countdown dec cursor_blink_countdown
bpl no_blink_cursor bpl no_blink_cursor
;; Check if cursor was visible or not, and toggle // Check if cursor was visible or not, and toggle
lda cursor_is_visible lda cursor_is_visible
bne undraw_cursor bne undraw_cursor
draw_cursor: draw_cursor:
@@ -46,7 +46,7 @@ draw_cursor:
sta cursor_saved_character sta cursor_saved_character
eor #$80 eor #$80
sta (current_screen_line_ptr),y sta (current_screen_line_ptr),y
;; Also set cursor colour // Also set cursor colour
lda (current_screen_line_colour_ptr),y lda (current_screen_line_colour_ptr),y
sta colour_under_cursor sta colour_under_cursor
lda text_colour lda text_colour
@@ -68,10 +68,10 @@ undraw_cursor:
lda #0 lda #0
sta cursor_is_visible sta cursor_is_visible
;; Fall through // Fall through
reset_blink_timer: reset_blink_timer:
;; Rest blink counter // Rest blink counter
;; (Compute's Mapping the 64, p39-40) // (Compute's Mapping the 64, p39-40)
lda #20 lda #20
sta cursor_blink_countdown sta cursor_blink_countdown
no_blink_cursor: no_blink_cursor:
@@ -80,7 +80,7 @@ no_blink_cursor:
disable_cursor: disable_cursor:
lda #$80 lda #$80
sta cursor_blink_disable sta cursor_blink_disable
;; FALL THROUGH // FALL THROUGH
hide_cursor_if_visible: hide_cursor_if_visible:
lda cursor_is_visible lda cursor_is_visible
bne undraw_cursor bne undraw_cursor
+1 -1
View File
@@ -1,4 +1,4 @@
; c64 prg p263 // c64 prg p263
cartridge_check: cartridge_check:
ldx #$04 ldx #$04
+37 -37
View File
@@ -1,64 +1,64 @@
;; //
;; Official Kernal routines, described in: // Official Kernal routines, described in:
;; //
;; - [RG64] C64 Programmer's Reference Guide - page 275 (CHKIN) / 276 (CKOUT) // - [RG64] C64 Programmer's Reference Guide - page 275 (CHKIN) / 276 (CKOUT)
;; - [CM64] Compute's Mapping the Commodore 64 - page 229 // - [CM64] Compute's Mapping the Commodore 64 - page 229
;; //
;; CPU registers that has to be preserved (see [RG64]): .Y // CPU registers that has to be preserved (see [RG64]): .Y
;; //
;; CHKIN implementation // CHKIN implementation
chkin_real: chkin_real:
;; Store Y for preservation // Store Y for preservation
tya tya
pha pha
;; Reset status // Reset status
jsr kernalstatus_reset jsr kernalstatus_reset
;; First retrieve the FAT/LAT/SAT table index (and check if file is open) // First retrieve the FAT/LAT/SAT table index (and check if file is open)
txa txa
jsr find_fls jsr find_fls
bcs chkinout_file_not_open bcs chkinout_file_not_open
;; Now we have table index in Y - first filter out unsuitable devices // Now we have table index in Y - first filter out unsuitable devices
lda FAT,Y lda FAT,Y
cmp #$01 cmp #$01
beq chkinout_device_not_present ; tape not implemented beq chkinout_device_not_present // tape not implemented
cmp #$02 cmp #$02
beq chkinout_device_not_present ; RS-232 not implemented beq chkinout_device_not_present // RS-232 not implemented
;; Fail if the file is open for writing (secondary address 1) // Fail if the file is open for writing (secondary address 1)
lda LAT, Y lda LAT, Y
cmp #$01 cmp #$01
beq chkinout_file_not_input beq chkinout_file_not_input
;; For IEC devices, send TALK + TKSA first // For IEC devices, send TALK + TKSA first
lda FAT,Y lda FAT,Y
jsr iec_check_devnum jsr iec_check_devnum
bcs chkin_set_device bcs chkin_set_device
jsr talk jsr TALK
bcs chkinout_device_not_present ; don't set DFLTN in case of failure bcs chkinout_device_not_present // don't set DFLTN in case of failure
lda LAT, Y lda LAT, Y
jsr tksa jsr TKSA
bcs chkinout_device_not_present bcs chkinout_device_not_present
chkin_set_device: chkin_set_device:
lda FAT,Y lda FAT,Y
sta DFLTN sta DFLTN
clc ; for success clc // for success
;; FALLTROUGH // FALLTROUGH
;; Common part for booth CHKIN and CKOUT // Common part for booth CHKIN and CKOUT
chkinout_end: chkinout_end:
tax tax
@@ -88,54 +88,54 @@ chkinout_file_not_output:
tay tay
jmp kernalerror_FILE_NOT_OUTPUT jmp kernalerror_FILE_NOT_OUTPUT
;; CKOUT implementation // CKOUT implementation
ckout_real: ckout_real:
;; Store Y for preservation // Store Y for preservation
tya tya
pha pha
;; Reset status // Reset status
jsr kernalstatus_reset jsr kernalstatus_reset
;; First retrieve the FAT/LAT/SAT table index (and check if file is open) // First retrieve the FAT/LAT/SAT table index (and check if file is open)
txa txa
jsr find_fls jsr find_fls
bcs chkinout_file_not_open bcs chkinout_file_not_open
;; Now we have table index in Y - first filter out unsuitable devices // Now we have table index in Y - first filter out unsuitable devices
lda FAT,Y lda FAT,Y
cmp #$01 cmp #$01
beq chkinout_device_not_present ; tape not implemented beq chkinout_device_not_present // tape not implemented
cmp #$02 cmp #$02
beq chkinout_device_not_present ; RS-232 not implemented beq chkinout_device_not_present // RS-232 not implemented
cmp #$00 cmp #$00
beq chkinout_file_not_output ; cannot output to keyboard - XXX check real ROM behaviour beq chkinout_file_not_output // cannot output to keyboard - XXX check real ROM behaviour
;; Fail if the file is open for reading (secondary address 0) // Fail if the file is open for reading (secondary address 0)
lda LAT, Y lda LAT, Y
beq chkinout_file_not_output beq chkinout_file_not_output
;; For IEC devices, send LISTEN + SECOND first // For IEC devices, send LISTEN + SECOND first
lda FAT,Y lda FAT,Y
jsr iec_check_devnum jsr iec_check_devnum
bcs chkout_set_device bcs chkout_set_device
jsr listen jsr LISTEN
bcs chkinout_device_not_present ; don't set DFLTO in case of failure bcs chkinout_device_not_present // don't set DFLTO in case of failure
lda LAT, Y lda LAT, Y
jsr second jsr SECOND
bcs chkinout_device_not_present bcs chkinout_device_not_present
chkout_set_device: chkout_set_device:
lda FAT,Y lda FAT,Y
sta DFLTO sta DFLTO
clc ; for success clc // for success
jmp chkinout_end jmp chkinout_end
+51 -51
View File
@@ -1,67 +1,67 @@
;; //
;; Official Kernal routine, described in: // Official Kernal routine, described in:
;; //
;; - [RG64] C64 Programmer's Reference Guide - page 277/278 // - [RG64] C64 Programmer's Reference Guide - page 277/278
;; - [CM64] Compute's Mapping the Commodore 64 - page 228 // - [CM64] Compute's Mapping the Commodore 64 - page 228
;; //
;; CPU registers that has to be preserved (see [RG64]): .Y // CPU registers that has to be preserved (see [RG64]): .Y
;; //
;; XXX keyboard part currently does not preserve register Y, to be fixed! // XXX keyboard part currently does not preserve register Y, to be fixed!
;; Reads a byte of input, unless from keyboard. // Reads a byte of input, unless from keyboard.
;; If from keyboard, then it gets a whole line of input, and returns the first char. // If from keyboard, then it gets a whole line of input, and returns the first char.
;; Repeated calls after that read out the successive bytes of the line of input. // Repeated calls after that read out the successive bytes of the line of input.
chrin_real: chrin_real:
;; Determine the device number // Determine the device number
lda DFLTN lda DFLTN
beq chrin_keyboard ; #$00 - keyboard beq chrin_keyboard // #$00 - keyboard
;; XXX add screen support // XXX add screen support
jsr iec_check_devnum jsr iec_check_devnum
bcc chrin_iec bcc chrin_iec
jmp lvs_device_not_found_error ; not a supported device jmp lvs_device_not_found_error // not a supported device
chrin_iec: chrin_iec:
jsr JACPTR jsr JACPTR
bcs chrin_done_fail bcs chrin_done_fail
;; FALLTROUGH // FALLTROUGH
chrin_done: chrin_done:
clc ; indicate success clc // indicate success
rts rts
chrin_done_fail: chrin_done_fail:
sec ; indicate failure sec // indicate failure
rts rts
chrin_keyboard: chrin_keyboard:
;; Save X // Save X
txa txa
pha pha
chrin_repeat: chrin_repeat:
;; Do we have a line of input we are currently returning? // Do we have a line of input we are currently returning?
;; If so, return the next byte, and clear the flag when we reach the end. // If so, return the next byte, and clear the flag when we reach the end.
;; Do we have a line of input waiting? // Do we have a line of input waiting?
lda keyboard_input_ready lda keyboard_input_ready
beq read_from_keyboard beq read_from_keyboard
;; Yes, we have input waiting at (start_of_keyboard_input)+keyboard_input_ready // Yes, we have input waiting at (start_of_keyboard_input)+keyboard_input_ready
;; When keyboard_input_ready = end_of_input_line, then we return a carriage return // When keyboard_input_ready = end_of_input_line, then we return a carriage return
;; and clear the flag // and clear the flag
cmp end_of_input_line cmp end_of_input_line
bne not_end_of_input bne not_end_of_input
;; Return carriage return and clear pending input flag // Return carriage return and clear pending input flag
lda #$00 lda #$00
sta keyboard_input_ready sta keyboard_input_ready
pla pla
@@ -71,7 +71,7 @@ chrin_repeat:
rts rts
not_end_of_input: not_end_of_input:
;; Return next byte of waiting input and advance index // Return next byte of waiting input and advance index
tay tay
pla pla
tax tax
@@ -86,7 +86,7 @@ read_from_keyboard:
jsr enable_cursor jsr enable_cursor
;; Wait for a key // Wait for a key
lda keys_in_key_buffer lda keys_in_key_buffer
beq chrin_repeat beq chrin_repeat
@@ -100,31 +100,31 @@ read_from_keyboard:
jsr hide_cursor_if_visible jsr hide_cursor_if_visible
;; It was enter. // It was enter.
;; Note that we have a line of input to return, and return the first byte thereof // Note that we have a line of input to return, and return the first byte thereof
;; after computing and storing its length. // after computing and storing its length.
;; (Compute's Mapping the 64, p96) // (Compute's Mapping the 64, p96)
;; Set pointer to line of input // Set pointer to line of input
lda current_screen_line_ptr+0 lda current_screen_line_ptr+0
sta start_of_keyboard_input+0 sta start_of_keyboard_input+0
lda current_screen_line_ptr+1 lda current_screen_line_ptr+1
sta start_of_keyboard_input+1 sta start_of_keyboard_input+1
;; Calculate length // Calculate length
jsr get_current_line_logical_length jsr get_current_line_logical_length
tay tay
iny iny
* dey !: dey
bmi empty_line bmi empty_line
lda (current_screen_line_ptr),y lda (current_screen_line_ptr),y
cmp #$20 cmp #$20
beq - beq !-
iny iny
sty end_of_input_line sty end_of_input_line
lda #$01 lda #$01
sta keyboard_input_ready sta keyboard_input_ready
;; Return first char of line // Return first char of line
ldy #$00 ldy #$00
pla pla
tax tax
@@ -134,9 +134,9 @@ read_from_keyboard:
rts rts
empty_line: empty_line:
;; For an empty line, just return the carriage return // For an empty line, just return the carriage return
;; (and don't forget to actually print the carriage return, so that // (and don't forget to actually print the carriage return, so that
;; the cursor advances and screen scrolls as required) // the cursor advances and screen scrolls as required)
pla pla
tax tax
clc clc
@@ -144,28 +144,28 @@ empty_line:
rts rts
not_enter: not_enter:
;; Print character // Print character
lda keyboard_buffer lda keyboard_buffer
jsr chrout jsr CHROUT
jsr pop_keyboard_buffer jsr pop_keyboard_buffer
;; Keep looking for input from keyboard until carriage return // Keep looking for input from keyboard until carriage return
jmp chrin_repeat jmp chrin_repeat
pop_keyboard_buffer: pop_keyboard_buffer:
;; Pop key out of keyboard buffer // Pop key out of keyboard buffer
;; Disable interrupts while reading from keyboard buffer // Disable interrupts while reading from keyboard buffer
;; so that no race conditions can occur // so that no race conditions can occur
sei sei
ldx #$00 ldx #$00
ldy #$01 ldy #$01
* lda keyboard_buffer,y !: lda keyboard_buffer,y
sta keyboard_buffer,x sta keyboard_buffer,x
inx inx
iny iny
cpy key_buffer_size cpy key_buffer_size
bne - bne !-
dec keys_in_key_buffer dec keys_in_key_buffer
cli cli
@@ -199,12 +199,12 @@ not_shifted:
cmp #$80 cmp #$80
bcs not_vendor bcs not_vendor
;; $60-$7F -> $A0-$BF // $60-$7F -> $A0-$BF
clc clc
adc #$40 adc #$40
;; FALLTROUGH // FALLTROUGH
not_vendor: not_vendor:
rts rts
+223 -223
View File
@@ -1,36 +1,36 @@
;; //
;; Official Kernal routine, described in: // Official Kernal routine, described in:
;; //
;; - [RG64] C64 Programmer's Reference Guide - page 278/279 // - [RG64] C64 Programmer's Reference Guide - page 278/279
;; - [CM64] Compute's Mapping the Commodore 64 - page 228 // - [CM64] Compute's Mapping the Commodore 64 - page 228
;; //
;; CPU registers that has to be preserved (see [RG64]): .Y // CPU registers that has to be preserved (see [RG64]): .Y
;; //
chrout_real: chrout_real:
sta last_printed_character_ascii sta last_printed_character_ascii
;; Save X and Y values // Save X and Y values
;; (Confirmed by writing a test program that X and Y // (Confirmed by writing a test program that X and Y
;; don't get modified, in agreement with C64 PRG's // don't get modified, in agreement with C64 PRG's
;; description of CHROUT) // description of CHROUT)
txa txa
pha pha
tya tya
pha pha
php php
;; Determine the device number // Determine the device number
lda DFLTO lda DFLTO
cmp #$03 ; screen cmp #$03 // screen
beq chrout_screen beq chrout_screen
jsr iec_check_devnum jsr iec_check_devnum
bcs chrout_done_unknown_device ; not a supported device bcs chrout_done_unknown_device // not a supported device
chrout_iec: chrout_iec:
@@ -38,19 +38,19 @@ chrout_iec:
jsr JCIOUT jsr JCIOUT
bcc chrout_done bcc chrout_done
;; FALLTROUGH // FALLTROUGH
chrout_done_fail: chrout_done_fail:
jsr show_cursor_if_enabled jsr show_cursor_if_enabled
plp plp
;; Restore X and Y // Restore X and Y
pla pla
tay tay
pla pla
tax tax
sec ; indicate failure sec // indicate failure
rts rts
chrout_done_unknown_device: chrout_done_unknown_device:
@@ -58,13 +58,13 @@ chrout_done_unknown_device:
plp plp
;; Restore X and Y // Restore X and Y
pla pla
tay tay
pla pla
tax tax
;; End wioth error // End wioth error
jmp lvs_device_not_found_error jmp lvs_device_not_found_error
chrout_done: chrout_done:
@@ -72,43 +72,43 @@ chrout_done:
plp plp
;; Restore X and Y // Restore X and Y
pla pla
tay tay
pla pla
tax tax
lda last_printed_character_ascii lda last_printed_character_ascii
clc ; indicate success clc // indicate success
rts rts
chrout_screen: chrout_screen:
;; Crude implementation of character output // Crude implementation of character output
sei ;; XXX why do we need to disable interrupts? sei // XXX why do we need to disable interrupts?
jsr hide_cursor_if_visible jsr hide_cursor_if_visible
lda last_printed_character_ascii lda last_printed_character_ascii
tax tax
;; Check for special characters // Check for special characters
cmp #$00 cmp #$00
bne not_00 bne not_00
jmp chrout_done jmp chrout_done
not_00: not_00:
;; Linefeed (simply ignored) // Linefeed (simply ignored)
;; Trivia: BASIC does CRLF with READY. prompt // Trivia: BASIC does CRLF with READY. prompt
cmp #$0a cmp #$0a
bne not_0a bne not_0a
jmp chrout_done jmp chrout_done
not_0a: not_0a:
;; Carriage return // Carriage return
cmp #$0d cmp #$0d
bne not_0d bne not_0d
;; RETURN clears quote and insert modes // RETURN clears quote and insert modes
lda #$00 lda #$00
sta quote_mode_flag sta quote_mode_flag
sta insert_mode sta insert_mode
@@ -118,9 +118,9 @@ not_0d:
cmp #$94 cmp #$94
bne not_94 bne not_94
;; Insert (shift-DELETE) // Insert (shift-DELETE)
;; Abort if line already max length, ie 79th char is not a space // Abort if line already max length, ie 79th char is not a space
jsr get_current_line_logical_length jsr get_current_line_logical_length
cmp #79 cmp #79
bne definitely_not_too_long bne definitely_not_too_long
@@ -129,11 +129,11 @@ not_0d:
cmp #$20 cmp #$20
beq definitely_not_too_long beq definitely_not_too_long
;; Line is too long to extend // Line is too long to extend
jmp chrout_done jmp chrout_done
definitely_not_too_long: definitely_not_too_long:
;; Work out if line needs to be expanded, and if so expand it // Work out if line needs to be expanded, and if so expand it
ldy #39 ldy #39
lda (current_screen_line_ptr),y lda (current_screen_line_ptr),y
cmp #$20 cmp #$20
@@ -142,18 +142,18 @@ definitely_not_too_long:
jsr screen_grow_logical_line jsr screen_grow_logical_line
no_need_to_extend: no_need_to_extend:
;; Shuffle chars towards end of line // Shuffle chars towards end of line
jsr get_current_line_logical_length jsr get_current_line_logical_length
tay tay
* !:
;; Note: While the following routine is obvious to any skilled // Note: While the following routine is obvious to any skilled
;; in the art as the most obvious simple and efficient solution, // in the art as the most obvious simple and efficient solution,
;; if the screen writes are before the colour writes, it results // if the screen writes are before the colour writes, it results
;; in a relatively long verbatim stretch of bytes when compared to // in a relatively long verbatim stretch of bytes when compared to
;; the C64 KERNAL. Thus we have swapped the order, just to reduce // the C64 KERNAL. Thus we have swapped the order, just to reduce
;; the potential for any argument of copyright infringement, even // the potential for any argument of copyright infringement, even
;; though we really don't believe that the routine can be copyrighted // though we really don't believe that the routine can be copyrighted
;; due to the lack of creativity. // due to the lack of creativity.
dey dey
lda (current_screen_line_colour_ptr),y lda (current_screen_line_colour_ptr),y
iny iny
@@ -165,36 +165,36 @@ no_need_to_extend:
dey dey
cpy current_screen_x cpy current_screen_x
bne - bne !-
;; Increase insert mode count (which causes quote-mode like behaviour) // Increase insert mode count (which causes quote-mode like behaviour)
inc insert_mode inc insert_mode
;; Put space in the inserted gap // Put space in the inserted gap
lda #$20 lda #$20
sta (current_screen_line_ptr),y sta (current_screen_line_ptr),y
jmp chrout_done jmp chrout_done
not_94: not_94:
;; DELETE in insert mode embeds control character // DELETE in insert mode embeds control character
ldx insert_mode ldx insert_mode
bne not_14 bne not_14
cmp #$14 cmp #$14
bne not_14 bne not_14
;; Delete // Delete
ldx current_screen_x ldx current_screen_x
bne delete_non_zero_column bne delete_non_zero_column
delete_at_column_0: delete_at_column_0:
ldy current_screen_y ldy current_screen_y
bne not_row_0 bne not_row_0
;; delete from row 0, col 0 does nothing // delete from row 0, col 0 does nothing
jmp chrout_done jmp chrout_done
not_row_0: not_row_0:
;; Column 0 delete just moves us to the end of the // Column 0 delete just moves us to the end of the
;; previous line, without actually deleting anything // previous line, without actually deleting anything
dec current_screen_y dec current_screen_y
jsr get_current_line_logical_length jsr get_current_line_logical_length
lda logical_line_length lda logical_line_length
@@ -204,13 +204,13 @@ not_row_0:
jmp chrout_done jmp chrout_done
delete_non_zero_column: delete_non_zero_column:
;; Copy rest of line down // Copy rest of line down
jsr get_current_line_logical_length jsr get_current_line_logical_length
ldy current_screen_x ldy current_screen_x
cpy logical_line_length cpy logical_line_length
beq done_delete beq done_delete
dey dey
* !:
iny iny
lda (current_screen_line_ptr),y lda (current_screen_line_ptr),y
dey dey
@@ -221,9 +221,9 @@ delete_non_zero_column:
sta (current_screen_line_colour_ptr),y sta (current_screen_line_colour_ptr),y
iny iny
cpy logical_line_length cpy logical_line_length
bne - bne !-
;; Clear char at end of line // Clear char at end of line
jsr get_current_line_logical_length jsr get_current_line_logical_length
tay tay
lda #$20 lda #$20
@@ -234,7 +234,7 @@ done_delete:
jmp chrout_done jmp chrout_done
not_14: not_14:
;; Check for quote mode // Check for quote mode
ldx quote_mode_flag ldx quote_mode_flag
bne is_quote_mode bne is_quote_mode
ldx insert_mode ldx insert_mode
@@ -242,51 +242,51 @@ not_14:
jmp not_quote_mode jmp not_quote_mode
is_quote_mode: is_quote_mode:
;; Is it a control code? // Is it a control code?
;; control codes are $00-$1f and $80-$9f // control codes are $00-$1f and $80-$9f
;; (from reading C64 PRG p379-381) // (from reading C64 PRG p379-381)
;; so we can just check if bits 5 or 6 are set, and if so, // so we can just check if bits 5 or 6 are set, and if so,
;; then it isn't a control character. // then it isn't a control character.
pha pha
and #$60 and #$60
bne + bne !+
;; Yes, a control code in quote mode means we display it as a reverse character // Yes, a control code in quote mode means we display it as a reverse character
pla pla
;; Low control codes are just +$80 // Low control codes are just +$80
clc clc
adc #$80 adc #$80
;; If it overflowed, then it is a high control code, // If it overflowed, then it is a high control code,
;; so we need to make it be $80 + $40 + char // so we need to make it be $80 + $40 + char
;; as we will have flipped back to just $00 + char, we should // as we will have flipped back to just $00 + char, we should
;; now add $c0 if C is set from overflow // now add $c0 if C is set from overflow
bcc low_ctrl_char bcc low_ctrl_char
adc #$bf ; C=1, so adding $BF + C = add $C0 adc #$bf // C=1, so adding $BF + C = add $C0
low_ctrl_char: low_ctrl_char:
jmp output_literal_char jmp output_literal_char
* !:
pla pla
not_quote_mode: not_quote_mode:
;; Check for colours // Check for colours
ldx #$f ldx #$f
colour_check_loop: colour_check_loop:
cmp colour_codes,x cmp colour_codes,x
bne + bne !+
stx text_colour stx text_colour
jmp chrout_done jmp chrout_done
* dex !: dex
bpl colour_check_loop bpl colour_check_loop
;; Compute's Mapping the 64 p38 // Compute's Mapping the 64 p38
cmp #$12 cmp #$12
bne not_12 bne not_12
lda #$80 lda #$80
sta reverse_video_flag sta reverse_video_flag
jmp chrout_done jmp chrout_done
not_12: not_12:
;; Compute's Mapping the 64 p 38 // Compute's Mapping the 64 p 38
cmp #$92 cmp #$92
bne not_92 bne not_92
lda #$00 lda #$00
@@ -294,17 +294,17 @@ not_12:
jmp chrout_done jmp chrout_done
not_92: not_92:
;; Check for cursor movement keys // Check for cursor movement keys
cmp #$11 cmp #$11
bne not_11 bne not_11
lda current_screen_x lda current_screen_x
clc clc
adc #40 adc #40
sta current_screen_x sta current_screen_x
;; We need to advance the pointer manually, as normalising // We need to advance the pointer manually, as normalising
;; now will break things. The pointer update is required // now will break things. The pointer update is required
;; so that we can tell if we really are on the bottom phys // so that we can tell if we really are on the bottom phys
;; screen line or not // screen line or not
jsr scroll_up_if_on_last_line jsr scroll_up_if_on_last_line
jsr calculate_screen_line_pointer jsr calculate_screen_line_pointer
jmp chrout_done jmp chrout_done
@@ -331,7 +331,7 @@ not_91:
jmp chrout_done jmp chrout_done
not_9d: not_9d:
;; Home cursor // Home cursor
cmp #$13 cmp #$13
bne not_13 bne not_13
lda #0 lda #0
@@ -341,7 +341,7 @@ not_9d:
jmp chrout_done jmp chrout_done
not_13: not_13:
;; Clear screen // Clear screen
cmp #$93 cmp #$93
bne not_clearscreen bne not_clearscreen
jsr clear_screen jsr clear_screen
@@ -349,41 +349,41 @@ not_13:
not_clearscreen: not_clearscreen:
;; Convert PETSCII to screen code // Convert PETSCII to screen code
;; Don't print other control codes // Don't print other control codes
cmp #$1f cmp #$1f
bcs + bcs !+
jmp chrout_done jmp chrout_done
* !:
;; Codes $C0-$DF become $40-$5F // Codes $C0-$DF become $40-$5F
;; But // But
cmp #$e0 cmp #$e0
bcs + bcs !+
cmp #$c0 cmp #$c0
bcc + bcc !+
and #$7f and #$7f
jmp not_high_char jmp not_high_char
* !:
;; Range $20-$3F is unchanged // Range $20-$3F is unchanged
cmp #$40 cmp #$40
bcc not_high_char bcc not_high_char
;; Unshifted letters and symbols from $40-$5F // Unshifted letters and symbols from $40-$5F
;; all end up being -$40 // all end up being -$40
;; (C64 PRG p376) // (C64 PRG p376)
;; But anything >= $80 needs to be -$40 // But anything >= $80 needs to be -$40
;; (C64 PRG p380-381) // (C64 PRG p380-381)
;; And bit 7 should be cleared, only to be // And bit 7 should be cleared, only to be
;; set by reverse video // set by reverse video
sec sec
sbc #$40 sbc #$40
;; Fix shifted chars by adding $20 again // Fix shifted chars by adding $20 again
cmp #$20 cmp #$20
bcc not_high_char bcc not_high_char
cmp #$40 cmp #$40
@@ -397,45 +397,45 @@ chrout_l1:
output_literal_char: output_literal_char:
;; Write normal character on the screen // Write normal character on the screen
pha pha
ldy current_screen_x ldy current_screen_x
ora reverse_video_flag ; Compute's Mapping the 64 p38 ora reverse_video_flag // Compute's Mapping the 64 p38
sta (current_screen_line_ptr),y sta (current_screen_line_ptr),y
;; Decrement number of chars waiting to be inserted // Decrement number of chars waiting to be inserted
lda insert_mode lda insert_mode
beq + beq !+
dec insert_mode dec insert_mode
* !:
pla pla
cmp #$22 cmp #$22
bne not_quote bne not_quote
;; Toggle quote flag if required // Toggle quote flag if required
lda quote_mode_flag lda quote_mode_flag
eor #$80 eor #$80
sta quote_mode_flag sta quote_mode_flag
not_quote: not_quote:
;; Set colour // Set colour
lda text_colour lda text_colour
sta (current_screen_line_colour_ptr),y sta (current_screen_line_colour_ptr),y
;; Advance the column, and scroll screen down if we need // Advance the column, and scroll screen down if we need
;; to insert a 2nd line in this logical line. // to insert a 2nd line in this logical line.
;; (eg Compute's Mapping the 64 p41) // (eg Compute's Mapping the 64 p41)
ldx current_screen_y ldx current_screen_y
iny iny
sty current_screen_x sty current_screen_x
cpy #40 cpy #40
bne + bne !+
jsr screen_grow_logical_line jsr screen_grow_logical_line
ldy current_screen_x ldy current_screen_x
* !:
cpy #80 cpy #80
bcc no_screen_advance_to_next_line bcc no_screen_advance_to_next_line
lda #0 lda #0
@@ -446,35 +446,35 @@ no_screen_advance_to_next_line:
screen_grow_logical_line: screen_grow_logical_line:
ldy current_screen_y ldy current_screen_y
;; Don't grow line if it is already grown // Don't grow line if it is already grown
lda screen_line_link_table,y lda screen_line_link_table,y
bpl + bpl !+
jmp done_grow_line jmp done_grow_line
* !:
lda #$80 lda #$80
sta screen_line_link_table,y sta screen_line_link_table,y
;; Now make space for the extra line added. // Now make space for the extra line added.
;; If we are on the last physical line of the screen, // If we are on the last physical line of the screen,
;; Then we need to scroll the screen up // Then we need to scroll the screen up
jsr scroll_up_if_on_last_line jsr scroll_up_if_on_last_line
;; Scroll screen down to make space // Scroll screen down to make space
;; As we are scrolling down, we start from the end, // As we are scrolling down, we start from the end,
;; and work backwards. We can't be as simple and efficient // and work backwards. We can't be as simple and efficient
;; here as we are for scrolling up, because we don't know // here as we are for scrolling up, because we don't know
;; how much must be scrolled. // how much must be scrolled.
;; Simple solution is to work out how many physical lines // Simple solution is to work out how many physical lines
;; need shifting down, and then move lines at a time after // need shifting down, and then move lines at a time after
;; initialising the pointers to the end area of the screen. // initialising the pointers to the end area of the screen.
ldx #25-2 ldx #25-2
ldy #0 ldy #0
count_rows_loop: count_rows_loop:
dex dex
lda screen_line_link_table,y lda screen_line_link_table,y
bpl + bpl !+
dex dex
* iny !: iny
cpy current_screen_y cpy current_screen_y
bne count_rows_loop bne count_rows_loop
@@ -482,14 +482,14 @@ count_rows_loop:
beq no_copy_down beq no_copy_down
bmi no_copy_down bmi no_copy_down
;; Set pointers to end of screen line, and one line // Set pointers to end of screen line, and one line
;; above. (It is always one physical line, because // above. (It is always one physical line, because
;; this can only happen when expanding a line from 40 to // this can only happen when expanding a line from 40 to
;; 80 characters). // 80 characters).
;; XXX - This is not very efficient, and longer than it // XXX - This is not very efficient, and longer than it
;; needs to be. Better would be to work out size to // needs to be. Better would be to work out size to
;; copy, and count it down in a pointer somewhere, so // copy, and count it down in a pointer somewhere, so
;; that loop iteration logic is simpler. // that loop iteration logic is simpler.
lda HIBASE lda HIBASE
clc clc
adc #3 adc #3
@@ -502,7 +502,7 @@ count_rows_loop:
lda #<$03C0 lda #<$03C0
sta current_screen_line_ptr+0 sta current_screen_line_ptr+0
sta current_screen_line_colour_ptr+0 sta current_screen_line_colour_ptr+0
;; souce address is line above // souce address is line above
sec sec
sbc #40 sbc #40
sta load_or_scroll_temp_pointer+0 sta load_or_scroll_temp_pointer+0
@@ -518,11 +518,11 @@ cl_inner:
dey dey
bpl cl_inner bpl cl_inner
;; Decrement all pointers by 40 // Decrement all pointers by 40
;; Low bytes are in common pairs // Low bytes are in common pairs
;; Old source is new destination // Old source is new destination
;; Use different registers to minimise byte similarity with C64 KERNAl // Use different registers to minimise byte similarity with C64 KERNAl
ldy load_or_scroll_temp_pointer+1 ldy load_or_scroll_temp_pointer+1
sty current_screen_line_ptr+1 sty current_screen_line_ptr+1
lda load_save_verify_end_address+1 lda load_save_verify_end_address+1
@@ -531,7 +531,7 @@ cl_inner:
sty current_screen_line_ptr+0 sty current_screen_line_ptr+0
sty current_screen_line_colour_ptr+0 sty current_screen_line_colour_ptr+0
;; Decrementing source pointers // Decrementing source pointers
lda load_or_scroll_temp_pointer+0 lda load_or_scroll_temp_pointer+0
sec sec
sbc #<40 sbc #<40
@@ -540,7 +540,7 @@ cl_inner:
lda load_or_scroll_temp_pointer+1 lda load_or_scroll_temp_pointer+1
sbc #>40 sbc #>40
sta load_or_scroll_temp_pointer+1 sta load_or_scroll_temp_pointer+1
;; convert to screen equivalent // convert to screen equivalent
sec sec
sbc HIBASE sbc HIBASE
clc clc
@@ -553,16 +553,16 @@ cl_inner:
no_copy_down: no_copy_down:
jsr calculate_screen_line_pointer jsr calculate_screen_line_pointer
;; Erase newly inserted line // Erase newly inserted line
ldy #79 ldy #79
* !:
lda text_colour lda text_colour
sta (current_screen_line_colour_ptr),y sta (current_screen_line_colour_ptr),y
lda #$20 lda #$20
sta (current_screen_line_ptr),y sta (current_screen_line_ptr),y
dey dey
cpy #40 cpy #40
bne - bne !-
rts rts
@@ -572,9 +572,9 @@ not_last_line:
scroll_up_if_on_last_line: scroll_up_if_on_last_line:
;; Colour RAM is always in fixed place, so is easiest // Colour RAM is always in fixed place, so is easiest
;; to use to check if we are on the last line. // to use to check if we are on the last line.
;; The last line is at $D800 + 24*40 = $DBC0 // The last line is at $D800 + 24*40 = $DBC0
lda current_screen_line_colour_ptr+1 lda current_screen_line_colour_ptr+1
cmp #>$DBC0 cmp #>$DBC0
bne not_last_line bne not_last_line
@@ -593,13 +593,13 @@ is_last_line:
dec current_screen_y dec current_screen_y
;; FALL THROUGH // FALL THROUGH
scroll_screen_up: scroll_screen_up:
;; Now scroll the whole screen up either one or two lines // Now scroll the whole screen up either one or two lines
;; based on whether the first screen line is linked or not. // based on whether the first screen line is linked or not.
;; Get pointers to start of screen + colour RAM // Get pointers to start of screen + colour RAM
lda HIBASE lda HIBASE
sta current_screen_line_ptr+1 sta current_screen_line_ptr+1
sta load_or_scroll_temp_pointer+1 sta load_or_scroll_temp_pointer+1
@@ -610,17 +610,17 @@ scroll_screen_up:
sta current_screen_line_ptr+0 sta current_screen_line_ptr+0
sta current_screen_line_colour_ptr+0 sta current_screen_line_colour_ptr+0
;; Get pointers to screen/colour RAM source // Get pointers to screen/colour RAM source
lda screen_line_link_table+0 lda screen_line_link_table+0
bmi + bmi !+
lda #40 lda #40
.byte $2C ; BIT $nnnn to skip next instruction .byte $2C // BIT $nnnn to skip next instruction
* !:
lda #80 lda #80
sta load_or_scroll_temp_pointer+0 sta load_or_scroll_temp_pointer+0
sta load_save_verify_end_address+0 sta load_save_verify_end_address+0
;; Copy first three pages // Copy first three pages
ldy #$00 ldy #$00
ldx #3 ldx #3
scroll_copy_loop: scroll_copy_loop:
@@ -639,9 +639,9 @@ scroll_copy_loop:
dex dex
bne scroll_copy_loop bne scroll_copy_loop
;; Copy last partial page // Copy last partial page
;; We need to copy 1000-(3*256)-line length // We need to copy 1000-(3*256)-line length
;; = 232 - line length // = 232 - line length
lda load_or_scroll_temp_pointer+0 lda load_or_scroll_temp_pointer+0
lda #232 lda #232
sec sec
@@ -656,7 +656,7 @@ scroll_copy_loop2:
dex dex
bne scroll_copy_loop2 bne scroll_copy_loop2
;; Fill in scrolled up area // Fill in scrolled up area
ldx load_or_scroll_temp_pointer+0 ldx load_or_scroll_temp_pointer+0
scroll_copy_loop3: scroll_copy_loop3:
lda text_colour lda text_colour
@@ -667,7 +667,7 @@ scroll_copy_loop3:
dex dex
bne scroll_copy_loop3 bne scroll_copy_loop3
;; Shift line linkage list // Shift line linkage list
ldy #0 ldy #0
ldx #24 ldx #24
link_copy: link_copy:
@@ -676,10 +676,10 @@ link_copy:
iny iny
dex dex
bne link_copy bne link_copy
;; Clear line link flag of last line // Clear line link flag of last line
stx screen_line_link_table+24 stx screen_line_link_table+24
;; Restore correct line pointers // Restore correct line pointers
jsr calculate_screen_line_pointer jsr calculate_screen_line_pointer
rts rts
@@ -689,7 +689,7 @@ get_current_line_logical_length:
lda screen_line_link_table,y lda screen_line_link_table,y
bpl line_not_linked_del bpl line_not_linked_del
lda #79 lda #79
.byte $2c ; BIT absolute mode, which we use to skip the next two instruction bytes .byte $2c // BIT absolute mode, which we use to skip the next two instruction bytes
line_not_linked_del: line_not_linked_del:
lda #39 lda #39
sta logical_line_length sta logical_line_length
@@ -697,21 +697,21 @@ line_not_linked_del:
screen_advance_to_next_line: screen_advance_to_next_line:
;; jsr hide_cursor_if_visible // jsr hide_cursor_if_visible
;; Go to start of line // Go to start of line
lda #0 lda #0
sta current_screen_x sta current_screen_x
;; Advance line number // Advance line number
ldy current_screen_y ldy current_screen_y
;; Do quick fix to line pointer to work out if it is off // Do quick fix to line pointer to work out if it is off
;; the bottom of the screen. // the bottom of the screen.
ldx #40 ldx #40
lda screen_line_link_table,y lda screen_line_link_table,y
bmi + bmi !+
.byte $2c .byte $2c
* ldx #80 !: ldx #80
txa txa
clc clc
adc current_screen_line_ptr+0 adc current_screen_line_ptr+0
@@ -722,22 +722,22 @@ screen_advance_to_next_line:
inc current_screen_y inc current_screen_y
;; Check if it will trigger scrolling // Check if it will trigger scrolling
;; Work out if we have gone off the bottom of the screen? // Work out if we have gone off the bottom of the screen?
;; 1040 > 1024, so if high byte of screen pointer is >= (HIBASE+4), // 1040 > 1024, so if high byte of screen pointer is >= (HIBASE+4),
;; then we are off the bottom of the screen // then we are off the bottom of the screen
lda current_screen_line_ptr+1 lda current_screen_line_ptr+1
sec sec
sbc HIBASE sbc HIBASE
cmp #3 cmp #3
bcc + bcc !+
lda current_screen_line_ptr+0 lda current_screen_line_ptr+0
cmp #$e7 cmp #$e7
bcc + bcc !+
;; Off the bottom of the screen // Off the bottom of the screen
jsr scroll_screen_up jsr scroll_screen_up
* !:
jsr calculate_screen_line_pointer jsr calculate_screen_line_pointer
@@ -751,38 +751,38 @@ add_40_to_screen_x:
rts rts
normalise_screen_x_y: normalise_screen_x_y:
;; Normalise X and Y values // Normalise X and Y values
;; If X < 0, then make X = X + 40 (or 80, if previous line is linked) // If X < 0, then make X = X + 40 (or 80, if previous line is linked)
* lda current_screen_x !: lda current_screen_x
bpl x_not_negative bpl x_not_negative
dec current_screen_y dec current_screen_y
;; Check that we didn't go backwards off the top of the screen // Check that we didn't go backwards off the top of the screen
bpl + bpl !+
lda #0 lda #0
sta current_screen_y sta current_screen_y
* jsr add_40_to_screen_x !: jsr add_40_to_screen_x
;; Check if line is linked, if so, add 40 again // Check if line is linked, if so, add 40 again
ldy current_screen_y ldy current_screen_y
lda screen_line_link_table,y lda screen_line_link_table,y
bpl + bpl !+
jsr add_40_to_screen_x jsr add_40_to_screen_x
* !:
x_not_negative: x_not_negative:
;; Work out if X is too big // Work out if X is too big
ldy current_screen_y ldy current_screen_y
lda screen_line_link_table,y lda screen_line_link_table,y
bpl + bpl !+
lda #79 lda #79
.byte $2C ; BIT $nnnn, used to skip next instruction .byte $2C // BIT $nnnn, used to skip next instruction
* lda #39 !: lda #39
cmp current_screen_x cmp current_screen_x
bcs x_not_too_big bcs x_not_too_big
;; X value is too big, so subtract 40 and increment Y // X value is too big, so subtract 40 and increment Y
lda current_screen_x lda current_screen_x
sec sec
sbc #40 sbc #40
@@ -791,28 +791,28 @@ x_not_negative:
x_not_too_big: x_not_too_big:
;; Make sure Y isn't negative // Make sure Y isn't negative
lda current_screen_y lda current_screen_y
bpl + bpl !+
lda #0 lda #0
sta current_screen_y sta current_screen_y
* !:
;; Make sure Y isn't too large for absolute size of // Make sure Y isn't too large for absolute size of
;; screen // screen
cmp #24 cmp #24
bcc + bcc !+
lda #24 lda #24
sta current_screen_y sta current_screen_y
* !:
;; Make sure Y isn't too much for the screen, taking // Make sure Y isn't too much for the screen, taking
;; into account the line link table // into account the line link table
ldy #24 ; max allowable line ldy #24 // max allowable line
ldx #0 ldx #0
link_count_loop: link_count_loop:
lda screen_line_link_table,x lda screen_line_link_table,x
bpl + bpl !+
dey dey
* inx !: inx
cpx #25 cpx #25
bne link_count_loop bne link_count_loop
tya tya
@@ -826,29 +826,29 @@ y_ok:
calculate_screen_line_pointer: calculate_screen_line_pointer:
jsr normalise_screen_x_y jsr normalise_screen_x_y
;; Reset pointer to start of screen // Reset pointer to start of screen
lda HIBASE lda HIBASE
sta current_screen_line_ptr+1 sta current_screen_line_ptr+1
lda #0 lda #0
sta current_screen_line_ptr+0 sta current_screen_line_ptr+0
;; Add 40 for every line, or 80 if the lines are linked // Add 40 for every line, or 80 if the lines are linked
ldx current_screen_y ldx current_screen_y
* !:
;; Stop if we have counted enough lines // Stop if we have counted enough lines
beq + beq !+
;; Add 40 or 80 based on whether the line is linked // Add 40 or 80 based on whether the line is linked
;; or not. // or not.
ldy #40 ldy #40
;; -1 offset is because we count down from N to 1, not // -1 offset is because we count down from N to 1, not
;; N-1 to 0. // N-1 to 0.
lda screen_line_link_table-1,x lda screen_line_link_table-1,x
bpl cslp_l1 bpl cslp_l1
ldy #80 ldy #80
cslp_l1: cslp_l1:
;; Add computed line length to pointer value // Add computed line length to pointer value
tya tya
clc clc
adc current_screen_line_ptr+0 adc current_screen_line_ptr+0
@@ -857,15 +857,15 @@ cslp_l1:
adc #0 adc #0
sta current_screen_line_ptr+1 sta current_screen_line_ptr+1
;; Loop back to next line // Loop back to next line
dex dex
jmp - jmp !-
* !:
;; FALL THROUGH // FALL THROUGH
update_colour_line_pointer: update_colour_line_pointer:
;; Now setup pointer to colour RAM // Now setup pointer to colour RAM
lda current_screen_line_ptr+0 lda current_screen_line_ptr+0
sta current_screen_line_colour_ptr+0 sta current_screen_line_colour_ptr+0
lda current_screen_line_ptr+1 lda current_screen_line_ptr+1
@@ -896,6 +896,6 @@ advance_screen_pointer_40_bytes:
jmp update_colour_line_pointer jmp update_colour_line_pointer
colour_codes: colour_codes:
;; CHR$ codes for the 16 colours // CHR$ codes for the 16 colours
.byte 144,5,28,159,156,30,31,158 .byte 144,5,28,159,156,30,31,158
.byte 129,149,150,151,152,153,154,155 .byte 129,149,150,151,152,153,154,155
+40 -40
View File
@@ -1,24 +1,24 @@
;; //
;; Official Kernal routine, described in: // Official Kernal routine, described in:
;; //
;; - [RG64] C64 Programmer's Reference Guide - page 280 // - [RG64] C64 Programmer's Reference Guide - page 280
;; - [CM64] Compute's Mapping the Commodore 64 - page 242 // - [CM64] Compute's Mapping the Commodore 64 - page 242
;; //
;; CPU registers that has to be preserved (see [RG64]): none // CPU registers that has to be preserved (see [RG64]): none
;; //
cint_real: cint_real:
;; According to [CM64], this routine checks for PAL/NTSC. It's definitely not done // According to [CM64], this routine checks for PAL/NTSC. It's definitely not done
;; within the 'BRK' part, this can be easily checked - POKE something // within the 'BRK' part, this can be easily checked - POKE something
;; to address 678 on a real C64, press STOP+RESTORE, the value won't change // to address 678 on a real C64, press STOP+RESTORE, the value won't change
;; Detect video system (PAL/NTSC), use Graham's method, as it's short and reliable // Detect video system (PAL/NTSC), use Graham's method, as it's short and reliable
;; see here: https://codebase64.org/doku.php?id=base:detect_pal_ntsc // see here: https://codebase64.org/doku.php?id=base:detect_pal_ntsc
lda #$C8 ; preparation, as the VIC might be uninitialized lda #$C8 // preparation, as the VIC might be uninitialized
sta VIC_SCROLX sta VIC_SCROLX
cint_w0: cint_w0:
@@ -28,18 +28,18 @@ cint_w1:
beq cint_w1 beq cint_w1
bmi cint_w0 bmi cint_w0
;; Result in A, if no interrupt happened during the test: // Result in A, if no interrupt happened during the test:
;; #$37 -> 312 rasterlines, PAL, VIC 6569 // #$37 -> 312 rasterlines, PAL, VIC 6569
;; #$06 -> 263 rasterlines, NTSC, VIC 6567R8 // #$06 -> 263 rasterlines, NTSC, VIC 6567R8
;; #$05 -> 262 rasterlines, NTSC, VIC 6567R56A // #$05 -> 262 rasterlines, NTSC, VIC 6567R56A
cmp #$07 cmp #$07
bcs cint_pal bcs cint_pal
cint_ntsc: cint_ntsc:
;; NTSC C64 (https://codebase64.org/doku.php?id=base:cpu_clocking), // NTSC C64 (https://codebase64.org/doku.php?id=base:cpu_clocking),
;; is clocked at 1.022727 MHz, so that 1/60s is 17045 CPU cycles // is clocked at 1.022727 MHz, so that 1/60s is 17045 CPU cycles
ldy #<17045 ldy #<17045
ldx #>17045 ldx #>17045
@@ -48,51 +48,51 @@ cint_ntsc:
stx CIA1_TIMAHI stx CIA1_TIMAHI
lda #$00 lda #$00
beq + beq !+
cint_pal: cint_pal:
lda #$01 lda #$01
* !:
sta PALNTSC sta PALNTSC
cint_brk: ; entry for BRK and STOP+RESTORE - XXX, where should it start? cint_brk: // entry for BRK and STOP+RESTORE - XXX, where should it start?
jsr setup_vicii jsr setup_vicii
;; Initialise cursor blink flags (Compute's Mapping the 64 p215) // Initialise cursor blink flags (Compute's Mapping the 64 p215)
lda #$00 lda #$00
sta cursor_blink_disable sta cursor_blink_disable
;; Set keyboard decode vector (Compute's Mapping the 64 p215) // Set keyboard decode vector (Compute's Mapping the 64 p215)
;; Set initial variables for our improved keyboard scan routine // Set initial variables for our improved keyboard scan routine
lda #$ff lda #$FF
ldx #6 ldx #6
* sta BufferOld,x !: sta BufferOld,x
dex dex
bpl - bpl !-
sta BufferQuantity sta BufferQuantity
;; Set key repeat delay (Compute's Mapping the 64 p215) // Set key repeat delay (Compute's Mapping the 64 p215)
;; Making some numbers up here: Repeat every ~1/10th sec // Making some numbers up here: Repeat every ~1/10th sec
;; But require key to be held for ~1/3sec before // But require key to be held for ~1/3sec before
;; repeating (Compute's Mapping the 64 p58) // repeating (Compute's Mapping the 64 p58)
ldx #22-2 ; Fudge factor to match speed ldx #22-2 // Fudge factor to match speed
stx key_first_repeat_delay stx key_first_repeat_delay
;; Set current colour for text (Compute's Mapping the 64 p215) // Set current colour for text (Compute's Mapping the 64 p215)
ldx #$01 ; default is light blue ($0E), but we use a different one ldx #$01 // default is light blue ($0E), but we use a different one
stx text_colour stx text_colour
;; Set maximum keyboard buffer size (Compute's Mapping the 64 p215) // Set maximum keyboard buffer size (Compute's Mapping the 64 p215)
ldx #10 ldx #10
stx key_buffer_size stx key_buffer_size
;; Put non-zero value in enable_case_switch // Put non-zero value in enable_case_switch
stx enable_case_switch stx enable_case_switch
;; Set default I/O devices (see SCINIT description at http://sta.c64.org/cbm64krnfunc.html) // Set default I/O devices (see SCINIT description at http://sta.c64.org/cbm64krnfunc.html)
jsr clrchn_reset jsr clrchn_reset
;; Fallthrough/jump to screen clear routine (Compute's Mapping the 64 p215) // Fallthrough/jump to screen clear routine (Compute's Mapping the 64 p215)
jmp clear_screen jmp clear_screen
+14 -14
View File
@@ -1,37 +1,37 @@
;; //
;; Official Kernal routine, described in: // Official Kernal routine, described in:
;; //
;; - [RG64] C64 Programmer's Reference Guide - page 279/280 // - [RG64] C64 Programmer's Reference Guide - page 279/280
;; - [CM64] Compute's Mapping the Commodore 64 - page 224 // - [CM64] Compute's Mapping the Commodore 64 - page 224
;; //
;; CPU registers that has to be preserved (see [RG64]): .X, .Y // CPU registers that has to be preserved (see [RG64]): .X, .Y
;; //
ciout: CIOUT:
pha pha
lda C3PO lda C3PO
bne ciout_send_byte bne ciout_send_byte
;; Nothing to send - set buffer as valid, store byte there // Nothing to send - set buffer as valid, store byte there
inc C3PO inc C3PO
;; Clear carry flag to indicate success // Clear carry flag to indicate success
clc clc
ciout_store_in_buffer: ciout_store_in_buffer:
;; Store in the buffer data to be sent next, return // Store in the buffer data to be sent next, return
pla pla
sta BSOUR sta BSOUR
rts rts
ciout_send_byte: ciout_send_byte:
clc ; don't send with EOI clc // don't send with EOI
jsr iec_tx_byte jsr iec_tx_byte
inc C3PO ; iec_tx_byte sets it to 0, but we still have something to send inc C3PO // iec_tx_byte sets it to 0, but we still have something to send
jmp ciout_store_in_buffer jmp ciout_store_in_buffer
+20 -20
View File
@@ -1,38 +1,38 @@
;; //
;; Official Kernal routine, described in: // Official Kernal routine, described in:
;; //
;; - [RG64] C64 Programmer's Reference Guide - page 281 // - [RG64] C64 Programmer's Reference Guide - page 281
;; - [CM64] Compute's Mapping the Commodore 64 - page 230 // - [CM64] Compute's Mapping the Commodore 64 - page 230
;; //
;; CPU registers that has to be preserved (see [RG64]): .Y // CPU registers that has to be preserved (see [RG64]): .Y
;; //
clall_real: clall_real:
;; Store .Y register // Store .Y register
tya tya
pha pha
;; Original routine probably just sets LDTND to 0, but this is not really safe, // Original routine probably just sets LDTND to 0, but this is not really safe,
;; so we actually close all the channels; at least IDE64 does the same for // so we actually close all the channels; at least IDE64 does the same for
;; it's channels, see CLALL description in the IDE64 User's Guide // it's channels, see CLALL description in the IDE64 User's Guide
* !:
ldy LDTND ldy LDTND
beq + beq !+
dey dey
lda LAT, y lda LAT, y
jsr JCLOSE jsr JCLOSE
jmp - jmp !-
* !:
;; Restore .Y register // Restore .Y register
pla pla
tay tay
;; 'C64 Programmers Reference Guide', page 281, claims it calls CLRCHN too // 'C64 Programmers Reference Guide', page 281, claims it calls CLRCHN too
jsr clrchn jsr CLRCHN
;; Not sure whether original Kernal does so, but it seems sane to also clear possible errors // Not sure whether original Kernal does so, but it seems sane to also clear possible errors
jmp kernalstatus_reset jmp kernalstatus_reset
+7 -7
View File
@@ -1,23 +1,23 @@
;; Common ppart of CLOSE and LOAD routines // Common ppart of CLOSE and LOAD routines
close_load: close_load:
tax tax
;; Command drive to stop talking and to close the file // Command drive to stop talking and to close the file
jsr untlk jsr UNTLK
txa txa
jsr listen jsr LISTEN
lda #$E0 ; CLOSE command lda #$E0 // CLOSE command
sta IEC_TMP2 sta IEC_TMP2
jsr iec_tx_command jsr iec_tx_command
jsr iec_tx_command_finalize jsr iec_tx_command_finalize
;; Tell drive to unlisten // Tell drive to unlisten
jsr unlsn jsr UNLSN
rts rts
+21 -21
View File
@@ -1,35 +1,35 @@
;; //
;; Official Kernal routine, described in: // Official Kernal routine, described in:
;; //
;; - [RG64] C64 Programmer's Reference Guide - page 282 // - [RG64] C64 Programmer's Reference Guide - page 282
;; - [CM64] Compute's Mapping the Commodore 64 - page 230 // - [CM64] Compute's Mapping the Commodore 64 - page 230
;; //
;; CPU registers that has to be preserved (see [RG64]): .Y // CPU registers that has to be preserved (see [RG64]): .Y
;; //
clrchn_real: clrchn_real:
;; Handle IEC input device // Handle IEC input device
lda DFLTN lda DFLTN
jsr iec_check_devnum jsr iec_check_devnum
bcs + bcs !+
;; Previous device was IEC one - send UNTALK first // Previous device was IEC one - send UNTALK first
jsr untlk jsr UNTLK
* !:
;; Restore output device to default // Restore output device to default
lda DFLTO lda DFLTO
jsr iec_check_devnum jsr iec_check_devnum
bcs + bcs !+
;; Handle IEC output device // Handle IEC output device
jsr unlsn jsr UNLSN
* !:
clrchn_reset: ;; entry needed by CHRIN clrchn_reset: // entry needed by CHRIN
;; Set input device number to keyboard // Set input device number to keyboard
lda #$00 lda #$00
sta DFLTN sta DFLTN
;; Set output device number to screen // Set output device number to screen
lda #$03 lda #$03
sta DFLTO sta DFLTO
+23 -23
View File
@@ -1,10 +1,10 @@
;; Clear screen and initialise line link table // Clear screen and initialise line link table
;; (Compute's Mapping the 64 p215-216) // (Compute's Mapping the 64 p215-216)
clear_screen: clear_screen:
;; Clear line link table // Clear line link table
;; (Compute's Mapping the 64 p215) // (Compute's Mapping the 64 p215)
lda #$00 lda #$00
ldy #24 ldy #24
@@ -13,27 +13,27 @@ clearscreen_l1:
dey dey
bpl clearscreen_l1 bpl clearscreen_l1
;; Y now = #$FF // Y now = #$FF
;; Clear screen RAM. // Clear screen RAM.
;; We should do this at HIBASE, which annoyingly // We should do this at HIBASE, which annoyingly
;; is no ZP, so we need to make a vector // is no ZP, so we need to make a vector
;; (Compute's Mapping the 64 p216) // (Compute's Mapping the 64 p216)
;; Get pointer to the screen into current_screen_line_ptr // Get pointer to the screen into current_screen_line_ptr
;; as it is the first appropriate place for it found when // as it is the first appropriate place for it found when
;; searching through the ZP allocations listed in // searching through the ZP allocations listed in
;; Compute's Mapping the 64 // Compute's Mapping the 64
sta current_screen_line_ptr+0 sta current_screen_line_ptr+0
lda hibase lda HIBASE
sta current_screen_line_ptr+1 sta current_screen_line_ptr+1
ldx #$03 ; countdown for pages to update ldx #$03 // countdown for pages to update
iny ; Y now = #$00 iny // Y now = #$00
lda #$20 ; space character lda #$20 // space character
clearscreen_l2: clearscreen_l2:
sta (current_screen_line_ptr),y sta (current_screen_line_ptr),y
iny iny
bne clearscreen_l2 bne clearscreen_l2
;; To draw only 1000 bytes, add 250 to address each time // To draw only 1000 bytes, add 250 to address each time
lda current_screen_line_ptr lda current_screen_line_ptr
clc clc
adc #<250 adc #<250
@@ -41,20 +41,20 @@ clearscreen_l2:
lda current_screen_line_ptr+1 lda current_screen_line_ptr+1
adc #>250 adc #>250
sta current_screen_line_ptr+1 sta current_screen_line_ptr+1
lda #$20 ; get space character again lda #$20 // get space character again
dex dex
bpl clearscreen_l2 bpl clearscreen_l2
;; Clear colour RAM // Clear colour RAM
;; (Compute's Mapping the 64 p216) // (Compute's Mapping the 64 p216)
lda text_colour lda text_colour
clearscreen_l3: clearscreen_l3:
sta $d800,y sta $d800,y
sta $d900,y sta $d900,y
sta $da00,y sta $da00,y
sta $db00-24,y ; so we only erase 1000 bytes sta $db00-24,y // so we only erase 1000 bytes
iny iny
bne clearscreen_l3 bne clearscreen_l3
;; (Compute's Mapping the 64 p216) // (Compute's Mapping the 64 p216)
jmp home_cursor jmp home_cursor
+7 -7
View File
@@ -1,20 +1,20 @@
setup_vicii: setup_vicii:
;; Set up default IO values (Compute's Mapping the 64 p215) // Set up default IO values (Compute's Mapping the 64 p215)
lda #$1B ; Enable text mode lda #$1B // Enable text mode
sta VIC_SCROLY sta VIC_SCROLY
lda #$C8 ; 40 column etc lda #$C8 // 40 column etc
sta VIC_SCROLX sta VIC_SCROLX
;; Compute's Mapping the 64, p156 // Compute's Mapping the 64, p156
;; We use a different colour scheme of white text on all blue // We use a different colour scheme of white text on all blue
lda #$06 lda #$06
sta VIC_EXTCOL sta VIC_EXTCOL
sta VIC_BGCOL0 sta VIC_BGCOL0
;; Turn off sprites (observed hanging around after running programs and resetting) // Turn off sprites (observed hanging around after running programs and resetting)
lda #$00 lda #$00
sta VIC_SPENA sta VIC_SPENA
;;FALLTROUGH // FALLTROUGH
+5 -5
View File
@@ -1,7 +1,7 @@
;; Kernal error codes are described in 'Commodore 64 Programmer's Reference Guide', page 306 // Kernal error codes are described in 'Commodore 64 Programmer's Reference Guide', page 306
kernalerror_ROUTINE_TERMINATED: ; by a STOP key kernalerror_ROUTINE_TERMINATED: // by a STOP key
lda #K_ERR_ROUTINE_TERMINATED lda #K_ERR_ROUTINE_TERMINATED
sec sec
rts rts
@@ -56,20 +56,20 @@ kernalerror_TOP_MEM_RS232:
sec sec
rts rts
;; Kernal status codes are described in 'Commodore 64 Programmer's Reference Guide', page 292 // Kernal status codes are described in 'Commodore 64 Programmer's Reference Guide', page 292
kernalstatus_reset: kernalstatus_reset:
lda #$00 lda #$00
sta IOSTATUS sta IOSTATUS
rts rts
kernalstatus_TIMEOUT_WRITE: ;; XXX detect this! kernalstatus_TIMEOUT_WRITE: // XXX detect this!
lda IOSTATUS lda IOSTATUS
ora #K_STS_TIMEOUT_WRITE ora #K_STS_TIMEOUT_WRITE
sta IOSTATUS sta IOSTATUS
rts rts
kernalstatus_TIMEOUT_READ: ;; XXX detect this! kernalstatus_TIMEOUT_READ: // XXX detect this!
lda IOSTATUS lda IOSTATUS
ora #K_STS_TIMEOUT_READ ora #K_STS_TIMEOUT_READ
sta IOSTATUS sta IOSTATUS
+14 -14
View File
@@ -1,27 +1,27 @@
;; //
;; Official Kernal routine, described in: // Official Kernal routine, described in:
;; //
;; - [RG64] C64 Programmer's Reference Guide - page 283 // - [RG64] C64 Programmer's Reference Guide - page 283
;; - [CM64] Compute's Mapping the Commodore 64 - page 227/228 // - [CM64] Compute's Mapping the Commodore 64 - page 227/228
;; //
;; CPU registers that has to be preserved (see [RG64]): .X, .Y // CPU registers that has to be preserved (see [RG64]): .X, .Y
;; //
;; XXX currently does not preserve registers, to be fixed! // XXX currently does not preserve registers, to be fixed!
getin: GETIN:
;; Wait for a key // Wait for a key
lda keys_in_key_buffer lda keys_in_key_buffer
bne + bne !+
;; Nothing in keyboard buffer to read // Nothing in keyboard buffer to read
sec sec
lda #$00 lda #$00
rts rts
* !:
lda keyboard_buffer lda keyboard_buffer
pha pha
+3 -3
View File
@@ -1,6 +1,6 @@
;; Our implementation is longer than the original one, // Our implementation is longer than the original one,
;; placing it here would cause a collision with CHROUT // placing it here would cause a collision with CHROUT
chrin: CHRIN:
jmp chrin_real jmp chrin_real
+3 -3
View File
@@ -1,6 +1,6 @@
;; Our implementation is longer than the original one, // Our implementation is longer than the original one,
;; placing it here would cause a collision with CHKIN // placing it here would cause a collision with CHKIN
chrout: CHROUT:
jmp chrout_real jmp chrout_real
+3 -3
View File
@@ -1,6 +1,6 @@
;; In our implementation CHKIN and CKOUT are closely tied, // In our implementation CHKIN and CKOUT are closely tied,
;; placing it here would cause a collision // placing it here would cause a collision
chkin: CHKIN:
jmp chkin_real jmp chkin_real
+3 -3
View File
@@ -1,6 +1,6 @@
;; In our implementation CHKIN and CKOUT are closely tied, // In our implementation CHKIN and CKOUT are closely tied,
;; placing it here would cause a collision // placing it here would cause a collision
ckout: CKOUT:
jmp ckout_real jmp ckout_real
+27 -27
View File
@@ -1,49 +1,49 @@
;; //
;; Official Kernal routine, described in: // Official Kernal routine, described in:
;; //
;; - [RG64] C64 Programmer's Reference Guide - page 281/282 // - [RG64] C64 Programmer's Reference Guide - page 281/282
;; - [CM64] Compute's Mapping the Commodore 64 - page 229/230 // - [CM64] Compute's Mapping the Commodore 64 - page 229/230
;; - https://www.pagetable.com/?p=1031, https://github.com/mist64/cbmbus_doc (IEC command) // - https://www.pagetable.com/?p=1031, https://github.com/mist64/cbmbus_doc (IEC command)
;; //
;; CPU registers that has to be preserved (see [RG64]): none // CPU registers that has to be preserved (see [RG64]): none
;; //
close: CLOSE:
;; XXX this needs more testing (opening 10 files at once, closing in various orders, etc) once the code is more mature // XXX this needs more testing (opening 10 files at once, closing in various orders, etc) once the code is more mature
;; Find the LAT / SAT / FAT entry which LAT corresponds to A // Find the LAT / SAT / FAT entry which LAT corresponds to A
jsr find_fls jsr find_fls
bcs close_error_not_found ;; XXX can we report error in IOSTATUS here? bcs close_error_not_found // XXX can we report error in IOSTATUS here?
;; We have the entry index in Y - check whether this is IEC device // We have the entry index in Y - check whether this is IEC device
lda FAT, y lda FAT, y
jsr iec_check_devnum jsr iec_check_devnum
bcs close_remove_from_table bcs close_remove_from_table
;; IEC device // IEC device
jsr iec_tx_flush ; make sure no byte is awaiting jsr iec_tx_flush // make sure no byte is awaiting
lda SAT, y ; get secondary address lda SAT, y // get secondary address
cmp #$60 cmp #$60
bne + bne !+
;; workaround for using CLOSE on reading executable - XXX is this a proper way? // workaround for using CLOSE on reading executable - XXX is this a proper way?
jsr close_load jsr close_load
jmp close_remove_from_table jmp close_remove_from_table
* !:
ora $E0 ; CLOSE command ora $E0 // CLOSE command
sta IEC_TMP2 sta IEC_TMP2
jsr iec_tx_command jsr iec_tx_command
bcs close_remove_from_table bcs close_remove_from_table
jsr iec_tx_command_finalize jsr iec_tx_command_finalize
close_remove_from_table: close_remove_from_table:
;; Remove channel from the table // Remove channel from the table
iny iny
cpy #$0A cpy #$0A
bpl + bpl !+
lda LAT, y lda LAT, y
sta LAT-1, y sta LAT-1, y
lda FAT, y lda FAT, y
@@ -51,14 +51,14 @@ close_remove_from_table:
lda SAT, y lda SAT, y
sta SAT-1, y sta SAT-1, y
jmp close_remove_from_table jmp close_remove_from_table
* !:
;; Decrement the list size variable // Decrement the list size variable
dec LDTND dec LDTND
clc ; report success - not sure if original CLOSE does this, but it's nevertheless a good practice clc // report success - not sure if original CLOSE does this, but it's nevertheless a good practice
rts rts
close_error_not_found: close_error_not_found:
sec ; report success - not sure if original CLOSE does this, but it's nevertheless a good practice sec // report success - not sure if original CLOSE does this, but it's nevertheless a good practice
rts rts
+3 -3
View File
@@ -1,6 +1,6 @@
;; Our implementation is longer than the original one, // Our implementation is longer than the original one,
;; placing it here would cause a collision with CLRCHN // placing it here would cause a collision with CLRCHN
clall: CLALL:
jmp clall_real jmp clall_real
+3 -3
View File
@@ -1,6 +1,6 @@
;; Our implementation is longer than the original one, // Our implementation is longer than the original one,
;; placing it here would cause a collision with OPEN // placing it here would cause a collision with OPEN
clrchn: CLRCHN:
jmp clrchn_real jmp clrchn_real
+32 -32
View File
@@ -1,23 +1,23 @@
;; //
;; Official Kernal routine, described in: // Official Kernal routine, described in:
;; //
;; - [RG64] C64 Programmer's Reference Guide - page 289 // - [RG64] C64 Programmer's Reference Guide - page 289
;; - [CM64] Compute's Mapping the Commodore 64 - page 230/231 // - [CM64] Compute's Mapping the Commodore 64 - page 230/231
;; //
;; CPU registers that has to be preserved (see [RG64]): none // CPU registers that has to be preserved (see [RG64]): none
;; //
open: OPEN:
;; Reset status // Reset status
jsr kernalstatus_reset jsr kernalstatus_reset
;; Check if the logical file number is unique // Check if the logical file number is unique
ldy LDTND ldy LDTND
* !:
beq + beq !+
dey dey
lda LAT, y lda LAT, y
cmp current_logical_filenum cmp current_logical_filenum
@@ -25,23 +25,23 @@ open:
jmp kernalerror_FILE_ALREADY_OPEN jmp kernalerror_FILE_ALREADY_OPEN
open_not_yet_open: open_not_yet_open:
cpy #$00 cpy #$00
jmp - jmp !-
* !:
;; Check if we have space in tables // Check if we have space in tables
ldy LDTND ldy LDTND
cpy #$0A cpy #$0A
bcc open_has_space bcc open_has_space
* !:
;; Table is full // Table is full
jmp kernalerror_TOO_MANY_OPEN_FILES jmp kernalerror_TOO_MANY_OPEN_FILES
open_has_space: open_has_space:
;; Update the tables // Update the tables
;; LAT / FAT / SAT support implemented according to // LAT / FAT / SAT support implemented according to
;; 'Compute's Mapping the Commodore 64', page 52 // 'Compute's Mapping the Commodore 64', page 52
lda current_logical_filenum lda current_logical_filenum
sta LAT, y sta LAT, y
@@ -53,16 +53,16 @@ open_has_space:
iny iny
sty LDTND sty LDTND
;; Check for command to send // Check for command to send
lda FNLEN lda FNLEN
beq open_done_success beq open_done_success
;; Check for IEC device // Check for IEC device
lda current_device_number lda current_device_number
jsr iec_check_devnum jsr iec_check_devnum
bcc open_iec bcc open_iec
;; FALLTROUGH // FALLTROUGH
open_done_success: open_done_success:
clc clc
@@ -70,21 +70,21 @@ open_done_success:
open_iec: open_iec:
;; We have a command to send to IEC device // We have a command to send to IEC device
jsr listen jsr LISTEN
bcc + bcc !+
jmp kernalerror_DEVICE_NOT_FOUND jmp kernalerror_DEVICE_NOT_FOUND
* !:
lda current_secondary_address lda current_secondary_address
jsr iec_cmd_open jsr iec_cmd_open
bcc + bcc !+
jmp kernalerror_DEVICE_NOT_FOUND jmp kernalerror_DEVICE_NOT_FOUND
* !:
;; We need our helpers to get to filenames under ROMs or IO area // We need our helpers to get to filenames under ROMs or IO area
jsr install_ram_routines jsr install_ram_routines
;; Send command ('file name') // Send command ('file name')
jsr lvs_send_file_name jsr lvs_send_file_name
jmp open_done_success jmp open_done_success
+92 -92
View File
@@ -1,146 +1,146 @@
;; //
;; Official Kernal routine, described in: // Official Kernal routine, described in:
;; //
;; - [RG64] C64 Programmer's Reference Guide - page 286 // - [RG64] C64 Programmer's Reference Guide - page 286
;; - [CM64] Compute's Mapping the Commodore 64 - page 231 // - [CM64] Compute's Mapping the Commodore 64 - page 231
;; - IEC reference at http://www.zimmers.net/anonftp/pub/cbm/programming/serial-bus.pdf // - IEC reference at http://www.zimmers.net/anonftp/pub/cbm/programming/serial-bus.pdf
;; //
;; CPU registers that has to be preserved (see [RG64]): none // CPU registers that has to be preserved (see [RG64]): none
;; //
;; Expects that SETLFS and SETNAM are called before hand. // Expects that SETLFS and SETNAM are called before hand.
;; $YYXX = load address. // $YYXX = load address.
;; (ignored if SETLFS channel = 1, i.e., like ,8,1) // (ignored if SETLFS channel = 1, i.e., like ,8,1)
;; If A=1 then VERIFY instead of LOAD. // If A=1 then VERIFY instead of LOAD.
;; On exit, $YYXX is the highest address into which data // On exit, $YYXX is the highest address into which data
;; will have been placed. // will have been placed.
;; XXX honor MSGFLG bit 6 // XXX honor MSGFLG bit 6
;; XXX add VERIFY support // XXX add VERIFY support
load: LOAD:
;; Are we loading or verifying? // Are we loading or verifying?
sta VERCK sta VERCK
;; Store start address of LOAD // Store start address of LOAD
stx STAL+0 stx STAL+0
sty STAL+1 sty STAL+1
;; Reset status // Reset status
jsr kernalstatus_reset jsr kernalstatus_reset
;; We need our helpers to get to filenames under ROMs or IO area // We need our helpers to get to filenames under ROMs or IO area
jsr install_ram_routines jsr install_ram_routines
;; Allow platform-specific routine to takeover the flow // Allow platform-specific routine to takeover the flow
`TARGET_HOOK_LOAD TARGET_HOOK_LOAD()
;; Check whether we support the requested device // Check whether we support the requested device
lda current_device_number lda current_device_number
and #$FC and #$FC
bne + bne !+
jmp lvs_illegal_device_number ; device number below 4, not an IEC device jmp lvs_illegal_device_number // device number below 4, not an IEC device
* !:
;; Device numbers above 30 are also illegal (see https://www.pagetable.com/?p=1031), // Device numbers above 30 are also illegal (see https://www.pagetable.com/?p=1031),
;; as the protocol combines device number with command code int one byte, // as the protocol combines device number with command code int one byte,
;; above 30 it is no longer possible (UNLISTEN and UNTALK codes prevent using // above 30 it is no longer possible (UNLISTEN and UNTALK codes prevent using
;; number 31), yet original ROMs show ILLEGAL DEVICE NUMBER error only // number 31), yet original ROMs show ILLEGAL DEVICE NUMBER error only
;; for devices 0-3; in our implementation LISTEN / TALK will cause device // for devices 0-3; in our implementation LISTEN / TALK will cause device
;; not present detected for numbers above 30 // not present detected for numbers above 30
;; Display SEARCHING FOR + filename // Display SEARCHING FOR + filename
jsr lvs_display_searching_for jsr lvs_display_searching_for
;; http://www.zimmers.net/anonftp/pub/cbm/programming/serial-bus.pdf // http://www.zimmers.net/anonftp/pub/cbm/programming/serial-bus.pdf
;; p13, 16; also p16 tells us this routine doesn't mess with the file table // p13, 16; also p16 tells us this routine doesn't mess with the file table
;; in the C64, only in the drive. // in the C64, only in the drive.
;; Call device to LISTEN (p16) // Call device to LISTEN (p16)
lda current_device_number lda current_device_number
jsr listen jsr LISTEN
bcc + bcc !+
jmp lvs_device_not_found_error ; XXX deduplicate with other jumps in this routine jmp lvs_device_not_found_error // XXX deduplicate with other jumps in this routine
* !:
;; Open channel 0 (reserved for file reading) // Open channel 0 (reserved for file reading)
lda #$00 lda #$00
jsr iec_cmd_open jsr iec_cmd_open
bcc + bcc !+
jmp lvs_device_not_found_error ; XXX deduplicate with other jumps in this routine jmp lvs_device_not_found_error // XXX deduplicate with other jumps in this routine
* !:
;; Send file name // Send file name
jsr lvs_send_file_name jsr lvs_send_file_name
bcc + bcc !+
jmp lvs_load_verify_error ; XXX deduplicate with other jumps in this routine jmp lvs_load_verify_error // XXX deduplicate with other jumps in this routine
* !:
;; Now command device to talk (p16) // Now command device to talk (p16)
lda current_device_number lda current_device_number
jsr talk jsr TALK
bcc + bcc !+
jmp lvs_load_verify_error ; XXX deduplicate with other jumps in this routine jmp lvs_load_verify_error // XXX deduplicate with other jumps in this routine
* !:
lda #$60 ; open channel / data (p3) , required according to p13 lda #$60 // open channel / data (p3) , required according to p13
sta IEC_TMP2 sta IEC_TMP2
jsr iec_tx_command jsr iec_tx_command
bcc + bcc !+
jmp lvs_load_verify_error ; XXX deduplicate with other jumps in this routine jmp lvs_load_verify_error // XXX deduplicate with other jumps in this routine
* !:
;; We are currently talker, so do the IEC turn around so that we // We are currently talker, so do the IEC turn around so that we
;; are the listener (p16) // are the listener (p16)
jsr iec_turnaround_to_listen jsr iec_turnaround_to_listen
bcc + bcc !+
jmp lvs_load_verify_error ; XXX deduplicate with other jumps in this routine jmp lvs_load_verify_error // XXX deduplicate with other jumps in this routine
* !:
;; Get load address and store it if secondary address is zero // Get load address and store it if secondary address is zero
jsr iec_rx_byte jsr iec_rx_byte
bcc + bcc !+
jmp lvs_file_not_found_error ; XXX deduplicate with other jumps in this routine jmp lvs_file_not_found_error // XXX deduplicate with other jumps in this routine
* !:
ldx current_secondary_address ldx current_secondary_address
beq + beq !+
sta STAL+0 sta STAL+0
* !:
jsr iec_rx_byte jsr iec_rx_byte
bcc + bcc !+
jmp lvs_file_not_found_error ; XXX deduplicate with other jumps in this routine jmp lvs_file_not_found_error // XXX deduplicate with other jumps in this routine
* !:
ldx current_secondary_address ldx current_secondary_address
beq + beq !+
sta STAL+1 sta STAL+1
* !:
;; Display start address // Display start address
jsr lvs_display_loading_verifying jsr lvs_display_loading_verifying
load_loop: load_loop:
;; We are now ready to receive bytes // We are now ready to receive bytes
jsr iec_rx_byte jsr iec_rx_byte
bcc + bcc !+
jmp lvs_load_verify_error ; XXX deduplicate with other jumps in this routine jmp lvs_load_verify_error // XXX deduplicate with other jumps in this routine
* !:
;; Handle the byte (store in memory / verify) // Handle the byte (store in memory / verify)
jsr lvs_handle_byte_load_verify jsr lvs_handle_byte_load_verify
bcc + bcc !+
jmp lvs_load_verify_error ; XXX deduplicate with other jumps in this routine jmp lvs_load_verify_error // XXX deduplicate with other jumps in this routine
* !:
;; Advance pointer to data // Advance pointer to data
jsr lvs_advance_pointer jsr lvs_advance_pointer
bcc + bcc !+
jmp lvs_wrap_around_error jmp lvs_wrap_around_error
* !:
;; Check for EOI - if so, this was the last byte // Check for EOI - if so, this was the last byte
lda IOSTATUS lda IOSTATUS
and #K_STS_EOI and #K_STS_EOI
beq load_loop beq load_loop
;; Display end address // Display end address
jsr lvs_display_done jsr lvs_display_done
;; Close file on drive // Close file on drive
lda current_device_number lda current_device_number
jsr close_load jsr close_load
;; Return last address // Return last address
jmp lvs_return_last_address jmp lvs_return_last_address
+10 -10
View File
@@ -1,13 +1,13 @@
;; //
;; Official Kernal routine, described in: // Official Kernal routine, described in:
;; //
;; - [RG64] C64 Programmer's Reference Guide - page 293/294 // - [RG64] C64 Programmer's Reference Guide - page 293/294
;; - [CM64] Compute's Mapping the Commodore 64 - page 231/232 // - [CM64] Compute's Mapping the Commodore 64 - page 231/232
;; - IEC reference at http://www.zimmers.net/anonftp/pub/cbm/programming/serial-bus.pdf // - IEC reference at http://www.zimmers.net/anonftp/pub/cbm/programming/serial-bus.pdf
;; //
;; CPU registers that has to be preserved (see [RG64]): none // CPU registers that has to be preserved (see [RG64]): none
;; //
save: SAVE:
rts rts
+15 -15
View File
@@ -1,24 +1,24 @@
;; //
;; Official Kernal routine, described in: // Official Kernal routine, described in:
;; //
;; - [RG64] C64 Programmer's Reference Guide - page 301 // - [RG64] C64 Programmer's Reference Guide - page 301
;; - [CM64] Compute's Mapping the Commodore 64 - page 232 // - [CM64] Compute's Mapping the Commodore 64 - page 232
;; //
;; CPU registers that has to be preserved (see [RG64]): .Y // CPU registers that has to be preserved (see [RG64]): .Y
;; //
stop: STOP:
;; Bit 7 of STKEY contains the state of the STOP key // Bit 7 of STKEY contains the state of the STOP key
;; (Compute's Mapping the 64, p27) // (Compute's Mapping the 64, p27)
;; BASIC checks carry flag to indicate STOP or not // BASIC checks carry flag to indicate STOP or not
lda STKEY lda STKEY
bpl stop_pressed bpl stop_pressed
;; By trial and error, we know that Z + C = BREAK // By trial and error, we know that Z + C = BREAK
;; and that neither should be set otherwise // and that neither should be set otherwise
lda #$ff lda #$FF
clc clc
rts rts
+30 -36
View File
@@ -1,70 +1,64 @@
;; //
;; Official Kernal routine, described in: // Official Kernal routine, described in:
;; //
;; - [RG64] C64 Programmer's Reference Guide - page 293 (RESTOR), 304 (VECTOR) // - [RG64] C64 Programmer's Reference Guide - page 293 (RESTOR), 304 (VECTOR)
;; - [CM64] Compute's Mapping the Commodore 64 - page 237 // - [CM64] Compute's Mapping the Commodore 64 - page 237
;; //
;; CPU registers that has to be preserved (see [RG64]): none // CPU registers that has to be preserved (see [RG64]): none
;; //
restor: RESTOR:
clc ;; clear carry - for writing to system table clc // clear carry - for writing to system table
ldx #<vector_defaults ldx #<vector_defaults
ldy #>vector_defaults ldy #>vector_defaults
;; FALLTHROUGH // FALLTHROUGH
vector: VECTOR:
.scope // Temporary storage location - checked on real C64 that this is the
// address originally used; after calling VECTOR and checking zero page
// area afterwards, the address could be found there
.label _caller_arr_ptr = MEMUS
;; Temporary storage location - checked on real C64 that this is the // According to 'Compute's Mapping the Commodore 64' page 237,
;; address originally used; after calling VECTOR and checking zero page // the CBM implementation does not disable IRQs - yet, the
;; area afterwards, the address could be found there // 'C64 Programmers Reference Guide' does not contain such
.alias _caller_arr_ptr MEMUS // warning and does not mention any preparations needed, so...
// better safe than sorry, disable the IRQ for the duration
;; According to 'Compute's Mapping the Commodore 64' page 237, // of vector manipulation
;; the CBM implementation does not disable IRQs - yet, the
;; 'C64 Programmers Reference Guide' does not contain such
;; warning and does not mention any preparations needed, so...
;; better safe than sorry, disable the IRQ for the duration
;; of vector manipulation
php php
cli cli
;; Prepare the user data pointer - strange order to reduce risk // Prepare the user data pointer - strange order to reduce risk
;; of potential similarity to the original routine // of potential similarity to the original routine
sty _caller_arr_ptr + 1 sty _caller_arr_ptr + 1
stx _caller_arr_ptr + 0 stx _caller_arr_ptr + 0
;; Select routine variant - store or restore vectors // Select routine variant - store or restore vectors
ldy #$1F ldy #$1F
bcc vector_restore bcc vector_restore
;; FALLTHROUGH // FALLTHROUGH
vector_store: vector_store:
*
lda CINV, y lda CINV, y
sta (_caller_arr_ptr), y sta (_caller_arr_ptr), y
dey dey
bpl - bpl vector_store
;; Restore status register (IRQ) before return // Restore status register (IRQ) before return
plp plp
rts rts
vector_restore: vector_restore:
*
lda (_caller_arr_ptr), y lda (_caller_arr_ptr), y
sta CINV, y sta CINV, y
dey dey
bpl - bpl vector_restore
;; Restore status register (IRQ) before return // Restore status register (IRQ) before return
plp plp
rts rts
.scend
+34 -34
View File
@@ -1,34 +1,34 @@
;; //
;; Official Kernal routine, described in: // Official Kernal routine, described in:
;; //
;; - [RG64] C64 Programmer's Reference Guide - page 285 // - [RG64] C64 Programmer's Reference Guide - page 285
;; - [CM64] Compute's Mapping the Commodore 64 - page 238 // - [CM64] Compute's Mapping the Commodore 64 - page 238
;; //
;; CPU registers that has to be preserved (see [RG64]): none // CPU registers that has to be preserved (see [RG64]): none
;; //
ioinit: IOINIT:
; Set $00/$01 port mode and value // Set $00/$01 port mode and value
; We want BASIC and KERNAL ROMs mapped, and datasette motor off // We want BASIC and KERNAL ROMs mapped, and datasette motor off
; (https://www.c64-wiki.com/wiki/Zeropage) // (https://www.c64-wiki.com/wiki/Zeropage)
;; XXX - Work around VICE bug: Writing $00 before $01 results in rubbish in $01 // XXX - Work around VICE bug: Writing $00 before $01 results in rubbish in $01
;; after. https://sourceforge.net/p/vice-emu/bugs/1057/ // after. https://sourceforge.net/p/vice-emu/bugs/1057/
lda #$27 lda #$27
ldx #$2F ldx #$2F
sta CPU_R6510 sta CPU_R6510
stx CPU_D6510 stx CPU_D6510
;; Silence the SID chips under common addresses // Silence the SID chips under common addresses
ldy #$00 ldy #$00
* !:
;; SIDs under $D4xx // SIDs under $D4xx
lda SID_SIGVOL, Y lda SID_SIGVOL, Y
and #$F0 and #$F0
sta SID_SIGVOL, Y sta SID_SIGVOL, Y
;; SIDs under $D5xx // SIDs under $D5xx
lda SID_SIGVOL + $100, Y lda SID_SIGVOL + $100, Y
and #$F0 and #$F0
sta SID_SIGVOL + $100, Y sta SID_SIGVOL + $100, Y
@@ -36,24 +36,24 @@ ioinit:
clc clc
adc #$20 adc #$20
tay tay
bne - bne !-
;; XXX: calibrate TOD for both CIA's, see here: https://codebase64.org/doku.php?id=base:efficient_tod_initialisation // XXX: calibrate TOD for both CIA's, see here: https://codebase64.org/doku.php?id=base:efficient_tod_initialisation
;; Enable CIA1 IRQ and ~50Hz timer (https://csdb.dk/forums/?roomid=11&topicid=69037) // Enable CIA1 IRQ and ~50Hz timer (https://csdb.dk/forums/?roomid=11&topicid=69037)
lda #$7F lda #$7F
sta CIA1_ICR ; disable all sta CIA1_ICR // disable all
;; Set timer interval to ~1/60th of a second // Set timer interval to ~1/60th of a second
;; (This value was calculated by running a custom IRQ handler on a C64 // (This value was calculated by running a custom IRQ handler on a C64
;; with original KERNAL, and writing the values of $DC04/5 to the screen // with original KERNAL, and writing the values of $DC04/5 to the screen
;; in the IRQ handler to see roughly what value the timers must be set to) // in the IRQ handler to see roughly what value the timers must be set to)
;; ldy #<16380 // ldy #<16380
;; ldx #>16380 // ldx #>16380
;; PAL C64 (https://codebase64.org/doku.php?id=base:cpu_clocking), // PAL C64 (https://codebase64.org/doku.php?id=base:cpu_clocking),
;; is clocked at 0.985248 MHz, so that 1/60s is 16421 CPU cycles // is clocked at 0.985248 MHz, so that 1/60s is 16421 CPU cycles
ldy #<16421 ldy #<16421
ldx #>16421 ldx #>16421
@@ -61,19 +61,19 @@ ioinit:
sty CIA1_TIMALO sty CIA1_TIMALO
stx CIA1_TIMAHI stx CIA1_TIMAHI
;; Enable timer interrupt // Enable timer interrupt
lda #$81 lda #$81
sta CIA1_ICR sta CIA1_ICR
;; Enable timer A to run continuously (http://codebase64.org/doku.php?id=base:timerinterrupts) // Enable timer A to run continuously (http://codebase64.org/doku.php?id=base:timerinterrupts)
lda #$11 lda #$11
sta CIA1_CRA sta CIA1_CRA
lda CIA1_ICR lda CIA1_ICR
;; Set DDR on CIA2 for IEC bus, VIC-II banking // Set DDR on CIA2 for IEC bus, VIC-II banking
lda #$3B lda #$3B
sta CIA2_DDRA sta CIA2_DDRA
;; Set IEC bus to its initial idle state // Set IEC bus to its initial idle state
jmp iec_set_idle jmp iec_set_idle
+3 -3
View File
@@ -1,6 +1,6 @@
;; Our implementation is longer than the original one, // Our implementation is longer than the original one,
;; placing it here would cause a collision with OPEN // placing it here would cause a collision with OPEN
cint: CINT:
jmp cint_real jmp cint_real
+60 -28
View File
@@ -1,31 +1,63 @@
;; //
;; This byte identifies Kernal revision. Sources: // This byte (hex $FF80, dec 65408) identifies Kernal revision on several machines. Although not all
;; - [CM64] Compute's Mapping the Commodore 64 (page 242/243) // of the, used it for versioning purpose, here is the list of all the values I could find. Sources:
;; - [MM] Marko Mäkelä article, http://www.zimmers.net/anonftp/pub/cbm/firmware/computers/c64/revisions.txt // - [CM64] Compute's Mapping the Commodore 64 (page 242/243)
;; - [VICE] Checked with ROMs included in VICE emulator // - [MM] Marko Mäkelä article, http://www.zimmers.net/anonftp/pub/cbm/firmware/computers/c64/revisions.txt
;; // - [VICE] Checked with ROMs included in VICE emulator
;; IDEA: put here a value, that is different from any version currently known, as // - [XEMU] Checked with ROMs retrieved by XEMU emulator
;; a warning that this is not a Commodore Kernal. Currently known numbers for C64 are: //
;; // IDEA: put here a value, that is different from any version currently known, as
;; - $00 - [CM64] then current number [MM] 901227-02 [VICE] C64 Revision 2 // a warning that this is not a Commodore Kernal or anything already known.
;; - $03 - [CM64] (not mentionned) [MM] 901227-02, 901227-03 [VICE] C64 Revision 3 //
;; - $43 - [CM64] (not mentionned) [MM] 251104-04 [VICE] SX-64 // C64 - values from the official ROMs:
;; - $64 - [CM64] PET64 ROM [MM] (not mentionned) [VICE] PET64 // - $00 - [CM64] then current number [MM] 901227-02 [VICE] C64 Revision 2
;; - $AA - [CM64] first version of ROM [MM] 901227-01 [VICE] C64 Revision 1 // - $03 - [CM64] (not mentionned) [MM] 901227-02, 901227-03 [VICE] C64 Revision 3
;; // - $43 - [CM64] (not mentionned) [MM] 251104-04 [VICE] SX-64
;; Values from unofficial ROMs: // - $64 - [CM64] PET64 ROM [MM] (not mentionned) [VICE] PET64
;; - $03 - SuperCPU ROM 1.40, 2.04, also unofficial 0.7 ROM from [VICE] // - $AA - [CM64] first version of ROM [MM] 901227-01 [VICE] C64 Revision 1
;; //
;; Values from other Commodore machines: // C64 - values from unofficial 3rd party ROMs:
;; C128: // - $00 - Turbo Trans, Turbo Access, Turbo Process
;; - $01 - see https://www.pagetable.com/?p=1058 // - $03 - SuperCPU ROM 1.40, 2.04, also unofficial 0.7 ROM from [VICE],
;; - $02 - unreleased updated ROM, see https://www.pagetable.com/?p=1058 // DolphinDOS 2.0, JiffyDOS 6.01, EXOS V3/4,
;; // Datel Mercury V3 US, Datel DOS-ROM V1.2, Datel Turbo ROM II V3.2+,
;; XXX check more unofficial C64 ROMs (JiffyDOS, DolphinDOS, etc.) and other machines // Turbo Process US,
;; VIC-20, PET, CBM II, 264 series, C65 prototypes, other sources for C128 ROMs // burst CIA 1/2 Kernal by Albert, SD2IEC Kernal 1.0/2.0/2.1/2.2 by Claus
;; // - $4A - S-JiffyDOS
// - $53 - Professional DOS V1, SpeedDOS Plus 2.7
// - $C3 - Cockroach Turbo ROM V1
//
// PET:
// - $40 - [VICE] PET 2001-8N
// - $A7 - [VICE] PET 30XX
// - $AA - [VICE] PET 40XX, PET 80XX, SuperPET
//
// CBM II:
// - $E0 - [VICE] 5x0, 6x0, 7x0 models
//
// VIC-20:
// - $16 - [VICE] all models, also VIC-20 JiffyDOS PAL/NTSC
//
// 264 family:
// - $01 - [VICE] 364
// - $05 - [VICE] C16, C116, Plus/4
// - $06 - (unofficial) JiffyDOS NTSC
// - $81 - [VICE] 232
// - $86 - (unofficial) JiffyDOS PAL
//
// C128:
// - $01 - see https://www.pagetable.com/?p=1058
// - $02 - unreleased updated ROM, see https://www.pagetable.com/?p=1058
//
// Commodore prototypes:
// - $04 - [XEMU] 64 mode ROM of the C65 prototype, ROM 910111
// - $FF - [XEMU] C65 native mode, ROM 910111
// - $FF - [XEMU] Commodore LCD
//
// Non-Commodore machines:
// - $FF - Commander X16 (emulator r28)
//
kernal_revision: kernal_revision:
.byte $FF .byte $FF // XXX possibly change this value (current candidate: $F0), $FF conflicts with other machines
+2 -2
View File
@@ -1,4 +1,4 @@
; $FFFA - CPU NMI Hanlder // $FFFA - CPU NMI Hanlder
; Uncontrovertial as this is also a CPU requirement. // Uncontrovertial as this is also a CPU requirement.
.word nmi_handler .word nmi_handler
+2 -2
View File
@@ -1,4 +1,4 @@
; $FFFC - CPU Reset Vector // $FFFC - CPU Reset Vector
; Uncontrovertial, as it is a CPU requirement, and nothing else. // Uncontrovertial, as it is a CPU requirement, and nothing else.
.word reset_entry .word reset_entry
+3 -3
View File
@@ -1,5 +1,5 @@
; $FFFE - CPU IRQ Vector. // $FFFE - CPU IRQ Vector.
; This is non-controvertial, as it is a 6502 CPU requirement, and we just have to point // This is non-controvertial, as it is a 6502 CPU requirement, and we just have to point
; it to whatever IRQ routine we make. // it to whatever IRQ routine we make.
.word irq_handler .word irq_handler
+7 -7
View File
@@ -1,18 +1,18 @@
;; Just a helper routines // Just a helper routines
;; Find the LAT / SAT / FAT entry index where LAT corresponds to A, returns index in Y // Find the LAT / SAT / FAT entry index where LAT corresponds to A, returns index in Y
;; Carry flag set means not found // Carry flag set means not found
find_fls: find_fls:
ldy LDTND ldy LDTND
beq find_fls_not_found ; table empty beq find_fls_not_found // table empty
* !:
dey dey
bmi find_fls_not_found ; no more entries bmi find_fls_not_found // no more entries
cmp LAT, y cmp LAT, y
bne - ; does not match, try the next one bne !- // does not match, try the next one
clc clc
rts rts
+2 -2
View File
@@ -1,5 +1,5 @@
;; Home the cursor // Home the cursor
;; (Compute's Mapping the 64 p216) // (Compute's Mapping the 64 p216)
home_cursor: home_cursor:
+13 -13
View File
@@ -1,22 +1,22 @@
;; //
;; Checks whether device number (in .A) is a correct IEC device number // Checks whether device number (in .A) is a correct IEC device number
;; //
;; Preserves .A, .X and .Y // Preserves .A, .X and .Y
;; //
iec_check_devnum: iec_check_devnum:
;; 0, 1, 2, or 3 are illegal - reserved for non-IEC devices on Commodore // 0, 1, 2, or 3 are illegal - reserved for non-IEC devices on Commodore
cmp #$04 cmp #$04
bcs + bcs !+
;; FALLTROUGH // FALLTROUGH
iec_check_devnum_failed: iec_check_devnum_failed:
sec ; indicate non-IEC device sec // indicate non-IEC device
rts rts
* !:
;; 31 and above are illegal too, due to IEC command encoding scheme, // 31 and above are illegal too, due to IEC command encoding scheme,
;; see https://www.pagetable.com/?p=1031 // see https://www.pagetable.com/?p=1031
cmp #$1F cmp #$1F
bcs iec_check_devnum_failed bcs iec_check_devnum_failed
;; Carry is clear here - indicates IEC device // Carry is clear here - indicates IEC device
rts rts
+7 -7
View File
@@ -1,16 +1,16 @@
;; //
;; Kernal internal IEC routine // Kernal internal IEC routine
;; //
;; - https://www.pagetable.com/?p=1031, https://github.com/mist64/cbmbus_doc // - https://www.pagetable.com/?p=1031, https://github.com/mist64/cbmbus_doc
;; //
iec_cmd_close: iec_cmd_close:
jsr iec_check_channel_openclose jsr iec_check_channel_openclose
bcc + bcc !+
jmp kernalerror_FILE_NOT_INPUT jmp kernalerror_FILE_NOT_INPUT
* !:
ora #$E0 ora #$E0
jmp common_open_close_unlsn_second jmp common_open_close_unlsn_second
+22 -22
View File
@@ -1,42 +1,42 @@
;; //
;; Kernal internal IEC routine // Kernal internal IEC routine
;; //
;; - https://www.pagetable.com/?p=1031, https://github.com/mist64/cbmbus_doc // - https://www.pagetable.com/?p=1031, https://github.com/mist64/cbmbus_doc
;; //
iec_cmd_open: ; similar to TKSA, but without turnaround iec_cmd_open: // similar to TKSA, but without turnaround
jsr iec_check_channel_openclose jsr iec_check_channel_openclose
bcc + bcc !+
jmp kernalerror_FILE_NOT_INPUT jmp kernalerror_FILE_NOT_INPUT
* !:
ora #$F0 ora #$F0
;; FALLTROUGH // FALLTROUGH
common_open_close_unlsn_second: ; common part of several commands common_open_close_unlsn_second: // common part of several commands
sta IEC_TMP2 sta IEC_TMP2
jsr iec_tx_command jsr iec_tx_command
bcs + ; branch if error bcs !+ // branch if error
jmp iec_tx_command_finalize jmp iec_tx_command_finalize
* !:
rts rts
iec_check_channel_openclose: iec_check_channel_openclose:
;; Due to OPEN/CLOSE/TKSA/SECOND command encoding (see https://www.pagetable.com/?p=1031), // Due to OPEN/CLOSE/TKSA/SECOND command encoding (see https://www.pagetable.com/?p=1031),
;; allowed channels are 0-15; report error if out of range // allowed channels are 0-15; report error if out of range
cmp #$10 cmp #$10
bcc + bcc !+
;; Workaround to allow reading executable files and disk directory // Workaround to allow reading executable files and disk directory
;; using OPEN routine - see https://www.pagetable.com/?p=273 for // using OPEN routine - see https://www.pagetable.com/?p=273 for
;; example usage // example usage
cmp #$60 cmp #$60
beq + beq !+
sec ; mark unsuitable channel number sec // mark unsuitable channel number
rts rts
* !:
clc ; mark suitable channel number clc // mark suitable channel number
rts rts
Loaded 100 of 198 files, more files were not shown because too many files have changed in this diff. Show more