Merge pull request #31 from FeralChild64/master

Kick Assembler + new routine placing algorithm
This commit is contained in:
gardners authored and GitHub committed 2019-09-11 07:49:56 +09:30
commit 206434789b
248 files changed
+5346 -3898

No files matched your search

+1 -4
View File
@@ -1,10 +1,7 @@
# Compilation related files # Compilation related files
temp.s assembler/KickAss*
temp.map
ophis.bin
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
+100 -102
View File
@@ -1,27 +1,41 @@
# Source files # Source files
SRC_COMMON = $(wildcard c64/aliases/*.s) SRCDIR_COMMON = c64/aliases
SRC_BASIC_COMMON = $(SRC_COMMON) $(wildcard c64/basic/*.s) SRCDIR_BASIC_COMMON = $(SRCDIR_COMMON) c64/basic
SRC_KERNAL_COMMON = $(SRC_COMMON) $(wildcard c64/kernal/*.s c64/kernal/jumptable/*.s c64/kernal/iec/*.s c64/kernal/interrupts/*.s) SRCDIR_KERNAL_COMMON = $(SRCDIR_COMMON) c64/kernal c64/kernal/jumptable c64/kernal/iec c64/kernal/interrupts
SRC_BASIC_generic = $(SRC_BASIC_COMMON) $(wildcard c64/basic/,target_generic/*.s) SRCDIR_BASIC_generic = $(SRCDIR_BASIC_COMMON) c64/basic/,target_generic
SRC_BASIC_mega65 = $(SRC_BASIC_COMMON) $(wildcard c64/basic/,target_mega65/*.s) SRCDIR_BASIC_mega65 = $(SRCDIR_BASIC_COMMON) c64/basic/,target_mega65
SRC_BASIC_ultimate64 = $(SRC_BASIC_COMMON) $(wildcard c64/basic/,target_ultimate64/*.s) SRCDIR_BASIC_ultimate64 = $(SRCDIR_BASIC_COMMON) c64/basic/,target_ultimate64
SRC_KERNAL_generic = $(SRC_KERNAL_COMMON) $(wildcard c64/kernal/,target_generic/*.s) SRCDIR_KERNAL_generic = $(SRCDIR_KERNAL_COMMON) c64/kernal/,target_generic
SRC_KERNAL_mega65 = $(SRC_KERNAL_COMMON) $(wildcard c64/kernal/,target_mega65/*.s) SRCDIR_KERNAL_mega65 = $(SRCDIR_KERNAL_COMMON) c64/kernal/,target_mega65
SRC_KERNAL_ultimate64 = $(SRC_KERNAL_COMMON) $(wildcard c64/kernal/,target_ultimate64/*.s) SRCDIR_KERNAL_ultimate64 = $(SRCDIR_KERNAL_COMMON) c64/kernal/,target_ultimate64
SRC_TOOLS = $(wildcard src/tools/*.c,src/tools/*.cc)
# List of tools # List of tools
TOOL_COLLECT_DATA = build/tools/collect_data TOOL_COLLECT_DATA = build/tools/collect_data
TOOL_COMPRESS_TEXT = build/tools/compress_text TOOL_COMPRESS_TEXT = build/tools/compress_text
TOOL_PNGPREPARE = build/tools/pngprepare TOOL_PNGPREPARE = build/tools/pngprepare
TOOL_PREPROCESS = build/tools/preprocess TOOL_BUILD_SEGMENT = build/tools/build_segment
TOOL_SIMILARITY = build/tools/similarity TOOL_SIMILARITY = build/tools/similarity
TOOL_ASSEMBLER = assembler/KickAss.jar
TOOLS_LIST = $(TOOL_COLLECT_DATA) $(TOOL_COMPRESS_TEXT) $(TOOL_PNGPREPARE) $(TOOL_PREPROCESS) $(TOOL_SIMILARITY) TOOLS_LIST = $(pathsubst src/tools/%,build/tools/%,$(basename $(SRC_TOOLS)))
# List of targets
STD_TARGET_LIST = build/kernal_generic.rom build/basic_generic.rom \
build/kernal_mega65.rom build/basic_mega65.rom \
build/kernal_ultimate64.rom build/basic_ultimate64.rom \
build/chargen.rom
EXT_TARGET_LIST = build/newc65.rom
REL_TARGET_LIST = $(pathsubst build/%,bin/%, $(STD_TARGET_LIST))
# GIT commit # GIT commit
@@ -31,131 +45,115 @@ GIT_COMMIT:= $(shell git log -1 --pretty='%h' | tr '[:lower:]' '[:upper:]')
.PHONY: all clean updatebin .PHONY: all clean updatebin
all: build/chargen build/newkern_generic build/newbasic_generic build/newc65 build/newkern_ultimate64 build/newbasic_ultimate64 all: $(STD_TARGET_LIST) $(EXT_TARGET_LIST)
Ophis:
git submodule init
git submodule update
clean: clean:
@rm -rf build @rm -rf build
@rm -f temp.s
@rm -f temp.map
@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: $(STD_TARGET_LIST)
cp build/chargen bin/chargen.rom cp build/chargen.rom bin/chargen.rom
cp build/newbasic_generic bin/basic_generic.rom cp build/basic_generic.rom bin/basic_generic.rom
cp build/newkern_generic bin/kernal_generic.rom cp build/kernal_generic.rom bin/kernal_generic.rom
cp build/newbasic_mega65 bin/basic_mega65.rom cp build/basic_mega65.rom bin/basic_mega65.rom
cp build/newkern_mega65 bin/kernal_mega65.rom cp build/kernal_mega65.rom bin/kernal_mega65.rom
cp build/newbasic_ultimate64 bin/basic_ultimate64.rom cp build/basic_ultimate64.rom bin/basic_ultimate64.rom
cp build/newkern_ultimate64 bin/kernal_ultimate64.rom cp build/kernal_ultimate64.rom bin/kernal_ultimate64.rom
# Rules - tools # Rules - tools
$(TOOL_COLLECT_DATA): src/collect_data.c Makefile $(TOOL_PNGPREPARE): src/pngprepare.c Makefile
@mkdir -p build/tools @mkdir -p build/tools
gcc -Wall -o $(TOOL_COLLECT_DATA) src/collect_data.c $(CC) -O2 -Wall -I/usr/local/include -L/usr/local/lib -o $@ $< -lpng
$(TOOL_COMPRESS_TEXT): src/compress_text.c Makefile $(TOOL_COMPRESS_TEXT): src/compress_text.c Makefile
@mkdir -p build/tools @mkdir -p build/tools
gcc -g -Wall -o $(TOOL_COMPRESS_TEXT) src/compress_text.c -lm $(CC) -O2 -Wall -I/usr/local/include -L/usr/local/lib -o $@ $< -lm
$(TOOL_PNGPREPARE): src/pngprepare.c Makefile build/tools/%: src/%.c Makefile
@mkdir -p build/tools @mkdir -p build/tools
$(CC) $(COPT) -I/usr/local/include -L/usr/local/lib -o $(TOOL_PNGPREPARE) src/pngprepare.c -lpng $(CC) -O2 -Wall -o $@ $<
$(TOOL_PREPROCESS): src/preprocess.c Makefile build/tools/%: src/%.cc Makefile
@mkdir -p build/tools @mkdir -p build/tools
gcc -g -Wall -o $(TOOL_PREPROCESS) src/preprocess.c $(CXX) -O2 -Wall -o $@ $<
$(TOOL_SIMILARITY): src/similarity.c Makefile
@mkdir -p build/tools
gcc -g -Wall -o $(TOOL_SIMILARITY) src/similarity.c
# Rules - CHARGEN # Rules - CHARGEN
build/chargen: $(TOOL_PNGPREPARE) assets/8x8font.png build/chargen.rom: $(TOOL_PNGPREPARE) assets/8x8font.png
$(TOOL_PNGPREPARE) charrom assets/8x8font.png build/chargen $(TOOL_PNGPREPARE) charrom assets/8x8font.png build/chargen.rom
# Dependencies # Dependencies - BASIC and KERNAL
build/basic_generic/OUT.BIN: Ophis $(TOOLS_LIST) $(SRC_BASIC_generic) build/basic/packed_messages.s build/target_generic/OUTB.BIN: $(TOOL_ASSEMBLER) $(TOOL_BUILD_SEGMENT) $(SRCDIR_BASIC_generic) $(foreach dir,$(SRCDIR_BASIC_generic),$(wildcard $(dir)/*.s)) build/,generated/packed_messages.s
build/kernal_generic/OUT.BIN: Ophis $(TOOLS_LIST) $(SRC_KERNAL_generic) build/target_mega65/OUTB.BIN: $(TOOL_ASSEMBLER) $(TOOL_BUILD_SEGMENT) $(SRCDIR_BASIC_mega65) $(foreach dir,$(SRCDIR_BASIC_mega65),$(wildcard $(dir)/*.s)) build/,generated/packed_messages.s
build/newrom_generic: build/basic_generic/OUT.BIN build/kernal_generic/OUT.BIN build/target_ultimate64/OUTB.BIN: $(TOOL_ASSEMBLER) $(TOOL_BUILD_SEGMENT) $(SRCDIR_BASIC_ultimate64) $(foreach dir,$(SRCDIR_BASIC_ultimate64),$(wildcard $(dir)/*.s)) build/,generated/packed_messages.s
build/newkern_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/target_generic/OUTK.BIN: $(TOOL_ASSEMBLER) $(TOOL_BUILD_SEGMENT) $(SRCDIR_KERNAL_generic) $(foreach dir,$(SRCDIR_KERNAL_generic),$(wildcard $(dir)/*.s))
build/kernal_mega65/OUT.BIN: Ophis $(TOOLS_LIST) $(SRC_KERNAL_mega65) build/target_mega65/OUTK.BIN: $(TOOL_ASSEMBLER) $(TOOL_BUILD_SEGMENT) $(SRCDIR_KERNAL_mega65) $(foreach dir,$(SRCDIR_KERNAL_mega65),$(wildcard $(dir)/*.s))
build/newrom_mega65: build/basic_mega65/OUT.BIN build/kernal_mega65/OUT.BIN build/target_ultimate64/OUTK.BIN: $(TOOL_ASSEMBLER) $(TOOL_BUILD_SEGMENT) $(SRCDIR_KERNAL_ultimate64) $(foreach dir,$(SRCDIR_KERNAL_ultimate64),$(wildcard $(dir)/*.s))
build/newkern_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/target_generic/newrom: build/target_generic/OUTB.BIN build/target_generic/OUTK.BIN
build/kernal_ultimate64/OUT.BIN: Ophis $(TOOLS_LIST) $(SRC_KERNAL_ultimate64) build/target_mega65/newrom: build/target_mega65/OUTB.BIN build/target_mega65/OUTK.BIN
build/newrom_ultimate64: build/basic_ultimate64/OUT.BIN build/kernal_ultimate64/OUT.BIN build/target_ultimate64/newrom: build/target_ultimate64/OUTB.BIN build/target_ultimate64/OUTK.BIN
build/newkern_ultimate64: build/newrom_ultimate64 Makefile
build/newbasic_ultimate64: build/newrom_ultimate64 Makefile
build/kernal_generic.rom: build/target_generic/newrom
build/kernal_mega65.rom: build/target_mega65/newrom
build/kernal_ultimate64.rom: build/target_ultimate64/newrom
build/basic_generic.rom: build/target_generic/newrom
build/basic_mega65.rom: build/target_mega65/newrom
build/basic_ultimate64.rom: build/target_ultimate64/newrom
# Rules - BASIC and KERNAL # Rules - BASIC and KERNAL
build/basic/packed_messages.s: $(TOOL_COMPRESS_TEXT) build/,generated/packed_messages.s: $(TOOL_COMPRESS_TEXT)
@mkdir -p build/basic @mkdir -p build/,generated
$(TOOL_COMPRESS_TEXT) > build/basic/packed_messages.s $(TOOL_COMPRESS_TEXT) > build/,generated/packed_messages.s
.PRECIOUS: build/basic_%/OUT.BIN .PRECIOUS: build/target_%/OUTB.BIN
build/basic_%/OUT.BIN: Ophis $(TOOLS_LIST) $(SRC_BASIC_$*) build/basic/packed_messages.s build/target_%/OUTB.BIN:
@mkdir -p build/basic_$* @mkdir -p build/target_$*
@rm -f build/basic_$*/* @rm -f $@* build/target_$*/BASIC*
@for SRC in $(SRC_BASIC_$*); do \ @$(TOOL_BUILD_SEGMENT) -s BASIC -i BASIC-$* -o OUTB.BIN -t build/target_$* -l a000 -h e4d2 $(SRCDIR_BASIC_$*) build/,generated/packed_messages.s
ln -s ../../$$SRC build/basic_$*/$$(basename $$SRC); \
done
@ln -s ../../build/basic/packed_messages.s build/basic_$*/packed_messages.s
$(TOOL_PREPROCESS) -d build/basic_$* -l a000 -h e4d2
.PRECIOUS: build/kernal_%/OUT.BIN .PRECIOUS: build/target_%/OUTK.BIN
build/kernal_%/OUT.BIN: Ophis $(TOOLS_LIST) $(SRC_KERNAL_$*) build/target_%/OUTK.BIN:
@mkdir -p build/kernal_$* @mkdir -p build/target_$*
@rm -f build/kernal_$*/* @rm -f $@* build/target_$*/KERNAL*
@for SRC in $(SRC_KERNAL_$*); do \ @$(TOOL_BUILD_SEGMENT) -s KERNAL -i KERNAL-$* -o OUTK.BIN -t build/target_$* -l e4d3 -h ffff $(SRCDIR_KERNAL_$*)
ln -s ../../$$SRC build/kernal_$*/$$(basename $$SRC); \
done
$(TOOL_PREPROCESS) -d build/kernal_$* -l e4d3 -h ffff
.PRECIOUS: build/newrom_% .PRECIOUS: build/target_%/newrom
build/newrom_%: build/basic_%/OUT.BIN build/kernal_%/OUT.BIN build/target_%/newrom:
cat build/basic_$*/OUT.BIN build/kernal_$*/OUT.BIN > build/newrom_$* cat build/target_$*/OUTB.BIN build/target_$*/OUTK.BIN > $@
.PRECIOUS: build/newkern_% .PRECIOUS: build/kernal_%.rom
build/newkern_%: build/newrom_% Makefile build/kernal_%.rom:
dd if=build/newrom_$* bs=8192 count=1 skip=2 of=build/newkern_$* dd if=build/target_$*/newrom bs=8192 count=1 skip=2 of=$@
.PRECIOUS: build/newbasic_% .PRECIOUS: build/basic_%.rom
build/newbasic_%: build/newrom_% Makefile build/basic_%.rom:
dd if=build/newrom_$* bs=8192 count=1 skip=0 of=build/newbasic_$* dd if=build/target_$*/newrom bs=8192 count=1 skip=0 of=$@
# Rules - platform 'Mega 65' specific # Rules - platform 'Mega 65' specific
build/newc65: build/newkern_mega65 build/newbasic_mega65 build/chargen Makefile build/newc65.rom: build/kernal_mega65.rom build/basic_mega65.rom build/chargen.rom Makefile
dd if=/dev/zero bs=4096 count=10 of=build/newc65 dd if=/dev/zero bs=4096 count=10 of=build/newc65.rom
cat build/newbasic_mega65 build/chargen build/chargen build/newkern_mega65 >> build/newc65 cat build/basic_mega65.rom build/chargen.rom build/chargen.rom build/kernal_mega65.rom >> build/newc65.rom
dd if=/dev/zero bs=65536 count=1 of=build/basic/padding dd if=/dev/zero bs=65536 count=1 of=build/padding
cat build/basic/padding >> build/newc65 cat build/padding >> build/newc65.rom
rm -f build/padding
# Rules - tests # Rules - tests
test: build/newkern_generic build/newbasic_generic test: build/kernal_generic.rom build/basic_generic.rom
x64 -kernal build/newkern_generic -basic build/newbasic_generic -8 empty.d64 x64 -kernal build/kernal_generic.rom -basic build/basic_generic.rom -8 empty.d64
testremote: build/newkern_generic build/newbasic_generic testremote: build/kernal_generic.rom build/basic_generic.rom
x64 -kernal build/newkern_generic -basic build/newbasic_generic -remotemonitor x64 -kernal build/kernal_generic.rom -basic build/basic_generic.rom -remotemonitor
testm65: build/newc65 testm65: build/newc65
m65 -b ../mega65-core/bin/mega65r1.bit -k ../mega65-core/bin/KICKUP.M65 -R build/newc65 -4 m65 -b ../mega65-core/bin/mega65r1.bit -k ../mega65-core/bin/KICKUP.M65 -R build/newc65.rom -4
testsimilarity: build/newrom_generic $(TOOL_SIMILARITY) testsimilarity: build/target_generic/newrom $(TOOL_SIMILARITY)
$(TOOL_SIMILARITY) kernal build/newrom_generic $(TOOL_SIMILARITY) kernal build/target_generic/newrom
$(TOOL_SIMILARITY) basic build/newrom_generic $(TOOL_SIMILARITY) basic build/target_generic/newrom
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.
View File
File renamed without changes.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
+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
.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 VERCKK = $93 // 0 = LOAD, 1 = VERIFY
.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 TSFCNT = $A3 // temporary variable for tape and IEC, [!] our usage probably differs in details
.label TBTCNT = $A4 // temporary variable for tape and IEC, [!] our usage probably differs in details
.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 MEMUSS = $C3 // $C3-$C4 temporary address for tape LOAD/SAVE
.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, start of BASIC memory
.label MEMSIZK = $283 // $283-$284, NOTE: Mapping the 64 erroneously has the hex as $282 (DEC is correct)
.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 TVSFLG = $2A6 // 0 = NTSC, 1 = PAL
// [!] 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
+113 -113
View File
@@ -1,126 +1,126 @@
; 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
; "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
+25 -26
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 TVSFLG
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
+47 -48
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,20 +139,19 @@ printf_retreat:
rts rts
printf_printhexbyte: printf_printhexbyte:
// Print the hex value in .A as two digits, idea by Haubitze
sed
pha pha
lsr lsr
lsr lsr
lsr lsr
lsr lsr
ora #$30 cmp #$0A
cmp #$3A adc #$30
bcc + jsr JCHROUT
adc #6
* jsr JCHROUT
pla pla
and #$0f and #$0F
ora #$30 cmp #$0A
cmp #$3A adc #$30
bcc + cld
adc #6 jmp JCHROUT
* jmp JCHROUT
+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
+68 -68
View File
@@ -1,73 +1,73 @@
; 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
;; 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
+41 -41
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 TVSFLG
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
+8 -8
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 TBTCNT
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
+28 -28
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 TBTCNT
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
+35 -33
View File
@@ -1,45 +1,47 @@
;; //
;; 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
beq kernalerror_FILE_ALREADY_OPEN bne open_not_yet_open
jmp kernalerror_FILE_ALREADY_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
@@ -51,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
@@ -68,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
+94 -95
View File
@@ -1,146 +1,145 @@
//
;; // 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 VERCKK
;; 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 TBTCNT
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 = MEMUSS
;; 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 $F0 // chosen not to conflict with anything known so far
+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
Loaded 100 of 248 files, more files were not shown because too many files have changed in this diff. Show more