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
+5545 -4097

No files matched your search

+1 -4
View File
@@ -1,10 +1,7 @@
# Compilation related files
temp.s
temp.map
ophis.bin
assembler/KickAss*
build/*
# 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
SRC_COMMON = $(wildcard c64/aliases/*.s)
SRC_BASIC_COMMON = $(SRC_COMMON) $(wildcard c64/basic/*.s)
SRC_KERNAL_COMMON = $(SRC_COMMON) $(wildcard c64/kernal/*.s c64/kernal/jumptable/*.s c64/kernal/iec/*.s c64/kernal/interrupts/*.s)
SRCDIR_COMMON = c64/aliases
SRCDIR_BASIC_COMMON = $(SRCDIR_COMMON) c64/basic
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)
SRC_BASIC_mega65 = $(SRC_BASIC_COMMON) $(wildcard c64/basic/,target_mega65/*.s)
SRC_BASIC_ultimate64 = $(SRC_BASIC_COMMON) $(wildcard c64/basic/,target_ultimate64/*.s)
SRCDIR_BASIC_generic = $(SRCDIR_BASIC_COMMON) c64/basic/,target_generic
SRCDIR_BASIC_mega65 = $(SRCDIR_BASIC_COMMON) c64/basic/,target_mega65
SRCDIR_BASIC_ultimate64 = $(SRCDIR_BASIC_COMMON) c64/basic/,target_ultimate64
SRC_KERNAL_generic = $(SRC_KERNAL_COMMON) $(wildcard c64/kernal/,target_generic/*.s)
SRC_KERNAL_mega65 = $(SRC_KERNAL_COMMON) $(wildcard c64/kernal/,target_mega65/*.s)
SRC_KERNAL_ultimate64 = $(SRC_KERNAL_COMMON) $(wildcard c64/kernal/,target_ultimate64/*.s)
SRCDIR_KERNAL_generic = $(SRCDIR_KERNAL_COMMON) c64/kernal/,target_generic
SRCDIR_KERNAL_mega65 = $(SRCDIR_KERNAL_COMMON) c64/kernal/,target_mega65
SRCDIR_KERNAL_ultimate64 = $(SRCDIR_KERNAL_COMMON) c64/kernal/,target_ultimate64
SRC_TOOLS = $(wildcard src/tools/*.c,src/tools/*.cc)
# List of tools
TOOL_COLLECT_DATA = build/tools/collect_data
TOOL_COMPRESS_TEXT = build/tools/compress_text
TOOL_PNGPREPARE = build/tools/pngprepare
TOOL_PREPROCESS = build/tools/preprocess
TOOL_SIMILARITY = build/tools/similarity
TOOL_COLLECT_DATA = build/tools/collect_data
TOOL_COMPRESS_TEXT = build/tools/compress_text
TOOL_PNGPREPARE = build/tools/pngprepare
TOOL_BUILD_SEGMENT = build/tools/build_segment
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
@@ -31,131 +45,115 @@ GIT_COMMIT:= $(shell git log -1 --pretty='%h' | tr '[:lower:]' '[:upper:]')
.PHONY: all clean updatebin
all: build/chargen build/newkern_generic build/newbasic_generic build/newc65 build/newkern_ultimate64 build/newbasic_ultimate64
Ophis:
git submodule init
git submodule update
all: $(STD_TARGET_LIST) $(EXT_TARGET_LIST)
clean:
@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
cp build/chargen bin/chargen.rom
cp build/newbasic_generic bin/basic_generic.rom
cp build/newkern_generic bin/kernal_generic.rom
cp build/newbasic_mega65 bin/basic_mega65.rom
cp build/newkern_mega65 bin/kernal_mega65.rom
cp build/newbasic_ultimate64 bin/basic_ultimate64.rom
cp build/newkern_ultimate64 bin/kernal_ultimate64.rom
updatebin: $(STD_TARGET_LIST)
cp build/chargen.rom bin/chargen.rom
cp build/basic_generic.rom bin/basic_generic.rom
cp build/kernal_generic.rom bin/kernal_generic.rom
cp build/basic_mega65.rom bin/basic_mega65.rom
cp build/kernal_mega65.rom bin/kernal_mega65.rom
cp build/basic_ultimate64.rom bin/basic_ultimate64.rom
cp build/kernal_ultimate64.rom bin/kernal_ultimate64.rom
# Rules - tools
$(TOOL_COLLECT_DATA): src/collect_data.c Makefile
$(TOOL_PNGPREPARE): src/pngprepare.c Makefile
@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
@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
$(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
gcc -g -Wall -o $(TOOL_PREPROCESS) src/preprocess.c
$(TOOL_SIMILARITY): src/similarity.c Makefile
@mkdir -p build/tools
gcc -g -Wall -o $(TOOL_SIMILARITY) src/similarity.c
$(CXX) -O2 -Wall -o $@ $<
# Rules - CHARGEN
build/chargen: $(TOOL_PNGPREPARE) assets/8x8font.png
$(TOOL_PNGPREPARE) charrom assets/8x8font.png build/chargen
build/chargen.rom: $(TOOL_PNGPREPARE) assets/8x8font.png
$(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/kernal_generic/OUT.BIN: Ophis $(TOOLS_LIST) $(SRC_KERNAL_generic)
build/newrom_generic: build/basic_generic/OUT.BIN build/kernal_generic/OUT.BIN
build/newkern_generic: build/newrom_generic Makefile
build/newbasic_generic: build/newrom_generic Makefile
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/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/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/basic_mega65/OUT.BIN: Ophis $(TOOLS_LIST) $(SRC_BASIC_mega65) build/basic/packed_messages.s
build/kernal_mega65/OUT.BIN: Ophis $(TOOLS_LIST) $(SRC_KERNAL_mega65)
build/newrom_mega65: build/basic_mega65/OUT.BIN build/kernal_mega65/OUT.BIN
build/newkern_mega65: build/newrom_mega65 Makefile
build/newbasic_mega65: build/newrom_mega65 Makefile
build/target_generic/OUTK.BIN: $(TOOL_ASSEMBLER) $(TOOL_BUILD_SEGMENT) $(SRCDIR_KERNAL_generic) $(foreach dir,$(SRCDIR_KERNAL_generic),$(wildcard $(dir)/*.s))
build/target_mega65/OUTK.BIN: $(TOOL_ASSEMBLER) $(TOOL_BUILD_SEGMENT) $(SRCDIR_KERNAL_mega65) $(foreach dir,$(SRCDIR_KERNAL_mega65),$(wildcard $(dir)/*.s))
build/target_ultimate64/OUTK.BIN: $(TOOL_ASSEMBLER) $(TOOL_BUILD_SEGMENT) $(SRCDIR_KERNAL_ultimate64) $(foreach dir,$(SRCDIR_KERNAL_ultimate64),$(wildcard $(dir)/*.s))
build/basic_ultimate64/OUT.BIN: Ophis $(TOOLS_LIST) $(SRC_BASIC_ultimate64) build/basic/packed_messages.s
build/kernal_ultimate64/OUT.BIN: Ophis $(TOOLS_LIST) $(SRC_KERNAL_ultimate64)
build/newrom_ultimate64: build/basic_ultimate64/OUT.BIN build/kernal_ultimate64/OUT.BIN
build/newkern_ultimate64: build/newrom_ultimate64 Makefile
build/newbasic_ultimate64: build/newrom_ultimate64 Makefile
build/target_generic/newrom: build/target_generic/OUTB.BIN build/target_generic/OUTK.BIN
build/target_mega65/newrom: build/target_mega65/OUTB.BIN build/target_mega65/OUTK.BIN
build/target_ultimate64/newrom: build/target_ultimate64/OUTB.BIN build/target_ultimate64/OUTK.BIN
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
build/basic/packed_messages.s: $(TOOL_COMPRESS_TEXT)
@mkdir -p build/basic
$(TOOL_COMPRESS_TEXT) > build/basic/packed_messages.s
build/,generated/packed_messages.s: $(TOOL_COMPRESS_TEXT)
@mkdir -p build/,generated
$(TOOL_COMPRESS_TEXT) > build/,generated/packed_messages.s
.PRECIOUS: build/basic_%/OUT.BIN
build/basic_%/OUT.BIN: Ophis $(TOOLS_LIST) $(SRC_BASIC_$*) build/basic/packed_messages.s
@mkdir -p build/basic_$*
@rm -f build/basic_$*/*
@for SRC in $(SRC_BASIC_$*); do \
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/target_%/OUTB.BIN
build/target_%/OUTB.BIN:
@mkdir -p build/target_$*
@rm -f $@* build/target_$*/BASIC*
@$(TOOL_BUILD_SEGMENT) -s BASIC -i BASIC-$* -o OUTB.BIN -t build/target_$* -l a000 -h e4d2 $(SRCDIR_BASIC_$*) build/,generated/packed_messages.s
.PRECIOUS: build/kernal_%/OUT.BIN
build/kernal_%/OUT.BIN: Ophis $(TOOLS_LIST) $(SRC_KERNAL_$*)
@mkdir -p build/kernal_$*
@rm -f build/kernal_$*/*
@for SRC in $(SRC_KERNAL_$*); do \
ln -s ../../$$SRC build/kernal_$*/$$(basename $$SRC); \
done
$(TOOL_PREPROCESS) -d build/kernal_$* -l e4d3 -h ffff
.PRECIOUS: build/target_%/OUTK.BIN
build/target_%/OUTK.BIN:
@mkdir -p build/target_$*
@rm -f $@* build/target_$*/KERNAL*
@$(TOOL_BUILD_SEGMENT) -s KERNAL -i KERNAL-$* -o OUTK.BIN -t build/target_$* -l e4d3 -h ffff $(SRCDIR_KERNAL_$*)
.PRECIOUS: build/newrom_%
build/newrom_%: build/basic_%/OUT.BIN build/kernal_%/OUT.BIN
cat build/basic_$*/OUT.BIN build/kernal_$*/OUT.BIN > build/newrom_$*
.PRECIOUS: build/target_%/newrom
build/target_%/newrom:
cat build/target_$*/OUTB.BIN build/target_$*/OUTK.BIN > $@
.PRECIOUS: build/newkern_%
build/newkern_%: build/newrom_% Makefile
dd if=build/newrom_$* bs=8192 count=1 skip=2 of=build/newkern_$*
.PRECIOUS: build/kernal_%.rom
build/kernal_%.rom:
dd if=build/target_$*/newrom bs=8192 count=1 skip=2 of=$@
.PRECIOUS: build/newbasic_%
build/newbasic_%: build/newrom_% Makefile
dd if=build/newrom_$* bs=8192 count=1 skip=0 of=build/newbasic_$*
.PRECIOUS: build/basic_%.rom
build/basic_%.rom:
dd if=build/target_$*/newrom bs=8192 count=1 skip=0 of=$@
# Rules - platform 'Mega 65' specific
build/newc65: build/newkern_mega65 build/newbasic_mega65 build/chargen Makefile
dd if=/dev/zero bs=4096 count=10 of=build/newc65
cat build/newbasic_mega65 build/chargen build/chargen build/newkern_mega65 >> build/newc65
dd if=/dev/zero bs=65536 count=1 of=build/basic/padding
cat build/basic/padding >> build/newc65
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.rom
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/padding
cat build/padding >> build/newc65.rom
rm -f build/padding
# Rules - tests
test: build/newkern_generic build/newbasic_generic
x64 -kernal build/newkern_generic -basic build/newbasic_generic -8 empty.d64
test: build/kernal_generic.rom build/basic_generic.rom
x64 -kernal build/kernal_generic.rom -basic build/basic_generic.rom -8 empty.d64
testremote: build/newkern_generic build/newbasic_generic
x64 -kernal build/newkern_generic -basic build/newbasic_generic -remotemonitor
testremote: build/kernal_generic.rom build/basic_generic.rom
x64 -kernal build/kernal_generic.rom -basic build/basic_generic.rom -remotemonitor
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)
$(TOOL_SIMILARITY) kernal build/newrom_generic
$(TOOL_SIMILARITY) basic build/newrom_generic
testsimilarity: build/target_generic/newrom $(TOOL_SIMILARITY)
$(TOOL_SIMILARITY) kernal build/target_generic/newrom
$(TOOL_SIMILARITY) basic build/target_generic/newrom
Submodule Ophis deleted from 15818e7666.
+2 -1
View File
@@ -1,5 +1,6 @@
# 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
+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
## Page 0
## Low memory locations (pages 0 - 3)
TODO
## Pages 2 & 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!
## BASIC
@@ -107,7 +101,7 @@ NOTE: Even the 'DONE' routines won't support features described as missing in on
| `$FFE7` | `CLALL` | DONE | |
| `$FFEA` | `UDTIM` | DONE | |
| `$FFED` | `SCREEN` | DONE | |
| `$FFF0` | `PLOT` | DONE | |
| `$FFF0` | `PLOT` | PARTIAL | cursor blink not handled |
| `$FFF3` | `IOBASE` | DONE | |
<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
;; Described in 'Commodore 64 Programmer's Reference Guide', page 306
// Kernal error codes - returned in the A register
// Described in 'Commodore 64 Programmer's Reference Guide', page 306
.alias K_ERR_ROUTINE_TERMINATED $00
.alias K_ERR_TOO_MANY_OPEN_FILES $01
.alias K_ERR_FILE_ALREADY_OPEN $02
.alias K_ERR_FILE_NOT_OPEN $03
.alias K_ERR_FILE_NOT_FOUND $04
.alias K_ERR_DEVICE_NOT_FOUND $05
.alias K_ERR_FILE_NOT_INPUT $06
.alias K_ERR_FILE_NOT_OUTPUT $07
.alias K_ERR_FILE_NAME_MISSING $08
.alias K_ERR_ILLEGAL_DEVICE_NUMBER $09
.alias K_ERR_TOP_MEM_RS232 $F0
.const K_ERR_ROUTINE_TERMINATED = $00
.const K_ERR_TOO_MANY_OPEN_FILES = $01
.const K_ERR_FILE_ALREADY_OPEN = $02
.const K_ERR_FILE_NOT_OPEN = $03
.const K_ERR_FILE_NOT_FOUND = $04
.const K_ERR_DEVICE_NOT_FOUND = $05
.const K_ERR_FILE_NOT_INPUT = $06
.const K_ERR_FILE_NOT_OUTPUT = $07
.const K_ERR_FILE_NAME_MISSING = $08
.const K_ERR_ILLEGAL_DEVICE_NUMBER = $09
.const K_ERR_TOP_MEM_RS232 = $F0
;; Kernal status codes for READST routine (IOSTATUS)
;; Described in 'Commodore 64 Programmer's Reference Guide', page 292
// Kernal status codes for READST routine (IOSTATUS)
// Described in 'Commodore 64 Programmer's Reference Guide', page 292
;; For IEC devices
.alias K_STS_TIMEOUT_WRITE $01
.alias K_STS_TIMEOUT_READ $02
.alias K_STS_EOI $40
.alias K_STS_DEVICE_NOT_FOUND $80
;; For tape deck
.alias K_STS_SHORT_BLOCK $04
.alias K_STS_LONG_BLOCK $08
.alias K_STS_READ_ERROR $10
.alias K_STS_CHECKSUM_ERROR $20
.alias K_STS_END_OF_FILE $40
.alias K_STS_END_OF_TAPE $80
// For IEC devices
.const K_STS_TIMEOUT_WRITE = $01
.const K_STS_TIMEOUT_READ = $02
.const K_STS_EOI = $40
.const K_STS_DEVICE_NOT_FOUND = $80
// For tape deck
.const K_STS_SHORT_BLOCK = $04
.const K_STS_LONG_BLOCK = $08
.const K_STS_READ_ERROR = $10
.const K_STS_CHECKSUM_ERROR = $20
.const K_STS_END_OF_FILE = $40
.const K_STS_END_OF_TAPE = $80
;; BASIC error codes, taken from http://sta.c64.org/cbm64baserr.html
.alias B_ERR_TOO_MANY_FILES $01
.alias B_ERR_FILE_OPEN $02
.alias B_ERR_FILE_NOT_OPEN $03
.alias B_ERR_FILE_NOT_FOUND $04
.alias B_ERR_DEVICE_NOT_PRESENT $05
.alias B_ERR_NOT_INPUT_FILE $06
.alias B_ERR_NOT_OUTPUT_FILE $07
.alias B_ERR_MISSING_FILENAME $08
.alias B_ERR_ILLEGAL_DEVICE_NUMBER $09
.alias B_ERR_NEXT_WITHOUT_FOR $0A
.alias B_ERR_SYNTAX $0B
.alias B_ERR_RETURN_WITHOUT_GOSUB $0C
.alias B_ERR_OUT_OF_DATA $0D
.alias B_ERR_ILLEGAL_QUANTITY $0E
.alias B_ERR_OVERFLOW $0F
.alias B_ERR_OUT_OF_MEMORY $10
.alias B_ERR_UNDEFD_STATEMENT $11
.alias B_ERR_BAD_SUBSCRIPT $12
.alias B_ERR_REDIMD_ARRAY $13
.alias B_ERR_DIVISION_BY_ZERO $14
.alias B_ERR_ILLEGAL_DIRECT $15
.alias B_ERR_TYPE_MISMATCH $16
.alias B_ERR_STRING_TOO_LONG $17
.alias B_ERR_FILE_DATA $18
.alias B_ERR_FORMULA_TOO_COMPLEX $19
.alias B_ERR_CANT_CONTINUE $1A
.alias B_ERR_UNDEFD_FUNCTION $1B
.alias B_ERR_VERIFY $1C
.alias B_ERR_LOAD $1D
.alias B_ERR_BREAK $1E
// BASIC error codes, taken from http://sta.c64.org/cbm64baserr.html
.const B_ERR_TOO_MANY_FILES = $01
.const B_ERR_FILE_OPEN = $02
.const B_ERR_FILE_NOT_OPEN = $03
.const B_ERR_FILE_NOT_FOUND = $04
.const B_ERR_DEVICE_NOT_PRESENT = $05
.const B_ERR_NOT_INPUT_FILE = $06
.const B_ERR_NOT_OUTPUT_FILE = $07
.const B_ERR_MISSING_FILENAME = $08
.const B_ERR_ILLEGAL_DEVICE_NUMBER = $09
.const B_ERR_NEXT_WITHOUT_FOR = $0A
.const B_ERR_SYNTAX = $0B
.const B_ERR_RETURN_WITHOUT_GOSUB = $0C
.const B_ERR_OUT_OF_DATA = $0D
.const B_ERR_ILLEGAL_QUANTITY = $0E
.const B_ERR_OVERFLOW = $0F
.const B_ERR_OUT_OF_MEMORY = $10
.const B_ERR_UNDEFD_STATEMENT = $11
.const B_ERR_BAD_SUBSCRIPT = $12
.const B_ERR_REDIMD_ARRAY = $13
.const B_ERR_DIVISION_BY_ZERO = $14
.const B_ERR_ILLEGAL_DIRECT = $15
.const B_ERR_TYPE_MISMATCH = $16
.const B_ERR_STRING_TOO_LONG = $17
.const B_ERR_FILE_DATA = $18
.const B_ERR_FORMULA_TOO_COMPLEX = $19
.const B_ERR_CANT_CONTINUE = $1A
.const B_ERR_UNDEFD_FUNCTION = $1B
.const B_ERR_VERIFY = $1C
.const B_ERR_LOAD = $1D
.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
.alias CPU_R6510 $01
.label CPU_D6510 = $00
.label CPU_R6510 = $01
;; VIC-II registers
// VIC-II registers
.alias VIC_SP0X $D000
.alias VIC_SP0Y $D001
.alias VIC_SP1X $D002
.alias VIC_SP1Y $D003
.alias VIC_SP2X $D004
.alias VIC_SP2Y $D005
.alias VIC_SP3X $D006
.alias VIC_SP3Y $D007
.alias VIC_SP4X $D008
.alias VIC_SP4Y $D009
.alias VIC_SP5X $D00A
.alias VIC_SP5Y $D00B
.alias VIC_SP6X $D00C
.alias VIC_SP6Y $D00D
.alias VIC_SP7X $D00E
.alias VIC_SP7Y $D00F
.label VIC_SP0X = $D000
.label VIC_SP0Y = $D001
.label VIC_SP1X = $D002
.label VIC_SP1Y = $D003
.label VIC_SP2X = $D004
.label VIC_SP2Y = $D005
.label VIC_SP3X = $D006
.label VIC_SP3Y = $D007
.label VIC_SP4X = $D008
.label VIC_SP4Y = $D009
.label VIC_SP5X = $D00A
.label VIC_SP5Y = $D00B
.label VIC_SP6X = $D00C
.label VIC_SP6Y = $D00D
.label VIC_SP7X = $D00E
.label VIC_SP7Y = $D00F
.alias VIC_MSIGX $D010
.alias VIC_SCROLY $D011
.alias VIC_RASTER $D012
.alias VIC_LPENX $D013
.alias VIC_LPENY $D014
.alias VIC_SPENA $D015
.alias VIC_SCROLX $D016
.alias VIC_YXPAND $D017
.alias VIC_YMCSB $D018
.alias VIC_IRQ $D019
.alias VIC_IRQMSK $D01A
.alias VIC_SPBGPR $D01B
.alias VIC_SPMC $D01C
.alias VIC_XXPAND $D01D
.alias VIC_SPSPCL $D01E
.alias VIC_SPBGCL $D01F
.label VIC_MSIGX = $D010
.label VIC_SCROLY = $D011
.label VIC_RASTER = $D012
.label VIC_LPENX = $D013
.label VIC_LPENY = $D014
.label VIC_SPENA = $D015
.label VIC_SCROLX = $D016
.label VIC_YXPAND = $D017
.label VIC_YMCSB = $D018
.label VIC_IRQ = $D019
.label VIC_IRQMSK = $D01A
.label VIC_SPBGPR = $D01B
.label VIC_SPMC = $D01C
.label VIC_XXPAND = $D01D
.label VIC_SPSPCL = $D01E
.label VIC_SPBGCL = $D01F
.alias VIC_EXTCOL $D020
.alias VIC_BGCOL0 $D021
.alias VIC_BGCOL1 $D022
.alias VIC_BGCOL2 $D023
.alias VIC_BGCOL3 $D024
.alias VIC_SPMC0 $D025
.alias VIC_SPMC1 $D026
.alias VIC_SP0COL $D027
.alias VIC_SP1COL $D028
.alias VIC_SP2COL $D029
.alias VIC_SP3COL $D02A
.alias VIC_SP4COL $D02B
.alias VIC_SP5COL $D02C
.alias VIC_SP6COL $D02D
.alias VIC_SP7COL $D02E
.label VIC_EXTCOL = $D020
.label VIC_BGCOL0 = $D021
.label VIC_BGCOL1 = $D022
.label VIC_BGCOL2 = $D023
.label VIC_BGCOL3 = $D024
.label VIC_SPMC0 = $D025
.label VIC_SPMC1 = $D026
.label VIC_SP0COL = $D027
.label VIC_SP1COL = $D028
.label VIC_SP2COL = $D029
.label VIC_SP3COL = $D02A
.label VIC_SP4COL = $D02B
.label VIC_SP5COL = $D02C
.label VIC_SP6COL = $D02D
.label VIC_SP7COL = $D02E
;; SID registers
// SID registers
.alias SID_FRELO1 $D400
.alias SID_FREHI1 $D401
.alias SID_PWLO1 $D402
.alias SID_PWHI1 $D403
.alias SID_VCREG1 $D404
.alias SID_ATDCY1 $D405
.alias SID_SUREL1 $D406
.label SID_FRELO1 = $D400
.label SID_FREHI1 = $D401
.label SID_PWLO1 = $D402
.label SID_PWHI1 = $D403
.label SID_VCREG1 = $D404
.label SID_ATDCY1 = $D405
.label SID_SUREL1 = $D406
.alias SID_FRELO2 $D407
.alias SID_FREHI2 $D408
.alias SID_PWLO2 $D409
.alias SID_PWHI2 $D40A
.alias SID_VCREG2 $D40B
.alias SID_ATDCY2 $D40C
.alias SID_SUREL2 $D40D
.label SID_FRELO2 = $D407
.label SID_FREHI2 = $D408
.label SID_PWLO2 = $D409
.label SID_PWHI2 = $D40A
.label SID_VCREG2 = $D40B
.label SID_ATDCY2 = $D40C
.label SID_SUREL2 = $D40D
.alias SID_FRELO3 $D40E
.alias SID_FREHI3 $D40F
.alias SID_PWLO3 $D410
.alias SID_PWHI3 $D411
.alias SID_VCREG3 $D412
.alias SID_ATDCY3 $D413
.alias SID_SUREL3 $D414
.label SID_FRELO3 = $D40E
.label SID_FREHI3 = $D40F
.label SID_PWLO3 = $D410
.label SID_PWHI3 = $D411
.label SID_VCREG3 = $D412
.label SID_ATDCY3 = $D413
.label SID_SUREL3 = $D414
.alias SID_CUTLO $D415
.alias SID_CUTHI $D416
.alias SID_RESON $D417
.alias SID_SIGVOL $D418
.alias SID_POTX $D419
.alias SID_POTY $D41A
.alias SID_RANDOM $D41B
.alias SID_ENV3 $D41C
.label SID_CUTLO = $D415
.label SID_CUTHI = $D416
.label SID_RESON = $D417
.label SID_SIGVOL = $D418
.label SID_POTX = $D419
.label SID_POTY = $D41A
.label SID_RANDOM = $D41B
.label SID_ENV3 = $D41C
;; CIA #1 registers
// CIA #1 registers
.alias CIA1_PRA $DC00
.alias CIA1_PRB $DC01
.alias CIA1_DDRA $DC02
.alias CIA1_DDRB $DC03
.label CIA1_PRA = $DC00
.label CIA1_PRB = $DC01
.label CIA1_DDRA = $DC02
.label CIA1_DDRB = $DC03
.alias CIA1_TIMALO $DC04
.alias CIA1_TIMAHI $DC05
.alias CIA1_TIMBLO $DC06
.alias CIA1_TIMBHI $DC07
.label CIA1_TIMALO = $DC04
.label CIA1_TIMAHI = $DC05
.label CIA1_TIMBLO = $DC06
.label CIA1_TIMBHI = $DC07
.alias CIA1_TODTEN $DC08
.alias CIA1_TODSEC $DC09
.alias CIA1_TODMIN $DC0A
.alias CIA1_TODHRS $DC0B
.label CIA1_TODTEN = $DC08
.label CIA1_TODSEC = $DC09
.label CIA1_TODMIN = $DC0A
.label CIA1_TODHRS = $DC0B
.alias CIA1_SDR $DC0C
.alias CIA1_ICR $DC0D
.alias CIA1_CRA $DC0E
.alias CIA1_CRB $DC0F
.label CIA1_SDR = $DC0C
.label CIA1_ICR = $DC0D
.label CIA1_CRA = $DC0E
.label CIA1_CRB = $DC0F
;; CIA #2 registers
// CIA #2 registers
.alias CIA2_PRA $DD00 ; VIC bank switching and IEC port
.alias CIA2_PRB $DD01
.alias CIA2_DDRA $DD02
.alias CIA2_DDRB $DD03
.label CIA2_PRA = $DD00 // VIC bank switching and IEC port
.label CIA2_PRB = $DD01
.label CIA2_DDRA = $DD02
.label CIA2_DDRB = $DD03
.alias CIA2_TIMALO $DD04
.alias CIA2_TIMAHI $DD05
.alias CIA2_TIMBLO $DD06
.alias CIA2_TIMBHI $DD07
.label CIA2_TIMALO = $DD04
.label CIA2_TIMAHI = $DD05
.label CIA2_TIMBLO = $DD06
.label CIA2_TIMBHI = $DD07
.alias CIA2_TODTEN $DD08
.alias CIA2_TODSEC $DD09
.alias CIA2_TODMIN $DD0A
.alias CIA2_TODHRS $DD0B
.label CIA2_TODTEN = $DD08
.label CIA2_TODSEC = $DD09
.label CIA2_TODMIN = $DD0A
.label CIA2_TODHRS = $DD0B
.alias CIA2_SDR $DD0C
.alias CIA2_ICR $DD0D
.alias CIA2_CRA $DD0E
.alias CIA2_CRB $DD0F
.label CIA2_SDR = $DD0C
.label CIA2_ICR = $DD0D
.label CIA2_CRA = $DD0E
.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)
.alias 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)
.alias 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_ATN_OUT = $08 // 1 - low (pulled), 0 - high (released)
.const BIT_CIA2_PRA_CLK_OUT = $10 // 1 - low (pulled), 0 - high (released)
.const BIT_CIA2_PRA_DAT_OUT = $20 // 1 - low (pulled), 0 - high (released)
.const BIT_CIA2_PRA_CLK_IN = $40 // 0 - low (pulled), 1 - high (released)
.const BIT_CIA2_PRA_DAT_IN = $80 // 0 - low (pulled), 1 - high (released)
+223 -85
View File
@@ -1,98 +1,236 @@
;;
;; Names of ZP and low memory locations
;; (https://www.c64-wiki.com/wiki/Zeropage)
;;
//
// Names of ZP and low memory locations:
// - 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)
//
// $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)
//
.alias TXTTAB $2B
.label IOSTATUS = $90
.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 --
;;
;; Page 0 - Kernal area ($90-$FF)
;;
.alias IOSTATUS $90
.alias STKEY $91 ; Keys down clears bits. STOP - bit 7, C= - bit 6, SPACE - bit 4, CTRL - bit 2
.alias VERCK $93 ; 0 = LOAD, 1 = VERIVY
.alias C3PO $94 ; flag - is BSOUR content valid
.alias BSOUR $95 ; serial bus buffered output byte
//
// Page 1
//
.alias LDTND $98 ; number of entries in LAT / FAT / SAT tables
.alias DFLTN $99
.alias DFLTO $9A
.alias MSGFLG $9D ; bit 6 = error messages, bit 7 = control message
.label STACK = $100 // $100-$1FF, processor stack
.alias TIME $A0 ; $A0-$A2, jiffy clock
.alias IEC_TMP1 $A3 ; temporary variable for tape and IEC
.alias IEC_TMP2 $A4 ; temporary variable for tape and IEC
.alias CMP0 $B0 ; $B0-$B1, temporary tape storage, we use it too for BRK instruction address
.alias FNLEN $B7 ; current file name length
.alias FNADDR $BB ; $BB-$BC, current file name pointer
.alias STAL $C1 ; $C1-$C2 LOAD/SAVE start address
.alias MEMUS $C3 ; $C3-$C4 temporary address for tape LOAD/SAVE
;;
;; Other low memory addresses
;;
//
// Pages 2 & 3
//
.alias BUF $200 ; $200-$250 (81 bytes), BASIC line editor input buffer
.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
;; 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
// 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 --
;; Registers for SYS call
.alias SAREG $30C
.alias SXREG $30D
.alias SYREG $30E
.alias SPREG $30F
.label SAREG = $30C // .A storage, for SYS call
.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 USRPOK $310 ; JMP instruction
.alias USRADD $311 ; $311 - $312
.label USRPOK = $310 // -- NOT IMPLEMENTED -- JMP instruction
.label USRADD = $311 // $311-$312 -- NOT IMPLEMENTED --
// $313 -- UNUSED -- free for user software
;; Kernal vectors - interrupts
.alias CINV $314
.alias CBINV $316
.alias NMINV $318
// Kernal vectors - interrupts
.label CINV = $314 // $314-$315
.label CBINV = $316 // $316-$317
.label NMINV = $318 // $318-$319
;; 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
// 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 TBUFFR $33C ; $33C-$3FB, tape buffer
// $314 $334-$33B -- UNUSED -- free for user software
.label TBUFFR = $33C // $33C-$3FB, -- NOT IMPLEMENTED --, tape buffer
// $3FC $3FC-$3FF -- UNUSED -- free for user software
+3 -4
View File
@@ -1,5 +1,4 @@
;; BASIC startup vector
.alias IBASIC_COLD_START $A000
.alias IBASIC_WARM_START $A002
// BASIC startup vectors
.label IBASIC_COLD_START = $A000
.label IBASIC_WARM_START = $A002
+4 -4
View File
@@ -1,5 +1,5 @@
;; Cartridge ROM locations
.alias ICART_COLD_START $8000 ; $8000-$8001, cartridge cold start vector
.alias ICART_WARM_START $8002 ; $8002-$8003, cartridge warm start vector (RESTORE key)
.alias CART_SIG $8004 ; 5 bytes, signature for cartridge detection
// Cartridge ROM locations
.label ICART_COLD_START = $8000 // $8000-$8001, cartridge cold start vector
.label ICART_WARM_START = $8002 // $8002-$8003, cartridge warm start vector (RESTORE key)
.label CART_SIG = $8004 // $8004-$8008, signature for cartridge detection
+40 -40
View File
@@ -1,41 +1,41 @@
;; Kernal jump table
.alias JCINT $FF81
.alias JIOINIT $FF84
.alias JRAMTAS $FF87
.alias JRESTOR $FF8A
.alias JVECTOR $FF8D
.alias JSETMSG $FF90
.alias JSECOND $FF93
.alias JTKSA $FF96
.alias JMEMTOP $FF99
.alias JMEMBOT $FF9C
.alias JSCNKEY $FF9F
.alias JSETTMO $FFA2
.alias JACPTR $FFA5
.alias JCIOUT $FFA8
.alias JUNTLK $FFAB
.alias JUNLSN $FFAE
.alias JLISTEN $FFB1
.alias JTALK $FFB4
.alias JREADST $FFB7
.alias JSETFLS $FFBA
.alias JSETNAM $FFBD
.alias JOPEN $FFC0
.alias JCLOSE $FFC3
.alias JCHKIN $FFC6
.alias JCKOUT $FFC9
.alias JCLRCHN $FFCC
.alias JCHRIN $FFCF
.alias JCHROUT $FFD2
.alias JLOAD $FFD5
.alias JSAVE $FFD8
.alias JSETTIM $FFDB
.alias JRDTIM $FFDE
.alias JSTOP $FFE1
.alias JGETIN $FFE4
.alias JCLALL $FFE7
.alias JUDTIM $FFEA
.alias JSCREEN $FFED
.alias JPLOT $FFF0
.alias JIOBASE $FFF3
// Kernal jump table
.label JCINT = $FF81
.label JIOINIT = $FF84
.label JRAMTAS = $FF87
.label JRESTOR = $FF8A
.label JVECTOR = $FF8D
.label JSETMSG = $FF90
.label JSECOND = $FF93
.label JTKSA = $FF96
.label JMEMTOP = $FF99
.label JMEMBOT = $FF9C
.label JSCNKEY = $FF9F
.label JSETTMO = $FFA2
.label JACPTR = $FFA5
.label JCIOUT = $FFA8
.label JUNTLK = $FFAB
.label JUNLSN = $FFAE
.label JLISTEN = $FFB1
.label JTALK = $FFB4
.label JREADST = $FFB7
.label JSETFLS = $FFBA
.label JSETNAM = $FFBD
.label JOPEN = $FFC0
.label JCLOSE = $FFC3
.label JCHKIN = $FFC6
.label JCKOUT = $FFC9
.label JCLRCHN = $FFCC
.label JCHRIN = $FFCF
.label JCHROUT = $FFD2
.label JLOAD = $FFD5
.label JSAVE = $FFD8
.label JSETTIM = $FFDB
.label JRDTIM = $FFDE
.label JSTOP = $FFE1
.label JGETIN = $FFE4
.label JCLALL = $FFE7
.label JUDTIM = $FFEA
.label JSCREEN = $FFED
.label JPLOT = $FFF0
.label JIOBASE = $FFF3
+114 -114
View File
@@ -1,126 +1,126 @@
; Names of ZP and low memory locations
; (Only those for now that we feel the need to implement initially)
; (https://www.c64-wiki.com/wiki/Zeropage)
// Names of ZP and low memory locations
// (Only those for now that we feel the need to implement initially)
// (https://www.c64-wiki.com/wiki/Zeropage)
.alias tokenise_work1 $7
.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
// XXX get rid of this file, use ,aliases_ram_lowmem.s instead
;; The various pointers that separate memory regions for BASIC storage
;; We have multiple names for the ones that mark the boundary of regions.
.alias basic_start_of_text_ptr $2b
.alias basic_end_of_text_ptr $2d
.alias basic_start_of_vars_ptr $2d
.alias basic_end_of_vars_ptr $2f
.alias basic_start_of_arrays_ptr $2f
.alias basic_end_of_arrays_ptr $31
.alias basic_start_of_free_space_ptr $31
.alias basic_start_of_strings_ptr $33
.alias basic_top_of_memory_ptr $37
.alias basic_current_line_number $39
.alias basic_previous_line_number $3b
.alias basic_current_line_ptr $3d
.label tokenise_work1 = $7
.label tokenise_work2 = $8
.label tokenise_work3 = $B
.label tokenise_work4 = $F
.label basic_line_number = $14
.label temp_string_ptr = $35
.label load_or_verify_or_tokenise_work5 = $C
.label basic_work22 = $22
.label basic_work23 = $23
.label basic_work24 = $24
.label basic_work25 = $25
;; Note that the statement point is in the CHRGET/CHRGOT routine
;; in ZP RAM. (Compute's Mapping the 64, p25)
.alias basic_current_statement_ptr $7a
// The various pointers that separate memory regions for BASIC storage
// We have multiple names for the ones that mark the boundary of regions.
.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
// 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
.alias basic_numeric_work_area $57 ; $57 - $60 inclusive = 10 bytes
.label basic_numeric_work_area = $57 // $57 - $60 inclusive = 10 bytes
;; Floating point accumulator 1 $61 - $68
.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
// Floating point accumulator 1 $61 - $68
.label basic_fac1_exponent = $61
.label basic_fac1_mantissa = $62 // $62 - $65
.label basic_fac1_sign = $66
.label basic_fac1_overflow = $68
.label basic_fac1_mantissa_lob = $70
.alias basic_fac2_exponent $69
.alias basic_fac2_mantissa $6A ; $6A - $6D
.alias basic_fac2_sign $6E
.label basic_fac2_exponent = $69
.label basic_fac2_mantissa = $6A // $6A - $6D
.label basic_fac2_sign = $6E
;; We also re-use FAC2 for memory move pointers, since
;; we can't be doing calculations while moving memory
.alias memmove_src $69
.alias memmove_dst $6b
.alias memmove_size $6d
// We also re-use FAC2 for memory move pointers, since
// we can't be doing calculations while moving memory
.label memmove_src = $69
.label memmove_dst = $6b
.label memmove_size = $6d
.alias current_file_num $98
.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
.label current_file_num = $98
.label cassette_buffer_bytes_used = $A6
.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
.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_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
.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
.alias basic_input_buffer BUF
; "Compute's Mapping the 64" book
.alias keyboard_buffer $0277
.alias text_colour $0286 ; p55
.alias colour_under_cursor $0287 ; p56
.alias key_buffer_size $0289 ; p57
.label basic_input_buffer = BUF
;; 0 = cursor keys, insert, delete and space repeat, but nothing else
;; 128 = all keys repeat
;; 64 = no keys repeat
.alias key_repeat_flags $028A ; p58
;; https://www.c64-wiki.com/wiki/Page_2
.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
// "Compute's Mapping the 64" book
.label keyboard_buffer = $0277
.label text_colour = $0286 // p55
.label colour_under_cursor = $0287 // p56
.label key_buffer_size = $0289 // p57
;; 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.
.alias missed_nmi_flag $2A7
.alias tiny_nmi_handler $2A8
.alias shift_mem_up tiny_nmi_handler+shift_mem_up_routine-tiny_nmi_handler_routine
.alias shift_mem_down tiny_nmi_handler+shift_mem_down_routine-tiny_nmi_handler_routine
.alias peek_under_roms tiny_nmi_handler+peek_under_roms_routine-tiny_nmi_handler_routine
.alias poke_under_roms tiny_nmi_handler+poke_under_roms_routine-tiny_nmi_handler_routine
.alias memmap_allram tiny_nmi_handler+memmap_allram_routine-tiny_nmi_handler_routine
.alias memmap_normal tiny_nmi_handler+memmap_normal_routine-tiny_nmi_handler_routine
// 0 = cursor keys, insert, delete and space repeat, but nothing else
// 128 = all keys repeat
// 64 = no keys repeat
.label key_repeat_flags = $028A // p58
// https://www.c64-wiki.com/wiki/Page_2
.label key_repeat_counter = $028B
.label key_first_repeat_delay = $028C
// 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
// 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 $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
@@ -21,21 +21,21 @@
.byte $20, $20, $1f, $20, $20, $96, $a3, $a3, $a3, $a3, $1f
.byte $92, $0D, $0D, $05, $00
;; Original Deft-supplied banner
;; .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,$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 $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 $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 $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 $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 $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 $0D,$05,$92,$00
// Original Deft-supplied banner
// .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,$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 $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 $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 $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 $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 $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 $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
}
+3 -2
View File
@@ -1,3 +1,4 @@
;; Compute's Mapping the C64 p88
// Compute's Mapping the C64 p88
.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
+5 -5
View File
@@ -1,6 +1,6 @@
;; Compute's Mapping the 64, p89
;; 8 character name
;; MEGABAS2 = "MEGA BASIC 2"
// Compute's Mapping the 64, p89
// 8 character name
// MEGABAS2 = "MEGA BASIC 2"
.byte $4D,$45,$47,$41,$42,$41,$53,$32
+6 -7
View File
@@ -1,19 +1,19 @@
;; Print string at $YYAA
;; Compute's Mapping the 64 p101
// Print string at $YYAA
// Compute's Mapping the 64 p101
print_string:
;; Setup pointer
// Setup pointer
sty temp_string_ptr+1
sta temp_string_ptr+0
txa
txa
pha
;; Get offset ready
// Get offset ready
ldy #$00
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
tax
@@ -28,7 +28,6 @@ print_string_loop:
iny
bne print_string_loop
print_string_end:
pla
+25 -26
View File
@@ -1,31 +1,31 @@
;; BASIC Cold start entry point
;; Compute's Mapping the 64 p211
// BASIC Cold start entry point
// Compute's Mapping the 64 p211
basic_cold_start:
;; Setup BASIC vectors at $0300
;; Initialise interpretor
;; Print start up message
// Setup BASIC vectors at $0300
// Initialise interpretor
// Print start up message
;; Print coloured part of the message
;; ldy #>startup_message
;; lda #<startup_message
;; jsr print_string
// Print coloured part of the message
// ldy #>startup_message
// lda #<startup_message
// jsr print_string
jsr printf // XXX don't use printf, keep it for debug purposes only
jsr printf
; Used 217 bytes
startup_banner:
`TARGET_HOOK_BANNER
TARGET_HOOK_BANNER()
;; Print PAL/NTSC
ldx #30 ; NTSC
lda PALNTSC
beq +
ldx #31 ; PAL
*
// Print PAL/NTSC
ldx #30 // NTSC
lda TVSFLG
beq !+
ldx #31 // PAL
!:
jsr print_packed_message
;; Work out free bytes, and display
// Work out free bytes, and display
jsr basic_do_new
lda basic_top_of_memory_ptr+0
sec
@@ -39,22 +39,21 @@ startup_banner:
lda #$20
jsr JCHROUT
;; Print the rest of the start up message
// Print the rest of the start up message
ldx #34
jsr print_packed_message
;; jump into warm start loop
// jump into warm start loop
jmp basic_warm_start
startup_message:
;; Clear the screen
startup_message: // XXX this is probably not needed anymore
// Clear the screen
.byte $93
;; Vertical bars in different colours
// Vertical bars in different colours
.byte $1C,$B4
.byte $9E,$B5
.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 $42,$41,$53,$49,$43
.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
;; been found with basic_find_line.
;; Really only consists of copying memory down.
;; 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
;; the following basic lines.
// Delete the current BASIC line, which is assumed to have already
// been found with basic_find_line.
// Really only consists of copying memory down.
// 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
// the following basic lines.
basic_delete_line:
;; jsr printf
;; .byte "DELETING LINE AT $"
;; .byte $f1,<basic_current_line_ptr,>basic_current_line_ptr
;; .byte $f0,<basic_current_line_ptr,>basic_current_line_ptr
;; .byte $0d,0
// jsr printf
// .text "DELETING LINE AT $"
// .byte $f1,<basic_current_line_ptr,>basic_current_line_ptr
// .byte $f0,<basic_current_line_ptr,>basic_current_line_ptr
// .byte $0d,0
;; Get address of next line
// Get address of next line
ldx #<basic_current_line_ptr
ldy #0
jsr peek_under_roms
@@ -21,7 +22,7 @@ basic_delete_line:
jsr peek_under_roms
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
sec
sbc basic_current_line_ptr+0
@@ -30,31 +31,31 @@ basic_delete_line:
sbc basic_current_line_ptr+1
sta tokenise_work4
;; jsr printf
;; .byte "LINE LENGTH IS $"
;; .byte $f0,<tokenise_work4,>tokenise_work4
;; .byte $f0,<tokenise_work3,>tokenise_work3
;; .byte $0d,0
// jsr printf
// .text "LINE LENGTH IS $"
// .byte $f0,<tokenise_work4,>tokenise_work4
// .byte $f0,<tokenise_work3,>tokenise_work3
// .byte $0d,0
lda tokenise_work4
sbc #0
cmp #$00
beq +
;; Line length is <0 or >255 bytes.
;; Either way, things are bad, so abort.
beq !+
// Line length is <0 or >255 bytes.
// Either way, things are bad, so abort.
jmp do_MEMORY_CORRUPT_error
*
;; Length can now be safely assumed to be in the low
;; byte only, i.e., stored in tokenise_work3
!:
// Length can now be safely assumed to be in the low
// byte only, i.e., stored in tokenise_work3
lda tokenise_work3
pha
tax
;; Shuffle everything down
// Shuffle everything down
jsr basic_shift_mem_down_and_relink
;; Now decrease top of BASIC mem
// Now decrease top of BASIC mem
pla
sta tokenise_work3
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:
;; Save error number
// Save error number
txa
pha
;; Print ? at start
lda #$0d
// Print ? at start
lda #$0D
jsr JCHROUT
lda #$3f
lda #$3F
jsr JCHROUT
;; Print main part of error message
// Print main part of error message
pla
tax
jsr print_packed_message
;; Print ERROR at end
// Print ERROR at end
lda #$20
jsr JCHROUT
ldx #33
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
lda #$0d
lda #$0D // XXX do we need this?
jsr JCHROUT
;; Reset stack, and go back to main loop
ldx #$fe
// Reset stack, and go back to main loop
ldx #$FE
txs
jmp basic_main_loop
+78 -79
View File
@@ -1,13 +1,13 @@
;; Jump back into the BASIC execute line loop
;; after first checking that we have a colon
;; or $00 char
// Jump back into the BASIC execute line loop
// after first checking that we have a colon
// or $00 char
basic_end_of_statement_check:
ldx #<basic_current_statement_ptr
ldy #0
jsr peek_under_roms
;; Consume any spaces
// Consume any spaces
cmp #$20
bne no_space_to_skip
jsr basic_consume_character
@@ -15,62 +15,62 @@ basic_end_of_statement_check:
no_space_to_skip:
cmp #$00
beq +
beq !+
cmp #$3a
beq +
beq !+
;; not end of statement
// not end of statement
clc
rts
*
!:
sec
rts
basic_execute_statement:
;; Check for RUN/STOP
// Check for RUN/STOP
lda STKEY
bmi +
bmi !+
jmp basic_do_break
*
;; Skip over any white space and :
!:
// Skip over any white space and :
ldy #0
ldx #<basic_current_statement_ptr
jsr peek_under_roms
jsr basic_end_of_statement_check
bcs basic_end_of_line
;; jsr printf
;; .byte "LINE PTR = $"
;; .byte $f1,<basic_current_line_ptr,>basic_current_line_ptr
;; .byte $f0,<basic_current_line_ptr,>basic_current_line_ptr
;; .byte ", STATEMENT PTR = $"
;; .byte $f1,<basic_current_statement_ptr,>basic_current_statement_ptr
;; .byte $f0,<basic_current_statement_ptr,>basic_current_statement_ptr
;; .byte $d,0
// jsr printf
// .text "LINE PTR = $"
// .byte $f1,<basic_current_line_ptr,>basic_current_line_ptr
// .byte $f0,<basic_current_line_ptr,>basic_current_line_ptr
// .text ", STATEMENT PTR = $"
// .byte $f1,<basic_current_statement_ptr,>basic_current_statement_ptr
// .byte $f0,<basic_current_statement_ptr,>basic_current_statement_ptr
// .byte $d,0
;; Go through the line until its end is reached.
;; If we reach the end are in direct mode, then
;; go back to reading input, else look for the
;; next line, and advance to that, or else
;; return to READY prompt because we have run out
;; of program.
// Go through the line until its end is reached.
// If we reach the end are in direct mode, then
// go back to reading input, else look for the
// next line, and advance to that, or else
// return to READY prompt because we have run out
// of program.
;; Get next char of program text, even if it is hiding under a ROM or the
;; IO area.
// Get next char of program text, even if it is hiding under a ROM or the
// IO area.
ldx #<basic_current_statement_ptr
ldy #0
jsr peek_under_roms
cmp #$00
beq basic_end_of_line
;; The checks should be done in order of frequency, so that we are as
;; fast as possible.
// The checks should be done in order of frequency, so that we are as
// fast as possible.
cmp #$7f
bcc not_a_token
;; It's a token: So get the jump table entry for it, push it on the stack
;; and then RTS to start it.
// It's a token: So get the jump table entry for it, push it on the stack
// and then RTS to start it.
asl
tax
lda basic_command_jump_table+1,x
@@ -78,42 +78,42 @@ basic_execute_statement:
lda basic_command_jump_table+0,x
pha
;; Now consume the character
// Now consume the character
jsr basic_consume_character
rts
not_a_token:
;; Space, which we can also just ignore
// Space, which we can also just ignore
cmp #$20
beq basic_skip_char
;; End of line?
// End of line?
cmp #$00
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
beq basic_skip_char
;; START wedge support
// START wedge support
;; Are we in direct mode?
;; DOS Wedge is a hacky solution (inelegant, but convenient),
;; BASIC programmers should implement communication with drives
;; the standard way, handling channels properly. Besides,
;; current implementation does not support characters under ROM
// Are we in direct mode?
// DOS Wedge is a hacky solution (inelegant, but convenient),
// BASIC programmers should implement communication with drives
// the standard way, handling channels properly. Besides,
// current implementation does not support characters under ROM
ldx basic_current_line_number+1
cpx #$ff
bne +
;; We are in direct mode, allow wedge to handle '@' sign
;; XXX Maybe it should be allowed only as the first command?
bne !+
// We are in direct mode, allow wedge to handle '@' sign
// XXX Maybe it should be allowed only as the first command?
cmp #$40
bne +
bne !+
jsr basic_consume_character
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
basic_skip_char:
@@ -124,14 +124,14 @@ basic_fetch_and_consume_character:
ldy #0
ldx #<basic_current_statement_ptr
jsr peek_under_roms
;; FALL THROUGH
// FALL THROUGH
basic_consume_character:
;; Advance basic text pointer
// Advance basic text pointer
inc basic_current_statement_ptr+0
bne +
bne !+
inc basic_current_statement_ptr+1
*
!:
rts
basic_unconsume_character:
@@ -146,46 +146,46 @@ basic_unconsume_character:
basic_end_of_line:
;; XXX - If not in direct mode, then advance to next line, if there is
;; one.
// XXX - If not in direct mode, then advance to next line, if there is
// one.
;; Are we in direct mode
// Are we in direct mode
lda basic_current_line_number+1
cmp #$ff
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
basic_not_direct_mode:
;; Copy line number to previous line number
// Copy line number to previous line number
lda basic_current_line_number+0
sta basic_previous_line_number+0
lda basic_current_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
;; Are we at the end of the program?
// Are we at the end of the program?
lda basic_current_line_ptr+0
ora basic_current_line_ptr+1
bne basic_execute_from_current_line
;; End of program found
// End of program found
jmp basic_main_loop
basic_execute_from_current_line:
;; Check if pointer is null, if so, we are at the end of
;; the program.
// Check if pointer is null, if so, we are at the end of
// the program.
ldy #0
ldx #<basic_current_line_ptr
jsr peek_pointer_null_check
bcs +
;; End of program reached
bcs !+
// End of program reached
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
clc
adc #4
@@ -194,7 +194,7 @@ basic_execute_from_current_line:
adc #0
sta basic_current_statement_ptr+1
;; Store line number
// Store line number
ldx #<basic_current_line_ptr
ldy #2
jsr peek_under_roms
@@ -206,7 +206,7 @@ basic_execute_from_current_line:
jmp basic_execute_statement
basic_command_jump_table:
;; $80 - $8F
// $80 - $8F
.word cmd_end-1
.word cmd_for-1
.word cmd_next-1
@@ -221,10 +221,10 @@ basic_command_jump_table:
.word cmd_if-1
.word cmd_restore-1
.word cmd_gosub-1
.word cmd_return -1
.word cmd_return-1
.word cmd_rem-1
;; $90-$9F
// $90-$9F
.word cmd_stop-1
.word cmd_on-1
.word cmd_wait-1
@@ -242,7 +242,7 @@ basic_command_jump_table:
.word cmd_sys-1
.word cmd_open-1
;; $A0-$AF
// $A0-$AF
.word cmd_close-1
.word cmd_get-1
.word cmd_new-1
@@ -260,7 +260,7 @@ basic_command_jump_table:
.word cmd_exponent-1
.word cmd_and-1
;; $B0-$BF
// $B0-$BF
.word cmd_or-1
.word cmd_greater-1
.word cmd_equal-1
@@ -278,7 +278,7 @@ basic_command_jump_table:
.word cmd_cos-1
.word cmd_sin-1
;; $C0-$CF
// $C0-$CF
.word cmd_tan-1
.word cmd_atn-1
.word cmd_peek-1
@@ -291,13 +291,13 @@ basic_command_jump_table:
.word cmd_right-1
.word cmd_mid-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
;; $D0-$DF
// $D0-$DF
.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
;; $E0-$EF
// $E0-$EF
.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
;; $F0-$FF
// $F0-$FF
.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
+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:
;; Get pointer to start of BASIC text
// Get pointer to start of BASIC text
lda basic_start_of_text_ptr+0
sta basic_current_line_ptr+0
lda basic_start_of_text_ptr+1
sta basic_current_line_ptr+1
basic_find_line_loop:
;; Then search for line number
;; Line number
// Then search for line number
// Line number
ldy #3
ldx #<basic_current_line_ptr
jsr peek_under_roms
cmp basic_line_number+1
beq +
beq !+
bcs line_num_too_high
bne not_this_line
*
!:
dey
jsr peek_under_roms
cmp basic_line_number+0
beq +
beq !+
bcs line_num_too_high
bne not_this_line
*
!:
clc
rts
not_this_line:
;; Not this line, so advance to next line
// Not this line, so advance to next line
ldx #<basic_current_line_ptr
jsr peek_pointer_null_check
bcs more_lines_exist
;; no more lines exist, return failure
// no more lines exist, return failure
line_num_too_high:
sec
rts
more_lines_exist:
;; XXX - Add program mangled check here to be triggered
;; if the link goes backwards.
;; Follow link to next line
// XXX - Add program mangled check here to be triggered
// if the link goes backwards.
// Follow link to next line
ldy #0
ldx #<basic_current_line_ptr
jsr peek_under_roms
+2 -2
View File
@@ -1,5 +1,5 @@
;; Advance basic_current_line_ptr by following the
;; link to the next line
// Advance basic_current_line_ptr by following the
// link to the next line
basic_find_next_line:
+26 -25
View File
@@ -1,25 +1,26 @@
;; Insert the tokenised line stored at $0200.
;; First work out where in the list to put it
;; (basic_find_line with the line number can be used to work
;; out the insertion point, as it should abort once it finds a
;; line number too high).
;; Then all we have to do is push the rest of the BASIC text up,
;; and update the pointers in all following basic lines.
// Insert the tokenised line stored at $0200.
// First work out where in the list to put it
// (basic_find_line with the line number can be used to work
// out the insertion point, as it should abort once it finds a
// line number too high).
// Then all we have to do is push the rest of the BASIC text up,
// and update the pointers in all following basic lines.
basic_insert_line:
;; 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,
;; and the zero-terminated line itself. This means 2+2+1 plus length
;; of tokenised string after the line number
// 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,
// and the zero-terminated line itself. This means 2+2+1 plus length
// of tokenised string after the line number
;; But first, remember where the pointer will be, so that we can
;; put the line in there after.
// But first, remember where the pointer will be, so that we can
// put the line in there after.
;; jsr printf
;; .byte "INSERTING LINE AT $"
;; .byte $f1,<basic_current_line_ptr,>basic_current_line_ptr
;; .byte $f0,<basic_current_line_ptr,>basic_current_line_ptr
;; .byte $0d,0
// jsr printf
// .text "INSERTING LINE AT $"
// .byte $f1,<basic_current_line_ptr,>basic_current_line_ptr
// .byte $f0,<basic_current_line_ptr,>basic_current_line_ptr
// .byte $0d,0
lda basic_current_line_ptr+0
pha
@@ -27,20 +28,20 @@ basic_insert_line:
pha
;; Get number of bytes in tokenised line after line number
// Get number of bytes in tokenised line after line number
lda tokenise_work2
sec
sbc tokenise_work1
;; Add on the four bytes space we need
// Add on the four bytes space we need
clc
adc #5
pha
tax
;; Make the space
// Make the space
jsr basic_shift_mem_up_and_relink
;; Now increase top of BASIC mem
// Now increase top of BASIC mem
pla
clc
adc basic_end_of_text_ptr+0
@@ -49,13 +50,13 @@ basic_insert_line:
adc #0
sta basic_end_of_text_ptr+1
;; Get pointer back
// Get pointer back
pla
sta basic_current_line_ptr+1
pla
sta basic_current_line_ptr+0
;; Write the line number
// Write the line number
ldy #2
ldx #<basic_current_line_ptr
lda basic_line_number+0
@@ -64,7 +65,7 @@ basic_insert_line:
lda basic_line_number+1
jsr poke_under_roms
;; Now store the line body itself
// Now store the line body itself
inc tokenise_work2
line_store_loop:
ldx tokenise_work1
+50 -51
View File
@@ -1,43 +1,43 @@
basic_main_loop:
;; XXX - Check if direct or program mode, and get next line of input
;; the appropriate way.
;; XXX - For now, it is hard coded to direct mode
// XXX - Check if direct or program mode, and get next line of input
// the appropriate way.
// XXX - For now, it is hard coded to direct mode
;; Tell user we are ready
// Tell user we are ready
jsr ready_message
basic_read_next_line:
;; Read a line of input
// Read a line of input
ldx #$00
read_line_loop:
jsr $ffcf ; KERNAL CHRIN
jsr JCHRIN
bcs read_line_loop
cmp #$0d
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
bcc +
;; Report STRING TOO LONG error (Compute's Mapping the 64 p93)
bcc !+
// Report STRING TOO LONG error (Compute's Mapping the 64 p93)
ldx #22
jmp basic_do_error
*
!:
sta basic_input_buffer,x
inx
jmp read_line_loop
got_line_of_input:
;; Store length of input buffer ready for tokenising
// Store length of input buffer ready for tokenising
stx tokenise_work1
;; Strip leading spaces from the line
// Strip leading spaces from the line
remove_leading_spaces:
lda $0200
cmp #$20
bne +
bne !+
ldx #1
rsl_l1: lda $0200,x
sta $01ff,x
@@ -45,40 +45,40 @@ rsl_l1: lda $0200,x
cpx tokenise_work1
bne rsl_l1
;; Reduce length of input by one
// Reduce length of input by one
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
*
;; Do printing of the new line
!:
// Do printing of the new line
lda #$0d
jsr JCHROUT
;; Ignore empty lines
// Ignore empty lines
lda tokenise_work1
beq basic_read_next_line
;; Else, tokenise the line
// Else, tokenise the 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
cmp #$30
bcc not_a_line
cmp #$39
bcs not_a_line
;; Yes, the line begins with a number.
;; Parse the line number and check validity
// Yes, the line begins with a number.
// Parse the line number and check validity
;; injest_number follows tokenise_work1 as the offset into the line,
;; so remember the line length somewhere else for now.
// injest_number follows tokenise_work1 as the offset into the line,
// so remember the line length somewhere else for now.
lda tokenise_work1
sta tokenise_work2
lda #$00
sta tokenise_work1
;; Try to read line number
// Try to read line number
lda #<$0200
sta basic_current_statement_ptr+0
lda #>$0200
@@ -86,67 +86,66 @@ rsl_l1: lda $0200,x
jsr basic_parse_line_number
;; Get pointer to next char
// Get pointer to next char
lda basic_current_statement_ptr+0
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
skip_spaces:
lda $0200,x
cmp #$20
bne +
bne !+
inx
bne skip_spaces
* stx tokenise_work1
!: stx tokenise_work1
;; 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
;; 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).
// 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
// 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).
jsr basic_do_clr
;; Delete line if present
// Delete line if present
jsr basic_find_line
bcs +
bcs !+
;; Delete the line, whether we are deleting or
;; replacing the line
// Delete the line, whether we are deleting or
// replacing the line
jsr basic_delete_line
*
;; Insert new line if non-zero length, i.e., that
;; we are not just deleting the line.
!:
// Insert new line if non-zero length, i.e., that
// we are not just deleting the line.
lda tokenise_work1
cmp tokenise_work2
beq +
beq !+
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
not_a_line:
;; Actually interpret the line
// Actually interpret the line
;; Setup pointer to the statement
// Setup pointer to the statement
lda #<$0200
sta basic_current_statement_ptr+0
lda #>$0200
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
sta basic_current_line_ptr+0
sta basic_current_line_ptr+1
;; Put invalid line number in current line number value,
;; so that we know we are in direct mode
;; (Compute's Mapping the 64 p19)
// Put invalid line number in current line number value,
// so that we know we are in direct mode
// (Compute's Mapping the 64 p19)
lda #$ff
sta basic_current_line_number+1
jmp basic_execute_statement
+8 -8
View File
@@ -3,22 +3,22 @@ basic_parse_line_number:
jsr injest_number
;; Check if the number is a valid line number
;; i.e., 16 bits, no exponent, no decimal
// Check if the number is a valid line number
// i.e., 16 bits, no exponent, no decimal
lda basic_fac1_mantissa+2
ora basic_fac1_mantissa+3
ora basic_fac1_exponent
beq +
beq !+
ml_bad_line_number:
;; Invalid line number
// Invalid line number
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
cmp #$ff
cmp #$FF
bne ml_bad_line_number
;; Got a valid line number.
// Got a valid line number.
lda basic_fac1_mantissa+0
sta basic_line_number+0
lda basic_fac1_mantissa+1
+52 -52
View File
@@ -1,16 +1,16 @@
basic_shift_mem_down_and_relink:
;; Shift memory down to basic_current_line_pointer
;; from X bytes further along.
// Shift memory down to basic_current_line_pointer
// from X bytes further along.
;; Destination is basic_current_line_ptr
// Destination is basic_current_line_ptr
lda basic_current_line_ptr+0
sta memmove_dst+0
lda basic_current_line_ptr+1
sta memmove_dst+1
;; Source is that plus X
// Source is that plus X
txa
pha ; also keep for later
pha // also keep for later
clc
adc basic_current_line_ptr+0
sta memmove_src+0
@@ -18,7 +18,7 @@ basic_shift_mem_down_and_relink:
adc #0
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
sec
sbc memmove_src+0
@@ -27,32 +27,32 @@ basic_shift_mem_down_and_relink:
sbc memmove_src+1
sta memmove_size+1
;; jsr printf
;; .byte "TOP OF BASIC = $"
;; .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 $0d
;; .byte "SHIFTING DOWN $"
;; .byte $f1,<memmove_size,>memmove_size
;; .byte $f0,<memmove_size,>memmove_size
;; .byte " BYTES FROM $"
;; .byte $f1,<memmove_src,>memmove_src
;; .byte $f0,<memmove_src,>memmove_src
;; .byte " TO $"
;; .byte $f1,<memmove_dst,>memmove_dst
;; .byte $f0,<memmove_dst,>memmove_dst
;; .byte $0d,0
// jsr printf
// .text "TOP OF BASIC = $"
// .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 $0d
// .text "SHIFTING DOWN $"
// .byte $f1,<memmove_size,>memmove_size
// .byte $f0,<memmove_size,>memmove_size
// .text " BYTES FROM $"
// .byte $f1,<memmove_src,>memmove_src
// .byte $f0,<memmove_src,>memmove_src
// .text " TO $"
// .byte $f1,<memmove_dst,>memmove_dst
// .byte $f0,<memmove_dst,>memmove_dst
// .byte $0d,0
;; The copy routine that copies under the ROMs is as simple
;; as possible to be as small as possible, so we have
;; to adjust the pointers and counts so that the simple
;; increment and decrement bounds checks work.
// The copy routine that copies under the ROMs is as simple
// as possible to be as small as possible, so we have
// to adjust the pointers and counts so that the simple
// increment and decrement bounds checks work.
;; Specifically we want Y pre-set so that the end of the
;; copy ends when Y = $00.
;; So if copying 1 byte, we want Y=$FF
;; This means we have to then reduce the source and
;; target pointers by the same amount
// Specifically we want Y pre-set so that the end of the
// copy ends when Y = $00.
// So if copying 1 byte, we want Y=$FF
// This means we have to then reduce the source and
// target pointers by the same amount
lda memmove_size+0
eor #$ff
@@ -75,50 +75,50 @@ basic_shift_mem_down_and_relink:
sbc #0
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
;; jsr printf
;; .byte "REVISED BOUNDS $"
;; .byte $f1,<memmove_size,>memmove_size
;; .byte $f0,<memmove_size,>memmove_size
;; .byte " BYTES FROM $"
;; .byte $f1,<memmove_src,>memmove_src
;; .byte $f0,<memmove_src,>memmove_src
;; .byte " TO $"
;; .byte $f1,<memmove_dst,>memmove_dst
;; .byte $f0,<memmove_dst,>memmove_dst
;; .byte $0d,0
// jsr printf
// .text "REVISED BOUNDS $"
// .byte $f1,<memmove_size,>memmove_size
// .byte $f0,<memmove_size,>memmove_size
// .text " BYTES FROM $"
// .byte $f1,<memmove_src,>memmove_src
// .byte $f0,<memmove_src,>memmove_src
// .text " TO $"
// .byte $f1,<memmove_dst,>memmove_dst
// .byte $f0,<memmove_dst,>memmove_dst
// .byte $0d,0
;; Get Y value ready for the copy
// Get Y value ready for the copy
ldy memmove_size+0
jsr shift_mem_down
;; Get length of deletion back
// Get length of deletion back
pla
sta tokenise_work3
;; Check if we still have any lines left
// Check if we still have any lines left
ldy #0
ldx #<basic_current_line_ptr
jsr peek_pointer_null_check
bcs relink_down_next_line
;; Nope, so just return
// Nope, so just return
clc
rts
relink_down_next_line:
;; inc $d020
;; jmp relink_down_next_line
// inc $d020
// jmp relink_down_next_line
;; Subtract tokenise_work3 from the pointer
// Subtract tokenise_work3 from the pointer
ldy #0
ldx #<basic_current_line_ptr+0
jsr peek_under_roms
sec
sbc tokenise_Work3
sbc tokenise_work3
sta memmove_src+0
iny
jsr peek_under_roms
@@ -134,13 +134,13 @@ relink_down_next_line:
jsr poke_under_roms
relink_down_loop:
;; Now advance pointer to the next line,
// Now advance pointer to the next line,
lda memmove_src+0
sta basic_current_line_ptr+0
lda memmove_src+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
jsr peek_pointer_null_check
bcs relink_down_next_line
+61 -61
View File
@@ -1,12 +1,12 @@
basic_shift_mem_up_and_relink:
;; Shift memory up from basic_current_line_ptr
;; X bytes.
// Shift memory up from basic_current_line_ptr
// X bytes.
;; NOTE: Pointers need to be reduced by one, due to the way
;; the copyroutine works, so we do that here.
;; Work out end point of destination
// NOTE: Pointers need to be reduced by one, due to the way
// the copyroutine works, so we do that here.
// Work out end point of destination
txa
clc
adc basic_end_of_text_ptr+0
@@ -22,7 +22,7 @@ basic_shift_mem_up_and_relink:
sbc #0
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
sec
sbc #1
@@ -31,7 +31,7 @@ basic_shift_mem_up_and_relink:
sbc #0
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
sec
sbc basic_current_line_ptr+0
@@ -40,25 +40,25 @@ basic_shift_mem_up_and_relink:
sbc basic_current_line_ptr+1
sta memmove_size+1
;; jsr printf
;; .byte "TOP OF BASIC = $"
;; .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 $0d
;; .byte "SHIFTING UP $"
;; .byte $f1,<memmove_size,>memmove_size
;; .byte $f0,<memmove_size,>memmove_size
;; .byte " BYTES FROM $"
;; .byte $f1,<memmove_src,>memmove_src
;; .byte $f0,<memmove_src,>memmove_src
;; .byte " TO $"
;; .byte $f1,<memmove_dst,>memmove_dst
;; .byte $f0,<memmove_dst,>memmove_dst
;; .byte $0d,0
// jsr printf
// .text "TOP OF BASIC = $"
// .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 $0d
// .text "SHIFTING UP $"
// .byte $f1,<memmove_size,>memmove_size
// .byte $f0,<memmove_size,>memmove_size
// .text " BYTES FROM $"
// .byte $f1,<memmove_src,>memmove_src
// .byte $f0,<memmove_src,>memmove_src
// .text " TO $"
// .byte $f1,<memmove_dst,>memmove_dst
// .byte $f0,<memmove_dst,>memmove_dst
// .byte $0d,0
;; 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
;; byte of the copy size.
// 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
// byte of the copy size.
lda memmove_src+0
sec
sbc memmove_size+0
@@ -75,35 +75,35 @@ basic_shift_mem_up_and_relink:
sbc #0
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
;; Then set Y to the number offset required
// Then set Y to the number offset required
ldy memmove_size+0
iny
stx tokenise_work3
;; jsr printf
;; .byte "REVISED BOUNDS $"
;; .byte $f1,<memmove_size,>memmove_size
;; .byte $f0,<memmove_size,>memmove_size
;; .byte " BYTES FROM $"
;; .byte $f1,<memmove_src,>memmove_src
;; .byte $f0,<memmove_src,>memmove_src
;; .byte " TO $"
;; .byte $f1,<memmove_dst,>memmove_dst
;; .byte $f0,<memmove_dst,>memmove_dst
;; .byte $0d,0
// jsr printf
// .text "REVISED BOUNDS $"
// .byte $f1,<memmove_size,>memmove_size
// .byte $f0,<memmove_size,>memmove_size
// .text " BYTES FROM $"
// .byte $f1,<memmove_src,>memmove_src
// .byte $f0,<memmove_src,>memmove_src
// .text " TO $"
// .byte $f1,<memmove_dst,>memmove_dst
// .byte $f0,<memmove_dst,>memmove_dst
// .byte $0d,0
;; Do the copy
// Do the copy
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
;; pointer to itself, so that we can add the shift
;; to make it end up pointing to the next line
// First, we need to point the current BASIC line
// pointer to itself, so that we can add the shift
// to make it end up pointing to the next line
ldy #0
ldx #<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
relink_up_next_line:
;; inc $d020
;; jmp relink_up_next_line
// inc $d020
// jmp relink_up_next_line
;; Advance pointer by tokenise_word3 bytes
// Advance pointer by tokenise_word3 bytes
ldy #0
ldx #<basic_current_line_ptr+0
jsr peek_under_roms
@@ -132,20 +132,20 @@ relink_up_next_line:
adc #0
sta memmove_src+1
;; jsr printf
;; .byte "LINE ADDR = $"
;; .byte $f1,<basic_current_line_ptr,>basic_end_of_text_ptr
;; .byte $f0,<basic_current_line_ptr,>basic_end_of_text_ptr
;; .byte $d," BEFORE = $"
;; .byte $f1,<memmove_dst,>memmove_dst
;; .byte $f0,<memmove_dst,>memmove_dst
;; .byte ", AFTER = $"
;; .byte $f1,<memmove_src,>memmove_src
;; .byte $f0,<memmove_src,>memmove_src
;; .byte $d
;; .byte 0
// jsr printf
// .text "LINE ADDR = $"
// .byte $f1,<basic_current_line_ptr,>basic_end_of_text_ptr
// .byte $f0,<basic_current_line_ptr,>basic_end_of_text_ptr
// .text $d," BEFORE = $"
// .byte $f1,<memmove_dst,>memmove_dst
// .byte $f0,<memmove_dst,>memmove_dst
// .text ", AFTER = $"
// .byte $f1,<memmove_src,>memmove_src
// .byte $f0,<memmove_src,>memmove_src
// .byte $d
// .byte 0
;; Write memmove_src back to current line pointer
// Write memmove_src back to current line pointer
ldy #0
ldx #<basic_current_line_ptr
lda memmove_src+0
@@ -156,13 +156,13 @@ relink_up_next_line:
relink_up_loop:
;; Now advance pointer to the next line,
// Now advance pointer to the next line,
lda memmove_src+0
sta basic_current_line_ptr+0
lda memmove_src+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
jsr peek_pointer_null_check
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:
jsr install_ram_routines
;; If warm start caused by BRK, print it address
// If warm start caused by BRK, print it address
lda CMP0
ora CMP0+1
beq +
beq !+
ldx #32
jsr print_packed_message
@@ -18,6 +18,6 @@ basic_warm_start:
lda #$0D
jsr JCHROUT
*
!:
jmp basic_main_loop
+3 -4
View File
@@ -1,4 +1,3 @@
;; Skip the gap between $C000-$DFFF
.checkpc $C000
.advance $DFFF,$00
.checkpc $E000
// Skip the gap between $C000-$DFFF
.fill $2000, $00
+13 -12
View File
@@ -1,23 +1,24 @@
cmd_stop:
basic_do_break:
jsr printf
.byte "BREAK",0
jsr printf // XXX don't use printf, use packed messages!
.text "BREAK"
.byte 0
;; Check for direct mode
;; Are we in direct mode
// Check for direct mode
// Are we in direct mode
lda basic_current_line_number+1
cmp #$ff
beq +
;; Not direct mode
jsr printf
.byte " IN ",0
cmp #$FF
beq !+
// Not direct mode
jsr printf // XXX don't use printf, use packed messages!
.text " IN "
.byte 0
lda basic_current_line_number+1
ldx basic_current_line_number+0
jsr print_integer
*
lda #$0d
!:
lda #$0D
jsr JCHROUT
cmd_end:
jmp basic_main_loop
+26 -26
View File
@@ -1,9 +1,9 @@
;; LIST basic text.
;; XXX - Doesn't currently support line number ranges
// LIST basic text.
// XXX - Doesn't currently support line number ranges
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
sta basic_current_line_ptr+0
lda basic_start_of_text_ptr+1
@@ -16,23 +16,23 @@ list_loop:
cmp #$00
bne list_more_lines
;; LIST terminates any running program,
;; because it has fiddled with the current line pointer.
;; (Confirmed by testing on a C64)
// LIST terminates any running program,
// because it has fiddled with the current line pointer.
// (Confirmed by testing on a C64)
jmp basic_main_loop
list_more_lines:
lda STKEY
bmi +
bmi !+
jmp basic_do_break
*
!:
jsr list_single_line
;; Now link to the next line
// Now link to the next line
jsr basic_find_next_line
jmp list_loop
list_single_line: ; entry point needed by DOS wedge
;; Print line number
list_single_line: // entry point needed by DOS wedge
// Print line number
ldy #3
jsr peek_under_roms
pha
@@ -44,8 +44,8 @@ list_single_line: ; entry point needed by DOS wedge
lda #$20
jsr JCHROUT
;; Iterate through printing out the line
;; contents
// Iterate through printing out the line
// contents
lda #0
sta quote_mode_flag
@@ -63,34 +63,34 @@ list_print_loop:
lda #$22
jmp list_is_literal
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
bne list_is_literal
cmp #$7f
bcc list_is_literal
;; Display a token
// Display a token
;; Save registers
// Save registers
tax
pha
tya
pha
;; Get pointer to compressed keyword list
// Get pointer to compressed keyword list
lda #<packed_keywords
sta temp_string_ptr+0
lda #>packed_keywords
sta temp_string_ptr+1
;; Subtract $80 from token to get offset in word
;; list
// Subtract $80 from token to get offset in word
// list
txa
and #$7f
tax
;; Now ask for it to be printed
// Now ask for it to be printed
ldy #$ff
jsr packed_word_search
@@ -100,11 +100,11 @@ list_not_quote:
cmp #$8f
bne list_not_rem
;; REM command locks quote flag on until the end of the line, allowing
;; funny characters in REM statements without problem.
// REM command locks quote flag on until the end of the line, allowing
// funny characters in REM statements without problem.
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
;; FALL THROUGH
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
list_not_rem:
iny
@@ -116,10 +116,10 @@ list_is_literal:
bne list_print_loop
list_end_of_line:
;; Clear reverse flag
// Clear reverse flag
lda #$92
jsr JCHROUT
;; Print end of line
// Print end of line
lda #$0d
jsr JCHROUT
rts
+66 -66
View File
@@ -1,64 +1,64 @@
cmd_load:
;; Parse filename
;; (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
;; to be able to peek under the ROMs for SAVE and VERIFY).
;; Parse optional device #
;; Parse optional secondary address
// Parse filename
// (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
// to be able to peek under the ROMs for SAVE and VERIFY).
// Parse optional device #
// Parse optional secondary address
;; XXX - C64 BASIC apparently doesn't clear variables after a LOAD in the
;; middle of a program. For safety, we do.
// XXX - C64 BASIC apparently doesn't clear variables after a LOAD in the
// middle of a program. For safety, we do.
jsr basic_do_clr
;; Setup Kernal to print control messages or not
lda #$80 ; display control messages and omit error messages
// Setup Kernal to print control messages or not
lda #$80 // display control messages and omit error messages
ldx basic_current_line_number+1
cpx #$FF
beq +
lda #$00 ; direct mode - don't display anything
*
beq !+
lda #$00 // direct mode - don't display anything
!:
jsr JSETMSG
;; Set filename and length
// Set filename and length
lda #$00
sta FNLEN
;; Without tape support, LOAD must have a filename
;; (This also skips any leading spaces)
// Without tape support, LOAD must have a filename
// (This also skips any leading spaces)
jsr basic_end_of_statement_check
bcc +
bcc !+
jmp do_MISSING_FILENAME_error
*
!:
jsr basic_fetch_and_consume_character
cmp #$22
beq +
jmp do_SYNTAX_ERROR
*
;; Filename starts here so set pointer
beq !+
jmp do_SYNTAX_error
!:
// Filename starts here so set pointer
lda basic_current_statement_ptr+0
sta current_filename_ptr+0
lda basic_current_statement_ptr+1
sta current_filename_ptr+1
;; Now search for end of line or closing quote
;; so that we know the length of the filename
// Now search for end of line or closing quote
// so that we know the length of the filename
getting_filename:
jsr basic_fetch_and_consume_character
cmp #$22
beq got_filename
cmp #$00
bne +
bne !+
jsr basic_unconsume_character
jmp got_filename
*
!:
inc FNLEN
jmp getting_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
stx current_device_number
jsr injest_comma
@@ -66,116 +66,116 @@ got_filename:
jsr basic_parse_line_number
lda basic_line_number+1
beq +
beq !+
jmp do_ILLEGAL_QUANTITY_error
*
!:
lda basic_line_number+0
sta current_device_number
got_devicenumber:
;; Now fetch the secondary address
// Now fetch the secondary address
lda #$00
sta current_secondary_address
jsr injest_comma
bcs got_secondaryaddress
jsr basic_parse_line_number
lda basic_line_number+1
bne +
bne !+
lda basic_line_number+0
sta current_secondary_address
jmp got_secondaryaddress
*
;; Second parameter is above 255, this can't be a secondary address
;; Use it as load address instead
;; XXX temporary syntax, it would be better to use something
;; XXX like 'LOAD"FILE",8 TO 49152'
!:
// Second parameter is above 255, this can't be a secondary address
// Use it as load address instead
// XXX temporary syntax, it would be better to use something
// XXX like 'LOAD"FILE",8 TO 49152'
ldx basic_line_number+0
ldy basic_line_number+1
bne got_loadaddress
got_secondaryaddress:
ldx #<$0801
ldx #<$0801 // XXX use start text vector
ldy #>$0801
got_loadaddress:
lda #$00 ; LOAD not verify
lda #$00 // LOAD not verify
jsr via_ILOAD
bcc +
bcc !+
;; A = KERNAL error code, which also almost match
;; basic ERROR codes, so we can just copy the
;; error code to X, decrement, and handle normally
// A = KERNAL error code, which also almost match
// basic ERROR codes, so we can just copy the
// error code to X, decrement, and handle normally
tax
dex
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
sty basic_end_of_text_ptr+1
;; Now relink the loaded program, as we cannot trust the line
;; links supplied. For example, the VICE virtual drive emulation
;; always supplies $0101 as the address of the next line.
// Now relink the loaded program, as we cannot trust the line
// links supplied. For example, the VICE virtual drive emulation
// always supplies $0101 as the address of the next line.
jsr basic_relink_program
;; After LOADing, we either start the program from the beginning,
;; or go back to the READY prompt if LOAD was called from direct mode.
// After LOADing, we either start the program from the beginning,
// 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
sta basic_current_line_ptr+0
lda basic_start_of_text_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
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
sta basic_current_line_ptr+0
lda basic_start_of_text_ptr+1
sta basic_current_line_ptr+1
basic_relink_loop:
;; Is the pointer to the end of the program
// Is the pointer to the end of the program
ldy #1
ldx #<basic_current_line_ptr+0
jsr peek_under_roms
cmp #$00
bne +
bne !+
;; End of program
// End of program
rts
*
;; Now search forward to find the end of the line
;; Skip forward pointer and line number
!:
// Now search forward to find the end of the line
// Skip forward pointer and line number
ldy #4
end_of_line_search:
ldx #<basic_current_line_ptr+0
jsr peek_under_roms
cmp #$00
beq +
beq !+
;; Not yet end of line
// Not yet end of line
iny
bne end_of_line_search
;; line too long
// line too long
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
;; Now overwrite the pointer (carefully)
;;
// Now overwrite the pointer (carefully)
//
tya
clc
adc basic_current_line_ptr+0
+21 -23
View File
@@ -2,18 +2,18 @@
cmd_new:
jsr basic_do_new
;; NEW command terminates execution
;; (Confirmed on a C64)
// NEW command terminates execution
// (Confirmed on a C64)
jmp basic_main_loop
cmd_clr:
jsr basic_do_clr
;; CLR command does not stop execution
;; (Cconfirmed on a c64)
// CLR command does not stop execution
// (Cconfirmed on a c64)
jmp basic_execute_statement
basic_do_new:
;; Setup pointers to memory storage
// Setup pointers to memory storage XXX should depend on text start vector
lda #<$0801
sta basic_start_of_text_ptr+0
lda #>$0801
@@ -22,8 +22,8 @@ basic_do_new:
lda #<$0803
sta basic_start_of_vars_ptr+0
;; Zero line pointer
;; XXX - We should also zero $0800, i.e., basic_start_of_text_ptr - 1
// Zero line pointer
// XXX - We should also zero $0800, i.e., basic_start_of_text_ptr - 1
ldy #$00
tya
sta (basic_start_of_text_ptr),y
@@ -31,32 +31,32 @@ basic_do_new:
sta (basic_start_of_text_ptr),y
;; Get top of memory.
;; If a cart is present, then it is $7FFF,
;; if not, then it is $F7FF, since we support having
;; programs and variables under ROM.
;; i.e., we support 56KB RAM for BASIC, keeping some space
;; free for some optimisation structures, e.g., FOR/NEXT loop
;; records (without them going on the stack), GOSUB stack
;; (same story), expression value cache?
// Get top of memory.
// If a cart is present, then it is $7FFF,
// if not, then it is $F7FF, since we support having
// programs and variables under ROM.
// i.e., we support 56KB RAM for BASIC, keeping some space
// free for some optimisation structures, e.g., FOR/NEXT loop
// records (without them going on the stack), GOSUB stack
// (same story), expression value cache?
sec ; Read, not write value
sec // Read, not write value
jsr JMEMTOP
cpx #$80
beq +
beq !+
lda #>$f7ff
.byte $2c
* lda #>$7FFF
.byte $2C
!: lda #>$7FFF
sta basic_top_of_memory_ptr+1
sta basic_start_of_strings_ptr+1
lda #<$f7ff
sta basic_top_of_memory_ptr+0
sta basic_start_of_strings_ptr+0
;; FALL THROUGH
// FALL THROUGH
basic_do_clr:
;; Clear variables, arrays and strings
// Clear variables, arrays and strings
lda basic_start_of_vars_ptr+0
sta basic_start_of_arrays_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
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:
jmp basic_end_of_line
+7 -7
View File
@@ -1,21 +1,21 @@
cmd_run:
;; RUN clears all variables
// RUN clears all variables
jsr basic_do_clr
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
sta basic_current_line_ptr+0
lda basic_start_of_text_ptr+1
sta basic_current_line_ptr+1
jsr basic_end_of_statement_check
bcs +
bcs !+
jsr basic_parse_line_number
jsr basic_find_line
bcc +
;; Line doesn't exist, so report error
bcc !+
// Line doesn't exist, so report error
jmp do_UNDEFD_STATEMENT_error
*
;; Run it!
!:
// Run it!
jmp basic_execute_from_current_line
+8 -8
View File
@@ -1,23 +1,23 @@
cmd_sys:
jsr basic_end_of_statement_check
bcc +
bcc !+
;; SYS requires an argument
jmp do_SYNTAX_ERROR
// SYS requires an argument
jmp do_SYNTAX_error
*
!:
jsr basic_parse_line_number
;; setup call
lda #$4C ;JMP
// setup call
lda #$4C // JMP opcode
sta USRPOK
lda basic_line_number+0
sta USRADD+0
lda basic_line_number+1
sta USRADD+1
;; Setup the register values
// Setup the register values
lda SPREG
pha
ldy SYREG
@@ -25,7 +25,7 @@ cmd_sys:
lda SAREG
plp
;; Call the routine.
// Call the routine.
jsr USRPOK
jmp basic_execute_statement
+9 -9
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_next:
@@ -13,7 +13,7 @@ cmd_restore:
cmd_gosub:
cmd_return:
;; $90-$9F
// $90-$9F
cmd_on:
cmd_wait:
cmd_save:
@@ -26,7 +26,7 @@ cmd_cont:
cmd_cmd:
cmd_open:
;; $A0-$AF
// $A0-$AF
cmd_close:
cmd_get:
cmd_tab:
@@ -43,7 +43,7 @@ cmd_div:
cmd_exponent:
cmd_and:
;; $B0-$BF
// $B0-$BF
cmd_or:
cmd_greater:
cmd_equal:
@@ -61,7 +61,7 @@ cmd_exp:
cmd_cos:
cmd_sin:
;; $C0-$CF
// $C0-$CF
cmd_tan:
cmd_atn:
cmd_peek:
@@ -73,10 +73,10 @@ cmd_chr:
cmd_left:
cmd_right:
cmd_mid:
cmd_go:
;; Undefined tokens
cmd_go:
// Undefined tokens
cmd_unimplemented:
jmp do_NOT_IMPLEMENTED_error
+55 -54
View File
@@ -1,48 +1,48 @@
;; As many errors are triggered from many places in the BASIC
;; interprettor, it is important to have an efficicent means of
;; calling them.
;; LDX #$nn / jmp do_basic_error
;; is the simplest, but takes 5 bytes.
;; Having a direct JMP address for each error is preferable, as
;; 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
;; to have a set of addresses that each execute a different
;; LDX #$nn command, reducing the cost of the jump table to 3
;; bytes per error number.
;; But we can do better with a bit of scullduggery and carnal
;; knowledge of ZP usage.
;; 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
;; 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,
;; 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
;; 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
;; of that argument can be safely executed as a CPU instruction.
;; NOP = $EA is the obvious choice, as if used as an argument to
;; $E6 will increment location $EA, which is another of the screen
;; link addresses.
// As many errors are triggered from many places in the BASIC
// interprettor, it is important to have an efficicent means of
// calling them.
// LDX #$nn / jmp do_basic_error
// is the simplest, but takes 5 bytes.
// Having a direct JMP address for each error is preferable, as
// 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
// to have a set of addresses that each execute a different
// LDX #$nn command, reducing the cost of the jump table to 3
// bytes per error number.
// But we can do better with a bit of scullduggery and carnal
// knowledge of ZP usage.
// 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
// 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,
// 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
// 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
// of that argument can be safely executed as a CPU instruction.
// NOP = $EA is the obvious choice, as if used as an argument to
// $E6 will increment location $EA, which is another of the screen
// link addresses.
;; This gives a total overhead of 18 bytes + 1 byte per error
;; message. This compares favourably to the 3 bytes per error
;; message that the $2C method would result in.
// This gives a total overhead of 18 bytes + 1 byte per error
// message. This compares favourably to the 3 bytes per error
// message that the $2C method would result in.
do_NOT_IMPLEMENTED_error:
.byte $E6
do_MEMORY_CORRUPT_error:
.byte $E6
;; the message "BYTES FREE"
// the message "BYTES FREE"
.byte $E6
;; the word ERROR
// the word ERROR
.byte $E6
;; The word "SAVING"
// The word "SAVING"
.byte $E6
;; The word "VERIFYING"
// The word "VERIFYING"
.byte $E6
;; The word "LOADING"
// The word "LOADING"
.byte $E6
;; The word "READY."
// The word "READY."
.byte $E6
do_LOAD_error:
.byte $E6
@@ -103,69 +103,70 @@ do_FILE_OPEN_error:
do_TO_MANY_FILES_error:
.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
pha
and #$80
sta $E6
pla
;; $E6 has even part
// $E6 has even part
asl
ora $EA
and #$7f
tax
;; Restore $EA to correct value in case the NOP above is used
;; as an argument to the preceeding INC $nn (opcode $E6).
LDA $EA
// Restore $EA to correct value in case the NOP above is used
// as an argument to the preceeding INC $nn (opcode $E6).
lda $EA
and #$80
sta $EA
;; FALL THROUGH
// FALL THROUGH
;; Error # in X
// Error # in X
do_basic_error:
;; "?"
// "?"
txa
pha
lda #$0d
jsr $ffd2
jsr JCHROUT
lda #$3f
jsr $ffd2
jsr JCHROUT
pla
tax
;; Error message text
// Error message text
jsr print_packed_message
;; A space between error name and word error
// A space between error name and word error
lda #$20
jsr $ffd2
;; "ERROR"
// "ERROR"
ldx #33
jsr print_packed_message
lda basic_current_line_number+1
cmp #$ff
beq +
beq !+
;; We were in a program, so show IN <line>
jsr printf
.byte " IN ",0
// We were in a program, so show IN <line>
jsr printf // XXX don't use printf, use packed messages
.text " IN "
.byte 0
lda basic_current_line_number+1
ldx basic_current_line_number+0
jsr print_integer
*
;; New lines
!:
// New lines
lda #$0d
jsr $ffd2
lda #$00
jsr $ffd2
;; XXX - Restore stack depth first?
// XXX - Restore stack depth first?
jmp basic_main_loop
+26 -26
View File
@@ -1,23 +1,23 @@
;; Multiply Floating Point Accumulator by 10
;; = 8x + 2x
;; Implement by shifting MAC left one bit,
;; and then keeping that value to add on after
;; shifting two more bits left.
;; This should be done using basic_fac1_overflow to
;; hold the overflow bits, so that the result can
;; be exponent adjusted after, if required.
// Multiply Floating Point Accumulator by 10
// = 8x + 2x
// Implement by shifting MAC left one bit,
// and then keeping that value to add on after
// shifting two more bits left.
// This should be done using basic_fac1_overflow to
// hold the overflow bits, so that the result can
// be exponent adjusted after, if required.
fac1_mul10:
lda #$00
sta basic_fac1_overflow
;; Multiply mantissa by 2
// Multiply mantissa by 2
jsr fac1_mantissa_mul2
;; copy down to BASIC numeric work area at $57
;; (basic_numeric_work_area)
;; (We copy all 7 bytes off the FAC1, so that we have
;; the overflow bits, and the copy is as small as possible)
// copy down to BASIC numeric work area at $57
// (basic_numeric_work_area)
// (We copy all 7 bytes off the FAC1, so that we have
// the overflow bits, and the copy is as small as possible)
ldx #7
f1m10_l1:
lda basic_fac1_mantissa,x
@@ -25,11 +25,11 @@ f1m10_l1:
dex
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
;; 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
ldx #0
clc
@@ -44,22 +44,22 @@ f1m10_l2:
adc basic_numeric_work_area+7
sta basic_fac1_overflow
;; Now shift right and increase exponent until overflow
;; bits = $00
// Now shift right and increase exponent until overflow
// bits = $00
f1m10_l3:
lda basic_fac1_overflow
bne +
;; All done, return
bne !+
// All done, return
clc
rts
*
;; Divide mantissa by two, and increment exponent
!:
// Divide mantissa by two, and increment exponent
jsr fac1_mantissa_div2
inc basic_fac1_exponent
lda basic_fac1_exponent
bpl f1m10_l3
;; Exponent has bit 7 set, so has wrapped.
;; = OVERFLOW ERROR
// Exponent has bit 7 set, so has wrapped.
// = OVERFLOW ERROR
jmp do_OVERFLOW_error
fac1_mantissa_mul2:
@@ -67,8 +67,8 @@ fac1_mantissa_mul2:
ldx #0
clc
f1m1_l1:
;; Multiply mantissa by 2, and store overflow
;; in basic_fac1_bits
// Multiply mantissa by 2, and store overflow
// in basic_fac1_bits
lda basic_fac1_mantissa,x
rol
sta basic_fac1_mantissa,x
@@ -82,7 +82,7 @@ f1m1_l1:
rts
fac1_mantissa_div2:
;; Divide mantissa by 2, including using overflow bits
// Divide mantissa by 2, including using overflow bits
clc
lda basic_fac1_overflow
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:
jsr basic_fetch_and_consume_character
cmp #$2C ; comma character
cmp #$2C // comma character
beq injest_comma_found
cmp #$20
beq injest_comma ; space, can always be skipped
cmp #$20 // space, can always be skipped
beq injest_comma
;; not found
// not found
jsr basic_unconsume_character
sec
rts
@@ -17,4 +17,3 @@ injest_comma:
injest_comma_found:
clc
rts
+50 -51
View File
@@ -1,37 +1,37 @@
;; Parse a number from the input buffer at (basic_current_statement_ptr)
;; Result is put into FAC1.
;; basic_current_statement_ptr is updated with first position after the number.
// Parse a number from the input buffer at (basic_current_statement_ptr)
// Result is put into FAC1.
// basic_current_statement_ptr is updated with first position after the number.
;; XXX - Remember decimal position and exponent, and apply them
;; after to produce normalised floating point number.
// XXX - Remember decimal position and exponent, and apply them
// after to produce normalised floating point number.
;; XXX - Doesn't use routines to access memory under ROMs etc.
;; This is important, because this routine operates on numbers in BASIC text.
// XXX - Doesn't use routines to access memory under ROMs etc.
// This is important, because this routine operates on numbers in BASIC text.
ij_not_a_digit:
;; XXX check for "." or "E"
;; Other chars terminate the accumulation.
// XXX check for "." or "E"
// Other chars terminate the accumulation.
;; Look for exponentiation marker
;; XXX - Implement me!
;; Probably should have a flag so that we know if we are accumulating
;; exponent or mantissa digits
// Look for exponentiation marker
// XXX - Implement me!
// Probably should have a flag so that we know if we are accumulating
// exponent or mantissa digits
;; Look for decimal point
// Look for decimal point
cmp #$2e
bne ij_not_decimal
lda tokenise_work4
cmp #$ff
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
rts
ij_found_decimal:
;; Found decimal.
;; Thus start counting digits after the decimal, so that we
;; can do the necessary number of divide by 10s on the final
;; number.
// Found decimal.
// Thus start counting digits after the decimal, so that we
// can do the necessary number of divide by 10s on the final
// number.
lda #$00
sta tokenise_work4
@@ -39,31 +39,30 @@ ij_found_decimal:
ij_not_decimal:
CLC
RTS
clc
rts
injest_number:
;; Clear FAC1
// Clear FAC1
jsr erase_fac1
;; Clear decimal position flag
// Clear decimal position flag
lda #$ff
sta tokenise_work4
;; Check if leading char is a - sign
;; Note: the - will have been tokenised to $AB
;; XXX - implement
// Check if leading char is a - sign
// Note: the - will have been tokenised to $AB
// XXX - implement
ldy #$00
lda (basic_current_statement_ptr),y
cmp #$AB
bne ij_not_minus
;; Set sign to negative
// Set sign to negative
lda #$ff
sta basic_fac1_sign
;; Skip over the minus sign
// Skip over the minus sign
jsr basic_consume_character
ij_not_minus:
@@ -77,43 +76,43 @@ ij_loop1:
cmp #$3a
bcs ij_not_a_digit
;; It is a digit
// It is a digit
;; Only add digit if we have not overflowed the accuracy of
;; the mantissa
// Only add digit if we have not overflowed the accuracy of
// the mantissa
lda basic_fac1_exponent
beq ij_accept_precision
;; We have an extra digit after saturating our precision.
;; Thus we should ignore the digit, and just multiply the FAC
;; by 10, but only if we have not seen a decimal point.
;; If we have seen a decimal point, then we can completely ignore
;; the digit, as it is contributing not recordable information
// We have an extra digit after saturating our precision.
// Thus we should ignore the digit, and just multiply the FAC
// by 10, but only if we have not seen a decimal point.
// If we have seen a decimal point, then we can completely ignore
// the digit, as it is contributing not recordable information
lda tokenise_work4
cmp #$ff
bne ij_seen_decimal_point
jsr fac1_mul10
;; Fall through
// Fall through
ij_seen_decimal_point:
jmp ij_consider_next_digit
ij_accept_precision:
;; We can accept more precision, so multiply the mantissa by 10, so that
;; we can add the new digit in
// We can accept more precision, so multiply the mantissa by 10, so that
// we can add the new digit in
jsr fac1_mul10
lda basic_fac1_exponent
bne ij_consider_next_digit
;; Get digit
// Get digit
ldy #$00
lda (basic_current_statement_ptr),y
sec
sbc #$30
;; Add to FAC1 mantissa
// Add to FAC1 mantissa
clc
adc basic_fac1_mantissa+0
sta basic_fac1_mantissa+0
@@ -127,16 +126,16 @@ ij_loop2:
dey
bne ij_loop2
bcc +
;; Carry set, so we have overflowed.
;; We should shift everything right one digit, and increase
;; the exponent by one. The non-zero exponent tells us that we
;; can't fit any more precision in.
bcc !+
// Carry set, so we have overflowed.
// We should shift everything right one digit, and increase
// the exponent by one. The non-zero exponent tells us that we
// can't fit any more precision in.
jsr fac1_mantissa_div2
*
!:
ij_consider_next_digit:
;; Consider next digit
// Consider next digit
jsr basic_consume_character
jmp ij_loop1
@@ -146,10 +145,10 @@ ij_consider_next_digit:
erase_fac1:
lda #$00
ldx #8
*
!:
sta basic_fac1_exponent,x
dex
bpl -
bpl !-
sta basic_fac1_mantissa_lob
rts
+88 -87
View File
@@ -1,76 +1,77 @@
;; Pack a word using the simple compression scheme.
;; This has to be the same implementation as in compress_text.c
;; because we compress input lines of BASIC to do the tokenisation.
;; This allows us to search through the compressed tokens directly
;; using the compressed fragment of BASIC, and thus work out the
;; token for a given piece of string.
;; This also helps ensure that we have an implementation that is totally
;; 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
;; larger keyword vocabs for BASIC 7 or BASIC 10 compatibility, since the
;; compression and decompression machinery is of fixed size.
// Pack a word using the simple compression scheme.
// This has to be the same implementation as in compress_text.c
// because we compress input lines of BASIC to do the tokenisation.
// This allows us to search through the compressed tokens directly
// using the compressed fragment of BASIC, and thus work out the
// token for a given piece of string.
// This also helps ensure that we have an implementation that is totally
// 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
// larger keyword vocabs for BASIC 7 or BASIC 10 compatibility, since the
// compression and decompression machinery is of fixed size.
pack_word:
;; Inputs:
;; X = offset of string to pack. Address is $0200 + X
;; tokenise_work1 = number of bytes to pack
;; tokenise_work2 = packed length of string
// Inputs:
// X = offset of string to pack. Address is $0200 + X
// tokenise_work1 = number of bytes to pack
// tokenise_work2 = packed length of string
;; Outputs:
;; Output is written to $0100 (bottom of stack).
// Outputs:
// Output is written to $0100 (bottom of stack).
;; Memory modified:
;; tokenise_work4 = temporary storage
;; 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
;; is incomplete, which is important for searching for abbreviated
;; key words.)
// Memory modified:
// tokenise_work4 = temporary storage
// 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
// is incomplete, which is important for searching for abbreviated
// key words.)
;; Make sure we have a sane request
// Make sure we have a sane request
lda tokenise_work1
bne +
bne !+
sec
rts
*
;; Initialise internal variables
!:
// Initialise internal variables
lda #$00
sta tokenise_work2
sta tokenise_work3
pack_char_loop:
;; Get the next char
// Get the next char
lda $0200,x
;; Work out what type of character we have, and thus
;; how we need to pack it.
// Work out what type of character we have, and thus
// how we need to pack it.
jsr get_packed_char_index
cmp #$00
bne not_exception_char
;; Char is an exception char.
;; We need to either finish the previous byte with $xF,
;; Or if there is no existing nybl, then we need to output
;; either $FE or $FF, depending on whether this is the last
;; byte or not
// Char is an exception char.
// We need to either finish the previous byte with $xF,
// Or if there is no existing nybl, then we need to output
// either $FE or $FF, depending on whether this is the last
// byte or not
lda tokenise_work3
bne have_nybl_before_exception_char
;; 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
// 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
inx
lda tokenise_work1
cmp #$01
beq at_end
lda #$FF
.byte $2C
at_end: LDA #$FE
at_end:
lda #$FE
dex
jsr write_unpacked_char
;; Fall through
// Fall through
output_exception_byte:
lda $0200,x
@@ -78,18 +79,18 @@ output_exception_byte:
jmp consider_next_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
lda $0100,y
ora #$0f
sta $0100,y
inc tokenise_work2
;; FALL THROUGH
// FALL THROUGH
write_literal_and_terminate_if_required:
;; Clear have nybl flag
// Clear have nybl flag
lda #$00
sta tokenise_work3
@@ -99,19 +100,19 @@ write_literal_and_terminate_if_required:
jmp 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
lda tokenise_work1
cmp #$01
beq +
beq !+
dex
jmp consider_next_char
*
!:
dex
;; Fall through
// Fall through
end_string:
;; Write end of string sequence if required
// Write end of string sequence if required
lda #$00
jsr write_unpacked_char
rts
@@ -124,53 +125,53 @@ write_unpacked_char:
rts
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
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
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
ldy tokenise_work2
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:
;; 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
ora $0100,y
sta $0100,y
stored_nybl:
;; Now toggle the nybl flag
// Now toggle the nybl flag
lda tokenise_work3
eor #$ff
sta tokenise_work3
;; 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
// 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
;; Count the filled up byte
// Count the filled up byte
inc tokenise_work2
;; Add termination byte if required
;; (This re-writes the same byte again, which we don't care about)
// Add termination byte if required
// (This re-writes the same byte again, which we don't care about)
jmp end_string_if_required
whole_byte_symbol:
;; It's a $Fx symbol.
;; But if we have a nybl to flush, then we handle it like
;; a full exception character
// It's a $Fx symbol.
// But if we have a nybl to flush, then we handle it like
// a full exception character
ldy tokenise_work3
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
lda $0100,y
ora #$0f
@@ -180,30 +181,30 @@ whole_byte_symbol:
jmp write_literal_and_terminate_if_required
nothing_to_flush:
;; Write the symbol as it is, or the literal
;; if it has been passed to us via fall-through
// Write the symbol as it is, or the literal
// if it has been passed to us via fall-through
jsr write_unpacked_char
jmp end_string_if_required
consider_next_char:
;; Pack next char
// Pack next char
inx
dec tokenise_work1
beq +
beq !+
jmp pack_char_loop
*
;; Add 1 to length if nybl waiting to be flushed
;; (but leave flag set so the caller knows if the
;; bottom nybl might be different if the string were
;; longer).
!:
// Add 1 to length if nybl waiting to be flushed
// (but leave flag set so the caller knows if the
// bottom nybl might be different if the string were
// longer).
lda tokenise_work3
beq +
beq !+
inc tokenise_work2
rts
*
;; Last byte was full, so we need at $00 on the end
;; (unless a $FE token was written 2 bytes ago)
!:
// Last byte was full, so we need at $00 on the end
// (unless a $FE token was written 2 bytes ago)
ldy tokenise_work2
iny
lda #$00
@@ -213,21 +214,21 @@ consider_next_char:
rts
get_packed_char_index:
;; Find char in A in the packed char list, and return
;; $1 - $E, $F1 - $FD if the charactar is abbreviable,
;; or else return $00 if the character has to be stored literally.
// Find char in A in the packed char list, and return
// $1 - $E, $F1 - $FD if the charactar is abbreviable,
// 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
find_char_loop:
cmp packed_message_chars,y
bne not_a_match
enumerate:
;; Is it a nybl abbreviable char?
// Is it a nybl abbreviable char?
cpy #14
bcs not_nybl_char
;; Yes, so add 1 and return it
// Yes, so add 1 and return it
iny
tya
rts
@@ -235,9 +236,9 @@ enumerate:
not_nybl_char:
cpy #27
bcs not_a_match
;; It's a $Fx character.
;; Since the lowest index is $E, and it should be encoded as $F1
;; we need to add $E3
// It's a $Fx character.
// Since the lowest index is $E, and it should be encoded as $F1
// we need to add $E3
tya
clc
adc #$E3
@@ -245,10 +246,10 @@ not_nybl_char:
not_a_match:
iny
;; Loop until we find it, or we discover it isn't
;; a character with a special encoding
// Loop until we find it, or we discover it isn't
// a character with a special encoding
cpy #27
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
rts
+4 -4
View File
@@ -1,5 +1,5 @@
;; Return C=1 if a pointer in BASIC memory space is NULL, else C=0
;; X = ZP pointer to check
// Return C=1 if a pointer in BASIC memory space is NULL, else C=0
// X = ZP pointer to check
peek_pointer_null_check:
ldy #$00
@@ -11,10 +11,10 @@ peek_pointer_null_check:
cmp #$00
bne ptr_not_null
;; Pointer is NULL
// Pointer is NULL
clc
rts
ptr_not_null:
sec
rts
+31 -30
View File
@@ -1,26 +1,27 @@
;; Works similar to $BDCD in original C64 BASIC
;; XXX Should eventually get replaced by a more flexible and optimal routine.
;; Temp result gets written to $0100-$0104
// Works similar to $BDCD in original C64 BASIC
// XXX Should eventually get replaced by a more flexible and optimal routine.
// Temp result gets written to $0100-$0104
print_integer:
pha
txa
pha
;; Clear temporary output
// Clear temporary output
lda #$00
ldy #5
* sta $0100,y
!: sta $0100,y
dey
bpl -
bpl !-
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:
cmp #$7f
bcc bit_clear
;; Bit set, so add the digits
// Bit set, so add the digits
pha
ldx #2
clc
@@ -45,16 +46,16 @@ next_lo_bit:
bcc lo_loop
;; Now do the same for upper byte
// Now do the same for upper byte
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:
cmp #$7f
bcc bit_clear_hi
;; Bit set, so add the digits
// Bit set, so add the digits
pha
ldx #4
clc
@@ -67,8 +68,8 @@ hi_add_loop:
dex
bpl hi_add_loop
pla
jmp next_hi_bit
jmp next_hi_bit
bit_clear_hi:
dey
dey
@@ -78,47 +79,47 @@ bit_clear_hi:
next_hi_bit:
asl
cpy #$7f
bcc hi_loop
bcc hi_loop
fix_carry:
;; Deal with any carries
// Deal with any carries
ldx #3
carry_fix_loop:
carry_fix_loop:
lda $0101,x
cmp #10
bcc +
bcc !+
inc $0100,x
sec
sbc #10
sta $0101,x
jmp carry_fix_loop
* dex
!: dex
bpl carry_fix_loop
post_carry:
post_carry:
;; Got digits.
;; Skip leading zeros, and print the resulting number
// Got digits.
// Skip leading zeros, and print the resulting number
;; Skip leading zeros
// Skip leading zeros
ldy #0
* lda $0100,y
!: lda $0100,y
bne found_start_of_number
iny
cpy #4
bne -
bne !-
found_start_of_number:
;; Print digits
* lda $0100,y
found_start_of_number:
// Print digits
!: lda $0100,y
ora #$30
jsr JCHROUT
iny
cpy #5
bne -
bne !-
rts
+67 -66
View File
@@ -1,41 +1,42 @@
;; This routine prints messages that have been packed
;; using the make_error_tables program.
;; The general idea is to save space in the ROM.
// This routine prints messages that have been packed
// using the make_error_tables program.
// 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:
;; X = message number
// .X = message number
lda #$ff
ldy #$ff
packed_message_search:
packed_message_search:
iny
cpx #$00
beq found_message_in_token_stream
lda packed_message_tokens,y
cmp #$ff
bne +
bne !+
dex
*
!:
cpy #$ff
bne packed_message_search
;; Could not find message
// Could not find message
sec
rts
found_message_in_token_stream:
;; Now print each word in the message
// Now print each word in the message
tya
pha
lda packed_message_tokens,y
cmp #$ff
beq +
beq !+
jsr print_packed_word
lda #$20
jsr JCHROUT
@@ -43,50 +44,50 @@ found_message_in_token_stream:
tay
iny
bne found_message_in_token_stream
*
!:
pla
;; Rub out space at the end
// Rub out space at the end
lda #$14
jsr JCHROUT
rts
print_packed_word:
;; A = the word to print
// A = the word to print
tax
;; Setup pointer to packed words
// Setup pointer to packed words
lda #<packed_message_words
sta temp_string_ptr+0
lda #>packed_message_words
sta temp_string_ptr+1
;; Find the word in the list
// Find the word in the list
ldy #$ff
packed_word_search:
iny
cpx #$00
beq found_packed_word
;; $x0 is an end of work marker
// $x0 is an end of work marker
lda (temp_string_ptr),y
and #$0f
cmp #$00
bne +
bne !+
dex
*
;; $FE $xx is an end of work marker
!:
// $FE $xx is an end of work marker
lda (temp_string_ptr),y
cmp #$fe
bne +
bne !+
dex
iny ; skip next byte
*
iny // skip next byte
!:
cmp #$ff
bne +
iny ; skip next byte
*
bne !+
iny // skip next byte
!:
;; Advance to next page if required
// Advance to next page if required
cpy #$ff
bne packed_word_search
inc temp_string_ptr+1
@@ -94,8 +95,8 @@ packed_word_search:
found_packed_word:
;; Get pointer to start of packed word
;; Make sure we don't wrap on a page boundary
// Get pointer to start of packed word
// Make sure we don't wrap on a page boundary
tya
clc
adc temp_string_ptr+0
@@ -104,14 +105,14 @@ found_packed_word:
adc #$00
sta temp_string_ptr+1
print_packed_string:
print_packed_string:
ldy #$ff
next_packed_word_char:
;; Y = offset into packed word data - 1
// .Y = offset into packed word data - 1
iny
;; Check for end of word
// Check for end of word
lda (temp_string_ptr),y
cmp #$00
beq end_of_packed_word
@@ -122,31 +123,31 @@ next_packed_word_char:
and #$f0
beq end_of_packed_word
;; Check if it is an uncommon char
// Check if it is an uncommon char
lda (temp_string_ptr),y
and #$f0
cmp #$f0
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
;; Put high nybl into low bits of X
// Put high nybl into low bits of X
lsr
lsr
lsr
lsr
tax
;; Save Y so it doesn't get clobbered by CHROUT
// Save Y so it doesn't get clobbered by CHROUT
tya
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
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
tay
lda (temp_string_ptr),y
@@ -155,54 +156,54 @@ next_packed_word_char:
cmp #$0f
beq no_lo_nybl_char
has_lo_nybl_char:
;; We need to print the low nybl char as well
has_lo_nybl_char:
// We need to print the low nybl char as well
tax
tya
pha
;; Skip lower nybls of $F or $0 in nybl packed
;; bytes, as these do not encode characters
// Skip lower nybls of $F or $0 in nybl packed
// bytes, as these do not encode characters
cpx #$f
beq +
has_nybl:
beq !+
has_nybl:
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
jsr JCHROUT
*
!:
pla
tay
;; FALL THROUGH
// FALLTHROUGH
no_lo_nybl_char:
;; If current byte has $0F in low nybl, then the next
;; byte is a whole byte.
// If current byte has $0F in low nybl, then the next
// byte is a whole byte.
lda (temp_string_ptr),y
and #$0f
cmp #$0f
beq next_is_literal_char
ready_for_next_char:
ready_for_next_char:
cpy #$ff
bne next_packed_word_char
end_of_packed_word:
;; Hit end of packed data
end_of_packed_word:
// Hit end of packed data
rts
last_literal:
jsr unpack_literal_char
rts
next_is_literal_char:
jsr unpack_literal_char
jmp ready_for_next_char
unpack_literal_char:
;; Output the literal char, and ready for next char
unpack_literal_char:
// Output the literal char, and ready for next char
iny
tya
pha
@@ -211,16 +212,16 @@ unpack_literal_char:
pla
tay
rts
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
and #$0f
clc
adc #14
;; We need to print the low nybl char as well
// We need to print the low nybl char as well
tax
tya
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,
;; which may also include special tokens that allow
;; printing of hex byte and word values stored at the indicated
;; addresses.
// Prints the literal zero-terminated string that follows,
// which may also include special tokens that allow
// printing of hex byte and word values stored at the indicated
// addresses.
;; .byte 1,$byte = display byte as hex
;; .byte 2,$low,$hi = display word as hex
;; .byte $f0+n,$low,$hi = display byte at $hi$lo+n as hex
// .byte 1,$byte = display byte as hex
// .byte 2,$low,$hi = display word as hex
// .byte $f0+n,$low,$hi = display byte at $hi$lo+n as hex
printf:
;; Temporary storage is between end of screen at $0400
;; and the sprite pointers at $7f8
// Temporary storage is between end of screen at $0400
// and the sprite pointers at $7f8
sta $7f0
stx $7f1
sty $7f2
@@ -19,14 +19,14 @@ printf:
pla
sta $7f3
;; Set up read routine
lda #$ad ; LDA $nnnn
// Set up read routine
lda #$ad // LDA $nnnn
sta $7f4
lda #$60
sta $7f7 ; RTS
sta $7f7 // RTS
;; Get PC of caller from the stack, so that
;; we can parse through it
// Get PC of caller from the stack, so that
// we can parse through it
pla
clc
adc #$01
@@ -39,8 +39,8 @@ printf_loop:
jsr $7f4
cmp #$00
bne printf_continues
;; Put return address on stack and restore
;; registers
// Put return address on stack and restore
// registers
lda $7f6
pha
lda $7f5
@@ -56,33 +56,33 @@ printf_loop:
printf_continues:
cmp #$01
bne not_hexbyte
;; Print a hex byte
// Print a hex byte
;; Skip the token
// Skip the token
jsr printf_advance
;; Read the low byte
// Read the low byte
jsr $7f4
;; Print as hex
// Print as hex
jsr printf_printhexbyte
jmp printf_nextchar
not_hexbyte:
cmp #$02
bne not_hexword
;; Print a hex word
// Print a hex word
;; Skip the token
// Skip the token
jsr printf_advance
jsr printf_advance
;; Read the high byte
// Read the high byte
jsr $7f4
;; Print as hex
// Print as hex
jsr printf_printhexbyte
;; Skip the token
// Skip the token
jsr printf_retreat
;; Read the low byte
// Read the low byte
jsr $7f4
;; Print as hex
// Print as hex
jsr printf_printhexbyte
jsr printf_advance
jmp printf_nextchar
@@ -91,11 +91,11 @@ not_hexword:
cmp #$f0
bcc not_pointer
;; Treat two-byte arg as base address
;; and lower 4 bits of token as offset from
;; that location.
// Treat two-byte arg as base address
// and lower 4 bits of token as offset from
// that location.
;; Get offset
// Get offset
and #$0f
tay
@@ -111,7 +111,7 @@ not_hexword:
jmp printf_nextchar
not_pointer:
;; Print character
// Print character
jsr JCHROUT
printf_nextchar:
@@ -120,15 +120,15 @@ printf_nextchar:
jmp printf_loop
printf_advance:
;; Advance pointer to next character
// Advance pointer to next character
inc $7f5
bne +
bne !+
inc $7f6
*
!:
rts
printf_retreat:
;; Retreat pointer to previous char
// Retreat pointer to previous char
lda $7f5
sec
sbc #1
@@ -139,20 +139,19 @@ printf_retreat:
rts
printf_printhexbyte:
// Print the hex value in .A as two digits, idea by Haubitze
sed
pha
lsr
lsr
lsr
lsr
ora #$30
cmp #$3A
bcc +
adc #6
* jsr JCHROUT
cmp #$0A
adc #$30
jsr JCHROUT
pla
and #$0f
ora #$30
cmp #$3A
bcc +
adc #6
* jmp JCHROUT
and #$0F
cmp #$0A
adc #$30
cld
jmp JCHROUT
+2 -2
View File
@@ -1,6 +1,6 @@
ready_message:
;; See src/make_error_tables.c for packed message handling
;; information.
// See src/make_error_tables.c for packed message handling
// information.
ldx #29
jmp print_packed_message
+10 -10
View File
@@ -1,19 +1,19 @@
select_device:
;; 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
;; drivers assigning these numbers to CBM-DOS capable devices - like some
;; IEEE-488 carts.
;;
;; If current device is not a drive, set device to 8 (first drive number)
;; Device number is left in X, for SETFLS Kernal routine
// 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
// drivers assigning these numbers to CBM-DOS capable devices - like some
// IEEE-488 carts.
//
// If current device is not a drive, set device to 8 (first drive number)
// 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
cpx #$08
bcs +
bcs !+
ldx #$08
*
!:
rts
+100 -100
View File
@@ -1,18 +1,18 @@
;; Tokenise a line of BASIC
;; Stored at $0200
;; Length in tokenise_work1
// Tokenise a line of BASIC
// Stored at $0200
// Length in tokenise_work1
tokenise_line:
;; 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
;; 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.
// 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
// 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.
;; $0110 = offset into string
;; $0111 = number of bytes to pack
;; $0112 = offset into tokenised output
;; $0113 = length of raw string
// $0110 = offset into string
// $0111 = number of bytes to pack
// $0112 = offset into tokenised output
// $0113 = length of raw string
lda #$00
sta $0110
@@ -24,56 +24,56 @@ tokenise_line:
tokenise_char:
;; Check if we have reached end of the line?
// Check if we have reached end of the line?
lda $0110
cmp $0113
bne +
bne !+
;; End of line reached
// End of line reached
;; Finished tokenising line
;; Update tokenise_work1 and terminate with null
// Finished tokenising line
// Update tokenise_work1 and terminate with null
ldx $0112
lda #$00
sta $0200,x
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
sta quote_mode_flag
rts
*
;; More to do
!:
// More to do
;; Maximum keyword length
// Maximum keyword length
lda #7
sta $0111
tokenise_char_loop:
;; Pack the word from the start (start = X, raw len = tokenise_work1)
;; Returns packed length in tokenise_work2 and writes the packed
;; word at $0100+
// Pack the word from the start (start = X, raw len = tokenise_work1)
// Returns packed length in tokenise_work2 and writes the packed
// word at $0100+
ldx $0110
lda $0200,x
cmp #$22
bne tk_not_quote
;; Quote
// Quote
lda quote_mode_flag
eor #$ff
sta quote_mode_flag
jmp tk_literal_char
tk_not_quote:
;; Check for literal characters in various ranges
;; (This just speeds the tokeniser up, by avoiding the packed token search
;; for such characters).
// Check for literal characters in various ranges
// (This just speeds the tokeniser up, by avoiding the packed token search
// for such characters).
;; SPACE and punctuation before +,- and *
// SPACE and punctuation before +,- and *
cmp #$2a
bcc tk_literal_char
;; Don't try to tokenise digits
// Don't try to tokenise digits
cmp #$30
bcc tk_might_be_keyword
cmp #$3a
@@ -81,41 +81,41 @@ tk_not_quote:
jmp tk_literal_char
tk_might_be_keyword:
;; Don't tokenise in quote mode
// Don't tokenise in quote mode
lda quote_mode_flag
bne tk_literal_char
;; Pack string
// Pack string
ldx $0110
lda $0111
sta tokenise_work1
;; XXX - We should implement an optimisation where we
;; trim the last symbol of successively, instead of re-packing the word
;; again with one less char each time.
;; XXX - We should limit the word length to the length of interesting chars
;; that are available.
// XXX - We should implement an optimisation where we
// trim the last symbol of successively, instead of re-packing the word
// again with one less char each time.
// XXX - We should limit the word length to the length of interesting chars
// that are available.
jsr pack_word
lda tokenise_work2
cmp #$10
bcc +
;; Packed string too long
bcc !+
// Packed string too long
jmp do_STRING_TOO_LONG_error
*
!:
;; Search for it in keywords
// Search for it in keywords
jsr keyword_search
;; Did we find a keyword?
// Did we find a keyword?
bcc found_token_in_line
;; Nope, so try shorter
// Nope, so try shorter
dec $0111
bne tokenise_char_loop
tk_literal_char:
;; Is not a token, so copy to output verbatim
// Is not a token, so copy to output verbatim
ldx $0110
ldy $0112
lda $0200,x
@@ -123,68 +123,68 @@ tk_literal_char:
inc $0112
inc $0110
;; Tokenise next char
// Tokenise next char
jmp tokenise_char
found_token_in_line:
;; Got a token, so write it out
// Got a token, so write it out
ldx $0112
sta $0200,x
inx
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
bne not_rem
sta quote_mode_flag
not_rem:
;; Now skip over the length of the token
// Now skip over the length of the token
lda $0110
clc
adc $0111
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
;; Search for word in keyword list
;; The packed form is canonical, so we can search for the keyword while
;; it remains compressed. This also saves a little time.
;; Algorithm is simply to find matching first bytes, and then look for
;; the rest being a match.
// Search for word in keyword list
// The packed form is canonical, so we can search for the keyword while
// it remains compressed. This also saves a little time.
// Algorithm is simply to find matching first bytes, and then look for
// the rest being a match.
keyword_search:
;; Search for the compressed keyword stored at $0100 in the list
;; of compressed keywords
;; tokenise_work1 = offset in line of input
;; tokenise_work2 = length of token we are matching
;; tokenise_work3 = offset in token list
;; load_or_verify_or_tokenise_work5 = temporary work space
;; X and Y registers used as temporary space.
;; returns C=1 if no matching token, else C=0 and A=token
// Search for the compressed keyword stored at $0100 in the list
// of compressed keywords
// tokenise_work1 = offset in line of input
// tokenise_work2 = length of token we are matching
// tokenise_work3 = offset in token list
// load_or_verify_or_tokenise_work5 = temporary work space
// X and Y registers used as temporary space.
// returns C=1 if no matching token, else C=0 and A=token
lda #$00
sta tokenise_work1
sta tokenise_work3
next_kw_offset:
;; Advance offset in compressed keyword list, to see if a match
;; BEGINS here
// Advance offset in compressed keyword list, to see if a match
// BEGINS here
;; Get count of bytes to compare
// Get count of bytes to compare
lda tokenise_work2
sta load_or_verify_or_tokenise_work5
;; Load current position
// Load current position
ldy tokenise_work3
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
lda tokenise_work3
cmp #packed_keyword_table_len
@@ -194,76 +194,76 @@ next_in_match:
lda $0100,x
cmp packed_keywords,y
bne next_kw_offset
;; Advance to next chars in source and target
// Advance to next chars in source and target
inx
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
;; Keyword matches!
// Keyword matches!
;; Now make sure we started on a keyword boundary
;; (we know we finished on one, because of the structure of the compressed
;; keyword data).
;; Offset 0
;; previous byte is $x0
;; two byte prior is $FE
// Now make sure we started on a keyword boundary
// (we know we finished on one, because of the structure of the compressed
// keyword data).
// Offset 0
// previous byte is $x0
// two byte prior is $FE
;; Get offset of first byte of this token
// Get offset of first byte of this token
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
beq word_boundary
dex
;; Previous byte is $x0 end token?
// Previous byte is $x0 end token?
lda packed_keywords,x
and #$0f
beq word_boundary
dex
;; Uber-previouss byte is $FE final literal token?
// Uber-previouss byte is $FE final literal token?
lda packed_keywords,x
cmp #$fe
beq word_boundary
;; Not a word boundary, so ignore
// Not a word boundary, so ignore
jmp next_kw_offset
word_boundary:
;; Found a token whose offset is in tokenise_work3
;; Now trace back to the start of the compressed keyword list
;; to work out what keyword number we are, so that we can return
;; the token number.
// Found a token whose offset is in tokenise_work3
// Now trace back to the start of the compressed keyword list
// to work out what keyword number we are, so that we can return
// the token number.
ldy #$80
token_count_loop:
lda packed_keywords,x
cmp #$fe
bne +
bne !+
iny
*
!:
and #$0f
cmp #$00
bne +
bne !+
iny
*
!:
cpx #$00
beq +
beq !+
dex
jmp token_count_loop
*
!:
tya
clc
rts
done_searching_for_token:
;; No token found
// No token found
sec
lda #$00
rts
+26 -29
View File
@@ -1,19 +1,19 @@
;; IMPORTANT:
;; These routines lengths cannot be changed without changing
;; the aliases for peek_under_roms, poke_under_roms etc
;; in ,aliases.s.
;; Thus those addresses are expressed using formulae.
// IMPORTANT:
// These routines lengths cannot be changed without changing
// the aliases for peek_under_roms, poke_under_roms etc
// in ,aliases.s.
// Thus those addresses are expressed using formulae.
install_ram_routines:
;; Copy routines into place
ldx #ram_routines_len-1
*
// Copy routines into place
ldx #ram_routines_end-ram_routines_start-1
!:
lda ram_routines_start,x
sta tiny_nmi_handler,x
dex
bpl -
bpl !-
;; Point NMI handler to tiny_nmi_handler
// Point NMI handler to tiny_nmi_handler
lda #<tiny_nmi_handler
sta $FFFE
lda #>tiny_nmi_handler
@@ -23,14 +23,14 @@ install_ram_routines:
ram_routines_start:
;; XXX - Routine order must match that of the KERNAL version of the file.
;; (since it has fewer routines)
// XXX - Routine order must match that of the KERNAL version of the file.
// (since it has fewer routines)
tiny_nmi_handler_routine:
inc missed_nmi_flag
rti
peek_under_roms_routine:
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
jsr memmap_allram
pa: lda ($00),y
@@ -40,7 +40,7 @@ pa: lda ($00),y
poke_under_roms_routine:
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
jsr memmap_allram
pb: sta ($00),y
@@ -64,12 +64,12 @@ memmap_allram_routine:
rts
shift_mem_up_routine:
;; Move memmove_size bytes from memmove_src to memmove_dst,
;; where memmove_dst > memmove_src
;; This means we have to copy from the back end down.
;; This routine assumes the pointers are already pointed
;; to the end of the areas, and that Y is correctly initialised
;; to allow the copy to begin.
// Move memmove_size bytes from memmove_src to memmove_dst,
// where memmove_dst > memmove_src
// This means we have to copy from the back end down.
// This routine assumes the pointers are already pointed
// to the end of the areas, and that Y is correctly initialised
// to allow the copy to begin.
php
jsr memmap_allram
smu1:
@@ -85,12 +85,12 @@ smu1:
jmp memmap_normal
shift_mem_down_routine:
;; Move memmove_size bytes from memmove_src to memmove_dst,
;; where memmove_dst > memmove_src
;; This means we have to copy from the back end down.
;; This routine assumes the pointers are already pointed
;; to the end of the areas, and that Y is correctly initialised
;; to allow the copy to begin.
// Move memmove_size bytes from memmove_src to memmove_dst,
// where memmove_dst > memmove_src
// This means we have to copy from the back end down.
// This routine assumes the pointers are already pointed
// to the end of the areas, and that Y is correctly initialised
// to allow the copy to begin.
php
jsr memmap_allram
smd1:
@@ -105,7 +105,4 @@ smd1:
plp
jmp memmap_normal
ram_routines_end:
.alias ram_routines_len ram_routines_end-ram_routines_start
+89 -89
View File
@@ -1,161 +1,161 @@
;; START wedge support
// START wedge support
wedge_dos:
;; Close all the channels, so that wedge has full control
// Close all the channels, so that wedge has full control
jsr JCLALL
;; Set file parameters, channel 15 is a typical one for commands
jsr select_device ; sets X register
// Set file parameters, channel 15 is a typical one for commands
jsr select_device // sets .X register
lda #$0F
ldy #$0F
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
lda (basic_current_statement_ptr), y
bne +
jmp wedge_dos_status ; XXX try to optimize this, perhaps move 'wedge_dos_status' above?
*
;; Check if asked for a directory
bne !+
jmp wedge_dos_status // XXX try to optimize this, perhaps move 'wedge_dos_status' above?
!:
// Check if asked for a directory
cmp #$24
bne +
bne !+
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
bcc wedge_dos_command ; char code before 0
bcc wedge_dos_command // char code before 0
cmp #$3A
bcs wedge_dos_command ; char code after 9
bcs wedge_dos_command // char code after 9
iny
lda (basic_current_statement_ptr), y
beq wedge_dos_change_drive ; end of buffer
beq wedge_dos_change_drive // end of buffer
cmp #$20
beq wedge_dos_change_drive
jmp -
jmp !-
wedge_dos_command:
;; Provide command name
// Provide command name
jsr wedge_dos_setnam
jsr JSETNAM
jsr JOPEN
bcc +
jmp wedge_dos_basic_error ; XXX combine with other such jumps
*
;; Retrieve status, print it if not OK
bcc !+
jmp wedge_dos_basic_error // XXX combine with other such jumps
!:
// Retrieve status, print it if not OK
jsr JCLALL
jsr wedge_dos_status_get
lda BUF+0
cmp #$30 ; '0'
cmp #$30 // '0'
bne wedge_dos_status_print
lda BUF+1
cmp #$30 ; '0'
cmp #$30 // '0'
bne wedge_dos_status_print
;; Clean-up and exit
// Clean-up and exit
jmp wedge_dos_clean_exit
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
lda basic_line_number+1
beq +
beq !+
jmp do_ILLEGAL_QUANTITY_error
*
!:
lda basic_line_number+0
cmp #$08
bpl +
bcs +
bpl !+
bcs !+
jmp do_ILLEGAL_DEVICE_NUMBER_error
*
!:
sta current_device_number
jmp basic_end_of_line
wedge_dos_status_get:
;; 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
// 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
;; Set remaining file parameters, open the channel
lda #$00 ; empty file name
// Set remaining file parameters, open the channel
lda #$00 // empty file name
jsr JSETNAM
jsr JOPEN
bcc +
jmp wedge_dos_basic_error ; XXX combine with other such jumps
*
bcc !+
jmp wedge_dos_basic_error // XXX combine with other such jumps
!:
;; Set channel for input
// Set channel for input
ldx #$0F
jsr JCHKIN
bcc +
jmp wedge_dos_basic_error ; XXX combine with other such jumps
*
bcc !+
jmp wedge_dos_basic_error // XXX combine with other such jumps
!:
ldy #$00
*
cpy #$50 ; buffer overflow protection
beq +
jsr JREADST ; retrieve errors
;; XXX error in case of status != EOF
;; Print out everything retrieved from the drive
bne +
!:
cpy #$50 // buffer overflow protection
beq !+
jsr JREADST // retrieve errors
// XXX error in case of status != EOF
// Print out everything retrieved from the drive
bne !+
jsr JCHRIN
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:
sta BUF, y
iny
jmp -
*
jmp !-
!:
rts
wedge_dos_status:
jsr wedge_dos_status_get
;; FALLTROUGH
// FALLTROUGH
wedge_dos_status_print:
;; Print buffered status
// Print buffered status
ldx #$00
*
!:
dey
bmi +
bmi !+
lda BUF, x
jsr JCHROUT
inx
bne -
*
;; Clean-up and exit
bne !-
!:
// Clean-up and exit
jmp wedge_dos_clean_exit
wedge_dos_directory:
;; First change the secondary address to the one suitable for
;; directory loading
lda #$00 ; logical device number
// First change the secondary address to the one suitable for
// directory loading
lda #$00 // logical device number
ldx current_device_number
ldy #$60
jsr JSETFLS
;; Provide file name
// Provide file name
jsr wedge_dos_setnam
;; Open the file
// Open the file
jsr JOPEN
bcs wedge_dos_basic_error
;; Set channel for file reading
// Set channel for file reading
ldx #$00
jsr JCHKIN
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
bcs wedge_dos_basic_error
jsr JCHRIN
@@ -163,37 +163,37 @@ wedge_dos_directory:
wedge_dos_directory_line:
;; Load a single line, reuse BASIC input buffer
// Load a single line, reuse BASIC input buffer
ldy #$FF
*
!:
iny
jsr JCHRIN
bcs wedge_dos_basic_error
sta BUF, y
cpy #$50
beq + ; line too long, terminate loading file
beq !+ // line too long, terminate loading file
jsr JREADST
bne + ; end of file
cpy #$04 ; 2 bytes (pointer to next line) + 2 bytes (line number)
bcc -
bne !+ // end of file
cpy #$04 // 2 bytes (pointer to next line) + 2 bytes (line number)
bcc !-
lda BUF, y
bne -
;; End of line, but not end of file
bne !-
// End of line, but not end of file
beq wedge_dos_directory_display
*
!:
lda #K_STS_END_OF_FILE
sta IOSTATUS ; make sure end of file is marked
;; FALLTROUGH
sta IOSTATUS // make sure end of file is marked
// FALLTROUGH
wedge_dos_directory_display:
cpy #$05 ; protection against malformed directory
cpy #$05 // protection against malformed directory
bcc wedge_dos_clean_exit
lda #$00 ; extra protection agains buffer overflow
lda #$00 // extra protection agains buffer overflow
sta BUF, y
;; Display line
// Display line
ldx #<BUF
stx basic_current_line_ptr+0
ldx #>BUF
@@ -201,14 +201,14 @@ wedge_dos_directory_display:
ldx #basic_current_line_ptr
jsr list_single_line
;; Read & display next line or quit
// Read & display next line or quit
lda IOSTATUS
beq wedge_dos_directory_line
;; FALLTROUGH
// FALLTROUGH
wedge_dos_clean_exit:
jsr JCLALL
;; Print new line
// Print new line
lda #$0D
jsr JCHROUT
jmp basic_end_of_line
@@ -222,17 +222,17 @@ wedge_dos_basic_error:
jmp do_basic_error
wedge_dos_setnam:
;; Now determine the length of the 'file' name
// Now determine the length of the 'file' name
ldy #$FF
*
!:
iny
lda (basic_current_statement_ptr), y
bne -
bne !-
;; Set the name to open
// Set the name to open
tya
ldx basic_current_statement_ptr+0
ldy basic_current_statement_ptr+1
jmp JSETNAM
;; END wedge support
// END wedge support
+68 -68
View File
@@ -1,73 +1,73 @@
; Names of ZP and low memory locations
; (Only those of relevance for the KERNAL)
; (And only those for now that we feel the need to implement initially)
; (https://www.c64-wiki.com/wiki/Zeropage)
// Names of ZP and low memory locations
// (Only those of relevance for the KERNAL)
// (And only those for now that we feel the need to implement initially)
// (https://www.c64-wiki.com/wiki/Zeropage)
.alias kernal_load_or_verify_flag $93
.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
// XXX get rid of this file, use ,aliases_ram_lowmem.s instead
.label kernal_load_or_verify_flag = $93
.label current_file_num = $98
.label input_device_number = DFLTN
.label cassette_buffer_bytes_used = $A6
.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
; "Compute's Mapping the 64" book
.alias keyboard_buffer $0277
.alias text_colour $0286 ; p55
.alias colour_under_cursor $0287 ; p56
.alias key_buffer_size $0289 ; p57
// "Compute's Mapping the 64" book
.label keyboard_buffer = $0277
.label text_colour = $0286 // p55
.label colour_under_cursor = $0287 // p56
.label key_buffer_size = $0289 // p57
;; 0 = cursor keys, insert, delete and space repeat, but nothing else
;; 128 = all keys repeat
;; 64 = no keys repeat
.alias key_repeat_flags $028A ; p58
;; https://www.c64-wiki.com/wiki/Page_2
.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
// 0 = cursor keys, insert, delete and space repeat, but nothing else
// 128 = all keys repeat
// 64 = no keys repeat
.label key_repeat_flags = $028A // p58
// https://www.c64-wiki.com/wiki/Page_2
.label key_repeat_counter = $028B
.label key_first_repeat_delay = $028C
// 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)
.alias missed_nmi_flag $2A7
.alias tiny_nmi_handler $2A8
.alias peek_under_roms tiny_nmi_handler+peek_under_roms_routine-tiny_nmi_handler_routine
.alias poke_under_roms tiny_nmi_handler+poke_under_roms_routine-tiny_nmi_handler_routine
.alias memmap_allram tiny_nmi_handler+memmap_allram_routine-tiny_nmi_handler_routine
.alias memmap_normal tiny_nmi_handler+memmap_normal_routine-tiny_nmi_handler_routine
// 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
.macend
.macro TARGET_HOOK_LOAD() {
}
+3 -3
View File
@@ -1,6 +1,6 @@
;; Target-specific hooks
// Target-specific hooks
.macro TARGET_HOOK_LOAD
.macend
.macro TARGET_HOOK_LOAD() {
}
@@ -1,57 +1,57 @@
;; Registers according to Ultimate 64 Command Interface description,
;; 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
// Registers according to Ultimate 64 Command Interface description,
// 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
;; Command interface registers
.alias U64_CONTROL $DF1C ; write
.alias U64_STATUS $DF1C ; read
.alias U64_COMMAND_DATA $DF1D ; write
.alias U64_IDENTIFICATION $DF1D ; read
.alias U64_RESPONSE_DATA $DF1E ; read only
.alias U64_STATUS_DATA $DF1F ; read only
// Command interface registers
.label U64_CONTROL = $DF1C // write
.label U64_STATUS = $DF1C // read
.label U64_COMMAND_DATA = $DF1D // write
.label U64_IDENTIFICATION = $DF1D // read
.label U64_RESPONSE_DATA = $DF1E // read only
.label U64_STATUS_DATA = $DF1F // read only
;; Constant for U64_IDENTIFICATION register
.alias U64_MAGIC_ID $C9
// Constant for U64_IDENTIFICATION register
.const U64_MAGIC_ID = $C9
;; Constants for U64_CONTROL register
.alias U64_CTRL_BIT_PUSH_CMD $01
.alias U64_CTRL_BIT_DATA_ACC $02
.alias U64_CTRL_BIT_ABORT $04
.alias U64_CTRL_BIT_CLR_ERR $08
// Constants for U64_CONTROL register
.const U64_CTRL_BIT_PUSH_CMD = $01
.const U64_CTRL_BIT_DATA_ACC = $02
.const U64_CTRL_BIT_ABORT = $04
.const U64_CTRL_BIT_CLR_ERR = $08
;; Constants for U64_STATUS register
.alias U64_STAT_BIT_CMD_BUSY $01
.alias U64_STAT_BIT_DATA_ACC $02
.alias U64_STAT_BIT_ABORT_P $04
.alias U64_STAT_BIT_ERROR $08
.alias U64_STAT_MASK_STATE $30 ; two bits!
.alias U64_STAT_BIT_STAT_AV $40
.alias U64_STAT_BIT_DATA_AV $80
// Constants for U64_STATUS register
.const U64_STAT_BIT_CMD_BUSY = $01
.const U64_STAT_BIT_DATA_ACC = $02
.const U64_STAT_BIT_ABORT_P = $04
.const U64_STAT_BIT_ERROR = $08
.const U64_STAT_MASK_STATE = $30 // two bits!
.const U64_STAT_BIT_STAT_AV = $40
.const U64_STAT_BIT_DATA_AV = $80
;; Interface targets
.alias U64_TARGET_DOS1 $01
.alias U64_TARGET_DOS2 $02
// Interface targets
.const U64_TARGET_DOS1 = $01
.const U64_TARGET_DOS2 = $02
;; DOS command codes
.alias U64_DOS_CMD_IDENTIFY $01
.alias U64_DOS_CMD_OPEN_FILE $02
.alias U64_DOS_CMD_CLOSE_FILE $03
.alias U64_DOS_CMD_READ_DATA $04
.alias U64_DOS_CMD_WRITE_DATA $05
.alias U64_DOS_CMD_FILE_SEEK $06
.alias U64_DOS_CMD_FILE_INFO $07
.alias U64_DOS_CMD_CHANGE_DIR $11
.alias U64_DOS_CMD_GET_PATH $12
.alias U64_DOS_CMD_OPEN_DIR $13
.alias U64_DOS_CMD_READ_DIR $14
.alias U64_DOS_CMD_COPY_UI_PATH $15
.alias U64_DOS_CMD_LOAD_REU $21
.alias U64_DOS_CMD_SAVE_REU $22
.alias U64_DOS_CMD_ECHO $F0
// DOS command codes
.const U64_DOS_CMD_IDENTIFY = $01
.const U64_DOS_CMD_OPEN_FILE = $02
.const U64_DOS_CMD_CLOSE_FILE = $03
.const U64_DOS_CMD_READ_DATA = $04
.const U64_DOS_CMD_WRITE_DATA = $05
.const U64_DOS_CMD_FILE_SEEK = $06
.const U64_DOS_CMD_FILE_INFO = $07
.const U64_DOS_CMD_CHANGE_DIR = $11
.const U64_DOS_CMD_GET_PATH = $12
.const U64_DOS_CMD_OPEN_DIR = $13
.const U64_DOS_CMD_READ_DIR = $14
.const U64_DOS_CMD_COPY_UI_PATH = $15
.const U64_DOS_CMD_LOAD_REU = $21
.const U64_DOS_CMD_SAVE_REU = $22
.const U64_DOS_CMD_ECHO = $F0
;; DOS file opening constants
.alias U64_FA_READ $01
.alias U64_FA_WRITE $02
.alias U64_FA_CREATE_NEW $03
.alias U64_FA_CREATE_ALWAYS $04
// DOS file opening constants
.const U64_FA_READ = $01
.const U64_FA_WRITE = $02
.const U64_FA_CREATE_NEW = $03
.const U64_FA_CREATE_ALWAYS = $04
@@ -1,9 +1,9 @@
;; Target-specific hooks
// Target-specific hooks
.macro TARGET_HOOK_LOAD
;; XXX disabled for now - the current file opening API is not
;; really suitable for easy usage from Kernal
;; jsr u64_load
.macend
.macro TARGET_HOOK_LOAD() {
// XXX disabled for now - the current file opening API is not
// really suitable for easy usage from Kernal
// jsr u64_load
}
@@ -1,52 +1,53 @@
;;
;; LOAD routine hook for fast loading via UltiDOS
;;
//
// LOAD routine hook for fast loading via UltiDOS
//
u64_load:
;; First check whether the command interface is enabled
// First check whether the command interface is enabled
lda U64_IDENTIFICATION
cmp #U64_MAGIC_ID
beq +
beq !+
u64_load_skip:
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
cmp #$20 ; for now use device number 32
cmp #$20 // for now use device number 32
bne u64_load_skip
;; Takeover the flow completely
// Takeover the flow completely
pla
pla
;; Display SEARCHING FOR + filename
// Display SEARCHING FOR + filename
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
;; Send a command to open the file
// Send a command to open the file
lda #U64_DOS_CMD_OPEN_FILE
jsr u64_load_send_cmd
lda #U64_FA_READ
jsr u64_load_send_cmd
jsr u64_load_send_filename
jsr u64_load_finalize_cmd
;; Check status
// Check status
jsr u64_load_check_status
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
.byte "DBG: NOT IMPLEMENTED",$0D,0
.text "DBG: NOT IMPLEMENTED"
.byte $0D,0
jmp lvs_wrap_around_error
rts
@@ -54,77 +55,77 @@ u64_load_skip:
u64_load_abort:
lda #U64_CTRL_BIT_ABORT
sta U64_CONTROL
*
!:
lda U64_STATUS
bne -
bne !-
rts
u64_load_send_cmd:
ldx #U64_TARGET_DOS2
stx U64_COMMAND_DATA ; target
sta U64_COMMAND_DATA ; command code
stx U64_COMMAND_DATA // target
sta U64_COMMAND_DATA // command code
rts
u64_load_send_filename:
ldy #0
u64_load_send_filename_loop:
cpy FNLEN
bne+
bne !+
rts
*
!:
ldx #<current_filename_ptr
jsr peek_under_roms
iny
sta U64_COMMAND_DATA
jmp u64_load_send_filename_loop
u64_load_finalize_cmd:
;; Push the command for execution
// Push the command for execution
lda #U64_CTRL_BIT_PUSH_CMD
sta U64_CONTROL
;; Wait till it is complete
*
// Wait till it is complete
!:
lda U64_STATUS
and #U64_STAT_BIT_CMD_BUSY
bne -
bne !-
rts
u64_load_check_status:
;; Wait till status is available
// Wait till status is available
lda U64_STATUS
and #U64_STAT_BIT_STAT_AV
beq u64_load_check_status
;; Status is ready - check the first character
// Status is ready - check the first character
lda U64_STATUS_DATA
jsr JCHROUT ; XXX for test only
cmp #$30 ; '0'
jsr JCHROUT // XXX for test only
cmp #$30 // '0'
bne u64_load_check_status_wrong
;; Check the second status character
// Check the second status character
lda U64_STATUS
and #U64_STAT_BIT_STAT_AV
beq u64_load_check_status_ok
lda U64_STATUS_DATA
jsr JCHROUT ; XXX for test only
cmp #$30 ; '0'
jsr JCHROUT // XXX for test only
cmp #$30 // '0'
beq u64_load_check_status_ok
;; FALLTROUGH
// FALLTROUGH
u64_load_check_status_wrong:
sec
bcs +
bcs !+
u64_load_check_status_ok:
clc
*
;; Now empty the status queue
!:
// Now empty the status queue
lda U64_STATUS
and #U64_STAT_BIT_STAT_AV
beq +
beq !+
lda U64_STATUS_DATA
jsr JCHROUT ; XXX for test only
jmp -
*
jsr JCHROUT // XXX for test only
jmp !-
!:
rts
+9 -10
View File
@@ -1,15 +1,14 @@
;;
;; Official Kernal routine, described in:
;;
;; - [RG64] C64 Programmer's Reference Guide - page 274
;; - [CM64] Compute's Mapping the Commodore 64 - page 224/225
;;
;; CPU registers that has to be preserved (see [RG64]): .Y
;;
//
// Official Kernal routine, described in:
//
// - [RG64] C64 Programmer's Reference Guide - page 274
// - [CM64] Compute's Mapping the Commodore 64 - page 224/225
//
// CPU registers that has to be preserved (see [RG64]): .Y
//
acptr:
ACPTR:
jsr kernalstatus_reset
jmp iec_rx_byte
+20 -20
View File
@@ -1,41 +1,41 @@
;; We have the following variables:
;; cursor_blink_disable
;; cursor_blink_countdown
;; cursor_saved_character
;; cursor_is_visible
;; colour_under_cursor
// We have the following variables:
// cursor_blink_disable
// cursor_blink_countdown
// cursor_saved_character
// cursor_is_visible
// colour_under_cursor
show_cursor_if_enabled:
lda cursor_blink_disable
beq +
beq !+
rts
* lda cursor_is_visible
!: lda cursor_is_visible
beq show_cursor
rts
show_cursor:
;; Set cursor as though it had just finished the off phase,
;; so that the call to blink_cursor paints it
// Set cursor as though it had just finished the off phase,
// so that the call to blink_cursor paints it
lda #$00
sta cursor_blink_countdown
sta cursor_is_visible
jsr blink_cursor
;; Then set the timeout to 1 frame, so that the cursor
;; blinks under key repeat conditions, like on the original KERNAL
// Then set the timeout to 1 frame, so that the cursor
// blinks under key repeat conditions, like on the original KERNAL
lda #$01
sta cursor_blink_countdown
rts
blink_cursor:
;; Is the cursor enabled?
// Is the cursor enabled?
lda cursor_blink_disable
bne no_blink_cursor
;; Do we need to redraw things?
// Do we need to redraw things?
dec cursor_blink_countdown
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
bne undraw_cursor
draw_cursor:
@@ -46,7 +46,7 @@ draw_cursor:
sta cursor_saved_character
eor #$80
sta (current_screen_line_ptr),y
;; Also set cursor colour
// Also set cursor colour
lda (current_screen_line_colour_ptr),y
sta colour_under_cursor
lda text_colour
@@ -68,10 +68,10 @@ undraw_cursor:
lda #0
sta cursor_is_visible
;; Fall through
// Fall through
reset_blink_timer:
;; Rest blink counter
;; (Compute's Mapping the 64, p39-40)
// Rest blink counter
// (Compute's Mapping the 64, p39-40)
lda #20
sta cursor_blink_countdown
no_blink_cursor:
@@ -80,7 +80,7 @@ no_blink_cursor:
disable_cursor:
lda #$80
sta cursor_blink_disable
;; FALL THROUGH
// FALL THROUGH
hide_cursor_if_visible:
lda cursor_is_visible
bne undraw_cursor
+1 -1
View File
@@ -1,4 +1,4 @@
; c64 prg p263
// c64 prg p263
cartridge_check:
ldx #$04
+37 -37
View File
@@ -1,64 +1,64 @@
;;
;; Official Kernal routines, described in:
;;
;; - [RG64] C64 Programmer's Reference Guide - page 275 (CHKIN) / 276 (CKOUT)
;; - [CM64] Compute's Mapping the Commodore 64 - page 229
;;
;; CPU registers that has to be preserved (see [RG64]): .Y
;;
//
// Official Kernal routines, described in:
//
// - [RG64] C64 Programmer's Reference Guide - page 275 (CHKIN) / 276 (CKOUT)
// - [CM64] Compute's Mapping the Commodore 64 - page 229
//
// CPU registers that has to be preserved (see [RG64]): .Y
//
;; CHKIN implementation
// CHKIN implementation
chkin_real:
;; Store Y for preservation
// Store Y for preservation
tya
pha
;; Reset status
// Reset status
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
jsr find_fls
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
cmp #$01
beq chkinout_device_not_present ; tape not implemented
beq chkinout_device_not_present // tape not implemented
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
cmp #$01
beq chkinout_file_not_input
;; For IEC devices, send TALK + TKSA first
// For IEC devices, send TALK + TKSA first
lda FAT,Y
jsr iec_check_devnum
bcs chkin_set_device
jsr talk
bcs chkinout_device_not_present ; don't set DFLTN in case of failure
jsr TALK
bcs chkinout_device_not_present // don't set DFLTN in case of failure
lda LAT, Y
jsr tksa
jsr TKSA
bcs chkinout_device_not_present
chkin_set_device:
lda FAT,Y
sta DFLTN
clc ; for success
;; FALLTROUGH
clc // for success
// FALLTROUGH
;; Common part for booth CHKIN and CKOUT
// Common part for booth CHKIN and CKOUT
chkinout_end:
tax
@@ -88,54 +88,54 @@ chkinout_file_not_output:
tay
jmp kernalerror_FILE_NOT_OUTPUT
;; CKOUT implementation
// CKOUT implementation
ckout_real:
;; Store Y for preservation
// Store Y for preservation
tya
pha
;; Reset status
// Reset status
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
jsr find_fls
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
cmp #$01
beq chkinout_device_not_present ; tape not implemented
beq chkinout_device_not_present // tape not implemented
cmp #$02
beq chkinout_device_not_present ; RS-232 not implemented
beq chkinout_device_not_present // RS-232 not implemented
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
beq chkinout_file_not_output
;; For IEC devices, send LISTEN + SECOND first
// For IEC devices, send LISTEN + SECOND first
lda FAT,Y
jsr iec_check_devnum
bcs chkout_set_device
jsr listen
bcs chkinout_device_not_present ; don't set DFLTO in case of failure
jsr LISTEN
bcs chkinout_device_not_present // don't set DFLTO in case of failure
lda LAT, Y
jsr second
jsr SECOND
bcs chkinout_device_not_present
chkout_set_device:
lda FAT,Y
sta DFLTO
clc ; for success
clc // for success
jmp chkinout_end
+60 -60
View File
@@ -1,67 +1,67 @@
;;
;; Official Kernal routine, described in:
;;
;; - [RG64] C64 Programmer's Reference Guide - page 277/278
;; - [CM64] Compute's Mapping the Commodore 64 - page 228
;;
;; CPU registers that has to be preserved (see [RG64]): .Y
;;
//
// Official Kernal routine, described in:
//
// - [RG64] C64 Programmer's Reference Guide - page 277/278
// - [CM64] Compute's Mapping the Commodore 64 - page 228
//
// 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.
;; 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.
// Reads a byte of input, unless from keyboard.
// 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.
chrin_real:
;; Determine the device number
// Determine the device number
lda DFLTN
beq chrin_keyboard ; #$00 - keyboard
;; XXX add screen support
beq chrin_keyboard // #$00 - keyboard
// XXX add screen support
jsr iec_check_devnum
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:
jsr JACPTR
bcs chrin_done_fail
;; FALLTROUGH
// FALLTROUGH
chrin_done:
clc ; indicate success
clc // indicate success
rts
chrin_done_fail:
sec ; indicate failure
sec // indicate failure
rts
chrin_keyboard:
;; Save X
// Save X
txa
pha
chrin_repeat:
;; 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.
// 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.
;; Do we have a line of input waiting?
// Do we have a line of input waiting?
lda keyboard_input_ready
beq read_from_keyboard
;; 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
;; and clear the flag
// 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
// and clear the flag
cmp end_of_input_line
bne not_end_of_input
;; Return carriage return and clear pending input flag
// Return carriage return and clear pending input flag
lda #$00
sta keyboard_input_ready
pla
@@ -71,7 +71,7 @@ chrin_repeat:
rts
not_end_of_input:
;; Return next byte of waiting input and advance index
// Return next byte of waiting input and advance index
tay
pla
tax
@@ -80,13 +80,13 @@ not_end_of_input:
inc keyboard_input_ready
clc
rts
read_from_keyboard:
read_from_keyboard:
jsr enable_cursor
;; Wait for a key
// Wait for a key
lda keys_in_key_buffer
beq chrin_repeat
@@ -100,31 +100,31 @@ read_from_keyboard:
jsr hide_cursor_if_visible
;; It was enter.
;; Note that we have a line of input to return, and return the first byte thereof
;; after computing and storing its length.
;; (Compute's Mapping the 64, p96)
// It was enter.
// Note that we have a line of input to return, and return the first byte thereof
// after computing and storing its length.
// (Compute's Mapping the 64, p96)
;; Set pointer to line of input
// Set pointer to line of input
lda current_screen_line_ptr+0
sta start_of_keyboard_input+0
lda current_screen_line_ptr+1
sta start_of_keyboard_input+1
;; Calculate length
// Calculate length
jsr get_current_line_logical_length
tay
iny
* dey
!: dey
bmi empty_line
lda (current_screen_line_ptr),y
cmp #$20
beq -
beq !-
iny
sty end_of_input_line
lda #$01
sta keyboard_input_ready
;; Return first char of line
// Return first char of line
ldy #$00
pla
tax
@@ -134,43 +134,43 @@ read_from_keyboard:
rts
empty_line:
;; For an empty line, just return the carriage return
;; (and don't forget to actually print the carriage return, so that
;; the cursor advances and screen scrolls as required)
// For an empty line, just return the carriage return
// (and don't forget to actually print the carriage return, so that
// the cursor advances and screen scrolls as required)
pla
tax
clc
lda #$0d
rts
not_enter:
;; Print character
not_enter:
// Print character
lda keyboard_buffer
jsr chrout
jsr CHROUT
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
pop_keyboard_buffer:
;; Pop key out of keyboard buffer
;; Disable interrupts while reading from keyboard buffer
;; so that no race conditions can occur
pop_keyboard_buffer:
// Pop key out of keyboard buffer
// Disable interrupts while reading from keyboard buffer
// so that no race conditions can occur
sei
ldx #$00
ldy #$01
* lda keyboard_buffer,y
!: lda keyboard_buffer,y
sta keyboard_buffer,x
inx
iny
cpy key_buffer_size
bne -
bne !-
dec keys_in_key_buffer
cli
rts
screen_code_to_petscii:
cmp #$1b
bcs not_alpha
@@ -185,7 +185,7 @@ not_alpha:
rts
not_punctuation:
not_punctuation:
cmp #$5b
bcs not_shifted
@@ -193,18 +193,18 @@ not_punctuation:
adc #$80
rts
not_shifted:
not_shifted:
cmp #$80
bcs not_vendor
;; $60-$7F -> $A0-$BF
// $60-$7F -> $A0-$BF
clc
adc #$40
;; FALLTROUGH
// FALLTROUGH
not_vendor:
rts
+253 -253
View File
File diff suppressed because it is too large. Load diff
+41 -41
View File
@@ -1,24 +1,24 @@
;;
;; Official Kernal routine, described in:
;;
;; - [RG64] C64 Programmer's Reference Guide - page 280
;; - [CM64] Compute's Mapping the Commodore 64 - page 242
;;
;; CPU registers that has to be preserved (see [RG64]): none
;;
//
// Official Kernal routine, described in:
//
// - [RG64] C64 Programmer's Reference Guide - page 280
// - [CM64] Compute's Mapping the Commodore 64 - page 242
//
// CPU registers that has to be preserved (see [RG64]): none
//
cint_real:
;; 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
;; to address 678 on a real C64, press STOP+RESTORE, the value won't change
// 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
// 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
;; see here: https://codebase64.org/doku.php?id=base:detect_pal_ntsc
// 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
lda #$C8 ; preparation, as the VIC might be uninitialized
lda #$C8 // preparation, as the VIC might be uninitialized
sta VIC_SCROLX
cint_w0:
@@ -28,18 +28,18 @@ cint_w1:
beq cint_w1
bmi cint_w0
;; Result in A, if no interrupt happened during the test:
;; #$37 -> 312 rasterlines, PAL, VIC 6569
;; #$06 -> 263 rasterlines, NTSC, VIC 6567R8
;; #$05 -> 262 rasterlines, NTSC, VIC 6567R56A
// Result in A, if no interrupt happened during the test:
// #$37 -> 312 rasterlines, PAL, VIC 6569
// #$06 -> 263 rasterlines, NTSC, VIC 6567R8
// #$05 -> 262 rasterlines, NTSC, VIC 6567R56A
cmp #$07
bcs cint_pal
cint_ntsc:
;; 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
// 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
ldy #<17045
ldx #>17045
@@ -48,51 +48,51 @@ cint_ntsc:
stx CIA1_TIMAHI
lda #$00
beq +
beq !+
cint_pal:
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
;; Initialise cursor blink flags (Compute's Mapping the 64 p215)
// Initialise cursor blink flags (Compute's Mapping the 64 p215)
lda #$00
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
lda #$ff
// Set initial variables for our improved keyboard scan routine
lda #$FF
ldx #6
* sta BufferOld,x
!: sta BufferOld,x
dex
bpl -
bpl !-
sta BufferQuantity
;; Set key repeat delay (Compute's Mapping the 64 p215)
;; Making some numbers up here: Repeat every ~1/10th sec
;; But require key to be held for ~1/3sec before
;; repeating (Compute's Mapping the 64 p58)
ldx #22-2 ; Fudge factor to match speed
// Set key repeat delay (Compute's Mapping the 64 p215)
// Making some numbers up here: Repeat every ~1/10th sec
// But require key to be held for ~1/3sec before
// repeating (Compute's Mapping the 64 p58)
ldx #22-2 // Fudge factor to match speed
stx key_first_repeat_delay
;; Set current colour for text (Compute's Mapping the 64 p215)
ldx #$01 ; default is light blue ($0E), but we use a different one
// Set current colour for text (Compute's Mapping the 64 p215)
ldx #$01 // default is light blue ($0E), but we use a different one
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
stx key_buffer_size
;; Put non-zero value in enable_case_switch
// Put non-zero value in 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
;; 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
+14 -14
View File
@@ -1,37 +1,37 @@
;;
;; Official Kernal routine, described in:
;;
;; - [RG64] C64 Programmer's Reference Guide - page 279/280
;; - [CM64] Compute's Mapping the Commodore 64 - page 224
;;
;; CPU registers that has to be preserved (see [RG64]): .X, .Y
;;
//
// Official Kernal routine, described in:
//
// - [RG64] C64 Programmer's Reference Guide - page 279/280
// - [CM64] Compute's Mapping the Commodore 64 - page 224
//
// CPU registers that has to be preserved (see [RG64]): .X, .Y
//
ciout:
CIOUT:
pha
lda C3PO
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
;; Clear carry flag to indicate success
// Clear carry flag to indicate success
clc
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
sta BSOUR
rts
ciout_send_byte:
clc ; don't send with EOI
clc // don't send with EOI
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
+20 -20
View File
@@ -1,38 +1,38 @@
;;
;; Official Kernal routine, described in:
;;
;; - [RG64] C64 Programmer's Reference Guide - page 281
;; - [CM64] Compute's Mapping the Commodore 64 - page 230
;;
;; CPU registers that has to be preserved (see [RG64]): .Y
;;
//
// Official Kernal routine, described in:
//
// - [RG64] C64 Programmer's Reference Guide - page 281
// - [CM64] Compute's Mapping the Commodore 64 - page 230
//
// CPU registers that has to be preserved (see [RG64]): .Y
//
clall_real:
;; Store .Y register
// Store .Y register
tya
pha
;; 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
;; it's channels, see CLALL description in the IDE64 User's Guide
*
// 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
// it's channels, see CLALL description in the IDE64 User's Guide
!:
ldy LDTND
beq +
beq !+
dey
lda LAT, y
jsr JCLOSE
jmp -
*
;; Restore .Y register
jmp !-
!:
// Restore .Y register
pla
tay
;; 'C64 Programmers Reference Guide', page 281, claims it calls CLRCHN too
jsr clrchn
// 'C64 Programmers Reference Guide', page 281, claims it calls CLRCHN too
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
+8 -8
View File
@@ -1,23 +1,23 @@
;; Common ppart of CLOSE and LOAD routines
// Common ppart of CLOSE and LOAD routines
close_load:
tax
;; Command drive to stop talking and to close the file
jsr untlk
// Command drive to stop talking and to close the file
jsr UNTLK
txa
jsr listen
jsr LISTEN
lda #$E0 ; CLOSE command
sta IEC_TMP2
lda #$E0 // CLOSE command
sta TBTCNT
jsr iec_tx_command
jsr iec_tx_command_finalize
;; Tell drive to unlisten
jsr unlsn
// Tell drive to unlisten
jsr UNLSN
rts
+21 -21
View File
@@ -1,35 +1,35 @@
;;
;; Official Kernal routine, described in:
;;
;; - [RG64] C64 Programmer's Reference Guide - page 282
;; - [CM64] Compute's Mapping the Commodore 64 - page 230
;;
;; CPU registers that has to be preserved (see [RG64]): .Y
;;
//
// Official Kernal routine, described in:
//
// - [RG64] C64 Programmer's Reference Guide - page 282
// - [CM64] Compute's Mapping the Commodore 64 - page 230
//
// CPU registers that has to be preserved (see [RG64]): .Y
//
clrchn_real:
;; Handle IEC input device
// Handle IEC input device
lda DFLTN
jsr iec_check_devnum
bcs +
;; Previous device was IEC one - send UNTALK first
jsr untlk
*
;; Restore output device to default
bcs !+
// Previous device was IEC one - send UNTALK first
jsr UNTLK
!:
// Restore output device to default
lda DFLTO
jsr iec_check_devnum
bcs +
;; Handle IEC output device
jsr unlsn
*
clrchn_reset: ;; entry needed by CHRIN
;; Set input device number to keyboard
bcs !+
// Handle IEC output device
jsr UNLSN
!:
clrchn_reset: // entry needed by CHRIN
// Set input device number to keyboard
lda #$00
sta DFLTN
;; Set output device number to screen
// Set output device number to screen
lda #$03
sta DFLTO
+23 -23
View File
@@ -1,10 +1,10 @@
;; Clear screen and initialise line link table
;; (Compute's Mapping the 64 p215-216)
// Clear screen and initialise line link table
// (Compute's Mapping the 64 p215-216)
clear_screen:
;; Clear line link table
;; (Compute's Mapping the 64 p215)
// Clear line link table
// (Compute's Mapping the 64 p215)
lda #$00
ldy #24
@@ -13,27 +13,27 @@ clearscreen_l1:
dey
bpl clearscreen_l1
;; Y now = #$FF
// Y now = #$FF
;; Clear screen RAM.
;; We should do this at HIBASE, which annoyingly
;; is no ZP, so we need to make a vector
;; (Compute's Mapping the 64 p216)
;; Get pointer to the screen into current_screen_line_ptr
;; as it is the first appropriate place for it found when
;; searching through the ZP allocations listed in
;; Compute's Mapping the 64
// Clear screen RAM.
// We should do this at HIBASE, which annoyingly
// is no ZP, so we need to make a vector
// (Compute's Mapping the 64 p216)
// Get pointer to the screen into current_screen_line_ptr
// as it is the first appropriate place for it found when
// searching through the ZP allocations listed in
// Compute's Mapping the 64
sta current_screen_line_ptr+0
lda hibase
lda HIBASE
sta current_screen_line_ptr+1
ldx #$03 ; countdown for pages to update
iny ; Y now = #$00
lda #$20 ; space character
ldx #$03 // countdown for pages to update
iny // Y now = #$00
lda #$20 // space character
clearscreen_l2:
sta (current_screen_line_ptr),y
iny
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
clc
adc #<250
@@ -41,20 +41,20 @@ clearscreen_l2:
lda current_screen_line_ptr+1
adc #>250
sta current_screen_line_ptr+1
lda #$20 ; get space character again
lda #$20 // get space character again
dex
bpl clearscreen_l2
;; Clear colour RAM
;; (Compute's Mapping the 64 p216)
// Clear colour RAM
// (Compute's Mapping the 64 p216)
lda text_colour
clearscreen_l3:
sta $d800,y
sta $d900,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
bne clearscreen_l3
;; (Compute's Mapping the 64 p216)
// (Compute's Mapping the 64 p216)
jmp home_cursor
+7 -7
View File
@@ -1,20 +1,20 @@
setup_vicii:
;; Set up default IO values (Compute's Mapping the 64 p215)
lda #$1B ; Enable text mode
// Set up default IO values (Compute's Mapping the 64 p215)
lda #$1B // Enable text mode
sta VIC_SCROLY
lda #$C8 ; 40 column etc
lda #$C8 // 40 column etc
sta VIC_SCROLX
;; Compute's Mapping the 64, p156
;; We use a different colour scheme of white text on all blue
// Compute's Mapping the 64, p156
// We use a different colour scheme of white text on all blue
lda #$06
sta VIC_EXTCOL
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
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
sec
rts
@@ -56,20 +56,20 @@ kernalerror_TOP_MEM_RS232:
sec
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:
lda #$00
sta IOSTATUS
rts
kernalstatus_TIMEOUT_WRITE: ;; XXX detect this!
kernalstatus_TIMEOUT_WRITE: // XXX detect this!
lda IOSTATUS
ora #K_STS_TIMEOUT_WRITE
sta IOSTATUS
rts
kernalstatus_TIMEOUT_READ: ;; XXX detect this!
kernalstatus_TIMEOUT_READ: // XXX detect this!
lda IOSTATUS
ora #K_STS_TIMEOUT_READ
sta IOSTATUS
+14 -14
View File
@@ -1,27 +1,27 @@
;;
;; Official Kernal routine, described in:
;;
;; - [RG64] C64 Programmer's Reference Guide - page 283
;; - [CM64] Compute's Mapping the Commodore 64 - page 227/228
;;
;; CPU registers that has to be preserved (see [RG64]): .X, .Y
;;
//
// Official Kernal routine, described in:
//
// - [RG64] C64 Programmer's Reference Guide - page 283
// - [CM64] Compute's Mapping the Commodore 64 - page 227/228
//
// 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
bne +
bne !+
;; Nothing in keyboard buffer to read
// Nothing in keyboard buffer to read
sec
lda #$00
rts
*
!:
lda keyboard_buffer
pha
+3 -3
View File
@@ -1,6 +1,6 @@
;; Our implementation is longer than the original one,
;; placing it here would cause a collision with CHROUT
// Our implementation is longer than the original one,
// placing it here would cause a collision with CHROUT
chrin:
CHRIN:
jmp chrin_real
+3 -3
View File
@@ -1,6 +1,6 @@
;; Our implementation is longer than the original one,
;; placing it here would cause a collision with CHKIN
// Our implementation is longer than the original one,
// placing it here would cause a collision with CHKIN
chrout:
CHROUT:
jmp chrout_real
+3 -3
View File
@@ -1,6 +1,6 @@
;; In our implementation CHKIN and CKOUT are closely tied,
;; placing it here would cause a collision
// In our implementation CHKIN and CKOUT are closely tied,
// placing it here would cause a collision
chkin:
CHKIN:
jmp chkin_real
+3 -3
View File
@@ -1,6 +1,6 @@
;; In our implementation CHKIN and CKOUT are closely tied,
;; placing it here would cause a collision
// In our implementation CHKIN and CKOUT are closely tied,
// placing it here would cause a collision
ckout:
CKOUT:
jmp ckout_real
+28 -28
View File
@@ -1,49 +1,49 @@
;;
;; Official Kernal routine, described in:
;;
;; - [RG64] C64 Programmer's Reference Guide - page 281/282
;; - [CM64] Compute's Mapping the Commodore 64 - page 229/230
;; - https://www.pagetable.com/?p=1031, https://github.com/mist64/cbmbus_doc (IEC command)
;;
;; CPU registers that has to be preserved (see [RG64]): none
;;
//
// Official Kernal routine, described in:
//
// - [RG64] C64 Programmer's Reference Guide - page 281/282
// - [CM64] Compute's Mapping the Commodore 64 - page 229/230
// - https://www.pagetable.com/?p=1031, https://github.com/mist64/cbmbus_doc (IEC command)
//
// 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
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
jsr iec_check_devnum
bcs close_remove_from_table
;; IEC device
// IEC device
jsr iec_tx_flush ; make sure no byte is awaiting
lda SAT, y ; get secondary address
jsr iec_tx_flush // make sure no byte is awaiting
lda SAT, y // get secondary address
cmp #$60
bne +
;; workaround for using CLOSE on reading executable - XXX is this a proper way?
bne !+
// workaround for using CLOSE on reading executable - XXX is this a proper way?
jsr close_load
jmp close_remove_from_table
*
ora $E0 ; CLOSE command
sta IEC_TMP2
!:
ora $E0 // CLOSE command
sta TBTCNT
jsr iec_tx_command
bcs close_remove_from_table
jsr iec_tx_command_finalize
close_remove_from_table:
;; Remove channel from the table
// Remove channel from the table
iny
cpy #$0A
bpl +
bpl !+
lda LAT, y
sta LAT-1, y
lda FAT, y
@@ -51,14 +51,14 @@ close_remove_from_table:
lda SAT, y
sta SAT-1, y
jmp close_remove_from_table
*
;; Decrement the list size variable
!:
// Decrement the list size variable
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
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
+3 -3
View File
@@ -1,6 +1,6 @@
;; Our implementation is longer than the original one,
;; placing it here would cause a collision with CLRCHN
// Our implementation is longer than the original one,
// placing it here would cause a collision with CLRCHN
clall:
CLALL:
jmp clall_real
+3 -3
View File
@@ -1,6 +1,6 @@
;; Our implementation is longer than the original one,
;; placing it here would cause a collision with OPEN
// Our implementation is longer than the original one,
// placing it here would cause a collision with OPEN
clrchn:
CLRCHN:
jmp clrchn_real
+35 -33
View File
@@ -1,45 +1,47 @@
;;
;; Official Kernal routine, described in:
;;
;; - [RG64] C64 Programmer's Reference Guide - page 289
;; - [CM64] Compute's Mapping the Commodore 64 - page 230/231
;;
;; CPU registers that has to be preserved (see [RG64]): none
;;
//
// Official Kernal routine, described in:
//
// - [RG64] C64 Programmer's Reference Guide - page 289
// - [CM64] Compute's Mapping the Commodore 64 - page 230/231
//
// CPU registers that has to be preserved (see [RG64]): none
//
open:
OPEN:
;; Reset status
// Reset status
jsr kernalstatus_reset
;; Check if the logical file number is unique
// Check if the logical file number is unique
ldy LDTND
*
beq +
!:
beq !+
dey
lda LAT, y
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
jmp -
*
;; Check if we have space in tables
jmp !-
!:
// Check if we have space in tables
ldy LDTND
cpy #$0A
bcc open_has_space
*
;; Table is full
!:
// Table is full
jmp kernalerror_TOO_MANY_OPEN_FILES
open_has_space:
;; Update the tables
// Update the tables
;; LAT / FAT / SAT support implemented according to
;; 'Compute's Mapping the Commodore 64', page 52
// LAT / FAT / SAT support implemented according to
// 'Compute's Mapping the Commodore 64', page 52
lda current_logical_filenum
sta LAT, y
@@ -51,16 +53,16 @@ open_has_space:
iny
sty LDTND
;; Check for command to send
// Check for command to send
lda FNLEN
beq open_done_success
;; Check for IEC device
// Check for IEC device
lda current_device_number
jsr iec_check_devnum
bcc open_iec
;; FALLTROUGH
// FALLTROUGH
open_done_success:
clc
@@ -68,21 +70,21 @@ open_done_success:
open_iec:
;; We have a command to send to IEC device
jsr listen
bcc +
// We have a command to send to IEC device
jsr LISTEN
bcc !+
jmp kernalerror_DEVICE_NOT_FOUND
*
!:
lda current_secondary_address
jsr iec_cmd_open
bcc +
bcc !+
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
;; Send command ('file name')
// Send command ('file name')
jsr lvs_send_file_name
jmp open_done_success
+94 -95
View File
@@ -1,146 +1,145 @@
;;
;; Official Kernal routine, described in:
;;
;; - [RG64] C64 Programmer's Reference Guide - page 286
;; - [CM64] Compute's Mapping the Commodore 64 - page 231
;; - IEC reference at http://www.zimmers.net/anonftp/pub/cbm/programming/serial-bus.pdf
;;
;; CPU registers that has to be preserved (see [RG64]): none
;;
//
// Official Kernal routine, described in:
//
// - [RG64] C64 Programmer's Reference Guide - page 286
// - [CM64] Compute's Mapping the Commodore 64 - page 231
// - IEC reference at http://www.zimmers.net/anonftp/pub/cbm/programming/serial-bus.pdf
//
// CPU registers that has to be preserved (see [RG64]): none
//
;; Expects that SETLFS and SETNAM are called before hand.
;; $YYXX = load address.
;; (ignored if SETLFS channel = 1, i.e., like ,8,1)
;; If A=1 then VERIFY instead of LOAD.
;; On exit, $YYXX is the highest address into which data
;; will have been placed.
// Expects that SETLFS and SETNAM are called before hand.
// $YYXX = load address.
// (ignored if SETLFS channel = 1, i.e., like ,8,1)
// If A=1 then VERIFY instead of LOAD.
// On exit, $YYXX is the highest address into which data
// will have been placed.
;; XXX honor MSGFLG bit 6
;; XXX add VERIFY support
// XXX honor MSGFLG bit 6
// XXX add VERIFY support
load:
LOAD:
;; Are we loading or verifying?
sta VERCK
// Are we loading or verifying?
sta VERCKK
;; Store start address of LOAD
// Store start address of LOAD
stx STAL+0
sty STAL+1
;; Reset status
// Reset status
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
;; Allow platform-specific routine to takeover the flow
`TARGET_HOOK_LOAD
// Allow platform-specific routine to takeover the flow
TARGET_HOOK_LOAD()
;; Check whether we support the requested device
// Check whether we support the requested device
lda current_device_number
and #$FC
bne +
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),
;; 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
;; number 31), yet original ROMs show ILLEGAL DEVICE NUMBER error only
;; for devices 0-3; in our implementation LISTEN / TALK will cause device
;; not present detected for numbers above 30
bne !+
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),
// 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
// number 31), yet original ROMs show ILLEGAL DEVICE NUMBER error only
// for devices 0-3; in our implementation LISTEN / TALK will cause device
// not present detected for numbers above 30
;; Display SEARCHING FOR + filename
// Display SEARCHING FOR + filename
jsr lvs_display_searching_for
;; 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
;; in the C64, only in the drive.
// 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
// in the C64, only in the drive.
;; Call device to LISTEN (p16)
// Call device to LISTEN (p16)
lda current_device_number
jsr listen
bcc +
jmp lvs_device_not_found_error ; XXX deduplicate with other jumps in this routine
*
;; Open channel 0 (reserved for file reading)
jsr LISTEN
bcc !+
jmp lvs_device_not_found_error // XXX deduplicate with other jumps in this routine
!:
// Open channel 0 (reserved for file reading)
lda #$00
jsr iec_cmd_open
bcc +
jmp lvs_device_not_found_error ; XXX deduplicate with other jumps in this routine
*
;; Send file name
bcc !+
jmp lvs_device_not_found_error // XXX deduplicate with other jumps in this routine
!:
// Send file name
jsr lvs_send_file_name
bcc +
jmp lvs_load_verify_error ; XXX deduplicate with other jumps in this routine
*
;; Now command device to talk (p16)
bcc !+
jmp lvs_load_verify_error // XXX deduplicate with other jumps in this routine
!:
// Now command device to talk (p16)
lda current_device_number
jsr talk
bcc +
jmp lvs_load_verify_error ; XXX deduplicate with other jumps in this routine
*
lda #$60 ; open channel / data (p3) , required according to p13
sta IEC_TMP2
jsr TALK
bcc !+
jmp lvs_load_verify_error // XXX deduplicate with other jumps in this routine
!:
lda #$60 // open channel / data (p3) , required according to p13
sta TBTCNT
jsr iec_tx_command
bcc +
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
;; are the listener (p16)
bcc !+
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
// are the listener (p16)
jsr iec_turnaround_to_listen
bcc +
jmp lvs_load_verify_error ; XXX deduplicate with other jumps in this routine
*
;; Get load address and store it if secondary address is zero
bcc !+
jmp lvs_load_verify_error // XXX deduplicate with other jumps in this routine
!:
// Get load address and store it if secondary address is zero
jsr iec_rx_byte
bcc +
jmp lvs_file_not_found_error ; XXX deduplicate with other jumps in this routine
*
bcc !+
jmp lvs_file_not_found_error // XXX deduplicate with other jumps in this routine
!:
ldx current_secondary_address
beq +
beq !+
sta STAL+0
*
!:
jsr iec_rx_byte
bcc +
jmp lvs_file_not_found_error ; XXX deduplicate with other jumps in this routine
*
bcc !+
jmp lvs_file_not_found_error // XXX deduplicate with other jumps in this routine
!:
ldx current_secondary_address
beq +
beq !+
sta STAL+1
*
;; Display start address
!:
// Display start address
jsr lvs_display_loading_verifying
load_loop:
;; We are now ready to receive bytes
// We are now ready to receive bytes
jsr iec_rx_byte
bcc +
jmp lvs_load_verify_error ; XXX deduplicate with other jumps in this routine
*
;; Handle the byte (store in memory / verify)
bcc !+
jmp lvs_load_verify_error // XXX deduplicate with other jumps in this routine
!:
// Handle the byte (store in memory / verify)
jsr lvs_handle_byte_load_verify
bcc +
jmp lvs_load_verify_error ; XXX deduplicate with other jumps in this routine
*
;; Advance pointer to data
bcc !+
jmp lvs_load_verify_error // XXX deduplicate with other jumps in this routine
!:
// Advance pointer to data
jsr lvs_advance_pointer
bcc +
bcc !+
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
and #K_STS_EOI
beq load_loop
;; Display end address
// Display end address
jsr lvs_display_done
;; Close file on drive
// Close file on drive
lda current_device_number
jsr close_load
;; Return last address
// Return last address
jmp lvs_return_last_address
+10 -10
View File
@@ -1,13 +1,13 @@
;;
;; Official Kernal routine, described in:
;;
;; - [RG64] C64 Programmer's Reference Guide - page 293/294
;; - [CM64] Compute's Mapping the Commodore 64 - page 231/232
;; - IEC reference at http://www.zimmers.net/anonftp/pub/cbm/programming/serial-bus.pdf
;;
;; CPU registers that has to be preserved (see [RG64]): none
;;
//
// Official Kernal routine, described in:
//
// - [RG64] C64 Programmer's Reference Guide - page 293/294
// - [CM64] Compute's Mapping the Commodore 64 - page 231/232
// - IEC reference at http://www.zimmers.net/anonftp/pub/cbm/programming/serial-bus.pdf
//
// CPU registers that has to be preserved (see [RG64]): none
//
save:
SAVE:
rts
+15 -15
View File
@@ -1,24 +1,24 @@
;;
;; Official Kernal routine, described in:
;;
;; - [RG64] C64 Programmer's Reference Guide - page 301
;; - [CM64] Compute's Mapping the Commodore 64 - page 232
;;
;; CPU registers that has to be preserved (see [RG64]): .Y
;;
//
// Official Kernal routine, described in:
//
// - [RG64] C64 Programmer's Reference Guide - page 301
// - [CM64] Compute's Mapping the Commodore 64 - page 232
//
// CPU registers that has to be preserved (see [RG64]): .Y
//
stop:
;; Bit 7 of STKEY contains the state of the STOP key
;; (Compute's Mapping the 64, p27)
STOP:
// Bit 7 of STKEY contains the state of the STOP key
// (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
bpl stop_pressed
;; By trial and error, we know that Z + C = BREAK
;; and that neither should be set otherwise
lda #$ff
// By trial and error, we know that Z + C = BREAK
// and that neither should be set otherwise
lda #$FF
clc
rts
+30 -36
View File
@@ -1,70 +1,64 @@
;;
;; Official Kernal routine, described in:
;;
;; - [RG64] C64 Programmer's Reference Guide - page 293 (RESTOR), 304 (VECTOR)
;; - [CM64] Compute's Mapping the Commodore 64 - page 237
;;
;; CPU registers that has to be preserved (see [RG64]): none
;;
//
// Official Kernal routine, described in:
//
// - [RG64] C64 Programmer's Reference Guide - page 293 (RESTOR), 304 (VECTOR)
// - [CM64] Compute's Mapping the Commodore 64 - page 237
//
// 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
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
;; address originally used; after calling VECTOR and checking zero page
;; area afterwards, the address could be found there
.alias _caller_arr_ptr MEMUS
;; According to 'Compute's Mapping the Commodore 64' page 237,
;; 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
// According to 'Compute's Mapping the Commodore 64' page 237,
// 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
cli
;; Prepare the user data pointer - strange order to reduce risk
;; of potential similarity to the original routine
// Prepare the user data pointer - strange order to reduce risk
// of potential similarity to the original routine
sty _caller_arr_ptr + 1
stx _caller_arr_ptr + 0
;; Select routine variant - store or restore vectors
// Select routine variant - store or restore vectors
ldy #$1F
bcc vector_restore
;; FALLTHROUGH
// FALLTHROUGH
vector_store:
*
lda CINV, y
sta (_caller_arr_ptr), y
dey
bpl -
bpl vector_store
;; Restore status register (IRQ) before return
// Restore status register (IRQ) before return
plp
rts
vector_restore:
*
lda (_caller_arr_ptr), y
sta CINV, y
dey
bpl -
bpl vector_restore
;; Restore status register (IRQ) before return
// Restore status register (IRQ) before return
plp
rts
.scend
+34 -34
View File
@@ -1,34 +1,34 @@
;;
;; Official Kernal routine, described in:
;;
;; - [RG64] C64 Programmer's Reference Guide - page 285
;; - [CM64] Compute's Mapping the Commodore 64 - page 238
;;
;; CPU registers that has to be preserved (see [RG64]): none
;;
//
// Official Kernal routine, described in:
//
// - [RG64] C64 Programmer's Reference Guide - page 285
// - [CM64] Compute's Mapping the Commodore 64 - page 238
//
// CPU registers that has to be preserved (see [RG64]): none
//
ioinit:
IOINIT:
; Set $00/$01 port mode and value
; We want BASIC and KERNAL ROMs mapped, and datasette motor off
; (https://www.c64-wiki.com/wiki/Zeropage)
;; XXX - Work around VICE bug: Writing $00 before $01 results in rubbish in $01
;; after. https://sourceforge.net/p/vice-emu/bugs/1057/
// Set $00/$01 port mode and value
// We want BASIC and KERNAL ROMs mapped, and datasette motor off
// (https://www.c64-wiki.com/wiki/Zeropage)
// XXX - Work around VICE bug: Writing $00 before $01 results in rubbish in $01
// after. https://sourceforge.net/p/vice-emu/bugs/1057/
lda #$27
ldx #$2F
sta CPU_R6510
stx CPU_D6510
;; Silence the SID chips under common addresses
// Silence the SID chips under common addresses
ldy #$00
*
;; SIDs under $D4xx
!:
// SIDs under $D4xx
lda SID_SIGVOL, Y
and #$F0
sta SID_SIGVOL, Y
;; SIDs under $D5xx
// SIDs under $D5xx
lda SID_SIGVOL + $100, Y
and #$F0
sta SID_SIGVOL + $100, Y
@@ -36,24 +36,24 @@ ioinit:
clc
adc #$20
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
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
;; 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)
;; ldy #<16380
;; ldx #>16380
// (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
// in the IRQ handler to see roughly what value the timers must be set to)
// ldy #<16380
// ldx #>16380
;; 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
// 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
ldy #<16421
ldx #>16421
@@ -61,19 +61,19 @@ ioinit:
sty CIA1_TIMALO
stx CIA1_TIMAHI
;; Enable timer interrupt
// Enable timer interrupt
lda #$81
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
sta CIA1_CRA
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
sta CIA2_DDRA
;; Set IEC bus to its initial idle state
// Set IEC bus to its initial idle state
jmp iec_set_idle
+3 -3
View File
@@ -1,6 +1,6 @@
;; Our implementation is longer than the original one,
;; placing it here would cause a collision with OPEN
// Our implementation is longer than the original one,
// placing it here would cause a collision with OPEN
cint:
CINT:
jmp cint_real
+60 -28
View File
@@ -1,31 +1,63 @@
;;
;; This byte identifies Kernal revision. Sources:
;; - [CM64] Compute's Mapping the Commodore 64 (page 242/243)
;; - [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
;; a warning that this is not a Commodore Kernal. Currently known numbers for C64 are:
;;
;; - $00 - [CM64] then current number [MM] 901227-02 [VICE] C64 Revision 2
;; - $03 - [CM64] (not mentionned) [MM] 901227-02, 901227-03 [VICE] C64 Revision 3
;; - $43 - [CM64] (not mentionned) [MM] 251104-04 [VICE] SX-64
;; - $64 - [CM64] PET64 ROM [MM] (not mentionned) [VICE] PET64
;; - $AA - [CM64] first version of ROM [MM] 901227-01 [VICE] C64 Revision 1
;;
;; Values from unofficial ROMs:
;; - $03 - SuperCPU ROM 1.40, 2.04, also unofficial 0.7 ROM from [VICE]
;;
;; Values from other Commodore machines:
;; C128:
;; - $01 - see https://www.pagetable.com/?p=1058
;; - $02 - unreleased updated ROM, see https://www.pagetable.com/?p=1058
;;
;; XXX check more unofficial C64 ROMs (JiffyDOS, DolphinDOS, etc.) and other machines
;; VIC-20, PET, CBM II, 264 series, C65 prototypes, other sources for C128 ROMs
;;
//
// This byte (hex $FF80, dec 65408) identifies Kernal revision on several machines. Although not all
// of the, used it for versioning purpose, here is the list of all the values I could find. Sources:
// - [CM64] Compute's Mapping the Commodore 64 (page 242/243)
// - [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
// - [XEMU] Checked with ROMs retrieved by XEMU emulator
//
// IDEA: put here a value, that is different from any version currently known, as
// a warning that this is not a Commodore Kernal or anything already known.
//
// C64 - values from the official ROMs:
// - $00 - [CM64] then current number [MM] 901227-02 [VICE] C64 Revision 2
// - $03 - [CM64] (not mentionned) [MM] 901227-02, 901227-03 [VICE] C64 Revision 3
// - $43 - [CM64] (not mentionned) [MM] 251104-04 [VICE] SX-64
// - $64 - [CM64] PET64 ROM [MM] (not mentionned) [VICE] PET64
// - $AA - [CM64] first version of ROM [MM] 901227-01 [VICE] C64 Revision 1
//
// C64 - values from unofficial 3rd party ROMs:
// - $00 - Turbo Trans, Turbo Access, Turbo Process
// - $03 - SuperCPU ROM 1.40, 2.04, also unofficial 0.7 ROM from [VICE],
// DolphinDOS 2.0, JiffyDOS 6.01, EXOS V3/4,
// Datel Mercury V3 US, Datel DOS-ROM V1.2, Datel Turbo ROM II V3.2+,
// Turbo Process US,
// 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:
.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
; Uncontrovertial as this is also a CPU requirement.
// $FFFA - CPU NMI Hanlder
// Uncontrovertial as this is also a CPU requirement.
.word nmi_handler
Loaded 100 of 248 files, more files were not shown because too many files have changed in this diff. Show more