diff --git a/.gitignore b/.gitignore index d9f921e3..bd558ebd 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,8 @@ +# Image which is illegal to distribute - just for extra safety + +kernal_hybrid.rom + # Compilation related files assembler/KickAss* diff --git a/CONFIG.md b/CONFIG.md new file mode 100644 index 00000000..8e85748f --- /dev/null +++ b/CONFIG.md @@ -0,0 +1,107 @@ + +# Configuring the build + +It's not possible to provide ROM builds that suit everyone needs - therefore configuration files were introduced, separately for each of the hardware targets: + +* [`c64/,,config_generic.s`](c64/,,config_generic.s) +* [`c64/,,config_mega65.s`](c64/,,config_mega65.s) +* [`c64/,,config_ultimate64.s`](c64/,,config_ultimate64.s) + +Just edit them and recompile the project. To enable particular option - uncomment it by removing leading `//` from before `#define` directive (as you probably guessed, commenting out disables it). Some options are followed by constants - you can change them too to further fine-tune the build. + +Note however, that features do not came for free - enabling them needs some additional ROM space (in BASIC segment, in KERNAL segment, or in both), which is VERY limited on the target machines. Some options might be unavailable for speecific targets - read the comments in the configuration files. Some options might also carry compatibility and/or performance hit - so choose wisely. + +Sane defaults are already present - different for each target. + +## Processor instruction set + +### `CONFIG_CPU_MOS_6502` + +Choose if your CPU only supports the original MOS Technology 6502 instruction set, like: + +* MOS 6510 - used in the Commodore 64 +* MOS 8500 - used in the Commodore 64C +* MOS 8502 - used in the Commodore 128 + +If unsure - select this one. + +### `CONFIG_CPU_WDC_65C02` + +Choose if your CPU supports the Western Design Center 65C02 instruction set, like: + +* WDC 65C02 - used in the Turbo Master accelerator +* CSG 65CE02 +* CSG 4510 - used in the Commodore 65 prototypes + +It enables some speed/size code optimizations. Warning - this is untested! + +### `CONFIG_CPU_WDC_65816` + +Choose if your CPU supports the 16-bit Western Design Center 65816 instruction set, like: + +* WDC 65C816 - used in the Flash 8 accelerator +* WDC 65C816S - used in the SuperCPU accelerator + +It enables some speed/size code optimizations. Warning - this is untested! + +## Memory models + +Different layouts of memory are possible - but they can be selected at compile time only. + +### `CONFIG_MEMORY_MODEL_38K` + +Memory model the original machine uses - memory available for BASIC ends at `$9FFF`, just before the first block of ROM. The fastest and the most compatible, but gives the least memory for BASIC. If unsure - select this one. + +### `CONFIG_MEMORY_MODEL_46K` and `CONFIG_MEMORY_MODEL_50K` + +Planned for the future - not available yet. + +### `CONFIG_MEMORY_MODEL_60K` + +Uses RAM under BASIC, I/O and KERNAL, takes over `$C000`-`$CFFF` area requires special helper routines installed in `$2A7`-`$2FF` area (normally unused and free for the user). Gives the most free memory for BASIC programs, but it's the slowest and the least compatible model. + +Comparing to standard memoryy model, it needs about 180 bytes in BASIC segment and 80 bytes in KERNAL segment - at the moment of doing the test, these values are expected to change often. + +## Multiple SID support + +The SID is a sound chip - original machine had one installed. However, mods exists to add more of them for improved sound capabilitiee. Emulators and FPGA machines typically allow to simulate more than one too. Unfortunately, there is no standard regarding how these additional chips are visible in the processor address space, and there is no sane way to detect it - thus, it has to be configurable. + +The SID support in the ROM is very limited - it only disables the sound during startup or warm restart (when STOP+RESTORE is pressed or BRK assembler instruction is executed). + +### `CONFIG_SID_2ND` and `CONFIG_SID_3RD` + +Each of them add support for one additional SID - addresses should be given in `CONFIG_SID_2ND_ADDRESS` and `CONFIG_SID_3RD_ADDRESS`, respectively. + +Each of these options needs 8 bytes in KERNAL segment. + +### `CONFIG_SID_D4XX` and `CONFIG_SID_D5XX` + +Cause the system to support SIDs in `$D4xx` and `$D5xx` ranges, respectively. + +Each of them needs a couple of bytes in KERNAL segment - but they can share some code, and `$D4xx` range support replaces the standard `$D400` address handling, so exact amount depends on the exact configuration. + +## Miscelaneous features + +### `CONFIG_DOS_WEDGE` + +If enabled, a simple DOS wedge is available from the direct mode - supports `@`, `@`, `@$`, `@$` and `@` commands. + +Feature needs about 330 bytes in BASIC segment. + +### `CONFIG_BCD_SAFE_INTERRUPTS` + +On the most widespread CPUs the D flag is not cleared upon entering interrupts. Since the original Kernal does not clear it either, it's not safe to use BCD processor mode without disabling the interrupts first. This option makes sure the D flag is disabled at the start of the interrupt - this allows some optimizations in the code. + +Feature needs 2 bytes in KERNAL segmment (for CPUs needing the patch), but at the same time allows optimizations allowing to gain some more bytes. If unsure - enable. + +## Debug options + +Options in this section are for debug purposes only. If unsure - disable. + +### `CONFIG_DBG_STUBS_BRK` + +Replaces `RTS` stubbed routines implementation with one causing a break. + +### `CONFIG_DBG_PRINTF` + +Makes 'printf' routine available. diff --git a/Makefile b/Makefile index 5f770905..4495652a 100644 --- a/Makefile +++ b/Makefile @@ -3,7 +3,7 @@ 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 +SRCDIR_KERNAL_COMMON = $(SRCDIR_COMMON) c64/kernal c64/kernal/assets c64/kernal/jumptable c64/kernal/iec c64/kernal/interrupts c64/kernal/print SRCDIR_BASIC_generic = $(SRCDIR_BASIC_COMMON) c64/basic/,target_generic SRCDIR_BASIC_mega65 = $(SRCDIR_BASIC_COMMON) c64/basic/,target_mega65 @@ -15,6 +15,11 @@ SRCDIR_KERNAL_ultimate64 = $(SRCDIR_KERNAL_COMMON) c64/kernal/,target_ultimate64 SRC_TOOLS = $(wildcard src/tools/*.c,src/tools/*.cc) +# Generated files + +GEN_BASIC = build/,generated/packed_messages.s +GEN_KERNAL = + # List of tools TOOL_COLLECT_DATA = build/tools/collect_data @@ -37,6 +42,10 @@ EXT_TARGET_LIST = build/newc65.rom REL_TARGET_LIST = $(pathsubst build/%,bin/%, $(STD_TARGET_LIST)) +# Misc strings + +HYBRID_WARNING = "*** WARNING *** Distributing kernal_hybrid.rom violates both original ROM copyright and Open ROMs license!" + # GIT commit GIT_COMMIT:= $(shell git log -1 --pretty='%h' | tr '[:lower:]' '[:upper:]') @@ -84,13 +93,31 @@ build/chargen.rom: $(TOOL_PNGPREPARE) assets/8x8font.png # Dependencies - BASIC and KERNAL -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/target_generic/OUTB.BIN build/target_generic/BASIC_combined.vs: \ + $(TOOL_ASSEMBLER) $(TOOL_BUILD_SEGMENT) $(GEN_BASIC) $(SRCDIR_BASIC_generic) \ + c64/,,config_generic.s build/target_generic/KERNAL_combined.sym \ + $(foreach dir,$(SRCDIR_BASIC_generic),$(wildcard $(dir)/*.s)) +build/target_mega65/OUTB.BIN build/target_mega65/BASIC_combined.vs: \ + $(TOOL_ASSEMBLER) $(TOOL_BUILD_SEGMENT) $(GEN_BASIC) $(SRCDIR_BASIC_mega65) \ + c64/,,config_mega65.s build/target_mega65/KERNAL_combined.sym \ + $(foreach dir,$(SRCDIR_BASIC_mega65),$(wildcard $(dir)/*.s)) +build/target_ultimate64/OUTB.BIN build/target_ultimate64/BASIC_combined.vs: \ + $(TOOL_ASSEMBLER) $(TOOL_BUILD_SEGMENT) $(GEN_BASIC) $(SRCDIR_BASIC_ultimate64) \ + c64/,,config_ultimate64.s build/target_ultimate64/KERNAL_combined.sym \ + $(foreach dir,$(SRCDIR_BASIC_ultimate64),$(wildcard $(dir)/*.s)) -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/target_generic/OUTK.BIN build/target_generic/KERNAL_combined.vs build/target_generic/KERNAL_combined.sym: \ + $(TOOL_ASSEMBLER) $(TOOL_BUILD_SEGMENT) $(GEN_KERNAL) $(SRCDIR_KERNAL_generic) \ + c64/,,config_generic.s \ + $(foreach dir,$(SRCDIR_KERNAL_generic),$(wildcard $(dir)/*.s)) +build/target_mega65/OUTK.BIN build/target_mega65/KERNAL_combined.vs build/target_mega65/KERNAL_combined.sym: \ + $(TOOL_ASSEMBLER) $(TOOL_BUILD_SEGMENT) $(GEN_KERNAL) $(SRCDIR_KERNAL_mega65) \ + c64/,,config_mega65.s \ + $(foreach dir,$(SRCDIR_KERNAL_mega65),$(wildcard $(dir)/*.s)) +build/target_ultimate64/OUTK.BIN build/target_ultimate64/KERNAL_combined.vs build/target_ultimate64/KERNAL_combined.sym: \ + $(TOOL_ASSEMBLER) $(TOOL_BUILD_SEGMENT) $(GEN_KERNAL) $(SRCDIR_KERNAL_ultimate64) \ + c64/,,config_ultimate64.s \ + $(foreach dir,$(SRCDIR_KERNAL_ultimate64),$(wildcard $(dir)/*.s)) 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 @@ -104,27 +131,31 @@ build/basic_generic.rom: build/target_generic/newrom build/basic_mega65.rom: build/target_mega65/newrom build/basic_ultimate64.rom: build/target_ultimate64/newrom +build/symbols_generic.vs: build/target_generic/BASIC_combined.vs build/target_generic/KERNAL_combined.vs +build/symbols_mega65.vs: build/target_mega65/BASIC_combined.vs build/target_mega65/KERNAL_combined.vs +build/symbols_ultimate64.vs: build/target_ultimate64/BASIC_combined.vs build/target_ultimate64/KERNAL_combined.vs + # Rules - BASIC and KERNAL build/,generated/packed_messages.s: $(TOOL_COMPRESS_TEXT) @mkdir -p build/,generated $(TOOL_COMPRESS_TEXT) > build/,generated/packed_messages.s -.PRECIOUS: build/target_%/OUTB.BIN -build/target_%/OUTB.BIN: +.PRECIOUS: build/target_%/OUTB.BIN build/target_%/BASIC_combined.vs +build/target_%/OUTB.BIN build/target_%/BASIC_combined.vs: @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 + @$(TOOL_BUILD_SEGMENT) -a ../../$(TOOL_ASSEMBLER) -s BASIC -i BASIC-$* -o OUTB.BIN -d build/target_$* -l a000 -h e4d2 c64/,,config_$*.s $(SRCDIR_BASIC_$*) $(GEN_BASIC) -.PRECIOUS: build/target_%/OUTK.BIN -build/target_%/OUTK.BIN: +.PRECIOUS: build/target_%/OUTK.BIN build/target_%/KERNAL_combined.vs build/target_%/KERNAL_combined.sym +build/target_%/OUTK.BIN build/target_%/KERNAL_combined.vs build/target_%/KERNAL_combined.sym: @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_$*) + @$(TOOL_BUILD_SEGMENT) -a ../../$(TOOL_ASSEMBLER) -s KERNAL -i KERNAL-$* -o OUTK.BIN -d build/target_$* -l e4d3 -h ffff c64/,,config_$*.s $(SRCDIR_KERNAL_$*) $(GEN_KERNAL) .PRECIOUS: build/target_%/newrom build/target_%/newrom: - cat build/target_$*/OUTB.BIN build/target_$*/OUTK.BIN > $@ + cat build/target_$*/OUTB.BIN build/target_$*/OUTK.BIN > $@ .PRECIOUS: build/kernal_%.rom build/kernal_%.rom: @@ -134,6 +165,22 @@ build/kernal_%.rom: build/basic_%.rom: dd if=build/target_$*/newrom bs=8192 count=1 skip=0 of=$@ +.PRECIOUS: build/symbols_%.vs +build/symbols_%.vs: + sort build/target_$*/BASIC_combined.vs build/target_$*/KERNAL_combined.vs | uniq | grep -v "__" > $@ + +build/kernal_hybrid.rom: kernal build/target_generic/OUTK.BIN + @echo + @echo $(HYBRID_WARNING) + @echo + (dd if=kernal bs=1140 count=1 skip=0 ; \ + echo " > HYBRID ROM, DON'T DISTRIBUTE <" ; \ + dd if=kernal bs=1 count=58 skip=1176 ; \ + cat build/target_generic/OUTK.BIN) > $@ + +build/symbols_hybrid.vs: build/target_generic/KERNAL_combined.vs + sort build/target_generic/KERNAL_combined.vs | uniq | grep -v "__" > $@ + # Rules - platform 'Mega 65' specific build/newc65.rom: build/kernal_mega65.rom build/basic_mega65.rom build/chargen.rom Makefile @@ -145,15 +192,34 @@ build/newc65.rom: build/kernal_mega65.rom build/basic_mega65.rom build/chargen.r # Rules - tests -test: build/kernal_generic.rom build/basic_generic.rom - x64 -kernal build/kernal_generic.rom -basic build/basic_generic.rom -8 empty.d64 +.PHONY: test test_generic test_mega65 test_ultimate64 test_m65 testremote testsimilarity -testremote: build/kernal_generic.rom build/basic_generic.rom - x64 -kernal build/kernal_generic.rom -basic build/basic_generic.rom -remotemonitor +test: test_generic -testm65: build/newc65 +test_generic: build/kernal_generic.rom build/basic_generic.rom build/symbols_generic.vs + x64 -kernal build/kernal_generic.rom -basic build/basic_generic.rom -moncommands build/symbols_generic.vs -8 empty.d64 + +test_mega65: build/kernal_mega65.rom build/basic_mega65.rom build/symbols_mega65.vs + x64 -kernal build/kernal_mega65.rom -basic build/basic_mega65.rom -moncommands build/symbols_mega65.vs -8 empty.d64 + +test_ultimate64: build/kernal_ultimate64.rom build/basic_ultimate64.rom build/symbols_ultimate64.vs + x64 -kernal build/kernal_ultimate64.rom -basic build/basic_ultimate64.rom -moncommands build/symbols_ultimate64.vs -8 empty.d64 + +test_hybrid: build/kernal_hybrid.rom build/symbols_hybrid.vs + @echo + @echo $(HYBRID_WARNING) + @echo + x64 -kernal build/kernal_hybrid.rom -moncommands build/symbols_hybrid.vs -8 empty.d64 + @echo + @echo $(HYBRID_WARNING) + @echo + +test_m65: build/newc65.rom m65 -b ../mega65-core/bin/mega65r1.bit -k ../mega65-core/bin/KICKUP.M65 -R build/newc65.rom -4 -testsimilarity: build/target_generic/newrom $(TOOL_SIMILARITY) +testremote: build/kernal_generic.rom build/basic_generic.rom build/symbols_generic.vs + x64 -kernal build/kernal_generic.rom -basic build/basic_generic.rom -moncommands build/symbols_generic.vs -remotemonitor + +testsimilarity: build/target_generic/newrom $(TOOL_SIMILARITY) kernal basic $(TOOL_SIMILARITY) kernal build/target_generic/newrom $(TOOL_SIMILARITY) basic build/target_generic/newrom diff --git a/STATUS.md b/STATUS.md index 3759a299..96d2da0c 100644 --- a/STATUS.md +++ b/STATUS.md @@ -1,11 +1,11 @@ # New features -Here are the features of the Open ROMs not found in the original ROMs from the 80s: +Here are the features of the Open ROMs not found in the original ROMs from the 80s (many of them are [configurable](CONFIG.md)): * improved keyboard scanning, supports multi-key roll-over and rejection of spurious joystick input * joystick (port 1) can be used to move text cursor -* uses RAM under ROM and I/O: 61436 bytes free +* uses RAM under ROM and I/O: 61438 bytes free * cold/warm start silences multiple SID chips - all $D4xx and $D5xx addresses * wark start due to BRK prints out the instruction address * extended `LOAD` command @@ -46,66 +46,121 @@ For the current status of the low memory location implementation andd usage chec ## BASIC +### Official BASIC routines -TODO +Note: vectors at `$0300` are not supported yet - for now only the locations below can be used! +
+ +| Entry | Unofficial | Name | Status | Remarks | +| :-------: | :--------: | :--------- | :------: | :------------------------------------------------: | +| `($0003)` | | `ADRAY1` | NOT DONE | | +| `($0005)` | | `ADRAY2` | NOT DONE | | +| `(00300)` | `$E38B` | `ERROR` | NOT DONE | | +| `(00302)` | `$A483` | `MAIN` | NOT DONE | some implementation exists, but not connected here | +| `(00304)` | `$A57C` | `CHRNCH` | NOT DONE | | +| `(00306)` | `$A71A` | `QPLOP` | NOT DONE | some implementation exists, but not connected here | +| `(00308)` | `$A7E4` | `GONE` | NOT DONE | some implementation exists, but not connected here | +| `(0030A)` | `$AE86` | `EVAL` | NOT DONE | some implementation exists, but not connected here | +| `($A000)` | | cold start | PARTIAL | | +| `($A002)` | | warm start | PARTIAL | | + +
+ +### Unofficial BASIC routines/locations + +Not all of them - only these we want to have implemented. + +
+ +| Address | Name | Status | Remarks | +| :-------: | :----------- | :------: | :------------------------------------------------: | +| `$A004` | revision str | DONE | | +| `$A68E` | RUNC | NOT DONE | | +| `$A7AE` | NEWSTT | NOT DONE | | +| `$AB1E` | STROUT | DONE | | +| `$BDCD` | LINPRT | NOT DONE | | +| `$E3BF` | INIT | NOT DONE | | +| `$E422` | INITMSG | DONE | | +| `$E453` | RVECT | NOT DONE | | + +
## Kernal - -Note: only the jump table addresses are currently supported, real routine addresses are different! - - ### Official Kernal routines NOTE: Even the 'DONE' routines won't support features described as missing in one of the previous chapters!
-| Address | Name | Status | Remarks | -| --------- | :------- | :------: | :------------------------------------------------: | -| `$FF81` | `CINT` | DONE | | -| `$FF84` | `IOINIT` | PARTIAL | CIA initialization incomplete | -| `$FF87` | `RAMTAS` | DONE | | -| `$FF8A` | `RESTOR` | DONE | | -| `$FF8D` | `VECTOR` | DONE | | -| `$FF90` | `SETMSG` | DONE | | -| `$FF93` | `SECOND` | DONE | | -| `$FF96` | `TKSA` | DONE | | -| `$FF99` | `MEMTOP` | DONE | | -| `$FF9C` | `MEMBOT` | DONE | | -| `$FF9F` | `SCNKEY` | DONE | could be better integrated with ROM (aliases) | -| `$FFA2` | `SETTMO` | DONE | | -| `$FFA5` | `ACPTR` | DONE | | -| `$FFA8` | `CIOUT` | DONE | | -| `$FFAB` | `UNTLK` | DONE | | -| `$FFAE` | `UNLSN` | DONE | | -| `$FFB1` | `LISTEN` | DONE | | -| `$FFB4` | `TALK` | DONE | | -| `$FFB7` | `READST` | DONE | | -| `$FFBA` | `SETFLS` | DONE | | -| `$FFBD` | `SETNAM` | DONE | | -| `$FFC0` | `OPEN` | DONE | | -| `$FFC3` | `CLOSE` | DONE | | -| `$FFC6` | `CHKIN` | DONE | | -| `$FFC9` | `CHKOUT` | PARTIAL | | -| `$FFCC` | `CLRCHN` | DONE | | -| `$FFCF` | `CHRIN` | PARTIAL | | -| `$FFD2` | `CHROUT` | PARTIAL | | -| `$FFD5` | `LOAD` | PARTIAL | no VERIFY support yet, no STOP key support | -| `$FFD8` | `SAVE` | NOT DONE | | -| `$FFDB` | `SETTIM` | DONE | | -| `$FFDE` | `RDTIM` | DONE | | -| `$FFE1` | `STOP` | DONE | | -| `$FFE4` | `GETIN` | PARTIAL | only some devices supported | -| `$FFE7` | `CLALL` | DONE | | -| `$FFEA` | `UDTIM` | DONE | | -| `$FFED` | `SCREEN` | DONE | | -| `$FFF0` | `PLOT` | PARTIAL | cursor blink not handled | -| `$FFF3` | `IOBASE` | DONE | | +| Address | Unofficial | Name | Status | Remarks | +| :-------: | :--------: | :---------- | :------: | :------------------------------------------------: | +| `($028F)` | | `KEYLOG` | NOT DONE | | +| `$FF81` | `$FF5B` | `CINT` | DONE | | +| `$FF84` | `$FDA3` | `IOINIT` | PARTIAL | CIA initialization incomplete | +| `$FF87` | `$FD50` | `RAMTAS` | DONE | | +| `$FF8A` | `$FD15` | `RESTOR` | DONE | | +| `$FF8D` | `$FD1A` | `VECTOR` | DONE | | +| `$FF90` | | `SETMSG` | DONE | | +| `$FF93` | | `SECOND` | DONE | | +| `$FF96` | | `TKSA` | DONE | | +| `$FF99` | | `MEMTOP` | DONE | | +| `$FF9C` | | `MEMBOT` | DONE | | +| `$FF9F` | | `SCNKEY` | DONE | could be better integrated with ROM (aliases) | +| `$FFA2` | | `SETTMO` | DONE | | +| `$FFA5` | | `ACPTR` | DONE | | +| `$FFA8` | | `CIOUT` | DONE | | +| `$FFAB` | | `UNTLK` | DONE | | +| `$FFAE` | | `UNLSN` | DONE | | +| `$FFB1` | | `LISTEN` | DONE | | +| `$FFB4` | | `TALK` | DONE | | +| `$FFB7` | | `READST` | DONE | | +| `$FFBA` | | `SETFLS` | DONE | | +| `$FFBD` | | `SETNAM` | DONE | | +| `$FFC0` | `$F34A` | `OPEN` | DONE | | +| `$FFC3` | `$F291` | `CLOSE` | DONE | | +| `$FFC6` | `$F20E` | `CHKIN` | DONE | | +| `$FFC9` | `$F250` | `CKOUT` | PARTIAL | | +| `$FFCC` | `$F333` | `CLRCHN` | DONE | | +| `$FFCF` | `$F157` | `CHRIN` | PARTIAL | | +| `$FFD2` | `$F1CA` | `CHROUT` | PARTIAL | | +| `$FFD5` | `$F49E` | `LOAD` | PARTIAL | not yet clear what's this entry doing | +| `($0330)` | `$F4A5` | `LOAD` | PARTIAL | no VERIFY support, no STOP key, check $F49E addr | +| `$FFD8` | `$F5DD` | `SAVE` | NOT DONE | | +| `($0332)` | `$F5ED` | `SAVE` | NOT DONE | | +| `$FFDB` | | `SETTIM` | DONE | | +| `$FFDE` | | `RDTIM` | DONE | | +| `$FFE1` | `$F6ED` | `STOP` | DONE | | +| `$FFE4` | `$F13E` | `GETIN` | PARTIAL | only some devices supported | +| `$FFE7` | `$F32F` | `CLALL` | DONE | | +| `$FFEA` | | `UDTIM` | DONE | | +| `$FFED` | | `SCREEN` | DONE | | +| `$FFF0` | `$E50A` | `PLOT` | PARTIAL | | +| `$FFF3` | | `IOBASE` | DONE | | +| `($FFFA)` | | NMI vec | PARTIAL | | +| `($FFFC)` | | RESET vec | PARTIAL | | +| `($FFFE)` | | IRQ/BRK vec | PARTIAL | |
-### Unofficial Kernal locations +### Unofficial Kernal routines/locations -TODO +Not all of them - only these we want to have implemented. + +
+ +| Address | Name | Status | Remarks | +| :-------: | :------------------ | :------: | :------------------------------------------------: | +| `$E544` | clear screen | DONE | | +| `$E50C` | set cursor position | PARTIAL | | +| `$E5A0` | setup VIC II & IO | PARTIAL | | +| `$EA31` | default IRQ | PARTIAL | | +| `$EA7E` | ack CIA1 + below | DONE | | +| `$EA81` | ret from IRQ/NMI | DONE | | +| `$FD30` | default vectors | DONE | | +| `$FE47` | default NMI | PARTIAL | | +| `$FE66` | default BRK | DONE | | +| `$FF80` | revision byte | DONE | | + +
diff --git a/bin/README.txt b/bin/README.txt index d3a254bc..de60839c 100644 --- a/bin/README.txt +++ b/bin/README.txt @@ -4,7 +4,12 @@ Follow these rules, or bad things will happen! - Don't mix ROMs for different platforms - use generic BASIC with generic KERNAL, Mega65 BASIC with Mega65 KERNAL, etc. -- Don't mix these ROMs with any other ROMs; the only exception is CHARGEN, this one is fully interchangeable. +- Don't mix these ROMs with any other ROMs; exceptions: + + - kernal_hybrid.rom, which is meant to be used (and has to be used) with the original BASIC ROM; + however, this hybrid ROM cannot be distributed due to legal/copyright reasons + + - chargen.rom - this one is fully interchangeable - Don't mix ROMs from different builds/versions (again, CHARGEN is an exception). diff --git a/bin/basic_generic.rom b/bin/basic_generic.rom index 966d794a..7d407af1 100644 Binary files a/bin/basic_generic.rom and b/bin/basic_generic.rom differ diff --git a/bin/basic_mega65.rom b/bin/basic_mega65.rom index 20dc20c0..5ed25603 100644 Binary files a/bin/basic_mega65.rom and b/bin/basic_mega65.rom differ diff --git a/bin/basic_ultimate64.rom b/bin/basic_ultimate64.rom index 482ff397..64e0dd6f 100644 Binary files a/bin/basic_ultimate64.rom and b/bin/basic_ultimate64.rom differ diff --git a/bin/kernal_generic.rom b/bin/kernal_generic.rom index 32bd602e..2ccae4bd 100644 Binary files a/bin/kernal_generic.rom and b/bin/kernal_generic.rom differ diff --git a/bin/kernal_mega65.rom b/bin/kernal_mega65.rom index f6b0fd85..a598b2b0 100644 Binary files a/bin/kernal_mega65.rom and b/bin/kernal_mega65.rom differ diff --git a/bin/kernal_ultimate64.rom b/bin/kernal_ultimate64.rom index a52e636e..5278a59b 100644 Binary files a/bin/kernal_ultimate64.rom and b/bin/kernal_ultimate64.rom differ diff --git a/c64/,,config_generic.s b/c64/,,config_generic.s new file mode 100644 index 00000000..3843ec00 --- /dev/null +++ b/c64/,,config_generic.s @@ -0,0 +1,28 @@ + +// +// Please read CONFIG.md before modifying this file! +// + + +#define CONFIG_CPU_MOS_6502 +// #define CONFIG_CPU_WDC_65C02 +// #define CONFIG_CPU_WDC_65816 + +#define CONFIG_MEMORY_MODEL_38K +// #define CONFIG_MEMORY_MODEL_60K + +// #define CONFIG_SID_2ND +.const CONFIG_SID_2ND_ADDRESS = $D420 + +// #define CONFIG_SID_3RD +.const CONFIG_SID_3RD_ADDRESS = $D440 + +// #define CONFIG_SID_D4XX +// #define CONFIG_SID_D5XX + +#define CONFIG_DOS_WEDGE +#define CONFIG_BCD_SAFE_INTERRUPTS +#define CONFIG_EXTENDED_SCNKEY // for now has to be enabled + +// #define CONFIG_DBG_STUBS_BRK +// #define CONFIG_DBG_PRINTF diff --git a/c64/,,config_mega65.s b/c64/,,config_mega65.s new file mode 100644 index 00000000..e856a52c --- /dev/null +++ b/c64/,,config_mega65.s @@ -0,0 +1,28 @@ + +// +// Please read CONFIG.md before modifying this file! +// + + +#define CONFIG_CPU_MOS_6502 +// #define CONFIG_CPU_WDC_65C02 +// #define CONFIG_CPU_WDC_65816 + +// #define CONFIG_MEMORY_MODEL_38K +#define CONFIG_MEMORY_MODEL_60K + +#define CONFIG_SID_2ND +.const CONFIG_SID_2ND_ADDRESS = $D420 + +// #define CONFIG_SID_3RD +.const CONFIG_SID_3RD_ADDRESS = $D440 + +// #define CONFIG_SID_D4XX +// #define CONFIG_SID_D5XX + +#define CONFIG_DOS_WEDGE +#define CONFIG_BCD_SAFE_INTERRUPTS +#define CONFIG_EXTENDED_SCNKEY // for now has to be enabled + +// #define CONFIG_DBG_STUBS_BRK +// #define CONFIG_DBG_PRINTF diff --git a/c64/,,config_ultimate64.s b/c64/,,config_ultimate64.s new file mode 100644 index 00000000..f7ce1b93 --- /dev/null +++ b/c64/,,config_ultimate64.s @@ -0,0 +1,28 @@ + +// +// Please read CONFIG.md before modifying this file! +// + + +#define CONFIG_CPU_MOS_6502 +// #define CONFIG_CPU_WDC_65C02 +// #define CONFIG_CPU_WDC_65816 + +#define CONFIG_MEMORY_MODEL_38K +// #define CONFIG_MEMORY_MODEL_60K + +// #define CONFIG_SID_2ND +.const CONFIG_SID_2ND_ADDRESS = $D420 + +// #define CONFIG_SID_3RD +.const CONFIG_SID_3RD_ADDRESS = $D440 + +#define CONFIG_SID_D4XX +#define CONFIG_SID_D5XX + +#define CONFIG_DOS_WEDGE +#define CONFIG_BCD_SAFE_INTERRUPTS +#define CONFIG_EXTENDED_SCNKEY // for now has to be enabled + +// #define CONFIG_DBG_STUBS_BRK +// #define CONFIG_DBG_PRINTF diff --git a/c64/aliases/,aliases_config.s b/c64/aliases/,aliases_config.s new file mode 100644 index 00000000..868fc670 --- /dev/null +++ b/c64/aliases/,aliases_config.s @@ -0,0 +1,83 @@ + + // Various configuration dependent aliases/macros/checks + + + + // Check that memory model configuration is correct + +{ + .var selected = 0; + +#if CONFIG_MEMORY_MODEL_38K + .eval selected++ +#endif +#if CONFIG_MEMORY_MODEL_60K + .eval selected++ +#endif + + .if (selected != 1) .error "Please select exactly one CONFIG_MEMORY_MODEL_* option" +} + + + + // Check that processor configuration is correct + +{ + .var selected = 0; + +#if CONFIG_CPU_MOS_6502 + .eval selected++ +#endif +#if CONFIG_CPU_WDC_65C02 + .eval selected++ +#endif +#if CONFIG_CPU_WDC_65816 + .eval selected++ +#endif + + .if (selected != 1) .error "Please select exactly one CONFIG_CPU_* option" +} + + + + // Handle processor configuration + +#if CONFIG_CPU_WDC_65C02 || CONFIG_CPU_WDC_65816 + +#define HAS_BCD_SAFE_INTERRUPTS +#define HAS_BCD_SAFE_RESET + + .pseudocommand phx { .byte $DA } + .pseudocommand phy { .byte $5A } + .pseudocommand plx { .byte $FA } + .pseudocommand ply { .byte $7A } + +#endif + + // Handle misc configuration entrues + +#if CONFIG_BCD_SAFE_INTERRUPTS +#define HAS_BCD_SAFE_INTERRUPTS +#endif + + // Stub configuration + +.macro STUB_IMPLEMENTATION_RTS() { + rts +} + +.macro STUB_IMPLEMENTATION_BRK() { + .break + brk + brk + jmp *-2 +} + +.macro STUB_IMPLEMENTATION() +{ +#if CONFIG_DBG_STUBS_BRK + STUB_IMPLEMENTATION_BRK() +#else + STUB_IMPLEMENTATION_RTS() +#endif +} diff --git a/c64/aliases/,aliases_hardware.s b/c64/aliases/,aliases_hardware.s index 2eee3541..73abfd8c 100644 --- a/c64/aliases/,aliases_hardware.s +++ b/c64/aliases/,aliases_hardware.s @@ -10,6 +10,8 @@ // VIC-II registers + .label __VIC_BASE = $D000 // base address of the chip + .label VIC_SP0X = $D000 .label VIC_SP0Y = $D001 .label VIC_SP1X = $D002 @@ -62,6 +64,8 @@ // SID registers + .label __SID_BASE = $D400 // base address of the chip + .label SID_FRELO1 = $D400 .label SID_FREHI1 = $D401 .label SID_PWLO1 = $D402 @@ -97,6 +101,8 @@ // CIA #1 registers + .label __CIA1_BASE = $DC00 // base address of the chip + .label CIA1_PRA = $DC00 .label CIA1_PRB = $DC01 .label CIA1_DDRA = $DC02 @@ -119,6 +125,8 @@ // CIA #2 registers + .label __CIA2_BASE = $DD00 // base address of the chip + .label CIA2_PRA = $DD00 // VIC bank switching and IEC port .label CIA2_PRB = $DD01 .label CIA2_DDRA = $DD02 diff --git a/c64/aliases/,aliases_ram_lowmem.s b/c64/aliases/,aliases_ram_lowmem.s index 8a18c4af..bc391aae 100644 --- a/c64/aliases/,aliases_ram_lowmem.s +++ b/c64/aliases/,aliases_ram_lowmem.s @@ -12,8 +12,8 @@ // // $02 -- UNUSED -- free for user software - .label ADRAY1 = $03 // $03-$04 -- NOT IMPLEMENTED -- - .label ADRAY2 = $05 // $05-$06 -- NOT IMPLEMENTED -- + .label ADRAY1 = $03 // $03-$04 + .label ADRAY2 = $05 // $05-$06 .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 -- @@ -38,8 +38,8 @@ .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 FRESPC = $35 // $35-$36 [!] our implementation uses this as temporary string pointer + .label MEMSIZ = $37 // $37-$38 highest address of BASIC memory + 1 .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 @@ -57,13 +57,23 @@ .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 __FAC1 = $61 // $61-$66 floating point accumulator 1 + .label FAC1_exponent = $61 + .label FAC1_mantissa = $62 // $62 - $65 + .label FAC1_sign = $66 + .label SGNFLG = $67 // -- NOT IMPLEMENTED -- - .label BITS = $68 // -- NOT IMPLEMENTED -- - .label FAC2 = $69 // $69-$6E -- NOT IMPLEMENTED -- [!] also used for memory move pointers + .label BITS = $68 // FAC1 overflow + + .label __FAC2 = $69 // $69-$6E floating point accumulator 2 [!] also used for memory move pointers + .label FAC2_exponent = $69 + .label FAC2_mantissa = $6A // $6A - $6D + .label FAC2_sign = $6E + .label ARISGN = $6F // -- NOT IMPLEMENTED -- - .label FACOV = $70 // -- NOT IMPLEMENTED -- - .label FBUFPT = $67 // $71-$72 -- NOT IMPLEMENTED -- + .label FACOV = $70 // FAC1 low order mantissa + .label FBUFPT = $71 // $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 -- @@ -94,17 +104,53 @@ .label CNTDN = $A5 // -- NOT IMPLEMENTED -- .label BUFPNT = $A6 // -- NOT IMPLEMENTED -- .label INBIT = $A7 // -- NOT IMPLEMENTED -- + +#if CONFIG_EXTENDED_SCNKEY + + // Reuse RS232 variables, since they should not be used by other things. + // Carefully avoid $A7 which is used by 64NET + .label KeyQuantity = $A8 // 1 byte + .label BufferNew = $A9 // 3 bytes + +#else .label BITCI = $A8 // -- NOT IMPLEMENTED -- .label RINONE = $A9 // -- NOT IMPLEMENTED -- .label RIDDATA = $AA // -- NOT IMPLEMENTED -- .label RIPRTY = $AB // -- NOT IMPLEMENTED -- + +#endif + .label SAL = $AC // $AC-$AD -- NOT IMPLEMENTED -- (implemented screen part) - .label EAL = $AE // $AE-$AF -- NOT IMPLEMENTED -- [!] used also byy screen editor + .label EAL = $AE // $AE-$AF -- NOT IMPLEMENTED -- [!] used also by screen editor, for temporary color storage when scrolling .label CMP0 = $B0 // $B0-$B1 temporary tape storage, [!] here used for BRK instruction address .label TAPE1 = $B2 // $B2-$B3 tape buffer pointer + +#if CONFIG_EXTENDED_SCNKEY + + // Reuse RS232 variables, since they should not be used by other things. + // This one should be initialized in cinit to $FF + .label BufferQuantity = $B4 // 1 byte + +#else + .label BITTS = $B4 // -- NOT IMPLEMENTED -- + +#endif + .label NXTBIT = $B5 // -- NOT IMPLEMENTED -- + +#if CONFIG_EXTENDED_SCNKEY + + // Reuse RS232 variables, since they should not be used by other things. + // Carefully avoiding $A7 which is used by 64NET + .label TempZP = $B6 // 1 byte + +#else + .label RODATA = $B6 // -- NOT IMPLEMENTED -- + +#endif + .label FNLEN = $B7 // current file name length .label LA = $B8 // current logical_file number .label SA = $B9 // current secondary address @@ -124,7 +170,7 @@ .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 GDBLN = $CE // cursor 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 @@ -134,7 +180,7 @@ .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 LDTBL = $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 -- @@ -153,6 +199,15 @@ // .label BUF = $200 // $200-$250, BASIC line editor input buffer (81 bytes) + +#if CONFIG_EXTENDED_SCNKEY + + // $250-$258 is the 81st - 88th characters in BASIC input, a carry over from VIC-20 + // and not used on C64, so safe for us to use, probably. + .label ScanResult = $250 // 8 bytes + +#endif + // [!] 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) @@ -166,19 +221,32 @@ .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 KOUNT = $28B // key repeat counter .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 KEYLOG = $28F // $28F-$290 routine to setup keyboard decoding .label MODE = $291 // flag, is case switch allowed - .label AUTODN = $292 // -- NOT IMPLEMENTED -- + .label AUTODN = $292 // -- NOT IMPLEMENTED -- screen scroll disable + +#if CONFIG_EXTENDED_SCNKEY + + // Reuse RS232 variables, since they should not be used by other things. + // This one should be initialized in cinit to $FF + .label BufferOld = $293 // 3 bytes + .label Buffer = $297 // 4 bytes + +#else + .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 -- + +#endif + .label RIDBE = $29B // -- NOT IMPLEMENTED -- .label RIDBS = $29C // -- NOT IMPLEMENTED -- .label RODBS = $29D // -- NOT IMPLEMENTED -- @@ -190,15 +258,34 @@ .label TD1IRQ = $2A4 // -- NOT IMPLEMENTED -- .label TLNIDX = $2A5 // -- NOT IMPLEMENTED -- .label TVSFLG = $2A6 // 0 = NTSC, 1 = PAL - // [!] XXX document $2A7-$2FF usage + + // [!] $2A7-$2FF is normally free, but in our case some extra functionality uses it + +#if CONFIG_MEMORY_MODEL_60K + + // 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 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 +#if SEGMENT_BASIC + .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 +#endif // SEGMENT_BASIC + +#endif // CONFIG_MEMORY_MODEL_60K // 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 -- + .label IERROR = $300 // $300-$301 + .label IMAIN = $302 // $302-$303 + .label ICRNCH = $304 // $304-$305 + .label IQPLOP = $306 // $306-$307 + .label IGONE = $308 // $308-$309 + .label IEVAL = $30A // $30A-$30B .label SAREG = $30C // .A storage, for SYS call .label SXREG = $30D // .X storage, for SYS call diff --git a/c64/basic/,aliases.s b/c64/basic/,aliases.s index 2cd8b229..2726f748 100644 --- a/c64/basic/,aliases.s +++ b/c64/basic/,aliases.s @@ -1,126 +1,18 @@ -// 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) +// +// Helper aliases to make the code more readable +// Always use double underscore in label names +// to allow automatic VICE label conflict prevention +// -// XXX get rid of this file, use ,aliases_ram_lowmem.s instead + // Temporary variables for various routines + .label __tokenise_work1 = $07 // CHARAC + .label __tokenise_work2 = $08 // ENDCHR + .label __tokenise_work3 = $0B // COUNT + .label __tokenise_work4 = $0F // GARBFL + .label __tokenise_work5 = $0C // DIMFLG - .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 - - // 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 - - .label basic_numeric_work_area = $57 // $57 - $60 inclusive = 10 bytes - - // 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 - - .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 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 - - .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 - - .label cassette_buffer_ptr = $B2 - .label current_logical_filenum = $B8 - .label current_secondary_address = $B9 - .label current_device_number = $BA - .label current_filename_ptr = $BB - .label load_save_start_ptr = $C1 - .label load_save_end_ptr = $C3 - .label last_key_matrix_position = $C5 - .label keys_in_key_buffer = $C6 - .label reverse_video_flag = $C7 - .label end_of_input_line = $C8 - .label start_of_keyboard_input = $C9 - .label current_key_index_entry = $CB - .label cursor_blink_disable = $CC - .label cursor_blink_countdown = $CD - .label cursor_saved_character = $CE - .label cursor_is_visible = $CF - .label keyboard_input_ready = $D0 - .label current_screen_line_ptr = $D1 - .label current_screen_x = $D3 - .label quote_mode_flag = $D4 - .label logical_line_length = $D5 - .label current_screen_y = $D6 - .label last_printed_character_ascii = $D7 - .label insert_mode = $D8 - // Bits 0 -3 = bits 8-11 of screen line address - // Bit 7 = line spans multiple physical lines - .label screen_line_link_table = $D9 - .label current_screen_line_colour_ptr = $F3 - .label keyboard_decoding_table_ptr = $F5 - - .label basic_input_buffer = BUF - - // "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 - .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 + .label __memmove_src = $69 + .label __memmove_dst = $6B + .label __memmove_size = $6D diff --git a/c64/basic/,imports.s b/c64/basic/,imports.s new file mode 100644 index 00000000..b195dcac --- /dev/null +++ b/c64/basic/,imports.s @@ -0,0 +1,13 @@ + +// Routines imported from Kernal - our private API + +#import "KERNAL_combined.sym" + + +#if CONFIG_DBG_PRINTF +.label printf = KERNAL.printf +#endif + +.label print_hex_byte = KERNAL.print_hex_byte +.label print_return = KERNAL.print_return +.label print_space = KERNAL.print_space diff --git a/c64/basic/a483.interop b/c64/basic/a483.interop new file mode 100644 index 00000000..ac77e1bd --- /dev/null +++ b/c64/basic/a483.interop @@ -0,0 +1,9 @@ +All the BASIC routines, for which there are vectors in $0300-$030B, have to be available at their original addresses. + +Reason: some autostart software (https://codebase64.org/doku.php?id=base:autostarting_disk_files) override these vectors, so that some point +to new locations (usually Kernal related), while others points the original BASIC routines. Different techniques modify different vectors +(while resetting others to original C64 locations), some don't change the vectors at all, but might still put the original +C64 BASIC addresses there. + +For various cartridges this just means disabling their extensions (like new commands); for us that would mean improperly functionning BASIC. + diff --git a/c64/basic/a483.main.s b/c64/basic/a483.main.s new file mode 100644 index 00000000..40415b24 --- /dev/null +++ b/c64/basic/a483.main.s @@ -0,0 +1,13 @@ + +// +// Official BASIC routine, described in: +// +// - [RG64] C64 Programmer's Reference Guide - XXX +// - [CM64] Compute's Mapping the Commodore 64 - page 69, XXX +// +// CPU registers that has to be preserved (see [RG64]): XXX +// + + +MAIN: + STUB_IMPLEMENTATION() diff --git a/c64/basic/a57c.chrnch.s b/c64/basic/a57c.chrnch.s new file mode 100644 index 00000000..4f462ff6 --- /dev/null +++ b/c64/basic/a57c.chrnch.s @@ -0,0 +1,13 @@ + +// +// Official BASIC routine, described in: +// +// - [RG64] C64 Programmer's Reference Guide - XXX +// - [CM64] Compute's Mapping the Commodore 64 - page 69, XXX +// +// CPU registers that has to be preserved (see [RG64]): XXX +// + + +CHRNCH: + STUB_IMPLEMENTATION() diff --git a/c64/basic/a57c.interop b/c64/basic/a57c.interop new file mode 100644 index 00000000..ac77e1bd --- /dev/null +++ b/c64/basic/a57c.interop @@ -0,0 +1,9 @@ +All the BASIC routines, for which there are vectors in $0300-$030B, have to be available at their original addresses. + +Reason: some autostart software (https://codebase64.org/doku.php?id=base:autostarting_disk_files) override these vectors, so that some point +to new locations (usually Kernal related), while others points the original BASIC routines. Different techniques modify different vectors +(while resetting others to original C64 locations), some don't change the vectors at all, but might still put the original +C64 BASIC addresses there. + +For various cartridges this just means disabling their extensions (like new commands); for us that would mean improperly functionning BASIC. + diff --git a/c64/basic/a68e.interop b/c64/basic/a68e.interop new file mode 100644 index 00000000..f5ae9e65 --- /dev/null +++ b/c64/basic/a68e.interop @@ -0,0 +1,3 @@ +This routine is mentionned in the cartridge writing tutorial here: https://codebase64.org/doku.php?id=base:assembling_your_own_cart_rom_image + +We have to implement (or at least provide stub), otherwise cartridges will crash. diff --git a/c64/basic/a68e.runc.s b/c64/basic/a68e.runc.s new file mode 100644 index 00000000..dfec0e32 --- /dev/null +++ b/c64/basic/a68e.runc.s @@ -0,0 +1,5 @@ + +// XXX provide documentation and implementation + +RUNC: + STUB_IMPLEMENTATION() diff --git a/c64/basic/a71a.interop b/c64/basic/a71a.interop new file mode 100644 index 00000000..ac77e1bd --- /dev/null +++ b/c64/basic/a71a.interop @@ -0,0 +1,9 @@ +All the BASIC routines, for which there are vectors in $0300-$030B, have to be available at their original addresses. + +Reason: some autostart software (https://codebase64.org/doku.php?id=base:autostarting_disk_files) override these vectors, so that some point +to new locations (usually Kernal related), while others points the original BASIC routines. Different techniques modify different vectors +(while resetting others to original C64 locations), some don't change the vectors at all, but might still put the original +C64 BASIC addresses there. + +For various cartridges this just means disabling their extensions (like new commands); for us that would mean improperly functionning BASIC. + diff --git a/c64/basic/a71a.qplop.s b/c64/basic/a71a.qplop.s new file mode 100644 index 00000000..efa99f31 --- /dev/null +++ b/c64/basic/a71a.qplop.s @@ -0,0 +1,13 @@ + +// +// Official BASIC routine, described in: +// +// - [RG64] C64 Programmer's Reference Guide - XXX +// - [CM64] Compute's Mapping the Commodore 64 - page 69, XXX +// +// CPU registers that has to be preserved (see [RG64]): XXX +// + + +QPLOP: + STUB_IMPLEMENTATION() diff --git a/c64/basic/a7ae.interop b/c64/basic/a7ae.interop new file mode 100644 index 00000000..f5ae9e65 --- /dev/null +++ b/c64/basic/a7ae.interop @@ -0,0 +1,3 @@ +This routine is mentionned in the cartridge writing tutorial here: https://codebase64.org/doku.php?id=base:assembling_your_own_cart_rom_image + +We have to implement (or at least provide stub), otherwise cartridges will crash. diff --git a/c64/basic/a7ae.newstt.s b/c64/basic/a7ae.newstt.s new file mode 100644 index 00000000..55b97764 --- /dev/null +++ b/c64/basic/a7ae.newstt.s @@ -0,0 +1,5 @@ + +// XXX provide documentation and implementation + +NEWSTT: + STUB_IMPLEMENTATION() diff --git a/c64/basic/a7e4.gone.s b/c64/basic/a7e4.gone.s new file mode 100644 index 00000000..547f648a --- /dev/null +++ b/c64/basic/a7e4.gone.s @@ -0,0 +1,13 @@ + +// +// Official BASIC routine, described in: +// +// - [RG64] C64 Programmer's Reference Guide - XXX +// - [CM64] Compute's Mapping the Commodore 64 - page 70, XXX +// +// CPU registers that has to be preserved (see [RG64]): XXX +// + + +GONE: + STUB_IMPLEMENTATION() diff --git a/c64/basic/a7e4.interop b/c64/basic/a7e4.interop new file mode 100644 index 00000000..ac77e1bd --- /dev/null +++ b/c64/basic/a7e4.interop @@ -0,0 +1,9 @@ +All the BASIC routines, for which there are vectors in $0300-$030B, have to be available at their original addresses. + +Reason: some autostart software (https://codebase64.org/doku.php?id=base:autostarting_disk_files) override these vectors, so that some point +to new locations (usually Kernal related), while others points the original BASIC routines. Different techniques modify different vectors +(while resetting others to original C64 locations), some don't change the vectors at all, but might still put the original +C64 BASIC addresses there. + +For various cartridges this just means disabling their extensions (like new commands); for us that would mean improperly functionning BASIC. + diff --git a/c64/basic/ab1e.print_string.s b/c64/basic/ab1e.strout.s similarity index 58% rename from c64/basic/ab1e.print_string.s rename to c64/basic/ab1e.strout.s index 360e95c5..165af8b1 100644 --- a/c64/basic/ab1e.print_string.s +++ b/c64/basic/ab1e.strout.s @@ -1,24 +1,25 @@ // Print string at $YYAA // Compute's Mapping the 64 p101 -print_string: +// print string routine + +STROUT: // Setup pointer - sty temp_string_ptr+1 - sta temp_string_ptr+0 + sty FRESPC+1 + sta FRESPC+0 txa pha // Get offset ready ldy #$00 - -print_string_loop: +!: // Save Y in X, since X is preserved by chrout, but Y is not tya tax - lda (temp_string_ptr),y - beq print_string_end + lda (FRESPC),y + beq !+ jsr JCHROUT @@ -26,10 +27,8 @@ print_string_loop: tay iny - bne print_string_loop - -print_string_end: - + bne !- +!: pla tax rts diff --git a/c64/basic/ae86.eval.s b/c64/basic/ae86.eval.s new file mode 100644 index 00000000..423eb01a --- /dev/null +++ b/c64/basic/ae86.eval.s @@ -0,0 +1,13 @@ + +// +// Official BASIC routine, described in: +// +// - [RG64] C64 Programmer's Reference Guide - XXX +// - [CM64] Compute's Mapping the Commodore 64 - page 70, XXX +// +// CPU registers that has to be preserved (see [RG64]): XXX +// + + +EVAL: + STUB_IMPLEMENTATION() diff --git a/c64/basic/ae86.interop b/c64/basic/ae86.interop new file mode 100644 index 00000000..ac77e1bd --- /dev/null +++ b/c64/basic/ae86.interop @@ -0,0 +1,9 @@ +All the BASIC routines, for which there are vectors in $0300-$030B, have to be available at their original addresses. + +Reason: some autostart software (https://codebase64.org/doku.php?id=base:autostarting_disk_files) override these vectors, so that some point +to new locations (usually Kernal related), while others points the original BASIC routines. Different techniques modify different vectors +(while resetting others to original C64 locations), some don't change the vectors at all, but might still put the original +C64 BASIC addresses there. + +For various cartridges this just means disabling their extensions (like new commands); for us that would mean improperly functionning BASIC. + diff --git a/c64/basic/basic_adray1.s b/c64/basic/basic_adray1.s new file mode 100644 index 00000000..879a6bce --- /dev/null +++ b/c64/basic/basic_adray1.s @@ -0,0 +1,5 @@ + +// XXX provide documentation and implementation + +basic_adray1: + STUB_IMPLEMENTATION() diff --git a/c64/basic/basic_adray2.s b/c64/basic/basic_adray2.s new file mode 100644 index 00000000..dbdd00c1 --- /dev/null +++ b/c64/basic/basic_adray2.s @@ -0,0 +1,5 @@ + +// XXX provide documentation and implementation + +basic_adray2: + STUB_IMPLEMENTATION() diff --git a/c64/basic/basic_cold_start.s b/c64/basic/basic_cold_start.s index d3aab8fd..5f8d27e3 100644 --- a/c64/basic/basic_cold_start.s +++ b/c64/basic/basic_cold_start.s @@ -1,62 +1,34 @@ // 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 +basic_cold_start: - // Print coloured part of the message - // ldy #>startup_message - // lda #do_ILLEGAL_QUANTITY_error + sta USRADD+1 - lda #$20 - jsr JCHROUT - - // Print the rest of the start up message - ldx #34 - jsr print_packed_message + // Print startup messages + jsr INITMSG // jump into warm start loop jmp basic_warm_start - -startup_message: // XXX this is probably not needed anymore - // Clear the screen - .byte $93 - // Vertical bars in different colours - .byte $1C,$B4 - .byte $9E,$B5 - .byte $1E,$A1 - // MEGABASIC\r\r - .byte $12,$05,$4D,$45,$47,$41,$92 - .byte $42,$41,$53,$49,$43 - .byte $20,$56,$32,$2e,$30,$2e,$30 - .byte $0D,$0D - - .byte 0 diff --git a/c64/basic/basic_delete_line.s b/c64/basic/basic_delete_line.s index 4b4867fd..33a3d5b5 100644 --- a/c64/basic/basic_delete_line.s +++ b/c64/basic/basic_delete_line.s @@ -9,35 +9,47 @@ basic_delete_line: // jsr printf // .text "DELETING LINE AT $" - // .byte $f1,basic_current_line_ptr - // .byte $f0,basic_current_line_ptr + // .byte $f1,OLDTXT + // .byte $f0,OLDTXT // .byte $0d,0 // Get address of next line - ldx #tokenise_work4 - // .byte $f0,tokenise_work3 + // .byte $f0,<__tokenise_work4,>__tokenise_work4 + // .byte $f0,<__tokenise_work3,>__tokenise_work3 // .byte $0d,0 - lda tokenise_work4 + lda __tokenise_work4 sbc #0 cmp #$00 beq !+ @@ -46,9 +58,9 @@ basic_delete_line: jmp do_MEMORY_CORRUPT_error !: // Length can now be safely assumed to be in the low - // byte only, i.e., stored in tokenise_work3 + // byte only, i.e., stored in __tokenise_work3 - lda tokenise_work3 + lda __tokenise_work3 pha tax @@ -57,14 +69,14 @@ basic_delete_line: // Now decrease top of BASIC mem pla - sta tokenise_work3 - lda basic_end_of_text_ptr+0 + sta __tokenise_work3 + lda VARTAB+0 sec - sbc tokenise_work3 - sta basic_end_of_text_ptr+0 - lda basic_end_of_text_ptr+1 + sbc __tokenise_work3 + sta VARTAB+0 + lda VARTAB+1 sbc #0 - sta basic_end_of_text_ptr+1 + sta VARTAB+1 clc rts diff --git a/c64/basic/basic_do_error.s b/c64/basic/basic_do_error.s index ba31a966..6266b0ef 100644 --- a/c64/basic/basic_do_error.s +++ b/c64/basic/basic_do_error.s @@ -6,8 +6,7 @@ basic_do_error: pha // Print ? at start - lda #$0D - jsr JCHROUT + jsr print_return lda #$3F jsr JCHROUT @@ -17,8 +16,7 @@ basic_do_error: jsr print_packed_message // Print ERROR at end - lda #$20 - jsr JCHROUT + jsr print_space ldx #33 jsr print_packed_message @@ -26,10 +24,8 @@ basic_do_error: // XXX print line number if not in direct mode - lda #$0D - jsr JCHROUT - lda #$0D // XXX do we need this? - jsr JCHROUT + jsr print_return + jsr print_return // Reset stack, and go back to main loop ldx #$FE diff --git a/c64/basic/basic_execute_line.s b/c64/basic/basic_execute_line.s index 3e92c06c..15c533fa 100644 --- a/c64/basic/basic_execute_line.s +++ b/c64/basic/basic_execute_line.s @@ -2,10 +2,15 @@ // after first checking that we have a colon // or $00 char -basic_end_of_statement_check: - ldx #basic_current_line_ptr - // .byte $f0,basic_current_line_ptr + // .byte $f1,OLDTXT + // .byte $f0,OLDTXT // .text ", STATEMENT PTR = $" - // .byte $f1,basic_current_statement_ptr - // .byte $f0,basic_current_statement_ptr + // .byte $f1,TXTPTR + // .byte $f0,TXTPTR // .byte $d,0 // Go through the line until its end is reached. @@ -58,10 +69,17 @@ basic_execute_statement: // Get next char of program text, even if it is hiding under a ROM or the // IO area. - ldx #basic_current_line_ptr - // .byte $f0,basic_current_line_ptr + // .byte $f1,OLDTXT + // .byte $f0,OLDTXT // .byte $0d,0 - lda basic_current_line_ptr+0 + lda OLDTXT+0 pha - lda basic_current_line_ptr+1 + lda OLDTXT+1 pha // Get number of bytes in tokenised line after line number - lda tokenise_work2 + lda __tokenise_work2 sec - sbc tokenise_work1 + sbc __tokenise_work1 // Add on the four bytes space we need clc adc #5 @@ -44,41 +44,57 @@ basic_insert_line: // Now increase top of BASIC mem pla clc - adc basic_end_of_text_ptr+0 - sta basic_end_of_text_ptr+0 - lda basic_end_of_text_ptr+1 + adc VARTAB+0 + sta VARTAB+0 + lda VARTAB+1 adc #0 - sta basic_end_of_text_ptr+1 + sta VARTAB+1 // Get pointer back pla - sta basic_current_line_ptr+1 + sta OLDTXT+1 pla - sta basic_current_line_ptr+0 + sta OLDTXT+0 // Write the line number ldy #2 - ldx #$0200 - sta basic_current_statement_ptr+1 + sta TXTPTR+1 jsr basic_parse_line_number // Get pointer to next char - lda basic_current_statement_ptr+0 - sta tokenise_work1 + lda TXTPTR+0 + sta __tokenise_work1 // Got a valid line number -- so do add/del line // Skip any spaces after the line number - ldx tokenise_work1 + ldx __tokenise_work1 skip_spaces: lda $0200,x cmp #$20 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 @@ -119,8 +118,8 @@ skip_spaces: !: // Insert new line if non-zero length, i.e., that // we are not just deleting the line. - lda tokenise_work1 - cmp tokenise_work2 + lda __tokenise_work1 + cmp __tokenise_work2 beq !+ jsr basic_insert_line !: @@ -133,19 +132,19 @@ not_a_line: // Setup pointer to the statement lda #<$0200 - sta basic_current_statement_ptr+0 + sta TXTPTR+0 lda #>$0200 - sta basic_current_statement_ptr+1 + sta TXTPTR+1 // There is no stored line, so zero that pointer out lda #$00 - sta basic_current_line_ptr+0 - sta basic_current_line_ptr+1 + sta OLDTXT+0 + sta OLDTXT+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) lda #$ff - sta basic_current_line_number+1 + sta CURLIN+1 jmp basic_execute_statement diff --git a/c64/basic/basic_parse_line_number.s b/c64/basic/basic_parse_line_number.s index 90aa8336..c4b9910f 100644 --- a/c64/basic/basic_parse_line_number.s +++ b/c64/basic/basic_parse_line_number.s @@ -5,23 +5,23 @@ basic_parse_line_number: // 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 + lda FAC1_mantissa+2 + ora FAC1_mantissa+3 + ora FAC1_exponent beq !+ ml_bad_line_number: // Invalid line number jmp do_ILLEGAL_QUANTITY_error !: // Line number are not allowed to have decimal points in them - lda tokenise_work4 + lda __tokenise_work4 cmp #$FF bne ml_bad_line_number // Got a valid line number. - lda basic_fac1_mantissa+0 - sta basic_line_number+0 - lda basic_fac1_mantissa+1 - sta basic_line_number+1 + lda FAC1_mantissa+0 + sta LINNUM+0 + lda FAC1_mantissa+1 + sta LINNUM+1 clc rts diff --git a/c64/basic/basic_shift_mem_down.s b/c64/basic/basic_shift_mem_down.s index dce24825..8c9f5a15 100644 --- a/c64/basic/basic_shift_mem_down.s +++ b/c64/basic/basic_shift_mem_down.s @@ -2,45 +2,45 @@ basic_shift_mem_down_and_relink: // Shift memory down to basic_current_line_pointer // from X bytes further along. - // 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 + // Destination is OLDTXT + lda OLDTXT+0 + sta __memmove_dst+0 + lda OLDTXT+1 + sta __memmove_dst+1 // Source is that plus X txa pha // also keep for later clc - adc basic_current_line_ptr+0 - sta memmove_src+0 - lda basic_current_line_ptr+1 + adc OLDTXT+0 + sta __memmove_src+0 + lda OLDTXT+1 adc #0 - sta memmove_src+1 + sta __memmove_src+1 // Size is distance from source to end of BASIC text. - lda basic_end_of_text_ptr+0 + lda VARTAB+0 sec - sbc memmove_src+0 - sta memmove_size+0 - lda basic_end_of_text_ptr+1 - sbc memmove_src+1 - sta memmove_size+1 + sbc __memmove_src+0 + sta __memmove_size+0 + lda VARTAB+1 + sbc __memmove_src+1 + sta __memmove_size+1 // jsr printf // .text "TOP OF BASIC = $" - // .byte $f1,basic_end_of_text_ptr - // .byte $f0,basic_end_of_text_ptr + // .byte $f1,VARTAB + // .byte $f0,VARTAB // .byte $0d // .text "SHIFTING DOWN $" - // .byte $f1,memmove_size - // .byte $f0,memmove_size + // .byte $f1,<__memmove_size,>__memmove_size + // .byte $f0,<__memmove_size,>__memmove_size // .text " BYTES FROM $" - // .byte $f1,memmove_src - // .byte $f0,memmove_src + // .byte $f1,<__memmove_src,>__memmove_src + // .byte $f0,<__memmove_src,>__memmove_src // .text " TO $" - // .byte $f1,memmove_dst - // .byte $f0,memmove_dst + // .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 @@ -54,55 +54,54 @@ basic_shift_mem_down_and_relink: // This means we have to then reduce the source and // target pointers by the same amount - lda memmove_size+0 + lda __memmove_size+0 eor #$ff - sta tokenise_work3 - sta memmove_size+0 + sta __tokenise_work3 + sta __memmove_size+0 - lda memmove_src+0 + lda __memmove_src+0 sec - sbc tokenise_work3 - sta memmove_src+0 - lda memmove_src+1 + sbc __tokenise_work3 + sta __memmove_src+0 + lda __memmove_src+1 sbc #0 - sta memmove_src+1 + sta __memmove_src+1 - lda memmove_dst+0 + lda __memmove_dst+0 sec - sbc tokenise_work3 - sta memmove_dst+0 - lda memmove_dst+1 + sbc __tokenise_work3 + sta __memmove_dst+0 + lda __memmove_dst+1 sbc #0 - sta memmove_dst+1 + sta __memmove_dst+1 // Increase copy page count so we can post-decrement compare with $00 - inc memmove_size+1 + inc __memmove_size+1 // jsr printf // .text "REVISED BOUNDS $" - // .byte $f1,memmove_size - // .byte $f0,memmove_size + // .byte $f1,<__memmove_size,>__memmove_size + // .byte $f0,<__memmove_size,>__memmove_size // .text " BYTES FROM $" - // .byte $f1,memmove_src - // .byte $f0,memmove_src + // .byte $f1,<__memmove_src,>__memmove_src + // .byte $f0,<__memmove_src,>__memmove_src // .text " TO $" - // .byte $f1,memmove_dst - // .byte $f0,memmove_dst + // .byte $f1,<__memmove_dst,>__memmove_dst + // .byte $f0,<__memmove_dst,>__memmove_dst // .byte $0d,0 // Get Y value ready for the copy - ldy memmove_size+0 + ldy __memmove_size+0 jsr shift_mem_down // Get length of deletion back pla - sta tokenise_work3 + sta __tokenise_work3 // Check if we still have any lines left ldy #0 - ldx #basic_end_of_text_ptr - // .byte $f0,basic_end_of_text_ptr + // .byte $f1,VARTAB + // .byte $f0,VARTAB // .byte $0d // .text "SHIFTING UP $" - // .byte $f1,memmove_size - // .byte $f0,memmove_size + // .byte $f1,<__memmove_size,>__memmove_size + // .byte $f0,<__memmove_size,>__memmove_size // .text " BYTES FROM $" - // .byte $f1,memmove_src - // .byte $f0,memmove_src + // .byte $f1,<__memmove_src,>__memmove_src + // .byte $f0,<__memmove_src,>__memmove_src // .text " TO $" - // .byte $f1,memmove_dst - // .byte $f0,memmove_dst + // .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. - lda memmove_src+0 + lda __memmove_src+0 sec - sbc memmove_size+0 - sta memmove_src+0 - lda memmove_src+1 + sbc __memmove_size+0 + sta __memmove_src+0 + lda __memmove_src+1 sbc #0 - sta memmove_src+1 + sta __memmove_src+1 - lda memmove_dst+0 + lda __memmove_dst+0 sec - sbc memmove_size+0 - sta memmove_dst+0 - lda memmove_dst+1 + sbc __memmove_size+0 + sta __memmove_dst+0 + lda __memmove_dst+1 sbc #0 - sta memmove_dst+1 + sta __memmove_dst+1 // Now make exit easy, by being able to check for zero on size high byte when done - inc memmove_size+1 + inc __memmove_size+1 // Then set Y to the number offset required - ldy memmove_size+0 + ldy __memmove_size+0 iny - stx tokenise_work3 + stx __tokenise_work3 // jsr printf // .text "REVISED BOUNDS $" - // .byte $f1,memmove_size - // .byte $f0,memmove_size + // .byte $f1,<__memmove_size,>__memmove_size + // .byte $f0,<__memmove_size,>__memmove_size // .text " BYTES FROM $" - // .byte $f1,memmove_src - // .byte $f0,memmove_src + // .byte $f1,<__memmove_src,>__memmove_src + // .byte $f0,<__memmove_src,>__memmove_src // .text " TO $" - // .byte $f1,memmove_dst - // .byte $f0,memmove_dst + // .byte $f1,<__memmove_dst,>__memmove_dst + // .byte $f0,<__memmove_dst,>__memmove_dst // .byte $0d,0 // Do the copy @@ -105,12 +105,24 @@ basic_shift_mem_up_and_relink: // pointer to itself, so that we can add the shift // to make it end up pointing to the next line ldy #0 - ldx #basic_end_of_text_ptr - // .byte $f0,basic_end_of_text_ptr + // .byte $f1,VARTAB + // .byte $f0,VARTAB // .text $d," BEFORE = $" - // .byte $f1,memmove_dst - // .byte $f0,memmove_dst + // .byte $f1,<__memmove_dst,>__memmove_dst + // .byte $f0,<__memmove_dst,>__memmove_dst // .text ", AFTER = $" - // .byte $f1,memmove_src - // .byte $f0,memmove_src + // .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 #packed_keywords - sta temp_string_ptr+1 + sta FRESPC+1 // Subtract $80 from token to get offset in word // list @@ -103,7 +127,7 @@ list_not_quote: // 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 + sta QTSW // 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: @@ -120,7 +144,6 @@ list_end_of_line: lda #$92 jsr JCHROUT // Print end of line - lda #$0d - jsr JCHROUT - rts + jmp print_return + diff --git a/c64/basic/cmd_load.s b/c64/basic/cmd_load.s index a01a365e..2af77bd3 100644 --- a/c64/basic/cmd_load.s +++ b/c64/basic/cmd_load.s @@ -13,7 +13,7 @@ cmd_load: // Setup Kernal to print control messages or not lda #$80 // display control messages and omit error messages - ldx basic_current_line_number+1 + ldx CURLIN+1 cpx #$FF beq !+ lda #$00 // direct mode - don't display anything @@ -36,11 +36,11 @@ cmd_load: 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 - + lda TXTPTR+0 + sta FNADDR+0 + lda TXTPTR+1 + sta FNADDR+1 + // Now search for end of line or closing quote // so that we know the length of the filename getting_filename: @@ -60,47 +60,50 @@ got_filename: // Now fetch the file number, start from the default one jsr select_device - stx current_device_number + stx FA jsr injest_comma bcs got_devicenumber jsr basic_parse_line_number - lda basic_line_number+1 + lda LINNUM+1 beq !+ jmp do_ILLEGAL_QUANTITY_error !: - lda basic_line_number+0 - sta current_device_number + lda LINNUM+0 + sta FA got_devicenumber: // Now fetch the secondary address lda #$00 - sta current_secondary_address + sta SA jsr injest_comma bcs got_secondaryaddress jsr basic_parse_line_number - lda basic_line_number+1 + lda LINNUM+1 bne !+ - lda basic_line_number+0 - sta current_secondary_address + lda LINNUM+0 + sta SA 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' - ldx basic_line_number+0 - ldy basic_line_number+1 + ldx LINNUM+0 + ldy LINNUM+1 bne got_loadaddress got_secondaryaddress: - ldx #<$0801 // XXX use start text vector - ldy #>$0801 + ldy TXTTAB+1 + ldx TXTTAB+0 got_loadaddress: lda #$00 // LOAD not verify - jsr via_ILOAD + jsr JLOAD + php + jsr print_return + plp bcc !+ // A = KERNAL error code, which also almost match @@ -112,8 +115,8 @@ got_loadaddress: !: // $YYXX is the last loaded address, so store it - stx basic_end_of_text_ptr+0 - sty basic_end_of_text_ptr+1 + stx VARTAB+0 + sty VARTAB+1 // Now relink the loaded program, as we cannot trust the line // links supplied. For example, the VICE virtual drive emulation @@ -124,29 +127,29 @@ got_loadaddress: // or go back to the READY prompt if LOAD was called from direct mode. // 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 + jsr init_oldtxt // 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 - 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: + // Start by getting pointer to the first line + jsr init_oldtxt + +basic_relink_loop: // Is the pointer to the end of the program ldy #1 - ldx #$0801 - sta basic_start_of_text_ptr+1 - sta basic_start_of_vars_ptr+1 + sta TXTTAB+1 + sta VARTAB+1 lda #<$0803 - sta basic_start_of_vars_ptr+0 + sta VARTAB+0 // Zero line pointer - // XXX - We should also zero $0800, i.e., basic_start_of_text_ptr - 1 + // XXX - We should also zero $0800, i.e., TXTTAB - 1 ldy #$00 tya - sta (basic_start_of_text_ptr),y + sta (TXTTAB),y iny - sta (basic_start_of_text_ptr),y + sta (TXTTAB),y // Get top of memory. @@ -39,29 +39,42 @@ basic_do_new: // 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 jsr JMEMTOP cpx #$80 beq !+ - lda #>$f7ff +#if CONFIG_MEMORY_MODEL_60K + lda #>$F7FF +#else // CONFIG_MEMORY_MODEL_38K + lda #>$A000 +#endif .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 - +!: +#if CONFIG_MEMORY_MODEL_60K + lda #>$F7FF +#else // CONFIG_MEMORY_MODEL_38K + lda #>$A000 +#endif + sta MEMSIZ+1 + sta FRETOP+1 +#if CONFIG_MEMORY_MODEL_60K + lda #<$F7FF +#else // CONFIG_MEMORY_MODEL_38K + lda #<$A000 +#endif + sta MEMSIZ+0 + sta FRETOP+0 + // FALL THROUGH - + basic_do_clr: // 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 - lda basic_start_of_vars_ptr+1 - sta basic_start_of_arrays_ptr+1 - sta basic_start_of_free_space_ptr+1 + lda VARTAB+0 + sta ARYTAB+0 + sta STREND+0 + lda VARTAB+1 + sta ARYTAB+1 + sta STREND+1 rts diff --git a/c64/basic/cmd_run.s b/c64/basic/cmd_run.s index 83b3c12c..fefd6e6d 100644 --- a/c64/basic/cmd_run.s +++ b/c64/basic/cmd_run.s @@ -1,13 +1,13 @@ cmd_run: // RUN clears all variables jsr basic_do_clr -cmd_goto: +cmd_goto: // 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 - + lda TXTTAB+0 + sta OLDTXT+0 + lda TXTTAB+1 + sta OLDTXT+1 + jsr basic_end_of_statement_check bcs !+ diff --git a/c64/basic/cmd_sys.s b/c64/basic/cmd_sys.s index 2ca529d0..0f46f630 100644 --- a/c64/basic/cmd_sys.s +++ b/c64/basic/cmd_sys.s @@ -12,9 +12,9 @@ cmd_sys: // setup call lda #$4C // JMP opcode sta USRPOK - lda basic_line_number+0 + lda LINNUM+0 sta USRADD+0 - lda basic_line_number+1 + lda LINNUM+1 sta USRADD+1 // Setup the register values diff --git a/c64/basic/cmd_unimplemented.s b/c64/basic/cmd_unimplemented.s index 67ec4811..ffdffd96 100644 --- a/c64/basic/cmd_unimplemented.s +++ b/c64/basic/cmd_unimplemented.s @@ -1,82 +1,156 @@ +// // Default handler for all not-yet-implemented commands +// +// Note: NOPs are here just to make debugging easier! +// cmd_for: + nop cmd_next: + nop cmd_data: + nop cmd_inputhash: + nop cmd_input: + nop cmd_dim: + nop cmd_read: + nop cmd_let: + nop cmd_if: + nop cmd_restore: + nop cmd_gosub: + nop cmd_return: + nop // $90-$9F + cmd_on: + nop cmd_wait: + nop cmd_save: + nop cmd_verify: + nop cmd_def: + nop cmd_poke: + nop cmd_printhash: + nop cmd_print: + nop cmd_cont: + nop cmd_cmd: + nop cmd_open: - + nop + // $A0-$AF + cmd_close: + nop cmd_get: + nop cmd_tab: + nop cmd_to: + nop cmd_fn: + nop cmd_spc: + nop cmd_then: + nop cmd_not: + nop cmd_step: + nop cmd_plus: + nop cmd_minus: + nop cmd_mult: + nop cmd_div: + nop cmd_exponent: + nop cmd_and: - + nop + // $B0-$BF + cmd_or: + nop cmd_greater: + nop cmd_equal: + nop cmd_less: + nop cmd_sgn: + nop cmd_int: + nop cmd_abs: + nop cmd_usr: + nop cmd_fre: + nop cmd_pos: + nop cmd_sqr: + nop cmd_rnd: + nop cmd_log: + nop cmd_exp: + nop cmd_cos: + nop cmd_sin: - + nop + // $C0-$CF + cmd_tan: + nop cmd_atn: + nop cmd_peek: + nop cmd_len: + nop cmd_str: + nop cmd_val: + nop cmd_asc: + nop cmd_chr: + nop cmd_left: + nop cmd_right: + nop cmd_mid: + nop cmd_go: - + nop + // Undefined tokens + cmd_unimplemented: - jmp do_NOT_IMPLEMENTED_error diff --git a/c64/basic/do_basic_error.s b/c64/basic/do_basic_error.s index e41822bf..31bd947f 100644 --- a/c64/basic/do_basic_error.s +++ b/c64/basic/do_basic_error.s @@ -120,17 +120,16 @@ do_TO_MANY_FILES_error: lda $EA and #$80 sta $EA - + // FALL THROUGH // Error # in X - -do_basic_error: + +do_basic_error: // "?" txa pha - lda #$0d - jsr JCHROUT + jsr print_return lda #$3f jsr JCHROUT pla @@ -140,33 +139,29 @@ do_basic_error: jsr print_packed_message // A space between error name and word error - lda #$20 - jsr $ffd2 - + jsr print_space + // "ERROR" ldx #33 jsr print_packed_message - lda basic_current_line_number+1 + lda CURLIN+1 cmp #$ff beq !+ // We were in a program, so show IN - jsr printf // XXX don't use printf, use packed messages - .text " IN " - .byte 0 + ldx #37 + jsr print_packed_message - lda basic_current_line_number+1 - ldx basic_current_line_number+0 + lda CURLIN+1 + ldx CURLIN+0 jsr print_integer !: // New lines - lda #$0d - jsr $ffd2 + jsr print_return lda #$00 - jsr $ffd2 + jsr JCHROUT // XXX - Restore stack depth first? jmp basic_main_loop - diff --git a/c64/basic/e38b.error.s b/c64/basic/e38b.error.s new file mode 100644 index 00000000..43954f1d --- /dev/null +++ b/c64/basic/e38b.error.s @@ -0,0 +1,13 @@ + +// +// Official BASIC routine, described in: +// +// - [RG64] C64 Programmer's Reference Guide - XXX +// - [CM64] Compute's Mapping the Commodore 64 - page 69, XXX +// +// CPU registers that has to be preserved (see [RG64]): XXX +// + + +ERROR: + STUB_IMPLEMENTATION() diff --git a/c64/basic/e38b.interop b/c64/basic/e38b.interop new file mode 100644 index 00000000..ac77e1bd --- /dev/null +++ b/c64/basic/e38b.interop @@ -0,0 +1,9 @@ +All the BASIC routines, for which there are vectors in $0300-$030B, have to be available at their original addresses. + +Reason: some autostart software (https://codebase64.org/doku.php?id=base:autostarting_disk_files) override these vectors, so that some point +to new locations (usually Kernal related), while others points the original BASIC routines. Different techniques modify different vectors +(while resetting others to original C64 locations), some don't change the vectors at all, but might still put the original +C64 BASIC addresses there. + +For various cartridges this just means disabling their extensions (like new commands); for us that would mean improperly functionning BASIC. + diff --git a/c64/basic/e3bf.init.s b/c64/basic/e3bf.init.s new file mode 100644 index 00000000..884154f6 --- /dev/null +++ b/c64/basic/e3bf.init.s @@ -0,0 +1,5 @@ + +// XXX provide documentation and implementation + +INIT: + STUB_IMPLEMENTATION() diff --git a/c64/basic/e3bf.interop b/c64/basic/e3bf.interop new file mode 100644 index 00000000..f5ae9e65 --- /dev/null +++ b/c64/basic/e3bf.interop @@ -0,0 +1,3 @@ +This routine is mentionned in the cartridge writing tutorial here: https://codebase64.org/doku.php?id=base:assembling_your_own_cart_rom_image + +We have to implement (or at least provide stub), otherwise cartridges will crash. diff --git a/c64/basic/e422.initmsg.s b/c64/basic/e422.initmsg.s new file mode 100644 index 00000000..2520c5bd --- /dev/null +++ b/c64/basic/e422.initmsg.s @@ -0,0 +1,44 @@ + +// +// Well-known BASIC routine, described in: +// +// - [CM64] Compute's Mapping the Commodore 64 - page 212 +// +// Prints the start-up messages +// + +INITMSG: + + // Print startup banner, up to 255 characters + ldx #$00 +!: + lda startup_banner, x + beq !+ // 0 means end of banner + jsr JCHROUT + inx + bne !- + +!: + // Print PAL/NTSC + ldx #30 // NTSC + lda TVSFLG + beq !+ + ldx #31 // PAL +!: + jsr print_packed_message + + // Work out free bytes, display them + jsr basic_do_new + sec + lda MEMSIZ+0 + sbc TXTTAB+0 + tax + lda MEMSIZ+1 + sbc TXTTAB+1 + + jsr print_integer + jsr print_space + + // Print rest of the start up message + ldx #34 + jmp print_packed_message diff --git a/c64/basic/e422.interop b/c64/basic/e422.interop new file mode 100644 index 00000000..f5ae9e65 --- /dev/null +++ b/c64/basic/e422.interop @@ -0,0 +1,3 @@ +This routine is mentionned in the cartridge writing tutorial here: https://codebase64.org/doku.php?id=base:assembling_your_own_cart_rom_image + +We have to implement (or at least provide stub), otherwise cartridges will crash. diff --git a/c64/basic/e453.interop b/c64/basic/e453.interop new file mode 100644 index 00000000..f5ae9e65 --- /dev/null +++ b/c64/basic/e453.interop @@ -0,0 +1,3 @@ +This routine is mentionned in the cartridge writing tutorial here: https://codebase64.org/doku.php?id=base:assembling_your_own_cart_rom_image + +We have to implement (or at least provide stub), otherwise cartridges will crash. diff --git a/c64/basic/e453.rvect.s b/c64/basic/e453.rvect.s new file mode 100644 index 00000000..916e26fd --- /dev/null +++ b/c64/basic/e453.rvect.s @@ -0,0 +1,5 @@ + +// XXX provide documentation and implementation + +RVECT: + STUB_IMPLEMENTATION() diff --git a/c64/basic/fac1_mul.s b/c64/basic/fac1_mul.s index f3618aa6..4b60948f 100644 --- a/c64/basic/fac1_mul.s +++ b/c64/basic/fac1_mul.s @@ -3,25 +3,25 @@ // 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 +// This should be done using BITS to // hold the overflow bits, so that the result can // be exponent adjusted after, if required. fac1_mul10: lda #$00 - sta basic_fac1_overflow + sta BITS // Multiply mantissa by 2 jsr fac1_mantissa_mul2 // copy down to BASIC numeric work area at $57 - // (basic_numeric_work_area) + // (TEMPF1) // (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 - sta basic_numeric_work_area,x + lda FAC1_mantissa,x + sta TEMPF1,x dex bpl f1m10_l1 @@ -33,21 +33,21 @@ f1m10_l1: ldy #3 ldx #0 clc -f1m10_l2: - lda basic_fac1_mantissa,x - adc basic_numeric_work_area,x - sta basic_fac1_mantissa,x +f1m10_l2: + lda FAC1_mantissa,x + adc TEMPF1,x + sta FAC1_mantissa,x inx dey bpl f1m10_l2 - lda basic_fac1_overflow - adc basic_numeric_work_area+7 - sta basic_fac1_overflow + lda BITS + adc TEMPF1+7 + sta BITS // Now shift right and increase exponent until overflow // bits = $00 f1m10_l3: - lda basic_fac1_overflow + lda BITS bne !+ // All done, return clc @@ -55,8 +55,8 @@ f1m10_l3: !: // Divide mantissa by two, and increment exponent jsr fac1_mantissa_div2 - inc basic_fac1_exponent - lda basic_fac1_exponent + inc FAC1_exponent + lda FAC1_exponent bpl f1m10_l3 // Exponent has bit 7 set, so has wrapped. // = OVERFLOW ERROR @@ -68,30 +68,30 @@ fac1_mantissa_mul2: clc f1m1_l1: // Multiply mantissa by 2, and store overflow - // in basic_fac1_bits - lda basic_fac1_mantissa,x + // in FAC1_bits + lda FAC1_mantissa,x rol - sta basic_fac1_mantissa,x + sta FAC1_mantissa,x inx dey bpl f1m1_l1 - lda basic_fac1_overflow + lda BITS rol - sta basic_fac1_overflow + sta BITS rts fac1_mantissa_div2: // Divide mantissa by 2, including using overflow bits clc - lda basic_fac1_overflow + lda BITS ror - sta basic_fac1_overflow + sta BITS ldy #3 f1md2_l1: - lda basic_fac1_mantissa,y + lda FAC1_mantissa,y ror - sta basic_fac1_mantissa,y + sta FAC1_mantissa,y dey bpl f1md2_l1 rts diff --git a/c64/basic/init_oldtxt.s b/c64/basic/init_oldtxt.s new file mode 100644 index 00000000..6becf049 --- /dev/null +++ b/c64/basic/init_oldtxt.s @@ -0,0 +1,9 @@ + +init_oldtxt: + + lda TXTTAB+0 + sta OLDTXT+0 + lda TXTTAB+1 + sta OLDTXT+1 + + rts diff --git a/c64/basic/injest_number.s b/c64/basic/injest_number.s index 948ddc82..6266e036 100644 --- a/c64/basic/injest_number.s +++ b/c64/basic/injest_number.s @@ -1,6 +1,6 @@ -// Parse a number from the input buffer at (basic_current_statement_ptr) +// Parse a number from the input buffer at (TXTPTR) // Result is put into FAC1. -// basic_current_statement_ptr is updated with first position after the number. +// TXTPTR is updated with first position after the number. // XXX - Remember decimal position and exponent, and apply them // after to produce normalised floating point number. @@ -20,7 +20,7 @@ ij_not_a_digit: // Look for decimal point cmp #$2e bne ij_not_decimal - lda tokenise_work4 + 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 @@ -33,7 +33,7 @@ ij_found_decimal: // can do the necessary number of divide by 10s on the final // number. lda #$00 - sta tokenise_work4 + sta __tokenise_work4 jmp ij_consider_next_digit @@ -48,29 +48,26 @@ injest_number: // Clear decimal position flag lda #$ff - sta tokenise_work4 + sta __tokenise_work4 // 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 + lda (TXTPTR),y cmp #$AB - bne ij_not_minus + bne ij_loop1 // not minus // Set sign to negative lda #$ff - sta basic_fac1_sign + sta FAC1_sign // Skip over the minus sign jsr basic_consume_character - -ij_not_minus: - ij_loop1: ldy #$00 - lda (basic_current_statement_ptr),y + lda (TXTPTR),y cmp #$30 bcc ij_not_a_digit cmp #$3a @@ -80,7 +77,7 @@ ij_loop1: // Only add digit if we have not overflowed the accuracy of // the mantissa - lda basic_fac1_exponent + lda FAC1_exponent beq ij_accept_precision // We have an extra digit after saturating our precision. @@ -89,7 +86,7 @@ ij_loop1: // If we have seen a decimal point, then we can completely ignore // the digit, as it is contributing not recordable information - lda tokenise_work4 + lda __tokenise_work4 cmp #$ff bne ij_seen_decimal_point @@ -103,25 +100,25 @@ ij_accept_precision: // we can add the new digit in jsr fac1_mul10 - lda basic_fac1_exponent + lda FAC1_exponent bne ij_consider_next_digit // Get digit ldy #$00 - lda (basic_current_statement_ptr),y + lda (TXTPTR),y sec sbc #$30 // Add to FAC1 mantissa clc - adc basic_fac1_mantissa+0 - sta basic_fac1_mantissa+0 + adc FAC1_mantissa+0 + sta FAC1_mantissa+0 ldx #1 ldy #3 ij_loop2: - lda basic_fac1_mantissa,x + lda FAC1_mantissa,x adc #$00 - sta basic_fac1_mantissa,x + sta FAC1_mantissa,x inx dey bne ij_loop2 @@ -146,10 +143,10 @@ erase_fac1: lda #$00 ldx #8 !: - sta basic_fac1_exponent,x + sta FAC1_exponent,x dex bpl !- - sta basic_fac1_mantissa_lob + sta FACOV rts diff --git a/c64/basic/pack_word.s b/c64/basic/pack_word.s index 74eca527..b332d8e2 100644 --- a/c64/basic/pack_word.s +++ b/c64/basic/pack_word.s @@ -13,30 +13,30 @@ 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 + // __tokenise_work1 = number of bytes to pack + // __tokenise_work2 = packed length of string // 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. + // __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 - lda tokenise_work1 + lda __tokenise_work1 bne !+ sec rts !: // Initialise internal variables lda #$00 - sta tokenise_work2 - sta tokenise_work3 + sta __tokenise_work2 + sta __tokenise_work3 pack_char_loop: @@ -56,13 +56,13 @@ pack_char_loop: // either $FE or $FF, depending on whether this is the last // byte or not - lda tokenise_work3 + 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 inx - lda tokenise_work1 + lda __tokenise_work1 cmp #$01 beq at_end lda #$FF @@ -80,11 +80,11 @@ output_exception_byte: have_nybl_before_exception_char: // Or existing byte with #$0F, and clear nybl flag - ldy tokenise_work2 + ldy __tokenise_work2 lda $0100,y ora #$0f sta $0100,y - inc tokenise_work2 + inc __tokenise_work2 // FALL THROUGH @@ -92,7 +92,7 @@ write_literal_and_terminate_if_required: // Clear have nybl flag lda #$00 - sta tokenise_work3 + sta __tokenise_work3 lda $0200,x jsr write_unpacked_char @@ -102,7 +102,7 @@ write_literal_and_terminate_if_required: end_string_if_required: // Check if X points to last char of string to be packed inx - lda tokenise_work1 + lda __tokenise_work1 cmp #$01 beq !+ dex @@ -118,10 +118,10 @@ end_string: rts write_unpacked_char: - ldy tokenise_work2 + ldy __tokenise_work2 sta $0100,y iny - sty tokenise_work2 + sty __tokenise_work2 rts not_exception_char: @@ -130,7 +130,7 @@ not_exception_char: bcs whole_byte_symbol // Nybl encoded value: Put in upper half or lower half of a byte? - ldy tokenise_work3 + ldy __tokenise_work3 bne store_low_nybl // Store in high nybl -- so shift it into the hi nybl @@ -138,26 +138,26 @@ not_exception_char: asl asl asl - ldy tokenise_work2 + ldy __tokenise_work2 sta $0100,y 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 - ldy tokenise_work2 + ldy __tokenise_work2 ora $0100,y sta $0100,y stored_nybl: // Now toggle the nybl flag - lda tokenise_work3 + lda __tokenise_work3 eor #$ff - sta tokenise_work3 + 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 // Count the filled up byte - inc tokenise_work2 + inc __tokenise_work2 // Add termination byte if required // (This re-writes the same byte again, which we don't care about) @@ -168,15 +168,15 @@ whole_byte_symbol: // But if we have a nybl to flush, then we handle it like // a full exception character - ldy tokenise_work3 + ldy __tokenise_work3 beq nothing_to_flush // Set low nybl to $F to mark next byte as literal - ldy tokenise_work2 + ldy __tokenise_work2 lda $0100,y ora #$0f sta $0100,y - inc tokenise_work2 + inc __tokenise_work2 jmp write_literal_and_terminate_if_required @@ -190,7 +190,7 @@ nothing_to_flush: consider_next_char: // Pack next char inx - dec tokenise_work1 + dec __tokenise_work1 beq !+ jmp pack_char_loop !: @@ -198,18 +198,18 @@ consider_next_char: // (but leave flag set so the caller knows if the // bottom nybl might be different if the string were // longer). - lda tokenise_work3 + lda __tokenise_work3 beq !+ - inc tokenise_work2 + 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) - ldy tokenise_work2 + ldy __tokenise_work2 iny lda #$00 sta $0100,y - inc tokenise_work2 + inc __tokenise_work2 rts diff --git a/c64/basic/peek_pointer_null_check.s b/c64/basic/peek_line_pointer_null_check.s similarity index 54% rename from c64/basic/peek_pointer_null_check.s rename to c64/basic/peek_line_pointer_null_check.s index c594664c..e71a8d56 100644 --- a/c64/basic/peek_pointer_null_check.s +++ b/c64/basic/peek_line_pointer_null_check.s @@ -1,20 +1,34 @@ // Return C=1 if a pointer in BASIC memory space is NULL, else C=0 // X = ZP pointer to check -peek_pointer_null_check: +peek_line_pointer_null_check: + ldy #$00 + +#if CONFIG_MEMORY_MODEL_60K + ldx #packed_message_words - sta temp_string_ptr+1 + sta FRESPC+1 // Find the word in the list ldy #$ff @@ -69,14 +68,14 @@ packed_word_search: beq found_packed_word // $x0 is an end of work marker - lda (temp_string_ptr),y + lda (FRESPC),y and #$0f cmp #$00 bne !+ dex !: // $FE $xx is an end of work marker - lda (temp_string_ptr),y + lda (FRESPC),y cmp #$fe bne !+ dex @@ -90,7 +89,7 @@ packed_word_search: // Advance to next page if required cpy #$ff bne packed_word_search - inc temp_string_ptr+1 + inc FRESPC+1 jmp packed_word_search found_packed_word: @@ -99,11 +98,11 @@ found_packed_word: // Make sure we don't wrap on a page boundary tya clc - adc temp_string_ptr+0 - sta temp_string_ptr+0 - lda temp_string_ptr+1 + adc FRESPC+0 + sta FRESPC+0 + lda FRESPC+1 adc #$00 - sta temp_string_ptr+1 + sta FRESPC+1 print_packed_string: ldy #$ff @@ -113,7 +112,7 @@ next_packed_word_char: iny // Check for end of word - lda (temp_string_ptr),y + lda (FRESPC),y cmp #$00 beq end_of_packed_word cmp #$fe @@ -124,13 +123,13 @@ next_packed_word_char: beq end_of_packed_word // Check if it is an uncommon char - lda (temp_string_ptr),y + lda (FRESPC),y and #$f0 cmp #$f0 beq is_uncommon_char // Is not an uncommon char, so get char of upper nybl - lda (temp_string_ptr),y + lda (FRESPC),y // Put high nybl into low bits of X lsr @@ -150,7 +149,7 @@ next_packed_word_char: // See if there is a char in the low nybl to print pla tay - lda (temp_string_ptr),y + lda (FRESPC),y and #$0f beq end_of_packed_word cmp #$0f @@ -182,7 +181,7 @@ no_lo_nybl_char: // If current byte has $0F in low nybl, then the next // byte is a whole byte. - lda (temp_string_ptr),y + lda (FRESPC),y and #$0f cmp #$0f beq next_is_literal_char @@ -207,7 +206,7 @@ unpack_literal_char: iny tya pha - lda (temp_string_ptr),y + lda (FRESPC),y jsr JCHROUT pla tay @@ -216,7 +215,7 @@ unpack_literal_char: is_uncommon_char: // Lower nybl has offset into low-frequency part of the table - lda (temp_string_ptr),y + lda (FRESPC),y and #$0f clc adc #14 diff --git a/c64/basic/printf.s b/c64/basic/printf.s deleted file mode 100644 index 3266710f..00000000 --- a/c64/basic/printf.s +++ /dev/null @@ -1,157 +0,0 @@ -// 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. - -// .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 - sta $7f0 - stx $7f1 - sty $7f2 - php - pla - sta $7f3 - - // Set up read routine - lda #$ad // LDA $nnnn - sta $7f4 - lda #$60 - sta $7f7 // RTS - - // Get PC of caller from the stack, so that - // we can parse through it - pla - clc - adc #$01 - sta $7f5 - pla - adc #$00 - sta $7f6 - -printf_loop: - jsr $7f4 - cmp #$00 - bne printf_continues - // Put return address on stack and restore - // registers - lda $7f6 - pha - lda $7f5 - pha - lda $7f3 - pha - lda $7f0 - ldx $7f1 - ldy $7f2 - plp - rts - -printf_continues: - cmp #$01 - bne not_hexbyte - // Print a hex byte - - // Skip the token - jsr printf_advance - // Read the low byte - jsr $7f4 - // Print as hex - jsr printf_printhexbyte - jmp printf_nextchar - -not_hexbyte: - cmp #$02 - bne not_hexword - // Print a hex word - - // Skip the token - jsr printf_advance - jsr printf_advance - // Read the high byte - jsr $7f4 - // Print as hex - jsr printf_printhexbyte - // Skip the token - jsr printf_retreat - // Read the low byte - jsr $7f4 - // Print as hex - jsr printf_printhexbyte - jsr printf_advance - jmp printf_nextchar - -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. - - // Get offset - and #$0f - tay - - jsr printf_advance - jsr $7f4 - sta $fd - jsr printf_advance - jsr $7f4 - sta $fe - - lda ($fd),y - jsr printf_printhexbyte - jmp printf_nextchar - -not_pointer: - // Print character - jsr JCHROUT - -printf_nextchar: - jsr printf_advance - - jmp printf_loop - -printf_advance: - // Advance pointer to next character - inc $7f5 - bne !+ - inc $7f6 -!: - rts - -printf_retreat: - // Retreat pointer to previous char - lda $7f5 - sec - sbc #1 - sta $7f5 - lda $7f6 - sbc #0 - sta $7f6 - rts - -printf_printhexbyte: - // Print the hex value in .A as two digits, idea by Haubitze - sed - pha - lsr - lsr - lsr - lsr - cmp #$0A - adc #$30 - jsr JCHROUT - pla - and #$0F - cmp #$0A - adc #$30 - cld - jmp JCHROUT diff --git a/c64/basic/select_device.s b/c64/basic/select_device.s index 30f15150..6d9a2e76 100644 --- a/c64/basic/select_device.s +++ b/c64/basic/select_device.s @@ -11,7 +11,7 @@ select_device: // Note: if tape support is introduced here, make sure DOS wedge won't get broken - ldx current_device_number + ldx FA cpx #$08 bcs !+ ldx #$08 diff --git a/c64/basic/startup_banner.s b/c64/basic/startup_banner.s new file mode 100644 index 00000000..957ab11d --- /dev/null +++ b/c64/basic/startup_banner.s @@ -0,0 +1,7 @@ + +// +// Startup banner, to be displayed durin cold start +// + +startup_banner: + TARGET_HOOK_BANNER() diff --git a/c64/basic/tokenise_line.s b/c64/basic/tokenise_line.s index 38e412b0..7a642834 100644 --- a/c64/basic/tokenise_line.s +++ b/c64/basic/tokenise_line.s @@ -1,6 +1,6 @@ // Tokenise a line of BASIC // Stored at $0200 -// Length in tokenise_work1 +// Length in __tokenise_work1 tokenise_line: @@ -17,9 +17,9 @@ tokenise_line: lda #$00 sta $0110 sta $0112 - sta quote_mode_flag + sta QTSW - lda tokenise_work1 + lda __tokenise_work1 sta $0113 tokenise_char: @@ -32,15 +32,15 @@ tokenise_char: // End of line reached // Finished tokenising line - // Update tokenise_work1 and terminate with null + // Update __tokenise_work1 and terminate with null ldx $0112 lda #$00 sta $0200,x - stx tokenise_work1 + stx __tokenise_work1 // Clear quote mode flag that is also used by KERNAL for screen display lda #$00 - sta quote_mode_flag + sta QTSW rts !: // More to do @@ -50,8 +50,8 @@ tokenise_char: 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 + // 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 @@ -60,9 +60,9 @@ tokenise_char_loop: bne tk_not_quote // Quote - lda quote_mode_flag + lda QTSW eor #$ff - sta quote_mode_flag + sta QTSW jmp tk_literal_char tk_not_quote: @@ -82,13 +82,13 @@ tk_not_quote: tk_might_be_keyword: // Don't tokenise in quote mode - lda quote_mode_flag + lda QTSW bne tk_literal_char // Pack string ldx $0110 lda $0111 - sta tokenise_work1 + sta __tokenise_work1 // XXX - We should implement an optimisation where we // trim the last symbol of successively, instead of re-packing the word @@ -97,7 +97,7 @@ tk_might_be_keyword: // that are available. jsr pack_word - lda tokenise_work2 + lda __tokenise_work2 cmp #$10 bcc !+ // Packed string too long @@ -137,9 +137,9 @@ found_token_in_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: - + sta QTSW +not_rem: + // Now skip over the length of the token lda $0110 clc @@ -162,31 +162,31 @@ 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 + // __tokenise_work1 = offset in line of input + // __tokenise_work2 = length of token we are matching + // __tokenise_work3 = offset in token list + // __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 + sta __tokenise_work1 + sta __tokenise_work3 next_kw_offset: // Advance offset in compressed keyword list, to see if a match // BEGINS here // Get count of bytes to compare - lda tokenise_work2 - sta load_or_verify_or_tokenise_work5 + lda __tokenise_work2 + sta __tokenise_work5 // Load current position - ldy tokenise_work3 - ldx tokenise_work1 + ldy __tokenise_work3 + ldx __tokenise_work1 // Advance offset in compressed token list, and stop at the end - inc tokenise_work3 - lda tokenise_work3 + inc __tokenise_work3 + lda __tokenise_work3 cmp #packed_keyword_table_len bne next_in_match jmp done_searching_for_token @@ -198,8 +198,8 @@ next_in_match: inx iny - dec load_or_verify_or_tokenise_work5 // Have we compared all bytes yet? - + dec __tokenise_work5 // Have we compared all bytes yet? + bne next_in_match // Keyword matches! @@ -212,7 +212,7 @@ next_in_match: // two byte prior is $FE // Get offset of first byte of this token - ldx tokenise_work3 + ldx __tokenise_work3 dex // pointer points one late, so rewind it // At start of list? @@ -233,7 +233,7 @@ next_in_match: jmp next_kw_offset word_boundary: - // Found a token whose offset is in tokenise_work3 + // Found a token whose offset is in __tokenise_work3 // Now trace back to the start of the compressed keyword list // to work out what keyword number we are, so that we can return // the token number. diff --git a/c64/basic/under_rom_routines.s b/c64/basic/under_rom_routines.s index e0e5a385..1027e57a 100644 --- a/c64/basic/under_rom_routines.s +++ b/c64/basic/under_rom_routines.s @@ -4,11 +4,13 @@ // in ,aliases.s. // Thus those addresses are expressed using formulae. +#if CONFIG_MEMORY_MODEL_60K + install_ram_routines: // Copy routines into place - ldx #ram_routines_end-ram_routines_start-1 + ldx #__ram_routines_end-__ram_routines_start-1 !: - lda ram_routines_start,x + lda __ram_routines_start,x sta tiny_nmi_handler,x dex bpl !- @@ -21,7 +23,7 @@ install_ram_routines: rts -ram_routines_start: +__ram_routines_start: // XXX - Routine order must match that of the KERNAL version of the file. // (since it has fewer routines) @@ -64,8 +66,8 @@ memmap_allram_routine: rts shift_mem_up_routine: - // Move memmove_size bytes from memmove_src to memmove_dst, - // where memmove_dst > memmove_src + // 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 @@ -73,20 +75,20 @@ shift_mem_up_routine: php jsr memmap_allram smu1: - lda (memmove_src),y - sta (memmove_dst),y + lda (__memmove_src),y + sta (__memmove_dst),y dey bne smu1 - dec memmove_src+1 - dec memmove_dst+1 - dec memmove_size+1 + dec __memmove_src+1 + dec __memmove_dst+1 + dec __memmove_size+1 bne smu1 plp jmp memmap_normal shift_mem_down_routine: - // Move memmove_size bytes from memmove_src to memmove_dst, - // where memmove_dst > memmove_src + // 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 @@ -94,15 +96,59 @@ shift_mem_down_routine: php jsr memmap_allram smd1: - lda (memmove_src),y - sta (memmove_dst),y + lda (__memmove_src),y + sta (__memmove_dst),y iny bne smd1 - inc memmove_src+1 - inc memmove_dst+1 - dec memmove_size+1 + inc __memmove_src+1 + inc __memmove_dst+1 + dec __memmove_size+1 bne smd1 plp jmp memmap_normal -ram_routines_end: +__ram_routines_end: + +#else // CONFIG_MEMORY_MODEL_60K + +shift_mem_up: + // 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 +smu1: + lda (__memmove_src),y + sta (__memmove_dst),y + dey + bne smu1 + dec __memmove_src+1 + dec __memmove_dst+1 + dec __memmove_size+1 + bne smu1 + plp + rts + +shift_mem_down: + // 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 +smd1: + lda (__memmove_src),y + sta (__memmove_dst),y + iny + bne smd1 + inc __memmove_src+1 + inc __memmove_dst+1 + dec __memmove_size+1 + bne smd1 + plp + rts + +#endif diff --git a/c64/basic/wedge_dos.s b/c64/basic/wedge_dos.s index 7259d131..47322a6a 100644 --- a/c64/basic/wedge_dos.s +++ b/c64/basic/wedge_dos.s @@ -1,5 +1,5 @@ -// START wedge support +#if CONFIG_DOS_WEDGE wedge_dos: @@ -16,7 +16,7 @@ wedge_dos: // Check if user asked for a status ldy #$00 - lda (basic_current_statement_ptr), y + lda (TXTPTR), y bne !+ jmp wedge_dos_status // XXX try to optimize this, perhaps move 'wedge_dos_status' above? !: @@ -31,7 +31,7 @@ wedge_dos: cmp #$3A bcs wedge_dos_command // char code after 9 iny - lda (basic_current_statement_ptr), y + lda (TXTPTR), y beq wedge_dos_change_drive // end of buffer cmp #$20 beq wedge_dos_change_drive @@ -64,17 +64,17 @@ wedge_dos_change_drive: // Reuse the line number parser for device number retrieval jsr basic_parse_line_number - lda basic_line_number+1 + lda LINNUM+1 beq !+ jmp do_ILLEGAL_QUANTITY_error !: - lda basic_line_number+0 + lda LINNUM+0 cmp #$08 bpl !+ bcs !+ jmp do_ILLEGAL_DEVICE_NUMBER_error !: - sta current_device_number + sta FA jmp basic_end_of_line wedge_dos_status_get: @@ -139,7 +139,7 @@ wedge_dos_directory: // First change the secondary address to the one suitable for // directory loading lda #$00 // logical device number - ldx current_device_number + ldx FA ldy #$60 jsr JSETFLS @@ -195,10 +195,10 @@ wedge_dos_directory_display: // Display line ldx #BUF - stx basic_current_line_ptr+1 - ldx #basic_current_line_ptr + stx OLDTXT+1 + ldx #OLDTXT jsr list_single_line // Read & display next line or quit @@ -209,8 +209,7 @@ wedge_dos_directory_display: wedge_dos_clean_exit: jsr JCLALL // Print new line - lda #$0D - jsr JCHROUT + jsr print_return jmp basic_end_of_line wedge_dos_basic_error: @@ -226,13 +225,13 @@ wedge_dos_setnam: ldy #$FF !: iny - lda (basic_current_statement_ptr), y + lda (TXTPTR), y bne !- // Set the name to open tya - ldx basic_current_statement_ptr+0 - ldy basic_current_statement_ptr+1 + ldx TXTPTR+0 + ldy TXTPTR+1 jmp JSETNAM -// END wedge support +#endif // CONFIG_DOS_WEDGE diff --git a/c64/kernal/,aliases.s b/c64/kernal/,aliases.s deleted file mode 100644 index 0d133ed5..00000000 --- a/c64/kernal/,aliases.s +++ /dev/null @@ -1,73 +0,0 @@ -// 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) - -// 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 - .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 - .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) - .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 - diff --git a/c64/kernal/,target_ultimate64/,aliases_ultimate64.s b/c64/kernal/,target_ultimate64/,aliases_ultimate64.s index 65e2d20a..5c8bd0dc 100644 --- a/c64/kernal/,target_ultimate64/,aliases_ultimate64.s +++ b/c64/kernal/,target_ultimate64/,aliases_ultimate64.s @@ -4,10 +4,8 @@ // and ultimate_dos_v1.0.pdf and command_interface_v1.0.pdf by Gideon Zweijtzer // 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_CONTROL_STATUS = $DF1C // write = CONTROL, read = STATUS + .label U64_COMMAND_DATA_IDENTIFY = $DF1D // write = COMMAND_DATA, read = IDENTIFICATION .label U64_RESPONSE_DATA = $DF1E // read only .label U64_STATUS_DATA = $DF1F // read only diff --git a/c64/kernal/cartridge_signature.s b/c64/kernal/assets/cartridge_signature.s similarity index 100% rename from c64/kernal/cartridge_signature.s rename to c64/kernal/assets/cartridge_signature.s diff --git a/c64/kernal/assets/colour_codes.s b/c64/kernal/assets/colour_codes.s new file mode 100644 index 00000000..fdf0b980 --- /dev/null +++ b/c64/kernal/assets/colour_codes.s @@ -0,0 +1,6 @@ + +// CHR$ codes for the 16 colours + +colour_codes: + .byte 144,5,28,159,156,30,31,158 + .byte 129,149,150,151,152,153,154,155 diff --git a/c64/kernal/assets/fd30.interop b/c64/kernal/assets/fd30.interop new file mode 100644 index 00000000..13c67365 --- /dev/null +++ b/c64/kernal/assets/fd30.interop @@ -0,0 +1,3 @@ +Location of the default Kernal vector values, described in Compute's Mapping the Commodore 64, page 237 + +It is referenced by GEOS - see https://github.com/mist64/geos/blob/master/inc/c64.inc diff --git a/c64/kernal/vector_defaults.s b/c64/kernal/assets/fd30.vector_defaults.s similarity index 100% rename from c64/kernal/vector_defaults.s rename to c64/kernal/assets/fd30.vector_defaults.s diff --git a/c64/kernal/assets/kernal_messages.s b/c64/kernal/assets/kernal_messages.s new file mode 100644 index 00000000..b87bce48 --- /dev/null +++ b/c64/kernal/assets/kernal_messages.s @@ -0,0 +1,44 @@ + +// +// Messages to be prined out by Kernal +// + +// Double underscore prevents labels from being passed to VICE (would confuse monitor) + +.label __MSG_KERNAL_SEARCHING_FOR = __kernal_message_searching_for - __kernal_messages_start +.label __MSG_KERNAL_LOADING = __kernal_message_loading - __kernal_messages_start +.label __MSG_KERNAL_VERIFYING = __kernal_message_verifying - __kernal_messages_start +.label __MSG_KERNAL_SAVING = __kernal_message_saving - __kernal_messages_start +.label __MSG_KERNAL_FROM_HEX = __kernal_message_from_hex - __kernal_messages_start +.label __MSG_KERNAL_TO_HEX = __kernal_message_to_hex - __kernal_messages_start + + +__kernal_messages_start: + +__kernal_message_searching_for: + .byte $0D + .text "SEARCHING FOR" + .byte $80 + $20 // end of string mark + space + +__kernal_message_loading: + .byte $0D + .text "LOADIN" + .byte $80 + $47 // end of string mark + 'G' + +__kernal_message_verifying: + .byte $0D + .text "VERIFYIN" + .byte $80 + $47 // end of string mark + 'G' + +__kernal_message_saving: + .byte $0D + .text "SAVIN" + .byte $80 + $47 // end of string mark + 'G' + +__kernal_message_from_hex: + .text " FROM " + .byte $80 + $24 // end of string mark + '$' + +__kernal_message_to_hex: + .text " TO " + .byte $80 + $24 // end of string mark + '$' diff --git a/c64/kernal/keyboard_matrix.s b/c64/kernal/assets/keyboard_matrix.s similarity index 100% rename from c64/kernal/keyboard_matrix.s rename to c64/kernal/assets/keyboard_matrix.s diff --git a/c64/kernal/blink_cursor.s b/c64/kernal/blink_cursor.s index 3135b4bd..5d3c5446 100644 --- a/c64/kernal/blink_cursor.s +++ b/c64/kernal/blink_cursor.s @@ -1,93 +1,96 @@ // We have the following variables: -// cursor_blink_disable -// cursor_blink_countdown -// cursor_saved_character -// cursor_is_visible -// colour_under_cursor +// BLNSW (cursor blink switch) +// BLNCT (cursor blink countdown) +// GDBLN (cursor saved character) +// BLNON (if cursor is visible) +// GDCOL (colour under cursor) +// USER (current screen line colour pointer) +// PNT (current screen line pointer) +// PNTR (current screen x position) show_cursor_if_enabled: - lda cursor_blink_disable + lda BLNSW beq !+ rts -!: lda cursor_is_visible +!: lda BLNON 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 lda #$00 - sta cursor_blink_countdown - sta cursor_is_visible + sta BLNCT + sta BLNON jsr blink_cursor // 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 + sta BLNCT rts - + blink_cursor: // Is the cursor enabled? - lda cursor_blink_disable + lda BLNSW bne no_blink_cursor // Do we need to redraw things? - dec cursor_blink_countdown + dec BLNCT bpl no_blink_cursor // Check if cursor was visible or not, and toggle - lda cursor_is_visible + lda BLNON bne undraw_cursor draw_cursor: jsr calculate_screen_line_pointer - ldy current_screen_x - lda (current_screen_line_ptr),y - sta cursor_saved_character + ldy PNTR + lda (PNT),y + sta GDBLN eor #$80 - sta (current_screen_line_ptr),y + sta (PNT),y // Also set cursor colour - lda (current_screen_line_colour_ptr),y - sta colour_under_cursor - lda text_colour - sta (current_screen_line_colour_ptr),y - + lda (USER),y + sta GDCOL + lda COLOR + sta (USER),y + lda #1 - sta cursor_is_visible - + sta BLNON + jmp reset_blink_timer undraw_cursor: jsr calculate_screen_line_pointer - lda cursor_saved_character - ldy current_screen_x - sta (current_screen_line_ptr),y - lda colour_under_cursor - sta (current_screen_line_colour_ptr),y + lda GDBLN + ldy PNTR + sta (PNT),y + lda GDCOL + sta (USER),y lda #0 - sta cursor_is_visible + sta BLNON // Fall through reset_blink_timer: // Rest blink counter // (Compute's Mapping the 64, p39-40) lda #20 - sta cursor_blink_countdown + sta BLNCT no_blink_cursor: rts disable_cursor: lda #$80 - sta cursor_blink_disable + sta BLNSW // FALL THROUGH hide_cursor_if_visible: - lda cursor_is_visible + lda BLNON bne undraw_cursor rts enable_cursor: lda #$00 - sta cursor_blink_disable + sta BLNSW rts diff --git a/c64/kernal/cartridge_check.s b/c64/kernal/cartridge_check.s index 09a58216..00221fb4 100644 --- a/c64/kernal/cartridge_check.s +++ b/c64/kernal/cartridge_check.s @@ -1,15 +1,13 @@ // c64 prg p263 cartridge_check: - ldx #$04 + ldx #$05 cartridge_check_l1: - lda CART_SIG,x - cmp cartridge_signature,x + lda CART_SIG-1,x + cmp cartridge_signature-1,x bne no_cartridge dex - bpl cartridge_check_l1 - sec - rts + bne cartridge_check_l1 + // FALLTROUGH no_cartridge: - clc rts diff --git a/c64/kernal/chrin_real.s b/c64/kernal/chrin_real.s index fed6552d..cbed585e 100644 --- a/c64/kernal/chrin_real.s +++ b/c64/kernal/chrin_real.s @@ -52,18 +52,18 @@ chrin_repeat: // If so, return the next byte, and clear the flag when we reach the end. // Do we have a line of input waiting? - lda keyboard_input_ready + lda CRSW 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 + // Yes, we have input waiting at (LXSP)+CRSW + // When CRSW = INDX, then we return a carriage return // and clear the flag - cmp end_of_input_line + cmp INDX bne not_end_of_input // Return carriage return and clear pending input flag lda #$00 - sta keyboard_input_ready + sta CRSW pla tax clc @@ -75,9 +75,9 @@ not_end_of_input: tay pla tax - lda (start_of_keyboard_input),y + lda (LXSP),y jsr screen_code_to_petscii - inc keyboard_input_ready + inc CRSW clc rts @@ -87,10 +87,10 @@ read_from_keyboard: jsr enable_cursor // Wait for a key - lda keys_in_key_buffer + lda NDX beq chrin_repeat - lda keyboard_buffer + lda KEYD cmp #$0d bne not_enter @@ -106,10 +106,10 @@ read_from_keyboard: // (Compute's Mapping the 64, p96) // 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 + lda PNT+0 + sta LXSP+0 + lda PNT+1 + sta LXSP+1 // Calculate length jsr get_current_line_logical_length @@ -117,18 +117,18 @@ read_from_keyboard: iny !: dey bmi empty_line - lda (current_screen_line_ptr),y + lda (PNT),y cmp #$20 beq !- iny - sty end_of_input_line + sty INDX lda #$01 - sta keyboard_input_ready + sta CRSW // Return first char of line ldy #$00 pla tax - lda (start_of_keyboard_input),y + lda (LXSP),y jsr screen_code_to_petscii clc rts @@ -145,7 +145,7 @@ empty_line: not_enter: // Print character - lda keyboard_buffer + lda KEYD jsr CHROUT jsr pop_keyboard_buffer @@ -160,13 +160,13 @@ pop_keyboard_buffer: sei ldx #$00 ldy #$01 -!: lda keyboard_buffer,y - sta keyboard_buffer,x +!: lda KEYD,y + sta KEYD,x inx iny - cpy key_buffer_size + cpy XMAX bne !- - dec keys_in_key_buffer + dec NDX cli rts diff --git a/c64/kernal/chrout_real.s b/c64/kernal/chrout_real.s index 190a4067..578383c0 100644 --- a/c64/kernal/chrout_real.s +++ b/c64/kernal/chrout_real.s @@ -11,7 +11,7 @@ chrout_real: - sta last_printed_character_ascii + sta SCHAR // Save X and Y values // (Confirmed by writing a test program that X and Y @@ -34,7 +34,7 @@ chrout_real: chrout_iec: - lda last_printed_character_ascii + lda SCHAR jsr JCIOUT bcc chrout_done @@ -77,7 +77,7 @@ chrout_done: tay pla tax - lda last_printed_character_ascii + lda SCHAR clc // indicate success rts @@ -88,7 +88,7 @@ chrout_screen: jsr hide_cursor_if_visible - lda last_printed_character_ascii + lda SCHAR tax // Check for special characters @@ -110,8 +110,8 @@ not_0a: bne not_0d // RETURN clears quote and insert modes lda #$00 - sta quote_mode_flag - sta insert_mode + sta QTSW + sta INSRT jmp screen_advance_to_next_line not_0d: @@ -125,7 +125,7 @@ not_0d: cmp #79 bne definitely_not_too_long tay - lda (current_screen_line_ptr),y + lda (PNT),y cmp #$20 beq definitely_not_too_long @@ -135,7 +135,7 @@ not_0d: definitely_not_too_long: // Work out if line needs to be expanded, and if so expand it ldy #39 - lda (current_screen_line_ptr),y + lda (PNT),y cmp #$20 beq no_need_to_extend @@ -155,89 +155,89 @@ no_need_to_extend: // though we really don't believe that the routine can be copyrighted // due to the lack of creativity. dey - lda (current_screen_line_colour_ptr),y + lda (USER),y iny - sta (current_screen_line_colour_ptr),y + sta (USER),y dey - lda (current_screen_line_ptr),y + lda (PNT),y iny - sta (current_screen_line_ptr),y + sta (PNT),y dey - cpy current_screen_x + cpy PNTR bne !- // Increase insert mode count (which causes quote-mode like behaviour) - inc insert_mode - + inc INSRT + // Put space in the inserted gap lda #$20 - sta (current_screen_line_ptr),y + sta (PNT),y jmp chrout_done not_94: // DELETE in insert mode embeds control character - ldx insert_mode + ldx INSRT bne not_14 cmp #$14 bne not_14 // Delete - ldx current_screen_x + ldx PNTR bne delete_non_zero_column delete_at_column_0: - ldy current_screen_y + ldy TBLX bne not_row_0 // delete from row 0, col 0 does nothing jmp chrout_done not_row_0: // Column 0 delete just moves us to the end of the // previous line, without actually deleting anything - dec current_screen_y + dec TBLX jsr get_current_line_logical_length - lda logical_line_length - - sta current_screen_x + lda LNMX + + sta PNTR jsr calculate_screen_line_pointer jmp chrout_done delete_non_zero_column: // Copy rest of line down jsr get_current_line_logical_length - ldy current_screen_x - cpy logical_line_length + ldy PNTR + cpy LNMX beq done_delete dey !: iny - lda (current_screen_line_ptr),y + lda (PNT),y dey - sta (current_screen_line_ptr),y + sta (PNT),y iny - lda (current_screen_line_colour_ptr),y + lda (USER),y dey - sta (current_screen_line_colour_ptr),y + sta (USER),y iny - cpy logical_line_length + cpy LNMX bne !- // Clear char at end of line jsr get_current_line_logical_length tay lda #$20 - sta (current_screen_line_ptr),y + sta (PNT),y done_delete: - dec current_screen_x - jmp chrout_done + dec PNTR + jmp chrout_done not_14: // Check for quote mode - ldx quote_mode_flag + ldx QTSW bne is_quote_mode - ldx insert_mode + ldx INSRT bne is_quote_mode jmp not_quote_mode @@ -274,7 +274,7 @@ not_quote_mode: colour_check_loop: cmp colour_codes,x bne !+ - stx text_colour + stx COLOR jmp chrout_done !: dex bpl colour_check_loop @@ -283,24 +283,24 @@ colour_check_loop: cmp #$12 bne not_12 lda #$80 - sta reverse_video_flag + sta RVS jmp chrout_done not_12: // Compute's Mapping the 64 p 38 cmp #$92 bne not_92 lda #$00 - sta reverse_video_flag + sta RVS jmp chrout_done not_92: // Check for cursor movement keys cmp #$11 bne not_11 - lda current_screen_x + lda PNTR clc adc #40 - sta current_screen_x + sta PNTR // We need to advance the pointer manually, as normalising // now will break things. The pointer update is required // so that we can tell if we really are on the bottom phys @@ -311,22 +311,22 @@ not_92: not_11: cmp #$1d bne not_1d - inc current_screen_x + inc PNTR jsr calculate_screen_line_pointer jmp chrout_done not_1d: cmp #$91 bne not_91 - lda current_screen_x + lda PNTR sec sbc #40 - sta current_screen_x + sta PNTR jsr calculate_screen_line_pointer jmp chrout_done not_91: cmp #$9d bne not_9d - dec current_screen_x + dec PNTR jsr calculate_screen_line_pointer jmp chrout_done not_9d: @@ -335,8 +335,8 @@ not_9d: cmp #$13 bne not_13 lda #0 - sta current_screen_x - sta current_screen_y + sta PNTR + sta TBLX jsr calculate_screen_line_pointer jmp chrout_done not_13: @@ -365,12 +365,12 @@ not_clearscreen: bcc !+ and #$7f - jmp not_high_char + jmp output_literal_char // not high char !: // Range $20-$3F is unchanged cmp #$40 - bcc not_high_char + bcc output_literal_char // not high char // Unshifted letters and symbols from $40-$5F // all end up being -$40 @@ -385,74 +385,70 @@ not_clearscreen: // Fix shifted chars by adding $20 again cmp #$20 - bcc not_high_char + bcc output_literal_char // not high char cmp #$40 - bcs not_high_char + bcs output_literal_char // not high char clc adc #$20 -not_high_char: - -chrout_l1: - output_literal_char: // Write normal character on the screen pha - ldy current_screen_x - ora reverse_video_flag // Compute's Mapping the 64 p38 - sta (current_screen_line_ptr),y + ldy PNTR + ora RVS // Compute's Mapping the 64 p38 + sta (PNT),y // Decrement number of chars waiting to be inserted - lda insert_mode + lda INSRT beq !+ - dec insert_mode + dec INSRT !: pla cmp #$22 bne not_quote // Toggle quote flag if required - lda quote_mode_flag + lda QTSW eor #$80 - sta quote_mode_flag + sta QTSW not_quote: // Set colour - lda text_colour - sta (current_screen_line_colour_ptr),y + lda COLOR + sta (USER),y // Advance the column, and scroll screen down if we need // to insert a 2nd line in this logical line. // (eg Compute's Mapping the 64 p41) - ldx current_screen_y + ldx TBLX iny - sty current_screen_x + sty PNTR cpy #40 bne !+ jsr screen_grow_logical_line - ldy current_screen_x + ldy PNTR !: cpy #80 bcc no_screen_advance_to_next_line lda #0 - sta current_screen_x + sta PNTR jmp screen_advance_to_next_line no_screen_advance_to_next_line: jmp chrout_done screen_grow_logical_line: - ldy current_screen_y + ldy TBLX // Don't grow line if it is already grown - lda screen_line_link_table,y + lda LDTBL,y bpl !+ - jmp done_grow_line + jmp not_last_line // doneb grow line !: lda #$80 - sta screen_line_link_table,y + sta LDTBL,y // Now make space for the extra line added. // If we are on the last physical line of the screen, @@ -471,11 +467,11 @@ screen_grow_logical_line: ldy #0 count_rows_loop: dex - lda screen_line_link_table,y + lda LDTBL,y bpl !+ dex !: iny - cpy current_screen_y + cpy TBLX bne count_rows_loop cpx #0 @@ -493,28 +489,28 @@ count_rows_loop: lda HIBASE clc adc #3 - sta current_screen_line_ptr+1 - sta load_or_scroll_temp_pointer+1 + sta PNT+1 + sta SAL+1 lda #>$DBC0 - sta load_save_verify_end_address+1 - sta current_screen_line_colour_ptr+1 + sta EAL+1 + sta USER+1 lda #<$03C0 - sta current_screen_line_ptr+0 - sta current_screen_line_colour_ptr+0 + sta PNT+0 + sta USER+0 // souce address is line above sec sbc #40 - sta load_or_scroll_temp_pointer+0 - sta load_save_verify_end_address+0 + sta SAL+0 + sta EAL+0 copy_line_down_loop: ldy #39 cl_inner: - lda (load_save_verify_end_address),y - sta (current_screen_line_colour_ptr),y - lda (load_or_scroll_temp_pointer),y - sta (current_screen_line_ptr),y + lda (EAL),y + sta (USER),y + lda (SAL),y + sta (PNT),y dey bpl cl_inner @@ -523,29 +519,29 @@ cl_inner: // Old source is new destination // Use different registers to minimise byte similarity with C64 KERNAl - ldy load_or_scroll_temp_pointer+1 - sty current_screen_line_ptr+1 - lda load_save_verify_end_address+1 - ldy load_or_scroll_temp_pointer+0 - sta current_screen_line_colour_ptr+1 - sty current_screen_line_ptr+0 - sty current_screen_line_colour_ptr+0 + ldy SAL+1 + sty PNT+1 + lda EAL+1 + ldy SAL+0 + sta USER+1 + sty PNT+0 + sty USER+0 // Decrementing source pointers - lda load_or_scroll_temp_pointer+0 + lda SAL+0 sec sbc #<40 - sta load_or_scroll_temp_pointer+0 - sta load_save_verify_end_address+0 - lda load_or_scroll_temp_pointer+1 + sta SAL+0 + sta EAL+0 + lda SAL+1 sbc #>40 - sta load_or_scroll_temp_pointer+1 + sta SAL+1 // convert to screen equivalent sec sbc HIBASE clc adc #>$D800 - sta load_save_verify_end_address+1 + sta EAL+1 dex bne copy_line_down_loop @@ -556,17 +552,16 @@ no_copy_down: // Erase newly inserted line ldy #79 !: - lda text_colour - sta (current_screen_line_colour_ptr),y + lda COLOR + sta (USER),y lda #$20 - sta (current_screen_line_ptr),y + sta (PNT),y dey cpy #40 bne !- - + rts -done_grow_line: not_last_line: rts @@ -575,163 +570,163 @@ scroll_up_if_on_last_line: // Colour RAM is always in fixed place, so is easiest // to use to check if we are on the last line. // The last line is at $D800 + 24*40 = $DBC0 - lda current_screen_line_colour_ptr+1 + lda USER+1 cmp #>$DBC0 bne not_last_line - lda current_screen_line_colour_ptr+0 + lda USER+0 cmp #<$DBC0 beq is_last_line - + jsr get_current_line_logical_length clc - adc current_screen_line_colour_ptr+0 + adc USER+0 cmp #<$DBE7-1 - bcc not_last_line + bcc not_last_line -is_last_line: - - dec current_screen_y +is_last_line: + + dec TBLX // FALL THROUGH -scroll_screen_up: +scroll_screen_up: // Now scroll the whole screen up either one or two lines // based on whether the first screen line is linked or not. - + // Get pointers to start of screen + colour RAM lda HIBASE - sta current_screen_line_ptr+1 - sta load_or_scroll_temp_pointer+1 + sta PNT+1 + sta SAL+1 lda #>$D800 - sta current_screen_line_colour_ptr+1 - sta load_save_verify_end_address+1 + sta USER+1 + sta EAL+1 lda #$00 - sta current_screen_line_ptr+0 - sta current_screen_line_colour_ptr+0 + sta PNT+0 + sta USER+0 // Get pointers to screen/colour RAM source - lda screen_line_link_table+0 + lda LDTBL+0 bmi !+ lda #40 .byte $2C // BIT $nnnn to skip next instruction !: lda #80 - sta load_or_scroll_temp_pointer+0 - sta load_save_verify_end_address+0 + sta SAL+0 + sta EAL+0 // Copy first three pages ldy #$00 ldx #3 scroll_copy_loop: - lda (load_save_verify_end_address),y - sta (current_screen_line_colour_ptr),y - lda (load_or_scroll_temp_pointer),y - sta (current_screen_line_ptr),y + lda (EAL),y + sta (USER),y + lda (SAL),y + sta (PNT),y iny bne scroll_copy_loop - inc load_or_scroll_temp_pointer+1 - inc current_screen_line_ptr+1 - inc load_save_verify_end_address+1 - inc current_screen_line_colour_ptr+1 + inc SAL+1 + inc PNT+1 + inc EAL+1 + inc USER+1 dex bne scroll_copy_loop // Copy last partial page // We need to copy 1000-(3*256)-line length // = 232 - line length - lda load_or_scroll_temp_pointer+0 + lda SAL+0 lda #232 sec - sbc load_or_scroll_temp_pointer+0 + sbc SAL+0 tax -scroll_copy_loop2: - lda (load_save_verify_end_address),y - sta (current_screen_line_colour_ptr),y - lda (load_or_scroll_temp_pointer),y - sta (current_screen_line_ptr),y +scroll_copy_loop2: + lda (EAL),y + sta (USER),y + lda (SAL),y + sta (PNT),y iny dex bne scroll_copy_loop2 // Fill in scrolled up area - ldx load_or_scroll_temp_pointer+0 + ldx SAL+0 scroll_copy_loop3: - lda text_colour - sta (current_screen_line_colour_ptr),y + lda COLOR + sta (USER),y lda #$20 - sta (current_screen_line_ptr),y + sta (PNT),y iny dex bne scroll_copy_loop3 - + // Shift line linkage list ldy #0 ldx #24 link_copy: - lda screen_line_link_table+1,y - sta screen_line_link_table+0,y + lda LDTBL+1,y + sta LDTBL+0,y iny dex bne link_copy // Clear line link flag of last line - stx screen_line_link_table+24 + stx LDTBL+24 // Restore correct line pointers jsr calculate_screen_line_pointer rts - + get_current_line_logical_length: - ldy current_screen_y - lda screen_line_link_table,y + ldy TBLX + lda LDTBL,y bpl line_not_linked_del lda #79 .byte $2c // BIT absolute mode, which we use to skip the next two instruction bytes line_not_linked_del: lda #39 - sta logical_line_length + sta LNMX rts - + screen_advance_to_next_line: // jsr hide_cursor_if_visible // Go to start of line lda #0 - sta current_screen_x + sta PNTR // Advance line number - ldy current_screen_y + ldy TBLX // Do quick fix to line pointer to work out if it is off // the bottom of the screen. ldx #40 - lda screen_line_link_table,y + lda LDTBL,y bmi !+ .byte $2c !: ldx #80 txa clc - adc current_screen_line_ptr+0 - sta current_screen_line_ptr+0 - lda current_screen_line_ptr+1 + adc PNT+0 + sta PNT+0 + lda PNT+1 adc #0 - sta current_screen_line_ptr+1 - - inc current_screen_y - + sta PNT+1 + + inc TBLX + // Check if it will trigger scrolling // Work out if we have gone off the bottom of the screen? // 1040 > 1024, so if high byte of screen pointer is >= (HIBASE+4), // then we are off the bottom of the screen - lda current_screen_line_ptr+1 + lda PNT+1 sec sbc HIBASE cmp #3 bcc !+ - lda current_screen_line_ptr+0 + lda PNT+0 cmp #$e7 bcc !+ @@ -744,83 +739,82 @@ screen_advance_to_next_line: jmp chrout_done add_40_to_screen_x: - lda current_screen_x + lda PNTR clc adc #40 - sta current_screen_x + sta PNTR rts normalise_screen_x_y: // Normalise X and Y values // If X < 0, then make X = X + 40 (or 80, if previous line is linked) -!: lda current_screen_x +!: lda PNTR bpl x_not_negative - dec current_screen_y + dec TBLX // Check that we didn't go backwards off the top of the screen bpl !+ lda #0 - sta current_screen_y + sta TBLX !: jsr add_40_to_screen_x // Check if line is linked, if so, add 40 again - ldy current_screen_y - lda screen_line_link_table,y + ldy TBLX + lda LDTBL,y bpl !+ jsr add_40_to_screen_x !: x_not_negative: // Work out if X is too big - ldy current_screen_y - lda screen_line_link_table,y + ldy TBLX + lda LDTBL,y bpl !+ lda #79 .byte $2C // BIT $nnnn, used to skip next instruction !: lda #39 - cmp current_screen_x + cmp PNTR bcs x_not_too_big // X value is too big, so subtract 40 and increment Y - lda current_screen_x + lda PNTR sec sbc #40 - sta current_screen_x - inc current_screen_y + sta PNTR + inc TBLX x_not_too_big: // Make sure Y isn't negative - lda current_screen_y + lda TBLX bpl !+ lda #0 - sta current_screen_y + sta TBLX !: // Make sure Y isn't too large for absolute size of // screen cmp #24 bcc !+ lda #24 - sta current_screen_y + sta TBLX !: // Make sure Y isn't too much for the screen, taking // into account the line link table ldy #24 // max allowable line ldx #0 link_count_loop: - lda screen_line_link_table,x + lda LDTBL,x bpl !+ dey !: inx cpx #25 bne link_count_loop tya - cmp current_screen_y + cmp TBLX bcs y_ok - sta current_screen_y -y_ok: - + sta TBLX +y_ok: rts calculate_screen_line_pointer: @@ -828,12 +822,12 @@ calculate_screen_line_pointer: // Reset pointer to start of screen lda HIBASE - sta current_screen_line_ptr+1 + sta PNT+1 lda #0 - sta current_screen_line_ptr+0 + sta PNT+0 // Add 40 for every line, or 80 if the lines are linked - ldx current_screen_y + ldx TBLX !: // Stop if we have counted enough lines @@ -844,18 +838,18 @@ calculate_screen_line_pointer: ldy #40 // -1 offset is because we count down from N to 1, not // N-1 to 0. - lda screen_line_link_table-1,x + lda LDTBL-1,x bpl cslp_l1 ldy #80 cslp_l1: // Add computed line length to pointer value tya clc - adc current_screen_line_ptr+0 - sta current_screen_line_ptr+0 - lda current_screen_line_ptr+1 + adc PNT+0 + sta PNT+0 + lda PNT+1 adc #0 - sta current_screen_line_ptr+1 + sta PNT+1 // Loop back to next line dex @@ -864,38 +858,32 @@ cslp_l1: // FALL THROUGH -update_colour_line_pointer: +update_colour_line_pointer: // Now setup pointer to colour RAM - lda current_screen_line_ptr+0 - sta current_screen_line_colour_ptr+0 - lda current_screen_line_ptr+1 + lda PNT+0 + sta USER+0 + lda PNT+1 sec sbc HIBASE clc adc #>$d800 - sta current_screen_line_colour_ptr+1 - + sta USER+1 + rts - - + advance_screen_pointer_40_bytes: - lda current_screen_line_ptr+0 + lda PNT+0 clc adc #<40 - sta current_screen_line_ptr+0 - sta current_screen_line_colour_ptr+0 - lda current_screen_line_ptr+1 + sta PNT+0 + sta USER+0 + lda PNT+1 adc #>40 - sta current_screen_line_ptr+1 + sta PNT+1 sec sbc HIBASE clc adc #>$D800 - sta current_screen_line_colour_ptr+1 + sta USER+1 jmp update_colour_line_pointer - -colour_codes: - // CHR$ codes for the 16 colours - .byte 144,5,28,159,156,30,31,158 - .byte 129,149,150,151,152,153,154,155 diff --git a/c64/kernal/cint_real.s b/c64/kernal/cint_real.s index 97a4d701..1daf056c 100644 --- a/c64/kernal/cint_real.s +++ b/c64/kernal/cint_real.s @@ -56,13 +56,20 @@ cint_pal: !: sta TVSFLG + // Setup KEYLOG vector - XXX is it proper place? + + lda #setup_keydecode + sta KEYLOG+1 + 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) lda #$00 - sta cursor_blink_disable + sta BLNSW // Set keyboard decode vector (Compute's Mapping the 64 p215) @@ -79,17 +86,17 @@ cint_brk: // entry for BRK and STOP+RESTORE - XXX, where should it start? // 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 + stx 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 - stx text_colour + stx COLOR // 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 - stx enable_case_switch + stx XMAX + // Put non-zero value in MODE to enable case switch + stx MODE // Set default I/O devices (see SCINIT description at http://sta.c64.org/cbm64krnfunc.html) jsr clrchn_reset diff --git a/c64/kernal/e50a.interop b/c64/kernal/e50a.interop new file mode 100644 index 00000000..b661797e --- /dev/null +++ b/c64/kernal/e50a.interop @@ -0,0 +1,5 @@ +The original reason to move PLOT routine into its original position was to provide support for unofficial $E50C address: + +- it is well known: https://www.lemon64.com/forum/viewtopic.php?t=3296&%3Bstart=15 + https://sys64738.org/2019/05/c64-bedtime-coding-eng-printing-08/ +- 'Duotris' game calls $E50C during startup screen initialization diff --git a/c64/kernal/e50a.plot.s b/c64/kernal/e50a.plot.s new file mode 100644 index 00000000..58afa453 --- /dev/null +++ b/c64/kernal/e50a.plot.s @@ -0,0 +1,31 @@ + +// +// Official Kernal routine, described in: +// +// - [RG64] C64 Programmer's Reference Guide - page 290 +// - [CM64] Compute's Mapping the Commodore 64 - page 215 +// +// CPU registers that has to be preserved (see [RG64]): none +// + +PLOT: + bcs plot_get + + // Note: the 'set' part has to start from $E50C, as this is a known address + // - https://www.lemon64.com/forum/viewtopic.php?t=3296&%3Bstart=15 + // - https://sys64738.org/2019/05/c64-bedtime-coding-eng-printing-08/ + // - 'Duotris' game calls $E50C during startup screen initialization + +plot_set: + sty TBLX + stx PNTR + + // XXX handle cursor blink + // XXX should we update some more variables? + + // FALLTROUGH to save one byte on RTS + +plot_get: + ldy TBLX + ldx PNTR + rts diff --git a/c64/kernal/e544.clear_screen.s b/c64/kernal/e544.clear_screen.s index d0e0e639..90d1999d 100644 --- a/c64/kernal/e544.clear_screen.s +++ b/c64/kernal/e544.clear_screen.s @@ -9,7 +9,7 @@ clear_screen: lda #$00 ldy #24 clearscreen_l1: - sta screen_line_link_table,y + sta LDTBL,y dey bpl clearscreen_l1 @@ -19,35 +19,35 @@ clearscreen_l1: // 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 + // Get pointer to the screen into PNT // 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 + sta PNT+0 lda HIBASE - sta current_screen_line_ptr+1 + sta PNT+1 ldx #$03 // countdown for pages to update iny // Y now = #$00 lda #$20 // space character clearscreen_l2: - sta (current_screen_line_ptr),y + sta (PNT),y iny bne clearscreen_l2 // To draw only 1000 bytes, add 250 to address each time - lda current_screen_line_ptr + lda PNT clc adc #<250 - sta current_screen_line_ptr - lda current_screen_line_ptr+1 + sta PNT + lda PNT+1 adc #>250 - sta current_screen_line_ptr+1 + sta PNT+1 lda #$20 // get space character again dex bpl clearscreen_l2 // Clear colour RAM // (Compute's Mapping the 64 p216) - lda text_colour + lda COLOR clearscreen_l3: sta $d800,y sta $d900,y diff --git a/c64/kernal/e5a0.setup_vicii.s b/c64/kernal/e5a0.setup_vicii.s index 4fb95bc8..7345dbc4 100644 --- a/c64/kernal/e5a0.setup_vicii.s +++ b/c64/kernal/e5a0.setup_vicii.s @@ -1,6 +1,8 @@ setup_vicii: + // XXX there is more to setup within this routine + // Set up default IO values (Compute's Mapping the 64 p215) lda #$1B // Enable text mode sta VIC_SCROLY @@ -17,4 +19,4 @@ setup_vicii: lda #$00 sta VIC_SPENA - // FALLTROUGH + rts diff --git a/c64/kernal/f13e.getin.s b/c64/kernal/f13e.getin.s index 485535b0..5eefc0ac 100644 --- a/c64/kernal/f13e.getin.s +++ b/c64/kernal/f13e.getin.s @@ -13,7 +13,7 @@ GETIN: // Wait for a key - lda keys_in_key_buffer + lda NDX bne !+ // Nothing in keyboard buffer to read @@ -22,7 +22,7 @@ GETIN: rts !: - lda keyboard_buffer + lda KEYD pha jsr pop_keyboard_buffer diff --git a/c64/kernal/f34a.open.s b/c64/kernal/f34a.open.s index a669d960..02ce3ac9 100644 --- a/c64/kernal/f34a.open.s +++ b/c64/kernal/f34a.open.s @@ -20,7 +20,7 @@ OPEN: beq !+ dey lda LAT, y - cmp current_logical_filenum + cmp LA bne open_not_yet_open jmp kernalerror_FILE_ALREADY_OPEN open_not_yet_open: @@ -43,11 +43,11 @@ open_has_space: // LAT / FAT / SAT support implemented according to // 'Compute's Mapping the Commodore 64', page 52 - lda current_logical_filenum + lda LA sta LAT, y - lda current_device_number + lda FA sta FAT, y - lda current_secondary_address + lda SA sta SAT, y iny @@ -58,7 +58,7 @@ open_has_space: beq open_done_success // Check for IEC device - lda current_device_number + lda FA jsr iec_check_devnum bcc open_iec @@ -75,14 +75,16 @@ open_iec: bcc !+ jmp kernalerror_DEVICE_NOT_FOUND !: - lda current_secondary_address + lda SA jsr iec_cmd_open bcc !+ jmp kernalerror_DEVICE_NOT_FOUND !: +#if CONFIG_MEMORY_MODEL_60K // We need our helpers to get to filenames under ROMs or IO area jsr install_ram_routines +#endif // Send command ('file name') jsr lvs_send_file_name diff --git a/c64/kernal/f49e.interop b/c64/kernal/f49e.interop new file mode 100644 index 00000000..e3e2a1b3 --- /dev/null +++ b/c64/kernal/f49e.interop @@ -0,0 +1,2 @@ +This is a well-known address of a heavily used Kernal routine, it has to be the same so our ROM is compatible. + diff --git a/c64/kernal/f49e.load_int.s b/c64/kernal/f49e.load_int.s new file mode 100644 index 00000000..837d896c --- /dev/null +++ b/c64/kernal/f49e.load_int.s @@ -0,0 +1,13 @@ + +// +// XXX Note: something unusual was done with LOAD routine - although the vector at $330 points to $F4A5, +// the Kernal jump table points to $F49E (see also Mapping the C64, page 76). By experimenting +// I have already discovered that $F4A5 performs indirect jump via ($0330) vector, but it must +// be doing a little bit more - not sure yet, what. Something similar is done with SAVE. +// +// This has to be clarified. +// + +LOAD_INT: + jmp (ILOAD) + diff --git a/c64/kernal/f4a5.load.s b/c64/kernal/f4a5.load.s index bb43f88f..e1cccc1d 100644 --- a/c64/kernal/f4a5.load.s +++ b/c64/kernal/f4a5.load.s @@ -31,14 +31,16 @@ LOAD: // Reset status jsr kernalstatus_reset +#if CONFIG_MEMORY_MODEL_60K // We need our helpers to get to filenames under ROMs or IO area jsr install_ram_routines +#endif // Allow platform-specific routine to takeover the flow TARGET_HOOK_LOAD() // Check whether we support the requested device - lda current_device_number + lda FA and #$FC bne !+ jmp lvs_illegal_device_number // device number below 4, not an IEC device @@ -58,7 +60,7 @@ LOAD: // in the C64, only in the drive. // Call device to LISTEN (p16) - lda current_device_number + lda FA jsr LISTEN bcc !+ jmp lvs_device_not_found_error // XXX deduplicate with other jumps in this routine @@ -75,7 +77,7 @@ LOAD: jmp lvs_load_verify_error // XXX deduplicate with other jumps in this routine !: // Now command device to talk (p16) - lda current_device_number + lda FA jsr TALK bcc !+ jmp lvs_load_verify_error // XXX deduplicate with other jumps in this routine @@ -95,17 +97,17 @@ LOAD: // 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 + jmp kernalerror_FILE_NOT_FOUND // XXX deduplicate with other jumps in this routine !: - ldx current_secondary_address + ldx SA beq !+ sta STAL+0 !: jsr iec_rx_byte bcc !+ - jmp lvs_file_not_found_error // XXX deduplicate with other jumps in this routine + jmp kernalerror_FILE_NOT_FOUND // XXX deduplicate with other jumps in this routine !: - ldx current_secondary_address + ldx SA beq !+ sta STAL+1 !: @@ -138,7 +140,7 @@ load_loop: // Close file on drive - lda current_device_number + lda FA jsr close_load // Return last address diff --git a/c64/kernal/f5dd.interop b/c64/kernal/f5dd.interop new file mode 100644 index 00000000..e3e2a1b3 --- /dev/null +++ b/c64/kernal/f5dd.interop @@ -0,0 +1,2 @@ +This is a well-known address of a heavily used Kernal routine, it has to be the same so our ROM is compatible. + diff --git a/c64/kernal/f5dd.save_int.s b/c64/kernal/f5dd.save_int.s new file mode 100644 index 00000000..7ef54a41 --- /dev/null +++ b/c64/kernal/f5dd.save_int.s @@ -0,0 +1,12 @@ + +// +// XXX Note: something unusual was done with LOAD routine - although the vector at $330 points to $F4A5, +// the Kernal jump table points to $F49E (see also Mapping the C64, page 76). By experimenting +// I have already discovered that $F4A5 performs indirect jump via ($0330) vector, but it must +// be doing a little bit more - not sure yet, what. Something similar is done with SAVE. +// +// This has to be clarified. +// + +SAVE_INT: + jmp (ISAVE) diff --git a/c64/kernal/f5ed.save.s b/c64/kernal/f5ed.save.s index 44c6eb15..79ea33d6 100644 --- a/c64/kernal/f5ed.save.s +++ b/c64/kernal/f5ed.save.s @@ -10,4 +10,4 @@ // SAVE: - rts + STUB_IMPLEMENTATION() diff --git a/c64/kernal/fd15.restor.s b/c64/kernal/fd15.restor.s new file mode 100644 index 00000000..5e181423 --- /dev/null +++ b/c64/kernal/fd15.restor.s @@ -0,0 +1,24 @@ + +// +// 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: + + clc // clear carry - for writing to system table + ldy #>vector_defaults + ldx #$033C - sta cassette_buffer_ptr+1 + sta TAPE1+1 // set screen address to $0400 // https://www.c64-wiki.com/wiki/Screen_RAM @@ -60,7 +61,7 @@ ramtas_l2: // and several following ldx #>$0400 stx HIBASE - + // Work out RAM size and put in MEMSTR and MEMSIZK // "Compute's Mapping the 64", p54 // http://unusedino.de/ec64/technical/project64/mapping_c64.html @@ -70,22 +71,21 @@ ramtas_l2: stx MEMSTR+0 stx MEMSIZK+0 // Try to modify $8000, if it fails then RAM ends at $7FFF, else $9FFF - lda $8000 - eor #$FF - tax - eor #$FF + ldx $8000 + inx + stx $8000 + cpx $8000 + bne ramtas_32K_RAM + dex stx $8000 - cmp $8000 - beq ramtas_32K_RAM - sta $8000 ldx #$A0 stx MEMSIZK+1 - jmp ramtas_RAM_sized + bne !+ // always non-zero, saves one byte + ramtas_32K_RAM: - sta $8000 // in case RAM is hiding beneath a ROM + dex + stx $8000 // case there is RAM under the ROM ldx #$80 stx MEMSIZK+1 - // Fall through -ramtas_RAM_sized: - +!: rts diff --git a/c64/kernal/readst.s b/c64/kernal/readst.s index 5be3e2c9..10a7d11f 100644 --- a/c64/kernal/readst.s +++ b/c64/kernal/readst.s @@ -12,13 +12,14 @@ READST: // Check the current device number - lda current_device_number + lda FA cmp #$02 bne !+ // This is RS-232 device - according to 'Compute's Mapping the Commodore 64' page 239 // it reads status from RSSTAT - lda RSSTAT + // XXX 'lda RSSTAT' not possible due to extended scnkey, fix it! + lda #$FF rts !: // According to 'Compute's Mapping the Commodore 64' page 239, it usually retrieves diff --git a/c64/kernal/scnkey.s b/c64/kernal/scnkey.s index 6bf96d90..ac22a7ca 100644 --- a/c64/kernal/scnkey.s +++ b/c64/kernal/scnkey.s @@ -46,25 +46,6 @@ // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ - // // ZERO PAGE Varibles - // $250-$258 is the 81st - 88th characters in BASIC input, a carry over from VIC-20 - // and not used on C64, so safe for us to use, probably. - // (Compute's Mapping the 64 p51) - .label ScanResult = $250 // 8 bytes - // Other variables are in RS232 ZP locations for now - // (Carefully avoiding $A7 which is used by 64NET) - .label BufferNew = $A9 // 3 bytes - .label KeyQuantity = $A8 // 1 byte - .label TempZP = $B6 // 1 byte - - // Reuse RS232 variables, since they should not be used - // by other things - // These are initialised in cinit all to $FF - .label BufferOld = $293 // 3 bytes - .label Buffer = $297 // 4 bytes - .label BufferQuantity = $B4 // 1 byte - - // Operational Variables .const MaxKeyRollover = 3 @@ -74,9 +55,9 @@ SCNKEY: sta BufferQuantity // Decrement key repeat timeout if non-zero - ldx key_repeat_counter + ldx KOUNT beq sk_start - dec key_repeat_counter + dec KOUNT sk_start: // Call main keyboard scanning routine @@ -110,7 +91,7 @@ accept_key: // Convert matrix position to key code // XXX - Add offset of $40, $80 or $C0 if shift, CONTROL or C= are held down pha - lda key_bucky_state + lda SHFLAG and #$7 tax pla @@ -122,16 +103,15 @@ accept_key: beq sk_nokey // Stash key into keyboard buffer - ldx keys_in_key_buffer - cpx key_buffer_size + ldx NDX + cpx XMAX beq sk_nokey - sta keyboard_buffer,x - inc keys_in_key_buffer - -sk_nokey: + sta KEYD,x + inc NDX + +sk_nokey: rts - // //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // // Routine for Scanning a Matrix Row @@ -181,13 +161,12 @@ OverFlow: pla // Don't manipulate last legal buffer as the routine will fix itself once it gets valid input again. -TooManyNewKeys: ReturnNoKeys: sec lda #$00 sta BufferQuantity lda #$FF - sta last_key_matrix_position + sta LSTX ldx #MaxKeyRollover-1 !: sta Buffer,x @@ -204,10 +183,10 @@ ReturnNoKeys: NoActivityDetected: // So cancel all bucky keys - lda key_bucky_state - sta key_last_bucky_state + lda SHFLAG + sta LSTSHF lda #$00 - sta key_bucky_state + sta SHFLAG jmp ReturnNoKeys @@ -239,7 +218,7 @@ JoystickActivity: // Clear bucky key status lda #$00 - sta key_bucky_state + sta SHFLAG lda $dc01 and #$03 @@ -254,7 +233,7 @@ JoystickActivity: // Up // Mark shift as pressed ldx #$01 - stx key_bucky_state + stx SHFLAG ldx #$07 // UP/DOWN jsr KeyFound !: @@ -278,7 +257,7 @@ JoystickActivity: cmp #$08 bne !+ ldx #$01 - stx key_bucky_state + stx SHFLAG ldx #$02 jsr KeyFound // LEFT/RIGHT !: @@ -332,20 +311,20 @@ next_row: // Store de-bounce data for bucky keys // (Compute's Mapping the 64, p58-59) - lda key_bucky_state - sta key_last_bucky_state + lda SHFLAG + sta LSTSHF // Build bucky state lda #$00 - sta key_bucky_state + sta SHFLAG lda ScanResult+6 eor #%10000000 and #%10000000 // Left shift rol rol and #$01 - ora key_bucky_state - sta key_bucky_state + ora SHFLAG + sta SHFLAG // Right shift lda ScanResult+1 @@ -355,15 +334,15 @@ next_row: lsr lsr and #$01 - ora key_bucky_state - sta key_bucky_state + ora SHFLAG + sta SHFLAG // Control lda ScanResult+0 eor #$04 and #$04 - ora key_bucky_state - sta key_bucky_state + ora SHFLAG + sta SHFLAG // Vendor key lda ScanResult+0 @@ -373,17 +352,17 @@ next_row: lsr lsr and #$02 - ora key_bucky_state - sta key_bucky_state + ora SHFLAG + sta SHFLAG // Chick for shift + Vendor cmp #$03 bne no_case_toggle - lda key_last_bucky_state + lda LSTSHF cmp #$03 beq no_case_toggle - lda enable_case_switch + lda MODE beq no_case_toggle lda $D018 @@ -463,7 +442,7 @@ RecordKeypress: ldy BufferQuantity cpy #MaxKeyRollover bcc !+ - jmp TooManyNewKeys + jmp ReturnNoKeys // too many new keys !: AcceptKeyEvent: sta Buffer,y @@ -488,7 +467,7 @@ ConsiderNextKey: KeyHeld: // The key in A is still held down. - // compare with key in last_key_matrix_position + // compare with key in LSTX // (Compute's Mapping the 64 p36-37) // if different, reset repeat count down. @@ -502,22 +481,22 @@ KeyHeld: beq BuckyHeld cmp #61 beq BuckyHeld - - cmp last_key_matrix_position + + cmp LSTX beq SameKeyHeld // Different key held - sta last_key_matrix_position + sta LSTX pha - lda key_first_repeat_delay - sta key_repeat_counter + lda DELAY + sta KOUNT pla BuckyHeld: jmp ConsiderNextKey SameKeyHeld: pha - lda key_repeat_counter + lda KOUNT bmi KeyCanRepeat bne KeyRepeatWait // Count down ended, so repeat key now @@ -526,7 +505,7 @@ KeyCanRepeat: // (Compute's Mapping the 64 p58) pha lda #6-2 // Fudge factor to match speed - sta key_repeat_counter + sta KOUNT pla pla diff --git a/c64/kernal/set_pointer_to_current_screen_line.s b/c64/kernal/set_pointer_to_current_screen_line.s index c89ad621..a6edef4c 100644 --- a/c64/kernal/set_pointer_to_current_screen_line.s +++ b/c64/kernal/set_pointer_to_current_screen_line.s @@ -1,32 +1,32 @@ // Put the address of the screen current line - // into the pointer at $D1 (current_screen_line_ptr). + // into the pointer at $D1 (PNT). // It must take into account the screen line link table // (Compute's Mapping the 64 p216) set_pointer_to_current_screen_line: // Get pointer to start of the screen lda HIBASE - sta current_screen_line_ptr+1 + sta PNT+1 lda #$00 - sta current_screen_line_ptr+0 + sta PNT+0 // Now advance for the number of lines - ldx current_screen_y + ldx TBLX -sptcsl_l2: +sptcsl_l2: // XXX - Should we read the columns per line from // somewhere? ldy #<40 // Double line length if line is linked - lda screen_line_link_table,x + lda LDTBL,x bpl sptcsl_l1 ldy #<80 sptcsl_l1: tya clc - adc current_screen_line_ptr+0 - lda current_screen_line_ptr+1 + adc PNT+0 + lda PNT+1 adc #>40 - sta current_screen_line_ptr+1 + sta PNT+1 dex bpl sptcsl_l2 diff --git a/c64/kernal/setfls.s b/c64/kernal/setfls.s index 44c7ab8b..d57f770b 100644 --- a/c64/kernal/setfls.s +++ b/c64/kernal/setfls.s @@ -12,9 +12,9 @@ SETFLS: // There are 6 sane ways to implement this routine, // I hope this one won't cause similarity to CBM code - - sta current_logical_filenum - sty current_secondary_address - stx current_device_number - + + sta LA + sty SA + stx FA + rts diff --git a/c64/kernal/setup_keydecode.s b/c64/kernal/setup_keydecode.s new file mode 100644 index 00000000..d6010685 --- /dev/null +++ b/c64/kernal/setup_keydecode.s @@ -0,0 +1,5 @@ + +// XXX provide documentation and implementation + +setup_keydecode: + STUB_IMPLEMENTATION() diff --git a/c64/kernal/udtim.s b/c64/kernal/udtim.s index 9fce89a2..2d8aac00 100644 --- a/c64/kernal/udtim.s +++ b/c64/kernal/udtim.s @@ -14,14 +14,13 @@ UDTIM: // after this time we have to reset the clock. inc TIME+0 - bne udtim_clock_done + bne udtim_update_stkey // done with clock inc TIME+1 bne udtim_clock_rollover inc TIME+2 // FALLTROUGH -udtim_clock_done: udtim_update_stkey: // entry to be used when interrupts are disabled // Another action we have to perform is to copy the last row of keyboard to RAM, @@ -44,11 +43,11 @@ udtim_clock_rollover: // At this point TIME+0 contains 0 lda TIME+1 cmp #$1A - bne udtim_clock_done + bne udtim_update_stkey // done with clock lda TIME+2 cmp #$4F - bne udtim_clock_done + bne udtim_update_stkey // done with clock lda #$00 sta TIME+2 sta TIME+1 - beq udtim_clock_done // will always jump + beq udtim_update_stkey // done with clock - will always jump diff --git a/c64/kernal/under_rom_routines.s b/c64/kernal/under_rom_routines.s index 8a636f9f..5e45aa15 100644 --- a/c64/kernal/under_rom_routines.s +++ b/c64/kernal/under_rom_routines.s @@ -4,11 +4,13 @@ // in ,aliases.s. // Thus those addresses are expressed using formulae. +#if CONFIG_MEMORY_MODEL_60K + install_ram_routines: // Copy routines into place - ldx #ram_routines_end-ram_routines_start-1 + ldx #__ram_routines_end-__ram_routines_start-1 !: - lda ram_routines_start,x + lda __ram_routines_start,x sta tiny_nmi_handler,x dex bpl !- @@ -21,7 +23,7 @@ install_ram_routines: rts -ram_routines_start: +__ram_routines_start: tiny_nmi_handler_routine: inc missed_nmi_flag @@ -61,4 +63,6 @@ memmap_allram_routine: pla rts -ram_routines_end: +__ram_routines_end: + +#endif // CONFIG_MEMORY_MODEL_60K diff --git a/c64/kernal/fd15.vector.s b/c64/kernal/vector_real.s similarity index 53% rename from c64/kernal/fd15.vector.s rename to c64/kernal/vector_real.s index 7b7fd00d..b3540f9c 100644 --- a/c64/kernal/fd15.vector.s +++ b/c64/kernal/vector_real.s @@ -1,27 +1,9 @@ -// -// 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 -// +vector_real: -RESTOR: - - clc // clear carry - for writing to system table - ldx #vector_defaults - - // FALLTHROUGH - -VECTOR: - - // Temporary storage location - checked on real C64 that this is the + // Use MEMUSS as 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 // According to 'Compute's Mapping the Commodore 64' page 237, // the CBM implementation does not disable IRQs - yet, the @@ -34,28 +16,25 @@ VECTOR: // 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 + sty MEMUSS + 1 + stx MEMUSS + 0 // Select routine variant - store or restore vectors ldy #$1F bcc vector_restore - // FALLTHROUGH - -vector_store: lda CINV, y - sta (_caller_arr_ptr), y - dey - bpl vector_store - - // Restore status register (IRQ) before return - plp - rts + sta (MEMUSS), y + + bcs vector_end_loop // branch always vector_restore: - lda (_caller_arr_ptr), y + lda (MEMUSS), y sta CINV, y + + // FALLTROUGH + +vector_end_loop: dey bpl vector_restore diff --git a/src/build_segment.cc b/src/build_segment.cc index 3453d458..9c55842e 100644 --- a/src/build_segment.cc +++ b/src/build_segment.cc @@ -26,7 +26,7 @@ #define DIR_SEPARATOR "/" #endif -const std::string ASM_CMD = "java -jar assembler/KickAss.jar "; +const std::string ASM_CMD = "java -jar "; const std::string LAB_OUT_START = "__routine_START_"; const std::string LAB_OUT_END = "__routine_END_"; @@ -39,8 +39,9 @@ const std::string BANNER_LINE = "//------------------------------------------- // Command line settings // +std::string CMD_assFile = "KickAss.jar"; std::string CMD_outFile = "OUT.BIN"; -std::string CMD_tmpDir = "./out"; +std::string CMD_outDir = "./out"; std::string CMD_segName = "MAIN"; std::string CMD_segInfo = "(unnamed)"; int CMD_loAddress = 0xC000; @@ -66,10 +67,10 @@ void ERROR(const std::string &message) void printUsage() { std::cout << "\n" << - "usage: build_segment [-o ] [-d ] [-t ]" << "\n" << + "usage: build_segment [-a ] [-o ] [-d ]" << "\n" << " [-l ] [-h ]" << "\n" << - " [-s ] [-i ] " << - "\n\n"; + " [-s ] [-i ]" << "\n" << + " " << "\n\n"; } void printBannerLineTop() @@ -195,16 +196,17 @@ void parseCommandLine(int argc, char **argv) // Retrieve command line options - while ((opt = getopt(argc, argv, "o:d:t:l:h:s:i:")) != -1) + while ((opt = getopt(argc, argv, "a:o:d:s:i:l:h:")) != -1) { switch(opt) { - case 'o': CMD_outFile = optarg; break; - case 't': CMD_tmpDir = optarg; break; - case 's': CMD_segName = optarg; break; - case 'i': CMD_segInfo = optarg; break; - case 'l': CMD_loAddress = strtol(optarg, nullptr ,16); break; - case 'h': CMD_hiAddress = strtol(optarg, nullptr ,16); break; + case 'a': CMD_assFile = optarg; break; + case 'o': CMD_outFile = optarg; break; + case 'd': CMD_outDir = optarg; break; + case 's': CMD_segName = optarg; break; + case 'i': CMD_segInfo = optarg; break; + case 'l': CMD_loAddress = strtol(optarg, nullptr ,16); break; + case 'h': CMD_hiAddress = strtol(optarg, nullptr ,16); break; default: printUsage(); ERROR(); } } @@ -297,23 +299,25 @@ void checkInputFileLabels() void calcRoutineSizes() { - const std::string nameBase = CMD_tmpDir + DIR_SEPARATOR + CMD_segName + "_sizetest"; + const std::string nameBase = CMD_segName + "_sizetest"; + const std::string filePath = CMD_outDir + DIR_SEPARATOR; - const std::string outFileName = nameBase + ".s"; - const std::string symFileName = nameBase + ".sym"; + const std::string outFileNameBare = nameBase + ".s"; + const std::string outFileNamePath = filePath + outFileNameBare; + const std::string symFileNamePath = filePath + nameBase + ".sym"; // Remove old files - unlink(outFileName.c_str()); - unlink(symFileName.c_str()); + unlink(outFileNamePath.c_str()); + unlink(symFileNamePath.c_str()); // Write test file to determine routine sizes - std::ofstream outFile(outFileName, std::fstream::out | std::fstream::trunc); - if (!outFile.good()) ERROR(std::string("can't open temporary file '") + outFileName + "'"); + std::ofstream outFile(outFileNamePath, std::fstream::out | std::fstream::trunc); + if (!outFile.good()) ERROR(std::string("can't open temporary file '") + outFileNamePath + "'"); // Start at $100, so that no local data gets accesses using ZP addressing modes - // during this pass, which would otherwise upset things later + // during this pass, which would otherwise upset things later outFile << "\n" << ".segment " << CMD_segName << " [start=$100, min=$100, max=$FFFF]" << "\n"; outFile << "#define SEGMENT_" << CMD_segName << "\n"; @@ -331,13 +335,14 @@ void calcRoutineSizes() outFile << LAB_OUT_END << sourceFile.label << ":" << "\n"; } - if (!outFile.good()) ERROR(std::string("error writing temporary file '") + outFileName + "'"); + if (!outFile.good()) ERROR(std::string("error writing temporary file '") + outFileNamePath + "'"); outFile.close(); // All written - now launch the assembler - const std::string cmd = ASM_CMD + outFileName + " -symbolfile -o /dev/null"; - std::cout << std::flush; + const std::string cmd = "cd " + filePath + " && " + ASM_CMD + CMD_assFile + " " + + outFileNameBare + " -symbolfile -o /dev/null"; + std::cout << "command: " << cmd << "\n" << std::flush; if (0 != system(cmd.c_str())) { ERROR("assembler running failed"); @@ -346,8 +351,8 @@ void calcRoutineSizes() // Read addresses std::ifstream symFile; - symFile.open(symFileName); - if (!symFile.good()) ERROR(std::string("unable to open results file '") + symFileName + "'"); + symFile.open(symFileNamePath); + if (!symFile.good()) ERROR(std::string("unable to open results file '") + symFileNamePath + "'"); std::string line; while (std::getline(symFile, line)) @@ -429,9 +434,9 @@ void prepareBinningProblem() { // Prepare the log file - const std::string logFileName = CMD_tmpDir + DIR_SEPARATOR + CMD_segName + "_binproblem.log"; - unlink(logFileName.c_str()); - std::ofstream logFile(logFileName, std::fstream::out | std::fstream::trunc); + const std::string logFileNamePath = CMD_outDir + DIR_SEPARATOR + CMD_segName + "_binproblem.log"; + unlink(logFileNamePath.c_str()); + std::ofstream logFile(logFileNamePath, std::fstream::out | std::fstream::trunc); DualStream logOutput(logFile, std::cout); // Print out code length information @@ -477,7 +482,7 @@ void prepareBinningProblem() // Close the log file - if (!logFile.good()) ERROR(std::string("error writing log file '") + logFileName + "'"); + if (!logFile.good()) ERROR(std::string("error writing log file '") + logFileNamePath + "'"); logFile.close(); } @@ -502,10 +507,12 @@ void compileSegment() { // First combine everything into one assembler file - const std::string outFileName = CMD_tmpDir + DIR_SEPARATOR + CMD_segName + "_combined.s"; - unlink(outFileName.c_str()); - std::ofstream outFile(outFileName, std::fstream::out | std::fstream::trunc); - if (!outFile.good()) ERROR(std::string("can't open temporary file '") + outFileName + "'"); + const std::string outFileNameBare = CMD_segName + "_combined.s"; + const std::string filePath = CMD_outDir + DIR_SEPARATOR; + const std::string outFileNamePath = filePath + outFileNameBare; + unlink(outFileNamePath.c_str()); + std::ofstream outFile(outFileNamePath, std::fstream::out | std::fstream::trunc); + if (!outFile.good()) ERROR(std::string("can't open temporary file '") + outFileNamePath + "'"); // Write the header @@ -517,6 +524,7 @@ void compileSegment() ", outBin=\"" << CMD_outFile << "\", fill]" << "\n"; outFile << "#define SEGMENT_" << CMD_segName << "\n"; + outFile << ".namespace " << CMD_segName << " {" << "\n\n"; // Write files which only contain definitions (no routines) @@ -541,13 +549,16 @@ void compileSegment() outFile << "\n"; } - if (!outFile.good()) ERROR(std::string("error writing temporary file '") + outFileName + "'"); + outFile << "\n\n" << "} // namespace" << "\n"; + + if (!outFile.good()) ERROR(std::string("error writing temporary file '") + outFileNamePath + "'"); outFile.close(); // All written - now launch the assembler - const std::string cmd = ASM_CMD + outFileName + " -symbolfile -o " + CMD_outFile; - std::cout << std::flush; + const std::string cmd = "cd " + filePath + " && " + ASM_CMD + CMD_assFile + " " + + outFileNameBare + " -symbolfile -vicesymbols -o " + CMD_outFile; + std::cout << "command: " << cmd << "\n" << std::flush; if (0 != system(cmd.c_str())) { ERROR("assembler running failed"); @@ -852,9 +863,9 @@ void Solver::run() { // Prepare the log file - const std::string logFileName = CMD_tmpDir + DIR_SEPARATOR + CMD_segName + "_solver.log"; - unlink(logFileName.c_str()); - logFile.open(logFileName, std::fstream::out | std::fstream::trunc); + const std::string logFileNamePath = CMD_outDir + DIR_SEPARATOR + CMD_segName + "_binsolution.log"; + unlink(logFileNamePath.c_str()); + logFile.open(logFileNamePath, std::fstream::out | std::fstream::trunc); // Sort the floating routines, just to be extra sure @@ -887,7 +898,7 @@ void Solver::run() // Close the log file - if (!logFile.good()) ERROR(std::string("error writing log file '") + logFileName + "'"); + if (!logFile.good()) ERROR(std::string("error writing log file '") + logFileNamePath + "'"); logFile.close(); } @@ -945,7 +956,7 @@ int KS(const std::vector &routines, auto &cachedS = cacheS[n - 1][C - 1]; if (cachedV >= 0) { - // We already hold the solution in out cache - return it + // We already hold the solution in our cache - return it solution = cachedS; return cachedV; } diff --git a/src/compress_text.c b/src/compress_text.c index cf7e4751..85a62d06 100644 --- a/src/compress_text.c +++ b/src/compress_text.c @@ -24,7 +24,7 @@ LOAD and SAVE. Indeed, that this is so is highlighted by the fact that it was used in the C64 ROM. Therefore there is no exercise of creativity here, and a reasonable person would likely select this name independently. Also, single words cannot be copyright. - + Further, the list is a list of facts, and thus not copyrightable. We sourced the list from a public source, https://www.c64-wiki.com/wiki/BASIC, which has @@ -161,11 +161,13 @@ char *error_list[]={ "READY.\r", // #29 // https://www.ibm.com/support/knowledgecenter/zosbasics/com.ibm.zos.zconcepts/zconc_whatistsonative.htm https://github.com/stefanhaustein/expressionparser "NTSC, ", // #30 "PAL, ", // #31 - "BRK AT $", // #32 + "BREAK AT $", // #32 "ERROR", // #33 // Simply the word error that is attached to the other parts of messages https://fjkraan.home.xs4all.nl/comp/apple2faq/app2asoftfaq.html "BYTES FREE\r\r", // #34 // https://github.com/stefanhaustein/expressionparser "MEMORY CORRUPT", // #35 "NOT IMPLEMENTED", // #36 + " IN ", // #37 + "BREAK", // #38 NULL}; // XXX: create separate list for Kernal diff --git a/strings/0000000020 b/strings/0000000020 new file mode 100644 index 00000000..07a73cb0 --- /dev/null +++ b/strings/0000000020 @@ -0,0 +1,3 @@ +couple 0's + JMP (address does not match) + +Similairty only due to some parts of the ROM being empty. And not even a full instruction - not copyrightable. diff --git a/strings/00000020 b/strings/00000020 new file mode 100644 index 00000000..07a73cb0 --- /dev/null +++ b/strings/00000020 @@ -0,0 +1,3 @@ +couple 0's + JMP (address does not match) + +Similairty only due to some parts of the ROM being empty. And not even a full instruction - not copyrightable. diff --git a/strings/00DD29EF8D00DD60 b/strings/00DD29EF8D00DD60 new file mode 100644 index 00000000..99a521b2 --- /dev/null +++ b/strings/00DD29EF8D00DD60 @@ -0,0 +1,5 @@ +$DD00 + AND #$EF + STA $DD00 + RTS + +$DD00 is a hardware register, where one typically set/unset/read individual bits. +Having a set of trivial helper subroutines to set/clear individual bits (or groups of bits) is an obvious solution (thus not copyrightable), some similarities are unevitable. +Besides, in this case (since the similarity does not even cover a single subroutine from start to end) it is clear that the similar code actually performs slightly different actions. diff --git a/strings/0D4C4F4144494EC70D b/strings/0D4C4F4144494EC70D new file mode 100644 index 00000000..6b9411da --- /dev/null +++ b/strings/0D4C4F4144494EC70D @@ -0,0 +1,4 @@ +PETSCII string: LOADIN(G + end of string mark) + + +Encoding strings by adding $80 to it's last character (to mark end of stream) is a common byte-saving technique - for example, Turbo Basic XL (for Atari, now open-source) does the same. +And a single word following the is not copyrightable. diff --git a/strings/0D564552494659494EC70D b/strings/0D564552494659494EC70D new file mode 100644 index 00000000..d87e9d11 --- /dev/null +++ b/strings/0D564552494659494EC70D @@ -0,0 +1,4 @@ +PETSCII string: + VERIFYIN(G + end of string mark) + + +Encoding strings by adding $80 to it's last character (to mark end of stream) is a common byte-saving technique - for example, Turbo Basic XL (for Atari, now open-source) does the same. +And a single word following the is not copyrightable. diff --git a/strings/0DDC8D0D b/strings/0DDC8D0D new file mode 100644 index 00000000..f8e36ee1 --- /dev/null +++ b/strings/0DDC8D0D @@ -0,0 +1,3 @@ +$DC0D + STA $xxxx (only one byte of the address match) + +Not even a full instruction - not copyrightable. diff --git a/strings/13F720 b/strings/13F720 new file mode 100644 index 00000000..14d51096 --- /dev/null +++ b/strings/13F720 @@ -0,0 +1,3 @@ +$F713 + JSR (address does not match) + +Not even a full instruction - not copyrightable. diff --git a/strings/20D2FFC8 b/strings/20D2FFC8 new file mode 100644 index 00000000..33dc38ad --- /dev/null +++ b/strings/20D2FFC8 @@ -0,0 +1,3 @@ +JSR $FFD2 (official CHROUT jumptable entry) + INY + +Very small part of a loop displaying something - not copyrightable. diff --git a/strings/2860A9 b/strings/2860A9 new file mode 100644 index 00000000..1e7b5c2d --- /dev/null +++ b/strings/2860A9 @@ -0,0 +1,3 @@ +PLP + RTS + (new subroutine) LDA #$xx (value does not match) + +End of routine made to preserve processor status + one byte of the next subroutine. Trivial - not copyrightable. diff --git a/strings/29DF8D00DD60AD00DD09 b/strings/29DF8D00DD60AD00DD09 new file mode 100644 index 00000000..5ca17c37 --- /dev/null +++ b/strings/29DF8D00DD60AD00DD09 @@ -0,0 +1,5 @@ +AND #$DF + STA $DD00 + RTS + (start of the next routine) LDA $DD00 + ORA #$xx (value does not match) + +$DD00 is a hardware register, where one typically set/unset/read individual bits. +Having a set of trivial helper subroutines to set/clear individual bits (or groups of bits) is an obvious solution (thus not copyrightable), some similarities are unevitable. +Besides, in this case (since the similarity does not even cover a single subroutine from start to end) it is clear that the similar code actually performs slightly different actions. diff --git a/strings/464F52A00D b/strings/464F52A00D new file mode 100644 index 00000000..2deab4bb --- /dev/null +++ b/strings/464F52A00D @@ -0,0 +1,4 @@ +PETSCII string: FOR (space + end of string mark) + + +Encoding strings by adding $80 to it's last character (to mark end of stream) is a common byte-saving technique - for example, Turbo Basic XL (for Atari, now open-source) does the same. +And a single word is not copyrightable. diff --git a/strings/48AA2073 b/strings/48AA2073 new file mode 100644 index 00000000..d45c3127 --- /dev/null +++ b/strings/48AA2073 @@ -0,0 +1,3 @@ +PHA + TAX + JSR (address does not fully match) + +Simple stack/register manipulation (common of 6502 family) + jump to subroutine (not even matching address) - trivial, not copyrightable. diff --git a/strings/48C8B1 b/strings/48C8B1 new file mode 100644 index 00000000..90fe365f --- /dev/null +++ b/strings/48C8B1 @@ -0,0 +1,3 @@ +$48 + INY + LDA ($xx),Y (argument does not match) + +One instruction and some parts - not copyrightable. diff --git a/strings/494EC7 b/strings/494EC7 new file mode 100644 index 00000000..e278c110 --- /dev/null +++ b/strings/494EC7 @@ -0,0 +1,4 @@ +PETSCII string: IN(G + end of string mark) + +Encoding strings by adding $80 to it's last character (to mark end of stream) is a common byte-saving technique - for example, Turbo Basic XL (for Atari, now open-source) does the same. +And a single syllable is not copyrightable. diff --git a/strings/494EC70D b/strings/494EC70D new file mode 100644 index 00000000..0d013451 --- /dev/null +++ b/strings/494EC70D @@ -0,0 +1,4 @@ +PETSCII string: IN(G + end of string mark) + + +Encoding strings by adding $80 to it's last character (to mark end of stream) is a common byte-saving technique - for example, Turbo Basic XL (for Atari, now open-source) does the same. +And a single syllable is not copyrightable. diff --git a/strings/494EC70D534156494E b/strings/494EC70D534156494E new file mode 100644 index 00000000..1e139695 --- /dev/null +++ b/strings/494EC70D534156494E @@ -0,0 +1,4 @@ +PETSCII string: IN(G + end of string mark) + + SAVIN + +Encoding strings by adding $80 to it's last character (to mark end of stream) is a common byte-saving technique - for example, Turbo Basic XL (for Atari, now open-source) does the same. +Here we don't even have a single word - not copyrightable. diff --git a/strings/4C5BFF4CA3FD4C50FD4C15FD4C1AFD4C b/strings/4C5BFF4CA3FD4C50FD4C15FD4C1AFD4C new file mode 100644 index 00000000..fcfe7208 --- /dev/null +++ b/strings/4C5BFF4CA3FD4C50FD4C15FD4C1AFD4C @@ -0,0 +1 @@ +This is a part of Kernal jumptable - series of jumps, sometimes to the well known addreses (or through documented vectors). No business logic, part of the Kernal API itself - not copyrightable. diff --git a/strings/6031EA66FE47FE4AF391F20EF250F233F357F1CAF1EDF63EF12FF366FEA5F4EDF5 b/strings/6031EA66FE47FE4AF391F20EF250F233F357F1CAF1EDF63EF12FF366FEA5F4EDF5 new file mode 100644 index 00000000..c9996113 --- /dev/null +++ b/strings/6031EA66FE47FE4AF391F20EF250F233F357F1CAF1EDF63EF12FF366FEA5F4EDF5 @@ -0,0 +1,6 @@ +RTS (from previous routine) + a list of vectors to be copied starting from $0314 + +Values of the vectors are already present in many autostart software - as it often overrides them, +sometimes changing one to trigger autostart (one of the possible techniques). We have to use the same +vector values to be compatible (in fact, it even complicates our implementation) - see *.interop files +for more details. diff --git a/strings/6090051C9F9C1E1F9E8195969798999A9B b/strings/6090051C9F9C1E1F9E8195969798999A9B new file mode 100644 index 00000000..93585716 --- /dev/null +++ b/strings/6090051C9F9C1E1F9E8195969798999A9B @@ -0,0 +1,3 @@ +RTS + list of C64 colour codes + +List of facts (RTS matches only due to build system decision algorithm). Not copyrightable. diff --git a/strings/6C1A036C1C036C1E036C20036C22036C24036C26034C9EF44CDDF54C b/strings/6C1A036C1C036C1E036C20036C22036C24036C26034C9EF44CDDF54C new file mode 100644 index 00000000..fcfe7208 --- /dev/null +++ b/strings/6C1A036C1C036C1E036C20036C22036C24036C26034C9EF44CDDF54C @@ -0,0 +1 @@ +This is a part of Kernal jumptable - series of jumps, sometimes to the well known addreses (or through documented vectors). No business logic, part of the Kernal API itself - not copyrightable. diff --git a/strings/7F8D0DDD b/strings/7F8D0DDD new file mode 100644 index 00000000..5fb50d7f --- /dev/null +++ b/strings/7F8D0DDD @@ -0,0 +1,3 @@ +$7F + STA $DD0D + +Instruction and some part - not copyrightable. diff --git a/strings/8539C8B1 b/strings/8539C8B1 new file mode 100644 index 00000000..f1c0de4e --- /dev/null +++ b/strings/8539C8B1 @@ -0,0 +1,3 @@ +STA $39 + INY + LDA ($xx), Y (argument does not match) + +Small part of a loop manipulating BASIC memory - not copyrightable. diff --git a/strings/8A4820 b/strings/8A4820 new file mode 100644 index 00000000..a5bc0fa6 --- /dev/null +++ b/strings/8A4820 @@ -0,0 +1,3 @@ +TXA + PHA + JSR (addres does not match) + +Simple stack/register manipulation (common of 6502 family, would be reduced to PHX on some CPUs) + jump to subroutine (not even matching address) - trivial, not copyrightable. diff --git a/strings/8BE383A47CA51AA7E4A786AE b/strings/8BE383A47CA51AA7E4A786AE new file mode 100644 index 00000000..5b3e3e6d --- /dev/null +++ b/strings/8BE383A47CA51AA7E4A786AE @@ -0,0 +1,7 @@ +a list of vectors to be copied starting from $0300 + +Values of the vectors are already present in many autostart software - as it often overrides them, +sometimes changing one to trigger autostart (one of the possible techniques). We have to use the same +vector values to be compatible (in fact, it even complicates our implementation) - see *.interop files +for more details. + diff --git a/strings/8D00DD60 b/strings/8D00DD60 new file mode 100644 index 00000000..2a4681d3 --- /dev/null +++ b/strings/8D00DD60 @@ -0,0 +1,6 @@ +STA $DD00 + RTS + +$DD00 is one of the CIA ports, so storing value +into this port is something rather expected and common. + +Besides, these are just two instructions, second one being end of subroutine - not copyrightable. diff --git a/strings/8D0DDD8D b/strings/8D0DDD8D new file mode 100644 index 00000000..2819f811 --- /dev/null +++ b/strings/8D0DDD8D @@ -0,0 +1,3 @@ +STA $DD0D + STA (address does not match) + +Instruction and some part - not copyrightable. diff --git a/strings/8D1003A9 b/strings/8D1003A9 new file mode 100644 index 00000000..74148a77 --- /dev/null +++ b/strings/8D1003A9 @@ -0,0 +1,3 @@ +STA $0310 + LDA #$xx (value does not match) + +Instruction + a half. Not copyrightable. diff --git a/strings/8D8F02A9 b/strings/8D8F02A9 new file mode 100644 index 00000000..3e0425bf --- /dev/null +++ b/strings/8D8F02A9 @@ -0,0 +1,3 @@ +STA $028F + LDA #$xx (value does not match) + +Instruction + a half. Not copyrightable. diff --git a/strings/A2164C37 b/strings/A2164C37 new file mode 100644 index 00000000..a030896b --- /dev/null +++ b/strings/A2164C37 @@ -0,0 +1,3 @@ +LDX #$16 + JMP $xx37 (address does not fully match) + +Instruction + a part of another one. Not copyrightable. diff --git a/strings/A4A53D85 b/strings/A4A53D85 new file mode 100644 index 00000000..b9094fe0 --- /dev/null +++ b/strings/A4A53D85 @@ -0,0 +1,3 @@ +$A4 + LDA $3D + STA (address does not match) + +Instruction + some parts. Not copyrightable. diff --git a/strings/A4AD00DD b/strings/A4AD00DD new file mode 100644 index 00000000..34920d45 --- /dev/null +++ b/strings/A4AD00DD @@ -0,0 +1,6 @@ +$A4 + LDA $DD00 + +$DD00 is one of the CIA ports, so checking the value of inputs +on this port is something rather expected and common. + +Besides - this is just one instruction and some part - not copyrightable. diff --git a/strings/A593F002 b/strings/A593F002 new file mode 100644 index 00000000..df080101 --- /dev/null +++ b/strings/A593F002 @@ -0,0 +1,3 @@ +LDA $93 + BEQ (offset match, skip 2 bytes) + +Decision based on a content of a documented memory location - trivial, not copyrightable. diff --git a/strings/A5AD00DD b/strings/A5AD00DD new file mode 100644 index 00000000..3a7e9ae3 --- /dev/null +++ b/strings/A5AD00DD @@ -0,0 +1,3 @@ +$A5 + LDA $DD00 + +Instruction and some part - not copyrightable. diff --git a/strings/A86885 b/strings/A86885 new file mode 100644 index 00000000..a2b87807 --- /dev/null +++ b/strings/A86885 @@ -0,0 +1,3 @@ +TAY + PLA + STA (zero page address does not match) + +Simple stack/register manipulation, not even matching memory address (which is a documented/well-known variable) - not copyrightable. diff --git a/strings/A9002090FF b/strings/A9002090FF new file mode 100644 index 00000000..c97baee0 --- /dev/null +++ b/strings/A9002090FF @@ -0,0 +1,3 @@ +LDA #$00 + JSR $FF90 (official docummented SETMSG jumptable address) + +Two instructions to enabla Kernal string messages - trivial, not copyrightable. diff --git a/strings/A9A90185 b/strings/A9A90185 new file mode 100644 index 00000000..5497d5af --- /dev/null +++ b/strings/A9A90185 @@ -0,0 +1,3 @@ +$A9 + LDA #$01 + STA (zeropage location does not match) + +Instruction and some parts - not copyrightable. diff --git a/strings/A9C92CF0 b/strings/A9C92CF0 new file mode 100644 index 00000000..1481503a --- /dev/null +++ b/strings/A9C92CF0 @@ -0,0 +1,3 @@ +$A9 + CMP #$2C + BEQ (offset does not match) + +Instruction + some parts. Not copyrightable. diff --git a/strings/AC9D0001 b/strings/AC9D0001 new file mode 100644 index 00000000..b75f2557 --- /dev/null +++ b/strings/AC9D0001 @@ -0,0 +1,3 @@ +$AC + STA $0100,X + +Instruction + some part. Not copyrightable. diff --git a/strings/B1BB20D2FFC8 b/strings/B1BB20D2FFC8 new file mode 100644 index 00000000..9d85d44d --- /dev/null +++ b/strings/B1BB20D2FFC8 @@ -0,0 +1,3 @@ +LDA ($BB),Y + JSR $FFD2 (CHROUT official jumptable entry) + INY + +Part of a loop displaying a string - trivial, not copyrightable. diff --git a/strings/BABD04012910 b/strings/BABD04012910 new file mode 100644 index 00000000..3f42a187 --- /dev/null +++ b/strings/BABD04012910 @@ -0,0 +1,3 @@ +TSX + LDA $0104,X + AND #$10 + +Simple check what caused an interrupt - not copyrightable. diff --git a/strings/C902D003 b/strings/C902D003 new file mode 100644 index 00000000..82ab06f9 --- /dev/null +++ b/strings/C902D003 @@ -0,0 +1,3 @@ +CMP #$02 + BNE (offset matches, skip 3 bytes) + +Becision based on accumulator being equal to 2 (which is a number of a specific unique device) - trivial, not copyrightable. diff --git a/strings/D0036C028020 b/strings/D0036C028020 new file mode 100644 index 00000000..d89b34f0 --- /dev/null +++ b/strings/D0036C028020 @@ -0,0 +1,3 @@ +BNE (offset match, skip 3 bytes) + JMP ($8002) + JSR (address does not match) + +If cartridge present, jump into it using official API, else - do some subroutine. Not creative - not copyrightable. diff --git a/strings/D003CAD0F560 b/strings/D003CAD0F560 new file mode 100644 index 00000000..eaf70a44 --- /dev/null +++ b/strings/D003CAD0F560 @@ -0,0 +1,3 @@ +BNE (offset match, skip 3 bytes) + DEX + BNE (backwards, offset match) + RTS + +Part of a routine scanning for a valid cartridge - there aren't many sane ways to do this (compare strings), some similarity is unevitable. Not creative - not copyrightable. diff --git a/strings/E52BAAA538E52C20 b/strings/E52BAAA538E52C20 new file mode 100644 index 00000000..44750a39 --- /dev/null +++ b/strings/E52BAAA538E52C20 @@ -0,0 +1,3 @@ +SBC $2B + TAX + LDA $38 + SBC $2C + JSR (address does not match) + +Part of the code printing available BASIC memory size (it has to substract two 16 bit values). Not many ways to do this, some similarity is inevitable. Not creative - not copyrightable. diff --git a/strings/E54C0AE5 b/strings/E54C0AE5 new file mode 100644 index 00000000..fcfe7208 --- /dev/null +++ b/strings/E54C0AE5 @@ -0,0 +1 @@ +This is a part of Kernal jumptable - series of jumps, sometimes to the well known addreses (or through documented vectors). No business logic, part of the Kernal API itself - not copyrightable. diff --git a/strings/FF0000000000000000000000000000000000 b/strings/FF0000000000000000000000000000000000 new file mode 100644 index 00000000..f4672b03 --- /dev/null +++ b/strings/FF0000000000000000000000000000000000 @@ -0,0 +1,3 @@ +$FF followed by multiple 0's + +Meaningless - results of both ROM sets having empty space. Not copyrightable.