Merge pull request #32 from FeralChild64/master

Further development
This commit is contained in:
gardners authored and GitHub committed 2019-10-05 22:27:59 +09:30
commit 5f14ae5dc6
186 files changed
+2755 -1623

No files matched your search

+4
View File
@@ -1,4 +1,8 @@
# Image which is illegal to distribute - just for extra safety
kernal_hybrid.rom
# Compilation related files # Compilation related files
assembler/KickAss* assembler/KickAss*
+107
View File
@@ -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 `@<drive_number>`, `@<command>`, `@$`, `@$<params>` 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.
+86 -20
View File
@@ -3,7 +3,7 @@
SRCDIR_COMMON = c64/aliases SRCDIR_COMMON = c64/aliases
SRCDIR_BASIC_COMMON = $(SRCDIR_COMMON) c64/basic 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_generic = $(SRCDIR_BASIC_COMMON) c64/basic/,target_generic
SRCDIR_BASIC_mega65 = $(SRCDIR_BASIC_COMMON) c64/basic/,target_mega65 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) SRC_TOOLS = $(wildcard src/tools/*.c,src/tools/*.cc)
# Generated files
GEN_BASIC = build/,generated/packed_messages.s
GEN_KERNAL =
# List of tools # List of tools
TOOL_COLLECT_DATA = build/tools/collect_data 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)) 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
GIT_COMMIT:= $(shell git log -1 --pretty='%h' | tr '[:lower:]' '[:upper:]') 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 # 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_generic/OUTB.BIN build/target_generic/BASIC_combined.vs: \
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 $(TOOL_ASSEMBLER) $(TOOL_BUILD_SEGMENT) $(GEN_BASIC) $(SRCDIR_BASIC_generic) \
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 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_generic/OUTK.BIN build/target_generic/KERNAL_combined.vs build/target_generic/KERNAL_combined.sym: \
build/target_mega65/OUTK.BIN: $(TOOL_ASSEMBLER) $(TOOL_BUILD_SEGMENT) $(SRCDIR_KERNAL_mega65) $(foreach dir,$(SRCDIR_KERNAL_mega65),$(wildcard $(dir)/*.s)) $(TOOL_ASSEMBLER) $(TOOL_BUILD_SEGMENT) $(GEN_KERNAL) $(SRCDIR_KERNAL_generic) \
build/target_ultimate64/OUTK.BIN: $(TOOL_ASSEMBLER) $(TOOL_BUILD_SEGMENT) $(SRCDIR_KERNAL_ultimate64) $(foreach dir,$(SRCDIR_KERNAL_ultimate64),$(wildcard $(dir)/*.s)) 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_generic/newrom: build/target_generic/OUTB.BIN build/target_generic/OUTK.BIN
build/target_mega65/newrom: build/target_mega65/OUTB.BIN build/target_mega65/OUTK.BIN build/target_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_mega65.rom: build/target_mega65/newrom
build/basic_ultimate64.rom: build/target_ultimate64/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 # Rules - BASIC and KERNAL
build/,generated/packed_messages.s: $(TOOL_COMPRESS_TEXT) build/,generated/packed_messages.s: $(TOOL_COMPRESS_TEXT)
@mkdir -p build/,generated @mkdir -p build/,generated
$(TOOL_COMPRESS_TEXT) > build/,generated/packed_messages.s $(TOOL_COMPRESS_TEXT) > build/,generated/packed_messages.s
.PRECIOUS: build/target_%/OUTB.BIN .PRECIOUS: build/target_%/OUTB.BIN build/target_%/BASIC_combined.vs
build/target_%/OUTB.BIN: build/target_%/OUTB.BIN build/target_%/BASIC_combined.vs:
@mkdir -p build/target_$* @mkdir -p build/target_$*
@rm -f $@* build/target_$*/BASIC* @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 .PRECIOUS: build/target_%/OUTK.BIN build/target_%/KERNAL_combined.vs build/target_%/KERNAL_combined.sym
build/target_%/OUTK.BIN: build/target_%/OUTK.BIN build/target_%/KERNAL_combined.vs build/target_%/KERNAL_combined.sym:
@mkdir -p build/target_$* @mkdir -p build/target_$*
@rm -f $@* build/target_$*/KERNAL* @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 .PRECIOUS: build/target_%/newrom
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 .PRECIOUS: build/kernal_%.rom
build/kernal_%.rom: build/kernal_%.rom:
@@ -134,6 +165,22 @@ build/kernal_%.rom:
build/basic_%.rom: build/basic_%.rom:
dd if=build/target_$*/newrom bs=8192 count=1 skip=0 of=$@ 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 # Rules - platform 'Mega 65' specific
build/newc65.rom: build/kernal_mega65.rom build/basic_mega65.rom build/chargen.rom Makefile 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 # Rules - tests
test: build/kernal_generic.rom build/basic_generic.rom .PHONY: test test_generic test_mega65 test_ultimate64 test_m65 testremote testsimilarity
x64 -kernal build/kernal_generic.rom -basic build/basic_generic.rom -8 empty.d64
testremote: build/kernal_generic.rom build/basic_generic.rom test: test_generic
x64 -kernal build/kernal_generic.rom -basic build/basic_generic.rom -remotemonitor
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 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) kernal build/target_generic/newrom
$(TOOL_SIMILARITY) basic build/target_generic/newrom $(TOOL_SIMILARITY) basic build/target_generic/newrom
+105 -50
View File
@@ -1,11 +1,11 @@
# New features # 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 * improved keyboard scanning, supports multi-key roll-over and rejection of spurious joystick input
* joystick (port 1) can be used to move text cursor * 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 * cold/warm start silences multiple SID chips - all $D4xx and $D5xx addresses
* wark start due to BRK prints out the instruction address * wark start due to BRK prints out the instruction address
* extended `LOAD` command * extended `LOAD` command
@@ -46,66 +46,121 @@ For the current status of the low memory location implementation andd usage chec
## BASIC ## BASIC
### Official BASIC routines
TODO Note: vectors at `$0300` are not supported yet - for now only the locations below can be used!
<br />
| 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 | |
<br />
### Unofficial BASIC routines/locations
Not all of them - only these we want to have implemented.
<br />
| 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 | |
<br />
## Kernal ## Kernal
Note: only the jump table addresses are currently supported, real routine addresses are different!
### Official Kernal routines ### Official Kernal routines
NOTE: Even the 'DONE' routines won't support features described as missing in one of the previous chapters! NOTE: Even the 'DONE' routines won't support features described as missing in one of the previous chapters!
<br /> <br />
| Address | Name | Status | Remarks | | Address | Unofficial | Name | Status | Remarks |
| --------- | :------- | :------: | :------------------------------------------------: | | :-------: | :--------: | :---------- | :------: | :------------------------------------------------: |
| `$FF81` | `CINT` | DONE | | | `($028F)` | | `KEYLOG` | NOT DONE | |
| `$FF84` | `IOINIT` | PARTIAL | CIA initialization incomplete | | `$FF81` | `$FF5B` | `CINT` | DONE | |
| `$FF87` | `RAMTAS` | DONE | | | `$FF84` | `$FDA3` | `IOINIT` | PARTIAL | CIA initialization incomplete |
| `$FF8A` | `RESTOR` | DONE | | | `$FF87` | `$FD50` | `RAMTAS` | DONE | |
| `$FF8D` | `VECTOR` | DONE | | | `$FF8A` | `$FD15` | `RESTOR` | DONE | |
| `$FF90` | `SETMSG` | DONE | | | `$FF8D` | `$FD1A` | `VECTOR` | DONE | |
| `$FF93` | `SECOND` | DONE | | | `$FF90` | | `SETMSG` | DONE | |
| `$FF96` | `TKSA` | DONE | | | `$FF93` | | `SECOND` | DONE | |
| `$FF99` | `MEMTOP` | DONE | | | `$FF96` | | `TKSA` | DONE | |
| `$FF9C` | `MEMBOT` | DONE | | | `$FF99` | | `MEMTOP` | DONE | |
| `$FF9F` | `SCNKEY` | DONE | could be better integrated with ROM (aliases) | | `$FF9C` | | `MEMBOT` | DONE | |
| `$FFA2` | `SETTMO` | DONE | | | `$FF9F` | | `SCNKEY` | DONE | could be better integrated with ROM (aliases) |
| `$FFA5` | `ACPTR` | DONE | | | `$FFA2` | | `SETTMO` | DONE | |
| `$FFA8` | `CIOUT` | DONE | | | `$FFA5` | | `ACPTR` | DONE | |
| `$FFAB` | `UNTLK` | DONE | | | `$FFA8` | | `CIOUT` | DONE | |
| `$FFAE` | `UNLSN` | DONE | | | `$FFAB` | | `UNTLK` | DONE | |
| `$FFB1` | `LISTEN` | DONE | | | `$FFAE` | | `UNLSN` | DONE | |
| `$FFB4` | `TALK` | DONE | | | `$FFB1` | | `LISTEN` | DONE | |
| `$FFB7` | `READST` | DONE | | | `$FFB4` | | `TALK` | DONE | |
| `$FFBA` | `SETFLS` | DONE | | | `$FFB7` | | `READST` | DONE | |
| `$FFBD` | `SETNAM` | DONE | | | `$FFBA` | | `SETFLS` | DONE | |
| `$FFC0` | `OPEN` | DONE | | | `$FFBD` | | `SETNAM` | DONE | |
| `$FFC3` | `CLOSE` | DONE | | | `$FFC0` | `$F34A` | `OPEN` | DONE | |
| `$FFC6` | `CHKIN` | DONE | | | `$FFC3` | `$F291` | `CLOSE` | DONE | |
| `$FFC9` | `CHKOUT` | PARTIAL | | | `$FFC6` | `$F20E` | `CHKIN` | DONE | |
| `$FFCC` | `CLRCHN` | DONE | | | `$FFC9` | `$F250` | `CKOUT` | PARTIAL | |
| `$FFCF` | `CHRIN` | PARTIAL | | | `$FFCC` | `$F333` | `CLRCHN` | DONE | |
| `$FFD2` | `CHROUT` | PARTIAL | | | `$FFCF` | `$F157` | `CHRIN` | PARTIAL | |
| `$FFD5` | `LOAD` | PARTIAL | no VERIFY support yet, no STOP key support | | `$FFD2` | `$F1CA` | `CHROUT` | PARTIAL | |
| `$FFD8` | `SAVE` | NOT DONE | | | `$FFD5` | `$F49E` | `LOAD` | PARTIAL | not yet clear what's this entry doing |
| `$FFDB` | `SETTIM` | DONE | | | `($0330)` | `$F4A5` | `LOAD` | PARTIAL | no VERIFY support, no STOP key, check $F49E addr |
| `$FFDE` | `RDTIM` | DONE | | | `$FFD8` | `$F5DD` | `SAVE` | NOT DONE | |
| `$FFE1` | `STOP` | DONE | | | `($0332)` | `$F5ED` | `SAVE` | NOT DONE | |
| `$FFE4` | `GETIN` | PARTIAL | only some devices supported | | `$FFDB` | | `SETTIM` | DONE | |
| `$FFE7` | `CLALL` | DONE | | | `$FFDE` | | `RDTIM` | DONE | |
| `$FFEA` | `UDTIM` | DONE | | | `$FFE1` | `$F6ED` | `STOP` | DONE | |
| `$FFED` | `SCREEN` | DONE | | | `$FFE4` | `$F13E` | `GETIN` | PARTIAL | only some devices supported |
| `$FFF0` | `PLOT` | PARTIAL | cursor blink not handled | | `$FFE7` | `$F32F` | `CLALL` | DONE | |
| `$FFF3` | `IOBASE` | 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 | |
<br /> <br />
### Unofficial Kernal locations ### Unofficial Kernal routines/locations
TODO Not all of them - only these we want to have implemented.
<br />
| 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 | |
<br />
+6 -1
View File
@@ -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 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). - Don't mix ROMs from different builds/versions (again, CHARGEN is an exception).
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
+28
View File
@@ -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
+28
View File
@@ -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
+28
View File
@@ -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
+83
View File
@@ -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
}
+8
View File
@@ -10,6 +10,8 @@
// VIC-II registers // VIC-II registers
.label __VIC_BASE = $D000 // base address of the chip
.label VIC_SP0X = $D000 .label VIC_SP0X = $D000
.label VIC_SP0Y = $D001 .label VIC_SP0Y = $D001
.label VIC_SP1X = $D002 .label VIC_SP1X = $D002
@@ -62,6 +64,8 @@
// SID registers // SID registers
.label __SID_BASE = $D400 // base address of the chip
.label SID_FRELO1 = $D400 .label SID_FRELO1 = $D400
.label SID_FREHI1 = $D401 .label SID_FREHI1 = $D401
.label SID_PWLO1 = $D402 .label SID_PWLO1 = $D402
@@ -97,6 +101,8 @@
// CIA #1 registers // CIA #1 registers
.label __CIA1_BASE = $DC00 // base address of the chip
.label CIA1_PRA = $DC00 .label CIA1_PRA = $DC00
.label CIA1_PRB = $DC01 .label CIA1_PRB = $DC01
.label CIA1_DDRA = $DC02 .label CIA1_DDRA = $DC02
@@ -119,6 +125,8 @@
// CIA #2 registers // CIA #2 registers
.label __CIA2_BASE = $DD00 // base address of the chip
.label CIA2_PRA = $DD00 // VIC bank switching and IEC port .label CIA2_PRA = $DD00 // VIC bank switching and IEC port
.label CIA2_PRB = $DD01 .label CIA2_PRB = $DD01
.label CIA2_DDRA = $DD02 .label CIA2_DDRA = $DD02
+109 -22
View File
@@ -12,8 +12,8 @@
// //
// $02 -- UNUSED -- free for user software // $02 -- UNUSED -- free for user software
.label ADRAY1 = $03 // $03-$04 -- NOT IMPLEMENTED -- .label ADRAY1 = $03 // $03-$04
.label ADRAY2 = $05 // $05-$06 -- NOT IMPLEMENTED -- .label ADRAY2 = $05 // $05-$06
.label CHARAC = $07 // [!] our implementation might be different XXX give more details .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 ENDCHR = $08 // [!] our implementation might be different XXX give more details
.label TRMPOS = $09 // -- NOT IMPLEMENTED -- .label TRMPOS = $09 // -- NOT IMPLEMENTED --
@@ -38,8 +38,8 @@
.label ARYTAB = $2F // $2F-$30 -- NOT IMPLEMENTED -- .label ARYTAB = $2F // $2F-$30 -- NOT IMPLEMENTED --
.label STREND = $31 // $31-$32 -- NOT IMPLEMENTED -- .label STREND = $31 // $31-$32 -- NOT IMPLEMENTED --
.label FRETOP = $33 // $33-$34 -- NOT IMPLEMENTED -- .label FRETOP = $33 // $33-$34 -- NOT IMPLEMENTED --
.label FRESPC = $35 // $35-$36 [!] our implementation might be different XXX give more details .label FRESPC = $35 // $35-$36 [!] our implementation uses this as temporary string pointer
.label MEMSIZ = $37 // $37-$38 -- NOT IMPLEMENTED -- highest address of BASIC memory .label MEMSIZ = $37 // $37-$38 highest address of BASIC memory + 1
.label CURLIN = $39 // $39-$3A current BASIC line number .label CURLIN = $39 // $39-$3A current BASIC line number
.label OLDLIN = $3B // $3B-$3C previous BASIC line number .label OLDLIN = $3B // $3B-$3C previous BASIC line number
.label OLDTXT = $3D // $3D-$3E current BASIC line pointer .label OLDTXT = $3D // $3D-$3E current BASIC line pointer
@@ -57,13 +57,23 @@
.label JMPER = $54 // $54-$56 -- NOT IMPLEMENTED -- .label JMPER = $54 // $54-$56 -- NOT IMPLEMENTED --
.label TEMPF1 = $57 // $57-$5B BASIC numeric work area .label TEMPF1 = $57 // $57-$5B BASIC numeric work area
.label TEMPF2 = $5C // $5C-$60 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 SGNFLG = $67 // -- NOT IMPLEMENTED --
.label BITS = $68 // -- NOT IMPLEMENTED -- .label BITS = $68 // FAC1 overflow
.label FAC2 = $69 // $69-$6E -- NOT IMPLEMENTED -- [!] also used for memory move pointers
.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 ARISGN = $6F // -- NOT IMPLEMENTED --
.label FACOV = $70 // -- NOT IMPLEMENTED -- .label FACOV = $70 // FAC1 low order mantissa
.label FBUFPT = $67 // $71-$72 -- NOT IMPLEMENTED -- .label FBUFPT = $71 // $71-$72 -- NOT IMPLEMENTED --
.label CHRGET = $73 // $73-$8A -- NOT IMPLEMENTED -- .label CHRGET = $73 // $73-$8A -- NOT IMPLEMENTED --
.label TXTPTR = $7A // $7A-$7B current BASIC statement pointer .label TXTPTR = $7A // $7A-$7B current BASIC statement pointer
.label RNDX = $8B // $8B-$8F -- NOT IMPLEMENTED -- .label RNDX = $8B // $8B-$8F -- NOT IMPLEMENTED --
@@ -94,17 +104,53 @@
.label CNTDN = $A5 // -- NOT IMPLEMENTED -- .label CNTDN = $A5 // -- NOT IMPLEMENTED --
.label BUFPNT = $A6 // -- NOT IMPLEMENTED -- .label BUFPNT = $A6 // -- NOT IMPLEMENTED --
.label INBIT = $A7 // -- 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 BITCI = $A8 // -- NOT IMPLEMENTED --
.label RINONE = $A9 // -- NOT IMPLEMENTED -- .label RINONE = $A9 // -- NOT IMPLEMENTED --
.label RIDDATA = $AA // -- NOT IMPLEMENTED -- .label RIDDATA = $AA // -- NOT IMPLEMENTED --
.label RIPRTY = $AB // -- NOT IMPLEMENTED -- .label RIPRTY = $AB // -- NOT IMPLEMENTED --
#endif
.label SAL = $AC // $AC-$AD -- NOT IMPLEMENTED -- (implemented screen part) .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 CMP0 = $B0 // $B0-$B1 temporary tape storage, [!] here used for BRK instruction address
.label TAPE1 = $B2 // $B2-$B3 tape buffer pointer .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 -- .label BITTS = $B4 // -- NOT IMPLEMENTED --
#endif
.label NXTBIT = $B5 // -- NOT IMPLEMENTED -- .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 -- .label RODATA = $B6 // -- NOT IMPLEMENTED --
#endif
.label FNLEN = $B7 // current file name length .label FNLEN = $B7 // current file name length
.label LA = $B8 // current logical_file number .label LA = $B8 // current logical_file number
.label SA = $B9 // current secondary address .label SA = $B9 // current secondary address
@@ -124,7 +170,7 @@
.label SFDX = $CB // -- NOT IMPLEMENTED -- .label SFDX = $CB // -- NOT IMPLEMENTED --
.label BLNSW = $CC // cursor blink disable flag .label BLNSW = $CC // cursor blink disable flag
.label BLNCT = $CD // cursor blink countdown .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 BLNON = $CF // cursor visibilityy flag
.label CRSW = $D0 // whether to input from screen or keyboard .label CRSW = $D0 // whether to input from screen or keyboard
.label PNT = $D1 // $D1-$D2 pointer to the current screen line .label PNT = $D1 // $D1-$D2 pointer to the current screen line
@@ -134,7 +180,7 @@
.label TBLX = $D6 // current screen Y position .label TBLX = $D6 // current screen Y position
.label SCHAR = $D7 // ASCII value of the last printed character .label SCHAR = $D7 // ASCII value of the last printed character
.label INSRT = $D8 // insert mode flag/counter .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 USER = $F3 // $F3-$F4 pointer to current color RAM location
.label KEYTAB = $F5 // $F5-$F6 -- NOT IMPLEMENTED -- .label KEYTAB = $F5 // $F5-$F6 -- NOT IMPLEMENTED --
.label RIBUF = $F7 // $F7-$F8 -- 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) .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 // [!] XXX document $251-$258 usage
.label LAT = $259 // $259-$262, logical file numbers (table, 10 bytes) .label LAT = $259 // $259-$262, logical file numbers (table, 10 bytes)
.label FAT = $263 // $263-$26C, device 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 HIBASE = $288 // high byte of start of screen
.label XMAX = $289 // max keyboard buffer size .label XMAX = $289 // max keyboard buffer size
.label RPTFLG = $28A // -- NOT IMPLEMENTED -- .label RPTFLG = $28A // -- NOT IMPLEMENTED --
.label KOUNT = $28B // -- NOT IMPLEMENTED -- .label KOUNT = $28B // key repeat counter
.label DELAY = $28C // -- NOT IMPLEMENTED -- .label DELAY = $28C // -- NOT IMPLEMENTED --
.label SHFLAG = $28D // bucky keys (SHIFT/CTRL/C=) flags .label SHFLAG = $28D // bucky keys (SHIFT/CTRL/C=) flags
.label LSTSHF = $28E // last bucky key 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 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 M51CRT = $293 // -- NOT IMPLEMENTED -- mock 6551
.label M51CDR = $294 // -- NOT IMPLEMENTED -- mock 6551 .label M51CDR = $294 // -- NOT IMPLEMENTED -- mock 6551
.label M51AJB = $295 // $295-$296 -- NOT IMPLEMENTED -- mock 6551 .label M51AJB = $295 // $295-$296 -- NOT IMPLEMENTED -- mock 6551
.label RSSTAT = $297 // -- NOT IMPLEMENTED -- mock 6551, RS-232 status .label RSSTAT = $297 // -- NOT IMPLEMENTED -- mock 6551, RS-232 status
.label BITNUM = $298 // -- NOT IMPLEMENTED -- .label BITNUM = $298 // -- NOT IMPLEMENTED --
.label BAUDOF = $299 // $299-$29A -- NOT IMPLEMENTED -- .label BAUDOF = $299 // $299-$29A -- NOT IMPLEMENTED --
#endif
.label RIDBE = $29B // -- NOT IMPLEMENTED -- .label RIDBE = $29B // -- NOT IMPLEMENTED --
.label RIDBS = $29C // -- NOT IMPLEMENTED -- .label RIDBS = $29C // -- NOT IMPLEMENTED --
.label RODBS = $29D // -- NOT IMPLEMENTED -- .label RODBS = $29D // -- NOT IMPLEMENTED --
@@ -190,15 +258,34 @@
.label TD1IRQ = $2A4 // -- NOT IMPLEMENTED -- .label TD1IRQ = $2A4 // -- NOT IMPLEMENTED --
.label TLNIDX = $2A5 // -- NOT IMPLEMENTED -- .label TLNIDX = $2A5 // -- NOT IMPLEMENTED --
.label TVSFLG = $2A6 // 0 = NTSC, 1 = PAL .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 // BASIC vectors
.label IERROR = $300 // $300-$301 -- NOT IMPLEMENTED -- .label IERROR = $300 // $300-$301
.label IMAIN = $302 // $302-$303 -- NOT IMPLEMENTED -- .label IMAIN = $302 // $302-$303
.label ICRNCH = $304 // $304-$305 -- NOT IMPLEMENTED -- .label ICRNCH = $304 // $304-$305
.label IQPLOP = $306 // $306-$307 -- NOT IMPLEMENTED -- .label IQPLOP = $306 // $306-$307
.label IGONE = $308 // $308-$309 -- NOT IMPLEMENTED -- .label IGONE = $308 // $308-$309
.label IEVAL = $30A // $30A-$30B -- NOT IMPLEMENTED -- .label IEVAL = $30A // $30A-$30B
.label SAREG = $30C // .A storage, for SYS call .label SAREG = $30C // .A storage, for SYS call
.label SXREG = $30D // .X storage, for SYS call .label SXREG = $30D // .X storage, for SYS call
+15 -123
View File
@@ -1,126 +1,18 @@
// Names of ZP and low memory locations //
// (Only those for now that we feel the need to implement initially) // Helper aliases to make the code more readable
// (https://www.c64-wiki.com/wiki/Zeropage) // 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 // We re-use FAC2 for memory move pointers, since
.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 can't be doing calculations while moving memory // we can't be doing calculations while moving memory
.label memmove_src = $69 .label __memmove_src = $69
.label memmove_dst = $6b .label __memmove_dst = $6B
.label memmove_size = $6d .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
+13
View File
@@ -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
+9
View File
@@ -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.
+13
View File
@@ -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()
+13
View File
@@ -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()
+9
View File
@@ -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.
+3
View File
@@ -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.
+5
View File
@@ -0,0 +1,5 @@
// XXX provide documentation and implementation
RUNC:
STUB_IMPLEMENTATION()
+9
View File
@@ -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.
+13
View File
@@ -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()
+3
View File
@@ -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.
+5
View File
@@ -0,0 +1,5 @@
// XXX provide documentation and implementation
NEWSTT:
STUB_IMPLEMENTATION()
+13
View File
@@ -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()
+9
View File
@@ -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.
@@ -1,24 +1,25 @@
// Print string at $YYAA // Print string at $YYAA
// Compute's Mapping the 64 p101 // Compute's Mapping the 64 p101
print_string: // print string routine
STROUT:
// Setup pointer // Setup pointer
sty temp_string_ptr+1 sty FRESPC+1
sta temp_string_ptr+0 sta FRESPC+0
txa txa
pha pha
// Get offset ready // Get offset ready
ldy #$00 ldy #$00
!:
print_string_loop:
// Save Y in X, since X is preserved by chrout, but Y is not // Save Y in X, since X is preserved by chrout, but Y is not
tya tya
tax tax
lda (temp_string_ptr),y lda (FRESPC),y
beq print_string_end beq !+
jsr JCHROUT jsr JCHROUT
@@ -26,10 +27,8 @@ print_string_loop:
tay tay
iny iny
bne print_string_loop bne !-
!:
print_string_end:
pla pla
tax tax
rts rts
+13
View File
@@ -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()
+9
View File
@@ -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.
+5
View File
@@ -0,0 +1,5 @@
// XXX provide documentation and implementation
basic_adray1:
STUB_IMPLEMENTATION()
+5
View File
@@ -0,0 +1,5 @@
// XXX provide documentation and implementation
basic_adray2:
STUB_IMPLEMENTATION()
+22 -50
View File
@@ -2,61 +2,33 @@
// Compute's Mapping the 64 p211 // Compute's Mapping the 64 p211
basic_cold_start: basic_cold_start:
// Setup BASIC vectors at $0300
// Initialise interpretor
// Print start up message
// Print coloured part of the message // Setup vectors at $300
// ldy #>startup_message ldy #$0B
// lda #<startup_message
// jsr print_string
jsr printf // XXX don't use printf, keep it for debug purposes only
startup_banner:
TARGET_HOOK_BANNER()
// Print PAL/NTSC
ldx #30 // NTSC
lda TVSFLG
beq !+
ldx #31 // PAL
!: !:
jsr print_packed_message lda basic_vector_defaults_1, y
sta IERROR, y
dey
bpl !-
// Work out free bytes, and display // Setup misc vectors
jsr basic_do_new ldy #$04
lda basic_top_of_memory_ptr+0 !:
sec lda basic_vector_defaults_2, y
sbc basic_end_of_text_ptr+0 sta ADRAY1, y
tax dey
lda basic_top_of_memory_ptr+1 bpl !-
sbc basic_end_of_text_ptr+1
jsr print_integer // Setup USRPOK
lda #$4C // JMP opcode
sta USRPOK
lda #<do_ILLEGAL_QUANTITY_error
sta USRADD+0
lda #>do_ILLEGAL_QUANTITY_error
sta USRADD+1
lda #$20 // Print startup messages
jsr JCHROUT jsr INITMSG
// Print the rest of the start up message
ldx #34
jsr print_packed_message
// jump into warm start loop // jump into warm start loop
jmp basic_warm_start 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
// <RVS><WHITE>MEGA<NORMAL>BASIC\r\r
.byte $12,$05,$4D,$45,$47,$41,$92
.byte $42,$41,$53,$49,$43
.byte $20,$56,$32,$2e,$30,$2e,$30
.byte $0D,$0D
.byte 0
+34 -22
View File
@@ -9,35 +9,47 @@ basic_delete_line:
// jsr printf // jsr printf
// .text "DELETING LINE AT $" // .text "DELETING LINE AT $"
// .byte $f1,<basic_current_line_ptr,>basic_current_line_ptr // .byte $f1,<OLDTXT,>OLDTXT
// .byte $f0,<basic_current_line_ptr,>basic_current_line_ptr // .byte $f0,<OLDTXT,>OLDTXT
// .byte $0d,0 // .byte $0d,0
// Get address of next line // Get address of next line
ldx #<basic_current_line_ptr
ldy #0 ldy #0
#if CONFIG_MEMORY_MODEL_60K
ldx #<OLDTXT
jsr peek_under_roms jsr peek_under_roms
sta tokenise_work3 #else // CONFIG_MEMORY_MODEL_38K
lda (OLDTXT),y
#endif
sta __tokenise_work3
iny iny
#if CONFIG_MEMORY_MODEL_60K
jsr peek_under_roms jsr peek_under_roms
sta tokenise_work4 #else // CONFIG_MEMORY_MODEL_38K
lda (OLDTXT),y
#endif
sta __tokenise_work4
// Work out length of this line by looking at the pointer // Work out length of this line by looking at the pointer
lda tokenise_work3 lda __tokenise_work3
sec sec
sbc basic_current_line_ptr+0 sbc OLDTXT+0
sta tokenise_work3 sta __tokenise_work3
lda tokenise_work4 lda __tokenise_work4
sbc basic_current_line_ptr+1 sbc OLDTXT+1
sta tokenise_work4 sta __tokenise_work4
// jsr printf // jsr printf
// .text "LINE LENGTH IS $" // .text "LINE LENGTH IS $"
// .byte $f0,<tokenise_work4,>tokenise_work4 // .byte $f0,<__tokenise_work4,>__tokenise_work4
// .byte $f0,<tokenise_work3,>tokenise_work3 // .byte $f0,<__tokenise_work3,>__tokenise_work3
// .byte $0d,0 // .byte $0d,0
lda tokenise_work4 lda __tokenise_work4
sbc #0 sbc #0
cmp #$00 cmp #$00
beq !+ beq !+
@@ -46,9 +58,9 @@ basic_delete_line:
jmp do_MEMORY_CORRUPT_error jmp do_MEMORY_CORRUPT_error
!: !:
// Length can now be safely assumed to be in the low // Length can now be safely assumed to be in the low
// byte only, i.e., stored in tokenise_work3 // byte only, i.e., stored in __tokenise_work3
lda tokenise_work3 lda __tokenise_work3
pha pha
tax tax
@@ -57,14 +69,14 @@ basic_delete_line:
// Now decrease top of BASIC mem // Now decrease top of BASIC mem
pla pla
sta tokenise_work3 sta __tokenise_work3
lda basic_end_of_text_ptr+0 lda VARTAB+0
sec sec
sbc tokenise_work3 sbc __tokenise_work3
sta basic_end_of_text_ptr+0 sta VARTAB+0
lda basic_end_of_text_ptr+1 lda VARTAB+1
sbc #0 sbc #0
sta basic_end_of_text_ptr+1 sta VARTAB+1
clc clc
rts rts
+4 -8
View File
@@ -6,8 +6,7 @@ basic_do_error:
pha pha
// Print ? at start // Print ? at start
lda #$0D jsr print_return
jsr JCHROUT
lda #$3F lda #$3F
jsr JCHROUT jsr JCHROUT
@@ -17,8 +16,7 @@ basic_do_error:
jsr print_packed_message jsr print_packed_message
// Print ERROR at end // Print ERROR at end
lda #$20 jsr print_space
jsr JCHROUT
ldx #33 ldx #33
jsr print_packed_message jsr print_packed_message
@@ -26,10 +24,8 @@ basic_do_error:
// XXX print line number if not in direct mode // XXX print line number if not in direct mode
lda #$0D jsr print_return
jsr JCHROUT jsr print_return
lda #$0D // XXX do we need this?
jsr JCHROUT
// Reset stack, and go back to main loop // Reset stack, and go back to main loop
ldx #$FE ldx #$FE
+70 -35
View File
@@ -3,9 +3,14 @@
// or $00 char // or $00 char
basic_end_of_statement_check: basic_end_of_statement_check:
ldx #<basic_current_statement_ptr
ldy #0 ldy #0
#if CONFIG_MEMORY_MODEL_60K
ldx #<TXTPTR
jsr peek_under_roms jsr peek_under_roms
#else // CONFIG_MEMORY_MODEL_38K
lda (TXTPTR),y
#endif
// Consume any spaces // Consume any spaces
cmp #$20 cmp #$20
@@ -31,22 +36,28 @@ basic_execute_statement:
// Check for RUN/STOP // Check for RUN/STOP
lda STKEY lda STKEY
bmi !+ bmi !+
jmp basic_do_break jmp cmd_stop
!: !:
// Skip over any white space and : // Skip over any white space and :
ldy #0 ldy #0
ldx #<basic_current_statement_ptr
#if CONFIG_MEMORY_MODEL_60K
ldx #<TXTPTR
jsr peek_under_roms jsr peek_under_roms
#else // CONFIG_MEMORY_MODEL_38K
lda (TXTPTR),y
#endif
jsr basic_end_of_statement_check jsr basic_end_of_statement_check
bcs basic_end_of_line bcs basic_end_of_line
// jsr printf // jsr printf
// .text "LINE PTR = $" // .text "LINE PTR = $"
// .byte $f1,<basic_current_line_ptr,>basic_current_line_ptr // .byte $f1,<OLDTXT,>OLDTXT
// .byte $f0,<basic_current_line_ptr,>basic_current_line_ptr // .byte $f0,<OLDTXT,>OLDTXT
// .text ", STATEMENT PTR = $" // .text ", STATEMENT PTR = $"
// .byte $f1,<basic_current_statement_ptr,>basic_current_statement_ptr // .byte $f1,<TXTPTR,>TXTPTR
// .byte $f0,<basic_current_statement_ptr,>basic_current_statement_ptr // .byte $f0,<TXTPTR,>TXTPTR
// .byte $d,0 // .byte $d,0
// Go through the line until its end is reached. // 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 // Get next char of program text, even if it is hiding under a ROM or the
// IO area. // IO area.
ldx #<basic_current_statement_ptr
ldy #0 ldy #0
#if CONFIG_MEMORY_MODEL_60K
ldx #<TXTPTR
jsr peek_under_roms jsr peek_under_roms
cmp #$00 cmp #$00
#else // CONFIG_MEMORY_MODEL_38K
lda (TXTPTR),y
#endif
beq basic_end_of_line beq basic_end_of_line
// The checks should be done in order of frequency, so that we are as // The checks should be done in order of frequency, so that we are as
@@ -94,14 +112,14 @@ not_a_token:
cmp #$3a cmp #$3a
beq basic_skip_char beq basic_skip_char
// START wedge support #if CONFIG_DOS_WEDGE
// Are we in direct mode? // Are we in direct mode?
// DOS Wedge is a hacky solution (inelegant, but convenient), // DOS Wedge is a hacky solution (inelegant, but convenient),
// BASIC programmers should implement communication with drives // BASIC programmers should implement communication with drives
// the standard way, handling channels properly. Besides, // the standard way, handling channels properly. Besides,
// current implementation does not support characters under ROM // current implementation does not support characters under ROM
ldx basic_current_line_number+1 ldx CURLIN+1
cpx #$ff cpx #$ff
bne !+ bne !+
// We are in direct mode, allow wedge to handle '@' sign // We are in direct mode, allow wedge to handle '@' sign
@@ -111,7 +129,8 @@ not_a_token:
jsr basic_consume_character jsr basic_consume_character
jmp wedge_dos jmp wedge_dos
!: !:
// END wedge support
#endif // CONFIG_DOS_WEDGE
// If all else fails, it's a syntax error // If all else fails, it's a syntax error
jmp do_SYNTAX_error jmp do_SYNTAX_error
@@ -122,26 +141,32 @@ basic_skip_char:
basic_fetch_and_consume_character: basic_fetch_and_consume_character:
ldy #0 ldy #0
ldx #<basic_current_statement_ptr
#if CONFIG_MEMORY_MODEL_60K
ldx #<TXTPTR
jsr peek_under_roms jsr peek_under_roms
#else // CONFIG_MEMORY_MODEL_38K
lda (TXTPTR),y
#endif
// FALL THROUGH // FALL THROUGH
basic_consume_character: basic_consume_character:
// Advance basic text pointer // Advance basic text pointer
inc basic_current_statement_ptr+0 inc TXTPTR+0
bne !+ bne !+
inc basic_current_statement_ptr+1 inc TXTPTR+1
!: !:
rts rts
basic_unconsume_character: basic_unconsume_character:
lda basic_current_statement_ptr+0 lda TXTPTR+0
sec sec
sbc #1 sbc #1
sta basic_current_statement_ptr+0 sta TXTPTR+0
lda basic_current_statement_ptr+1 lda TXTPTR+1
sbc #0 sbc #0
sta basic_current_statement_ptr+1 sta TXTPTR+1
rts rts
basic_end_of_line: basic_end_of_line:
@@ -150,7 +175,7 @@ basic_end_of_line:
// one. // one.
// Are we in direct mode // Are we in direct mode
lda basic_current_line_number+1 lda CURLIN+1
cmp #$ff cmp #$ff
bne basic_not_direct_mode bne basic_not_direct_mode
@@ -159,17 +184,17 @@ basic_end_of_line:
basic_not_direct_mode: basic_not_direct_mode:
// Copy line number to previous line number // Copy line number to previous line number
lda basic_current_line_number+0 lda CURLIN+0
sta basic_previous_line_number+0 sta OLDLIN+0
lda basic_current_line_number+1 lda CURLIN+1
sta basic_previous_line_number+1 sta OLDLIN+1
// Advance the basic line pointer to the next line // Advance the basic line pointer to the next line
jsr basic_follow_link_to_next_line jsr basic_follow_link_to_next_line
// Are we at the end of the program? // Are we at the end of the program?
lda basic_current_line_ptr+0 lda OLDTXT+0
ora basic_current_line_ptr+1 ora OLDTXT+1
bne basic_execute_from_current_line bne basic_execute_from_current_line
// End of program found // End of program found
@@ -179,29 +204,39 @@ basic_execute_from_current_line:
// Check if pointer is null, if so, we are at the end of // Check if pointer is null, if so, we are at the end of
// the program. // the program.
ldy #0 ldy #0
ldx #<basic_current_line_ptr jsr peek_line_pointer_null_check
jsr peek_pointer_null_check
bcs !+ bcs !+
// End of program reached // End of program reached
jmp basic_main_loop jmp basic_main_loop
!: !:
// Skip pointer and line number to get address of first statement // Skip pointer and line number to get address of first statement
lda basic_current_line_ptr+0 lda OLDTXT+0
clc clc
adc #4 adc #4
sta basic_current_statement_ptr+0 sta TXTPTR+0
lda basic_current_line_ptr+1 lda OLDTXT+1
adc #0 adc #0
sta basic_current_statement_ptr+1 sta TXTPTR+1
// Store line number
ldx #<basic_current_line_ptr
ldy #2 ldy #2
#if CONFIG_MEMORY_MODEL_60K
ldx #<OLDTXT
jsr peek_under_roms jsr peek_under_roms
sta basic_current_line_number+0 #else // CONFIG_MEMORY_MODEL_38K
lda (OLDTXT),y
#endif
sta CURLIN+0
iny iny
#if CONFIG_MEMORY_MODEL_60K
jsr peek_under_roms jsr peek_under_roms
sta basic_current_line_number+1 #else // CONFIG_MEMORY_MODEL_38K
lda (OLDTXT),y
#endif
sta CURLIN+1
jmp basic_execute_statement jmp basic_execute_statement
+36 -13
View File
@@ -1,29 +1,41 @@
// Find the BASIC line with number basic_line_number // Find the BASIC line with number LINNUM
basic_find_line: basic_find_line:
// Get pointer to start of BASIC text // Get pointer to start of BASIC text
lda basic_start_of_text_ptr+0 lda TXTTAB+0
sta basic_current_line_ptr+0 sta OLDTXT+0
lda basic_start_of_text_ptr+1 lda TXTTAB+1
sta basic_current_line_ptr+1 sta OLDTXT+1
basic_find_line_loop: basic_find_line_loop:
// Then search for line number // Then search for line number
// Line number // Line number
ldy #3 ldy #3
ldx #<basic_current_line_ptr
#if CONFIG_MEMORY_MODEL_60K
ldx #<OLDTXT+0
jsr peek_under_roms jsr peek_under_roms
cmp basic_line_number+1 #else // CONFIG_MEMORY_MODEL_38K
lda (OLDTXT),y
#endif
cmp LINNUM+1
beq !+ beq !+
bcs line_num_too_high bcs line_num_too_high
bne not_this_line bne not_this_line
!: !:
dey dey
#if CONFIG_MEMORY_MODEL_60K
jsr peek_under_roms jsr peek_under_roms
cmp basic_line_number+0 #else // CONFIG_MEMORY_MODEL_38K
lda (OLDTXT),y
#endif
cmp LINNUM+0
beq !+ beq !+
bcs line_num_too_high bcs line_num_too_high
bne not_this_line bne not_this_line
@@ -32,8 +44,7 @@ basic_find_line_loop:
rts rts
not_this_line: not_this_line:
// Not this line, so advance to next line // Not this line, so advance to next line
ldx #<basic_current_line_ptr jsr peek_line_pointer_null_check
jsr peek_pointer_null_check
bcs more_lines_exist bcs more_lines_exist
// no more lines exist, return failure // no more lines exist, return failure
@@ -46,13 +57,25 @@ more_lines_exist:
// if the link goes backwards. // if the link goes backwards.
// Follow link to next line // Follow link to next line
ldy #0 ldy #0
ldx #<basic_current_line_ptr
#if CONFIG_MEMORY_MODEL_60K
ldx #<OLDTXT+0
jsr peek_under_roms jsr peek_under_roms
#else // CONFIG_MEMORY_MODEL_38K
lda (OLDTXT),y
#endif
sta $0100 sta $0100
iny iny
#if CONFIG_MEMORY_MODEL_60K
jsr peek_under_roms jsr peek_under_roms
sta basic_current_line_ptr+1 #else // CONFIG_MEMORY_MODEL_38K
lda (OLDTXT),y
#endif
sta OLDTXT+1
lda $0100 lda $0100
sta basic_current_line_ptr+0 sta OLDTXT+0
jmp basic_find_line_loop jmp basic_find_line_loop
+16 -4
View File
@@ -1,15 +1,27 @@
// Advance basic_current_line_ptr by following the // Advance OLDTXT by following the
// link to the next line // link to the next line
basic_find_next_line: basic_find_next_line:
ldy #0 ldy #0
ldx #<basic_current_line_ptr
#if CONFIG_MEMORY_MODEL_60K
ldx #<OLDTXT+0
jsr peek_under_roms jsr peek_under_roms
#else // CONFIG_MEMORY_MODEL_38K
lda (OLDTXT),y
#endif
pha pha
iny iny
#if CONFIG_MEMORY_MODEL_60K
jsr peek_under_roms jsr peek_under_roms
sta basic_current_line_ptr+1 #else // CONFIG_MEMORY_MODEL_38K
lda (OLDTXT),y
#endif
sta OLDTXT+1
pla pla
sta basic_current_line_ptr+0 sta OLDTXT+0
rts rts
+15 -3
View File
@@ -1,11 +1,23 @@
basic_follow_link_to_next_line: basic_follow_link_to_next_line:
ldy #0 ldy #0
ldx #<basic_current_line_ptr
#if CONFIG_MEMORY_MODEL_60K
ldx #<OLDTXT+0
jsr peek_under_roms jsr peek_under_roms
#else // CONFIG_MEMORY_MODEL_38K
lda (OLDTXT),y
#endif
pha pha
iny iny
#if CONFIG_MEMORY_MODEL_60K
jsr peek_under_roms jsr peek_under_roms
sta basic_current_line_ptr+1 #else // CONFIG_MEMORY_MODEL_38K
lda (OLDTXT),y
#endif
sta OLDTXT+1
pla pla
sta basic_current_line_ptr+0 sta OLDTXT+0
rts rts
+39 -23
View File
@@ -18,20 +18,20 @@ basic_insert_line:
// jsr printf // jsr printf
// .text "INSERTING LINE AT $" // .text "INSERTING LINE AT $"
// .byte $f1,<basic_current_line_ptr,>basic_current_line_ptr // .byte $f1,<OLDTXT,>OLDTXT
// .byte $f0,<basic_current_line_ptr,>basic_current_line_ptr // .byte $f0,<OLDTXT,>OLDTXT
// .byte $0d,0 // .byte $0d,0
lda basic_current_line_ptr+0 lda OLDTXT+0
pha pha
lda basic_current_line_ptr+1 lda OLDTXT+1
pha pha
// Get number of bytes in tokenised line after line number // Get number of bytes in tokenised line after line number
lda tokenise_work2 lda __tokenise_work2
sec sec
sbc tokenise_work1 sbc __tokenise_work1
// Add on the four bytes space we need // Add on the four bytes space we need
clc clc
adc #5 adc #5
@@ -44,41 +44,57 @@ basic_insert_line:
// Now increase top of BASIC mem // Now increase top of BASIC mem
pla pla
clc clc
adc basic_end_of_text_ptr+0 adc VARTAB+0
sta basic_end_of_text_ptr+0 sta VARTAB+0
lda basic_end_of_text_ptr+1 lda VARTAB+1
adc #0 adc #0
sta basic_end_of_text_ptr+1 sta VARTAB+1
// Get pointer back // Get pointer back
pla pla
sta basic_current_line_ptr+1 sta OLDTXT+1
pla pla
sta basic_current_line_ptr+0 sta OLDTXT+0
// Write the line number // Write the line number
ldy #2 ldy #2
ldx #<basic_current_line_ptr lda LINNUM+0
lda basic_line_number+0
#if CONFIG_MEMORY_MODEL_60K
ldx #<OLDTXT+0
jsr poke_under_roms jsr poke_under_roms
#else // CONFIG_MEMORY_MODEL_38K
sta (OLDTXT),y
#endif
iny iny
lda basic_line_number+1 lda LINNUM+1
#if CONFIG_MEMORY_MODEL_60K
jsr poke_under_roms jsr poke_under_roms
#else // CONFIG_MEMORY_MODEL_38K
sta (OLDTXT),y
#endif
// Now store the line body itself // Now store the line body itself
inc tokenise_work2 inc __tokenise_work2
line_store_loop: line_store_loop:
ldx tokenise_work1 ldx __tokenise_work1
lda $0200,x lda $0200,x
inc tokenise_work1 inc __tokenise_work1
ldx #<basic_current_line_ptr
iny iny
#if CONFIG_MEMORY_MODEL_60K
ldx #<OLDTXT+0
jsr poke_under_roms jsr poke_under_roms
lda tokenise_work1 #else // CONFIG_MEMORY_MODEL_38K
cmp tokenise_work2 sta (OLDTXT),y
#endif
lda __tokenise_work1
cmp __tokenise_work2
bne line_store_loop bne line_store_loop
dec tokenise_work2 dec __tokenise_work2
clc clc
rts rts
+23 -24
View File
@@ -24,14 +24,14 @@ read_line_loop:
ldx #22 ldx #22
jmp basic_do_error jmp basic_do_error
!: !:
sta basic_input_buffer,x sta BUF,x
inx inx
jmp read_line_loop jmp read_line_loop
got_line_of_input: got_line_of_input:
// Store length of input buffer ready for tokenising // Store length of input buffer ready for tokenising
stx tokenise_work1 stx __tokenise_work1
// Strip leading spaces from the line // Strip leading spaces from the line
remove_leading_spaces: remove_leading_spaces:
@@ -42,20 +42,19 @@ remove_leading_spaces:
rsl_l1: lda $0200,x rsl_l1: lda $0200,x
sta $01ff,x sta $01ff,x
inx inx
cpx tokenise_work1 cpx __tokenise_work1
bne rsl_l1 bne rsl_l1
// Reduce length of input by one // Reduce length of input by one
dec tokenise_work1 dec __tokenise_work1
// Stop trying to rim if we run out of input // Stop trying to rim if we run out of input
bne remove_leading_spaces bne remove_leading_spaces
!: !:
// Do printing of the new line // Do printing of the new line
lda #$0d jsr print_return
jsr JCHROUT
// Ignore empty lines // Ignore empty lines
lda tokenise_work1 lda __tokenise_work1
beq basic_read_next_line beq basic_read_next_line
// Else, tokenise the line // Else, tokenise the line
@@ -71,36 +70,36 @@ rsl_l1: lda $0200,x
// Yes, the line begins with a number. // Yes, the line begins with a number.
// Parse the line number and check validity // Parse the line number and check validity
// injest_number follows tokenise_work1 as the offset into the line, // injest_number follows __tokenise_work1 as the offset into the line,
// so remember the line length somewhere else for now. // so remember the line length somewhere else for now.
lda tokenise_work1 lda __tokenise_work1
sta tokenise_work2 sta __tokenise_work2
lda #$00 lda #$00
sta tokenise_work1 sta __tokenise_work1
// Try to read line number // Try to read line number
lda #<$0200 lda #<$0200
sta basic_current_statement_ptr+0 sta TXTPTR+0
lda #>$0200 lda #>$0200
sta basic_current_statement_ptr+1 sta TXTPTR+1
jsr basic_parse_line_number jsr basic_parse_line_number
// Get pointer to next char // Get pointer to next char
lda basic_current_statement_ptr+0 lda TXTPTR+0
sta tokenise_work1 sta __tokenise_work1
// Got a valid line number -- so do add/del line // Got a valid line number -- so do add/del line
// Skip any spaces after the line number // Skip any spaces after the line number
ldx tokenise_work1 ldx __tokenise_work1
skip_spaces: skip_spaces:
lda $0200,x lda $0200,x
cmp #$20 cmp #$20
bne !+ bne !+
inx inx
bne skip_spaces bne skip_spaces
!: stx tokenise_work1 !: stx __tokenise_work1
// First, clear all variables, so that we only have to shove BASIC text around. // First, clear all variables, so that we only have to shove BASIC text around.
// (We could later remove this requirement, and the only effect should be // (We could later remove this requirement, and the only effect should be
@@ -119,8 +118,8 @@ skip_spaces:
!: !:
// Insert new line if non-zero length, i.e., that // Insert new line if non-zero length, i.e., that
// we are not just deleting the line. // we are not just deleting the line.
lda tokenise_work1 lda __tokenise_work1
cmp tokenise_work2 cmp __tokenise_work2
beq !+ beq !+
jsr basic_insert_line jsr basic_insert_line
!: !:
@@ -133,19 +132,19 @@ not_a_line:
// Setup pointer to the statement // Setup pointer to the statement
lda #<$0200 lda #<$0200
sta basic_current_statement_ptr+0 sta TXTPTR+0
lda #>$0200 lda #>$0200
sta basic_current_statement_ptr+1 sta TXTPTR+1
// There is no stored line, so zero that pointer out // There is no stored line, so zero that pointer out
lda #$00 lda #$00
sta basic_current_line_ptr+0 sta OLDTXT+0
sta basic_current_line_ptr+1 sta OLDTXT+1
// Put invalid line number in current line number value, // Put invalid line number in current line number value,
// so that we know we are in direct mode // so that we know we are in direct mode
// (Compute's Mapping the 64 p19) // (Compute's Mapping the 64 p19)
lda #$ff lda #$ff
sta basic_current_line_number+1 sta CURLIN+1
jmp basic_execute_statement jmp basic_execute_statement
+8 -8
View File
@@ -5,23 +5,23 @@ basic_parse_line_number:
// Check if the number is a valid line number // Check if the number is a valid line number
// i.e., 16 bits, no exponent, no decimal // i.e., 16 bits, no exponent, no decimal
lda basic_fac1_mantissa+2 lda FAC1_mantissa+2
ora basic_fac1_mantissa+3 ora FAC1_mantissa+3
ora basic_fac1_exponent ora FAC1_exponent
beq !+ beq !+
ml_bad_line_number: ml_bad_line_number:
// Invalid line number // Invalid line number
jmp do_ILLEGAL_QUANTITY_error jmp do_ILLEGAL_QUANTITY_error
!: !:
// Line number are not allowed to have decimal points in them // Line number are not allowed to have decimal points in them
lda tokenise_work4 lda __tokenise_work4
cmp #$FF cmp #$FF
bne ml_bad_line_number bne ml_bad_line_number
// Got a valid line number. // Got a valid line number.
lda basic_fac1_mantissa+0 lda FAC1_mantissa+0
sta basic_line_number+0 sta LINNUM+0
lda basic_fac1_mantissa+1 lda FAC1_mantissa+1
sta basic_line_number+1 sta LINNUM+1
clc clc
rts rts
+82 -61
View File
@@ -2,45 +2,45 @@ basic_shift_mem_down_and_relink:
// Shift memory down to basic_current_line_pointer // Shift memory down to basic_current_line_pointer
// from X bytes further along. // from X bytes further along.
// Destination is basic_current_line_ptr // Destination is OLDTXT
lda basic_current_line_ptr+0 lda OLDTXT+0
sta memmove_dst+0 sta __memmove_dst+0
lda basic_current_line_ptr+1 lda OLDTXT+1
sta memmove_dst+1 sta __memmove_dst+1
// Source is that plus X // Source is that plus X
txa txa
pha // also keep for later pha // also keep for later
clc clc
adc basic_current_line_ptr+0 adc OLDTXT+0
sta memmove_src+0 sta __memmove_src+0
lda basic_current_line_ptr+1 lda OLDTXT+1
adc #0 adc #0
sta memmove_src+1 sta __memmove_src+1
// Size is distance from source to end of BASIC text. // Size is distance from source to end of BASIC text.
lda basic_end_of_text_ptr+0 lda VARTAB+0
sec sec
sbc memmove_src+0 sbc __memmove_src+0
sta memmove_size+0 sta __memmove_size+0
lda basic_end_of_text_ptr+1 lda VARTAB+1
sbc memmove_src+1 sbc __memmove_src+1
sta memmove_size+1 sta __memmove_size+1
// jsr printf // jsr printf
// .text "TOP OF BASIC = $" // .text "TOP OF BASIC = $"
// .byte $f1,<basic_end_of_text_ptr,>basic_end_of_text_ptr // .byte $f1,<VARTAB,>VARTAB
// .byte $f0,<basic_end_of_text_ptr,>basic_end_of_text_ptr // .byte $f0,<VARTAB,>VARTAB
// .byte $0d // .byte $0d
// .text "SHIFTING DOWN $" // .text "SHIFTING DOWN $"
// .byte $f1,<memmove_size,>memmove_size // .byte $f1,<__memmove_size,>__memmove_size
// .byte $f0,<memmove_size,>memmove_size // .byte $f0,<__memmove_size,>__memmove_size
// .text " BYTES FROM $" // .text " BYTES FROM $"
// .byte $f1,<memmove_src,>memmove_src // .byte $f1,<__memmove_src,>__memmove_src
// .byte $f0,<memmove_src,>memmove_src // .byte $f0,<__memmove_src,>__memmove_src
// .text " TO $" // .text " TO $"
// .byte $f1,<memmove_dst,>memmove_dst // .byte $f1,<__memmove_dst,>__memmove_dst
// .byte $f0,<memmove_dst,>memmove_dst // .byte $f0,<__memmove_dst,>__memmove_dst
// .byte $0d,0 // .byte $0d,0
// The copy routine that copies under the ROMs is as simple // The copy routine that copies under the ROMs is as simple
@@ -54,55 +54,54 @@ basic_shift_mem_down_and_relink:
// This means we have to then reduce the source and // This means we have to then reduce the source and
// target pointers by the same amount // target pointers by the same amount
lda memmove_size+0 lda __memmove_size+0
eor #$ff eor #$ff
sta tokenise_work3 sta __tokenise_work3
sta memmove_size+0 sta __memmove_size+0
lda memmove_src+0 lda __memmove_src+0
sec sec
sbc tokenise_work3 sbc __tokenise_work3
sta memmove_src+0 sta __memmove_src+0
lda memmove_src+1 lda __memmove_src+1
sbc #0 sbc #0
sta memmove_src+1 sta __memmove_src+1
lda memmove_dst+0 lda __memmove_dst+0
sec sec
sbc tokenise_work3 sbc __tokenise_work3
sta memmove_dst+0 sta __memmove_dst+0
lda memmove_dst+1 lda __memmove_dst+1
sbc #0 sbc #0
sta memmove_dst+1 sta __memmove_dst+1
// Increase copy page count so we can post-decrement compare with $00 // Increase copy page count so we can post-decrement compare with $00
inc memmove_size+1 inc __memmove_size+1
// jsr printf // jsr printf
// .text "REVISED BOUNDS $" // .text "REVISED BOUNDS $"
// .byte $f1,<memmove_size,>memmove_size // .byte $f1,<__memmove_size,>__memmove_size
// .byte $f0,<memmove_size,>memmove_size // .byte $f0,<__memmove_size,>__memmove_size
// .text " BYTES FROM $" // .text " BYTES FROM $"
// .byte $f1,<memmove_src,>memmove_src // .byte $f1,<__memmove_src,>__memmove_src
// .byte $f0,<memmove_src,>memmove_src // .byte $f0,<__memmove_src,>__memmove_src
// .text " TO $" // .text " TO $"
// .byte $f1,<memmove_dst,>memmove_dst // .byte $f1,<__memmove_dst,>__memmove_dst
// .byte $f0,<memmove_dst,>memmove_dst // .byte $f0,<__memmove_dst,>__memmove_dst
// .byte $0d,0 // .byte $0d,0
// Get Y value ready for the copy // Get Y value ready for the copy
ldy memmove_size+0 ldy __memmove_size+0
jsr shift_mem_down jsr shift_mem_down
// Get length of deletion back // Get length of deletion back
pla pla
sta tokenise_work3 sta __tokenise_work3
// Check if we still have any lines left // Check if we still have any lines left
ldy #0 ldy #0
ldx #<basic_current_line_ptr jsr peek_line_pointer_null_check
jsr peek_pointer_null_check
bcs relink_down_next_line bcs relink_down_next_line
// Nope, so just return // Nope, so just return
clc clc
@@ -113,36 +112,58 @@ relink_down_next_line:
// inc $d020 // inc $d020
// jmp relink_down_next_line // jmp relink_down_next_line
// Subtract tokenise_work3 from the pointer // Subtract __tokenise_work3 from the pointer
ldy #0 ldy #0
ldx #<basic_current_line_ptr+0
#if CONFIG_MEMORY_MODEL_60K
ldx #<OLDTXT+0
jsr peek_under_roms jsr peek_under_roms
#else // CONFIG_MEMORY_MODEL_38K
lda (OLDTXT),y
#endif
sec sec
sbc tokenise_work3 sbc __tokenise_work3
sta memmove_src+0 sta __memmove_src+0
iny iny
#if CONFIG_MEMORY_MODEL_60K
jsr peek_under_roms jsr peek_under_roms
#else // CONFIG_MEMORY_MODEL_38K
lda (OLDTXT),y
#endif
sbc #0 sbc #0
sta memmove_src+1 sta __memmove_src+1
ldy #0 ldy #0
ldx #<basic_current_line_ptr lda __memmove_src+0
lda memmove_src+0
#if CONFIG_MEMORY_MODEL_60K
ldx #<OLDTXT+0
jsr poke_under_roms jsr poke_under_roms
#else // CONFIG_MEMORY_MODEL_38K
sta (OLDTXT),y
#endif
iny iny
lda memmove_src+1 lda __memmove_src+1
#if CONFIG_MEMORY_MODEL_60K
jsr poke_under_roms jsr poke_under_roms
#else // CONFIG_MEMORY_MODEL_38K
sta (OLDTXT),y
#endif
relink_down_loop: relink_down_loop:
// Now advance pointer to the next line, // Now advance pointer to the next line,
lda memmove_src+0 lda __memmove_src+0
sta basic_current_line_ptr+0 sta OLDTXT+0
lda memmove_src+1 lda __memmove_src+1
sta basic_current_line_ptr+1 sta OLDTXT+1
// Have we run out of lines to patch? // Have we run out of lines to patch?
ldx #<basic_current_line_ptr jsr peek_line_pointer_null_check
jsr peek_pointer_null_check
bcs relink_down_next_line bcs relink_down_next_line
clc clc
+108 -74
View File
@@ -1,7 +1,7 @@
basic_shift_mem_up_and_relink: basic_shift_mem_up_and_relink:
// Shift memory up from basic_current_line_ptr // Shift memory up from OLDTXT
// X bytes. // X bytes.
// NOTE: Pointers need to be reduced by one, due to the way // NOTE: Pointers need to be reduced by one, due to the way
@@ -9,91 +9,91 @@ basic_shift_mem_up_and_relink:
// Work out end point of destination // Work out end point of destination
txa txa
clc clc
adc basic_end_of_text_ptr+0 adc VARTAB+0
sta memmove_dst+0 sta __memmove_dst+0
lda basic_end_of_text_ptr+1 lda VARTAB+1
adc #0 adc #0
sta memmove_dst+1 sta __memmove_dst+1
lda memmove_dst+0 lda __memmove_dst+0
sec sec
sbc #1 sbc #1
sta memmove_dst+0 sta __memmove_dst+0
lda memmove_dst+1 lda __memmove_dst+1
sbc #0 sbc #0
sta memmove_dst+1 sta __memmove_dst+1
// End point of source is just current end of BASIC text // End point of source is just current end of BASIC text
lda basic_end_of_text_ptr+0 lda VARTAB+0
sec sec
sbc #1 sbc #1
sta memmove_src+0 sta __memmove_src+0
lda basic_end_of_text_ptr+1 lda VARTAB+1
sbc #0 sbc #0
sta memmove_src+1 sta __memmove_src+1
// Work out size of region to copy // Work out size of region to copy
lda basic_end_of_text_ptr+0 lda VARTAB+0
sec sec
sbc basic_current_line_ptr+0 sbc OLDTXT+0
sta memmove_size+0 sta __memmove_size+0
lda basic_end_of_text_ptr+1 lda VARTAB+1
sbc basic_current_line_ptr+1 sbc OLDTXT+1
sta memmove_size+1 sta __memmove_size+1
// jsr printf // jsr printf
// .text "TOP OF BASIC = $" // .text "TOP OF BASIC = $"
// .byte $f1,<basic_end_of_text_ptr,>basic_end_of_text_ptr // .byte $f1,<VARTAB,>VARTAB
// .byte $f0,<basic_end_of_text_ptr,>basic_end_of_text_ptr // .byte $f0,<VARTAB,>VARTAB
// .byte $0d // .byte $0d
// .text "SHIFTING UP $" // .text "SHIFTING UP $"
// .byte $f1,<memmove_size,>memmove_size // .byte $f1,<__memmove_size,>__memmove_size
// .byte $f0,<memmove_size,>memmove_size // .byte $f0,<__memmove_size,>__memmove_size
// .text " BYTES FROM $" // .text " BYTES FROM $"
// .byte $f1,<memmove_src,>memmove_src // .byte $f1,<__memmove_src,>__memmove_src
// .byte $f0,<memmove_src,>memmove_src // .byte $f0,<__memmove_src,>__memmove_src
// .text " TO $" // .text " TO $"
// .byte $f1,<memmove_dst,>memmove_dst // .byte $f1,<__memmove_dst,>__memmove_dst
// .byte $f0,<memmove_dst,>memmove_dst // .byte $f0,<__memmove_dst,>__memmove_dst
// .byte $0d,0 // .byte $0d,0
// To make life simple for the copy routine that lives in RAM, // To make life simple for the copy routine that lives in RAM,
// we have to adjust the end pointers down one page and set Y to the low // we have to adjust the end pointers down one page and set Y to the low
// byte of the copy size. // byte of the copy size.
lda memmove_src+0 lda __memmove_src+0
sec sec
sbc memmove_size+0 sbc __memmove_size+0
sta memmove_src+0 sta __memmove_src+0
lda memmove_src+1 lda __memmove_src+1
sbc #0 sbc #0
sta memmove_src+1 sta __memmove_src+1
lda memmove_dst+0 lda __memmove_dst+0
sec sec
sbc memmove_size+0 sbc __memmove_size+0
sta memmove_dst+0 sta __memmove_dst+0
lda memmove_dst+1 lda __memmove_dst+1
sbc #0 sbc #0
sta memmove_dst+1 sta __memmove_dst+1
// Now make exit easy, by being able to check for zero on size high byte when done // Now make exit easy, by being able to check for zero on size high byte when done
inc memmove_size+1 inc __memmove_size+1
// Then set Y to the number offset required // Then set Y to the number offset required
ldy memmove_size+0 ldy __memmove_size+0
iny iny
stx tokenise_work3 stx __tokenise_work3
// jsr printf // jsr printf
// .text "REVISED BOUNDS $" // .text "REVISED BOUNDS $"
// .byte $f1,<memmove_size,>memmove_size // .byte $f1,<__memmove_size,>__memmove_size
// .byte $f0,<memmove_size,>memmove_size // .byte $f0,<__memmove_size,>__memmove_size
// .text " BYTES FROM $" // .text " BYTES FROM $"
// .byte $f1,<memmove_src,>memmove_src // .byte $f1,<__memmove_src,>__memmove_src
// .byte $f0,<memmove_src,>memmove_src // .byte $f0,<__memmove_src,>__memmove_src
// .text " TO $" // .text " TO $"
// .byte $f1,<memmove_dst,>memmove_dst // .byte $f1,<__memmove_dst,>__memmove_dst
// .byte $f0,<memmove_dst,>memmove_dst // .byte $f0,<__memmove_dst,>__memmove_dst
// .byte $0d,0 // .byte $0d,0
// Do the copy // Do the copy
@@ -105,12 +105,24 @@ basic_shift_mem_up_and_relink:
// pointer to itself, so that we can add the shift // pointer to itself, so that we can add the shift
// to make it end up pointing to the next line // to make it end up pointing to the next line
ldy #0 ldy #0
ldx #<basic_current_line_ptr+0
lda basic_current_line_ptr+0 lda OLDTXT+0
#if CONFIG_MEMORY_MODEL_60K
ldx #<OLDTXT+0
jsr poke_under_roms jsr poke_under_roms
#else // CONFIG_MEMORY_MODEL_38K
sta (OLDTXT),y
#endif
iny iny
lda basic_current_line_ptr+1 lda OLDTXT+1
#if CONFIG_MEMORY_MODEL_60K
jsr poke_under_roms jsr poke_under_roms
#else // CONFIG_MEMORY_MODEL_38K
sta (OLDTXT),y
#endif
relink_up_next_line: relink_up_next_line:
// inc $d020 // inc $d020
@@ -118,53 +130,75 @@ relink_up_next_line:
// Advance pointer by tokenise_word3 bytes // Advance pointer by tokenise_word3 bytes
ldy #0 ldy #0
ldx #<basic_current_line_ptr+0
#if CONFIG_MEMORY_MODEL_60K
ldx #<OLDTXT+0
jsr peek_under_roms jsr peek_under_roms
sta memmove_dst+0 #else // CONFIG_MEMORY_MODEL_38K
lda (OLDTXT),y
#endif
sta __memmove_dst+0
clc clc
adc tokenise_work3 adc __tokenise_work3
sta memmove_src+0 sta __memmove_src+0
iny iny
php php
#if CONFIG_MEMORY_MODEL_60K
jsr peek_under_roms jsr peek_under_roms
sta memmove_dst+1 cmp #$00
#else // CONFIG_MEMORY_MODEL_38K
lda (OLDTXT),y
#endif
sta __memmove_dst+1
plp plp
adc #0 adc #0
sta memmove_src+1 sta __memmove_src+1
// jsr printf // jsr printf
// .text "LINE ADDR = $" // .text "LINE ADDR = $"
// .byte $f1,<basic_current_line_ptr,>basic_end_of_text_ptr // .byte $f1,<OLDTXT,>VARTAB
// .byte $f0,<basic_current_line_ptr,>basic_end_of_text_ptr // .byte $f0,<OLDTXT,>VARTAB
// .text $d," BEFORE = $" // .text $d," BEFORE = $"
// .byte $f1,<memmove_dst,>memmove_dst // .byte $f1,<__memmove_dst,>__memmove_dst
// .byte $f0,<memmove_dst,>memmove_dst // .byte $f0,<__memmove_dst,>__memmove_dst
// .text ", AFTER = $" // .text ", AFTER = $"
// .byte $f1,<memmove_src,>memmove_src // .byte $f1,<__memmove_src,>__memmove_src
// .byte $f0,<memmove_src,>memmove_src // .byte $f0,<__memmove_src,>__memmove_src
// .byte $d // .byte $d
// .byte 0 // .byte 0
// Write memmove_src back to current line pointer // Write __memmove_src back to current line pointer
ldy #0 ldy #0
ldx #<basic_current_line_ptr lda __memmove_src+0
lda memmove_src+0
jsr poke_under_roms
iny
lda memmove_src+1
jsr poke_under_roms
#if CONFIG_MEMORY_MODEL_60K
ldx #<OLDTXT+0
jsr poke_under_roms
#else // CONFIG_MEMORY_MODEL_38K
sta (OLDTXT),y
#endif
iny
lda __memmove_src+1
#if CONFIG_MEMORY_MODEL_60K
jsr poke_under_roms
#else // CONFIG_MEMORY_MODEL_38K
sta (OLDTXT),y
#endif
relink_up_loop: relink_up_loop:
// Now advance pointer to the next line, // Now advance pointer to the next line,
lda memmove_src+0 lda __memmove_src+0
sta basic_current_line_ptr+0 sta OLDTXT+0
lda memmove_src+1 lda __memmove_src+1
sta basic_current_line_ptr+1 sta OLDTXT+1
// Have we run out of lines to patch? // Have we run out of lines to patch?
ldx #<basic_current_line_ptr jsr peek_line_pointer_null_check
jsr peek_pointer_null_check
bcs relink_up_next_line bcs relink_up_next_line
rts rts
+21
View File
@@ -0,0 +1,21 @@
//
// Default values for BASIC vectors - described in:
//
// - [RG64] C64 Programmer's Reference Guide - pages 68-70
// - [CM64] Compute's Mapping the Commodore 64 - page 318
//
basic_vector_defaults_1:
.word ERROR // IERROR
.word MAIN // IMAIN
.word CHRNCH // ICHRNCH
.word QPLOP // IQPLOP
.word GONE // IGONE
.word EVAL // IEVAL
basic_vector_defaults_2:
.word basic_adray1 // ADRAY1
.word basic_adray2 // ADRAY2
+7 -5
View File
@@ -1,7 +1,11 @@
// Clear screen etc, show READY prompt. // Clear screen etc, show READY prompt.
basic_warm_start: basic_warm_start:
#if CONFIG_MEMORY_MODEL_60K
// We need our helpers to get to filenames under ROMs or IO area
jsr install_ram_routines jsr install_ram_routines
#endif
// If warm start caused by BRK, print it address // If warm start caused by BRK, print it address
lda CMP0 lda CMP0
@@ -12,12 +16,10 @@ basic_warm_start:
jsr print_packed_message jsr print_packed_message
lda CMP0+1 lda CMP0+1
jsr printf_printhexbyte jsr print_hex_byte
lda CMP0+0 lda CMP0+0
jsr printf_printhexbyte jsr print_hex_byte
lda #$0D jsr print_return
jsr JCHROUT
!: !:
jmp basic_main_loop jmp basic_main_loop
+1
View File
@@ -0,0 +1 @@
At least the FB64 (a file browser) uses this routine - but outputting number as ASCI is defintelyy useful routine, certainly much more programs use it.
+10
View File
@@ -0,0 +1,10 @@
//
// Well-known BASIC routine, described in:
//
// - [CM64] Compute's Mapping the Commodore 64 - page 116, XXX
//
LINPRT:
STUB_IMPLEMENTATION()
+11 -13
View File
@@ -1,24 +1,22 @@
cmd_stop: cmd_stop:
basic_do_break: ldx #38 // "BREAK"
jsr printf // XXX don't use printf, use packed messages! jsr print_packed_message
.text "BREAK"
.byte 0
// Check for direct mode
// Are we in direct mode // Are we in direct mode
lda basic_current_line_number+1 lda CURLIN+1
cmp #$FF cmp #$FF
beq !+ beq !+
// Not direct mode // Not direct mode
jsr printf // XXX don't use printf, use packed messages! ldx #37
.text " IN " jsr print_packed_message
.byte 0
lda basic_current_line_number+1 lda CURLIN+1
ldx basic_current_line_number+0 ldx CURLIN+0
jsr print_integer jsr print_integer
!: !:
lda #$0D jsr print_return
jsr JCHROUT
cmd_end: cmd_end:
jmp basic_main_loop jmp basic_main_loop
+42 -19
View File
@@ -4,16 +4,23 @@
cmd_list: cmd_list:
// Set current line pointer to start of memory // Set current line pointer to start of memory
lda basic_start_of_text_ptr+0 lda TXTTAB+0
sta basic_current_line_ptr+0 sta OLDTXT+0
lda basic_start_of_text_ptr+1 lda TXTTAB+1
sta basic_current_line_ptr+1 sta OLDTXT+1
list_loop: list_loop:
ldx #<basic_current_line_ptr
ldy #1 ldy #1
#if CONFIG_MEMORY_MODEL_60K
ldx #<OLDTXT+0
jsr peek_under_roms jsr peek_under_roms
cmp #$00 cmp #$00
#else // CONFIG_MEMORY_MODEL_38K
lda (OLDTXT),y
#endif
bne list_more_lines bne list_more_lines
// LIST terminates any running program, // LIST terminates any running program,
@@ -24,7 +31,7 @@ list_loop:
list_more_lines: list_more_lines:
lda STKEY lda STKEY
bmi !+ bmi !+
jmp basic_do_break jmp cmd_stop
!: !:
jsr list_single_line jsr list_single_line
// Now link to the next line // Now link to the next line
@@ -34,37 +41,54 @@ list_more_lines:
list_single_line: // entry point needed by DOS wedge list_single_line: // entry point needed by DOS wedge
// Print line number // Print line number
ldy #3 ldy #3
#if CONFIG_MEMORY_MODEL_60K
jsr peek_under_roms jsr peek_under_roms
#else // CONFIG_MEMORY_MODEL_38K
lda (OLDTXT),y
#endif
pha pha
dey dey
#if CONFIG_MEMORY_MODEL_60K
jsr peek_under_roms jsr peek_under_roms
#else // CONFIG_MEMORY_MODEL_38K
lda (OLDTXT),y
#endif
tax tax
pla pla
jsr print_integer jsr print_integer
lda #$20 jsr print_space
jsr JCHROUT
// Iterate through printing out the line // Iterate through printing out the line
// contents // contents
lda #0 lda #0
sta quote_mode_flag sta QTSW
ldy #4 ldy #4
list_print_loop: list_print_loop:
ldx #<basic_current_line_ptr
#if CONFIG_MEMORY_MODEL_60K
ldx #<OLDTXT
jsr peek_under_roms jsr peek_under_roms
cmp #$00 cmp #$00
#else // CONFIG_MEMORY_MODEL_38K
lda (OLDTXT),y
#endif
beq list_end_of_line beq list_end_of_line
cmp #$22 cmp #$22
bne list_not_quote bne list_not_quote
lda quote_mode_flag lda QTSW
eor #$ff eor #$ff
sta quote_mode_flag sta QTSW
lda #$22 lda #$22
jmp list_is_literal jmp list_is_literal
list_not_quote: list_not_quote:
// Check quote mode, and display as literal if required // Check quote mode, and display as literal if required
ldx quote_mode_flag ldx QTSW
bne list_is_literal bne list_is_literal
cmp #$7f cmp #$7f
@@ -80,9 +104,9 @@ list_not_quote:
// Get pointer to compressed keyword list // Get pointer to compressed keyword list
lda #<packed_keywords lda #<packed_keywords
sta temp_string_ptr+0 sta FRESPC+0
lda #>packed_keywords lda #>packed_keywords
sta temp_string_ptr+1 sta FRESPC+1
// Subtract $80 from token to get offset in word // Subtract $80 from token to get offset in word
// list // list
@@ -103,7 +127,7 @@ list_not_quote:
// REM command locks quote flag on until the end of the line, allowing // REM command locks quote flag on until the end of the line, allowing
// funny characters in REM statements without problem. // funny characters in REM statements without problem.
inc $0427 inc $0427
sta quote_mode_flag // Any value other than $00 or $FF will lock quote mode on, so the token value of REM is fine here sta QTSW // Any value other than $00 or $FF will lock quote mode on, so the token value of REM is fine here
// FALL THROUGH // FALL THROUGH
list_not_rem: list_not_rem:
@@ -120,7 +144,6 @@ list_end_of_line:
lda #$92 lda #$92
jsr JCHROUT jsr JCHROUT
// Print end of line // Print end of line
lda #$0d jmp print_return
jsr JCHROUT
rts
+56 -38
View File
@@ -13,7 +13,7 @@ cmd_load:
// Setup Kernal to print control messages or not // Setup Kernal to print control messages or not
lda #$80 // display control messages and omit error messages lda #$80 // display control messages and omit error messages
ldx basic_current_line_number+1 ldx CURLIN+1
cpx #$FF cpx #$FF
beq !+ beq !+
lda #$00 // direct mode - don't display anything lda #$00 // direct mode - don't display anything
@@ -36,10 +36,10 @@ cmd_load:
jmp do_SYNTAX_error jmp do_SYNTAX_error
!: !:
// Filename starts here so set pointer // Filename starts here so set pointer
lda basic_current_statement_ptr+0 lda TXTPTR+0
sta current_filename_ptr+0 sta FNADDR+0
lda basic_current_statement_ptr+1 lda TXTPTR+1
sta current_filename_ptr+1 sta FNADDR+1
// Now search for end of line or closing quote // Now search for end of line or closing quote
// so that we know the length of the filename // so that we know the length of the filename
@@ -60,47 +60,50 @@ got_filename:
// Now fetch the file number, start from the default one // Now fetch the file number, start from the default one
jsr select_device jsr select_device
stx current_device_number stx FA
jsr injest_comma jsr injest_comma
bcs got_devicenumber bcs got_devicenumber
jsr basic_parse_line_number jsr basic_parse_line_number
lda basic_line_number+1 lda LINNUM+1
beq !+ beq !+
jmp do_ILLEGAL_QUANTITY_error jmp do_ILLEGAL_QUANTITY_error
!: !:
lda basic_line_number+0 lda LINNUM+0
sta current_device_number sta FA
got_devicenumber: got_devicenumber:
// Now fetch the secondary address // Now fetch the secondary address
lda #$00 lda #$00
sta current_secondary_address sta SA
jsr injest_comma jsr injest_comma
bcs got_secondaryaddress bcs got_secondaryaddress
jsr basic_parse_line_number jsr basic_parse_line_number
lda basic_line_number+1 lda LINNUM+1
bne !+ bne !+
lda basic_line_number+0 lda LINNUM+0
sta current_secondary_address sta SA
jmp got_secondaryaddress jmp got_secondaryaddress
!: !:
// Second parameter is above 255, this can't be a secondary address // Second parameter is above 255, this can't be a secondary address
// Use it as load address instead // Use it as load address instead
// XXX temporary syntax, it would be better to use something // XXX temporary syntax, it would be better to use something
// XXX like 'LOAD"FILE",8 TO 49152' // XXX like 'LOAD"FILE",8 TO 49152'
ldx basic_line_number+0 ldx LINNUM+0
ldy basic_line_number+1 ldy LINNUM+1
bne got_loadaddress bne got_loadaddress
got_secondaryaddress: got_secondaryaddress:
ldx #<$0801 // XXX use start text vector ldy TXTTAB+1
ldy #>$0801 ldx TXTTAB+0
got_loadaddress: got_loadaddress:
lda #$00 // LOAD not verify lda #$00 // LOAD not verify
jsr via_ILOAD jsr JLOAD
php
jsr print_return
plp
bcc !+ bcc !+
// A = KERNAL error code, which also almost match // A = KERNAL error code, which also almost match
@@ -112,8 +115,8 @@ got_loadaddress:
!: !:
// $YYXX is the last loaded address, so store it // $YYXX is the last loaded address, so store it
stx basic_end_of_text_ptr+0 stx VARTAB+0
sty basic_end_of_text_ptr+1 sty VARTAB+1
// Now relink the loaded program, as we cannot trust the line // Now relink the loaded program, as we cannot trust the line
// links supplied. For example, the VICE virtual drive emulation // links supplied. For example, the VICE virtual drive emulation
@@ -124,10 +127,7 @@ got_loadaddress:
// or go back to the READY prompt if LOAD was called from direct mode. // or go back to the READY prompt if LOAD was called from direct mode.
// Reset to start of program // Reset to start of program
lda basic_start_of_text_ptr+0 jsr init_oldtxt
sta basic_current_line_ptr+0
lda basic_start_of_text_ptr+1
sta basic_current_line_ptr+1
// XXX - should run program if LOAD was used in program mode // XXX - should run program if LOAD was used in program mode
jmp basic_main_loop jmp basic_main_loop
@@ -136,17 +136,20 @@ got_loadaddress:
basic_relink_program: basic_relink_program:
// Start by getting pointer to the first line // Start by getting pointer to the first line
lda basic_start_of_text_ptr+0 jsr init_oldtxt
sta basic_current_line_ptr+0
lda basic_start_of_text_ptr+1
sta basic_current_line_ptr+1
basic_relink_loop: basic_relink_loop:
// Is the pointer to the end of the program // Is the pointer to the end of the program
ldy #1 ldy #1
ldx #<basic_current_line_ptr+0
#if CONFIG_MEMORY_MODEL_60K
ldx #<OLDTXT+0
jsr peek_under_roms jsr peek_under_roms
cmp #$00 cmp #$00
#else // CONFIG_MEMORY_MODEL_38K
lda (OLDTXT),y
#endif
bne !+ bne !+
// End of program // End of program
@@ -156,8 +159,14 @@ basic_relink_loop:
// Skip forward pointer and line number // Skip forward pointer and line number
ldy #4 ldy #4
end_of_line_search: end_of_line_search:
ldx #<basic_current_line_ptr+0
#if CONFIG_MEMORY_MODEL_60K
ldx #<OLDTXT+0
jsr peek_under_roms jsr peek_under_roms
#else // CONFIG_MEMORY_MODEL_38K
lda (OLDTXT),y
#endif
cmp #$00 cmp #$00
beq !+ beq !+
@@ -178,22 +187,31 @@ end_of_line_search:
// //
tya tya
clc clc
adc basic_current_line_ptr+0 adc OLDTXT+0
pha pha
php php
ldy #0 ldy #0
ldx #<basic_current_line_ptr+0
#if CONFIG_MEMORY_MODEL_60K
ldx #<OLDTXT+0
jsr poke_under_roms jsr poke_under_roms
#else // CONFIG_MEMORY_MODEL_38K
sta (OLDTXT),y
#endif
plp plp
lda basic_current_line_ptr+1 lda OLDTXT+1
adc #0 adc #0
ldy #1 ldy #1
#if CONFIG_MEMORY_MODEL_60K
jsr poke_under_roms jsr poke_under_roms
sta basic_current_line_ptr+1 #else // CONFIG_MEMORY_MODEL_38K
sta (OLDTXT),y
#endif
sta OLDTXT+1
pla pla
sta basic_current_line_ptr+0 sta OLDTXT+0
jmp basic_relink_loop jmp basic_relink_loop
via_ILOAD:
jmp (ILOAD)
+33 -20
View File
@@ -15,20 +15,20 @@ cmd_clr:
basic_do_new: basic_do_new:
// Setup pointers to memory storage XXX should depend on text start vector // Setup pointers to memory storage XXX should depend on text start vector
lda #<$0801 lda #<$0801
sta basic_start_of_text_ptr+0 sta TXTTAB+0
lda #>$0801 lda #>$0801
sta basic_start_of_text_ptr+1 sta TXTTAB+1
sta basic_start_of_vars_ptr+1 sta VARTAB+1
lda #<$0803 lda #<$0803
sta basic_start_of_vars_ptr+0 sta VARTAB+0
// Zero line pointer // Zero line pointer
// XXX - We should also zero $0800, i.e., basic_start_of_text_ptr - 1 // XXX - We should also zero $0800, i.e., TXTTAB - 1
ldy #$00 ldy #$00
tya tya
sta (basic_start_of_text_ptr),y sta (TXTTAB),y
iny iny
sta (basic_start_of_text_ptr),y sta (TXTTAB),y
// Get top of memory. // Get top of memory.
@@ -44,24 +44,37 @@ basic_do_new:
jsr JMEMTOP jsr JMEMTOP
cpx #$80 cpx #$80
beq !+ beq !+
lda #>$f7ff #if CONFIG_MEMORY_MODEL_60K
lda #>$F7FF
#else // CONFIG_MEMORY_MODEL_38K
lda #>$A000
#endif
.byte $2C .byte $2C
!: lda #>$7FFF !:
sta basic_top_of_memory_ptr+1 #if CONFIG_MEMORY_MODEL_60K
sta basic_start_of_strings_ptr+1 lda #>$F7FF
lda #<$f7ff #else // CONFIG_MEMORY_MODEL_38K
sta basic_top_of_memory_ptr+0 lda #>$A000
sta basic_start_of_strings_ptr+0 #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 // FALL THROUGH
basic_do_clr: basic_do_clr:
// Clear variables, arrays and strings // Clear variables, arrays and strings
lda basic_start_of_vars_ptr+0 lda VARTAB+0
sta basic_start_of_arrays_ptr+0 sta ARYTAB+0
sta basic_start_of_free_space_ptr+0 sta STREND+0
lda basic_start_of_vars_ptr+1 lda VARTAB+1
sta basic_start_of_arrays_ptr+1 sta ARYTAB+1
sta basic_start_of_free_space_ptr+1 sta STREND+1
rts rts
+4 -4
View File
@@ -3,10 +3,10 @@ cmd_run:
jsr basic_do_clr jsr basic_do_clr
cmd_goto: cmd_goto:
// Reset line pointer to first line of program. // Reset line pointer to first line of program.
lda basic_start_of_text_ptr+0 lda TXTTAB+0
sta basic_current_line_ptr+0 sta OLDTXT+0
lda basic_start_of_text_ptr+1 lda TXTTAB+1
sta basic_current_line_ptr+1 sta OLDTXT+1
jsr basic_end_of_statement_check jsr basic_end_of_statement_check
bcs !+ bcs !+
+2 -2
View File
@@ -12,9 +12,9 @@ cmd_sys:
// setup call // setup call
lda #$4C // JMP opcode lda #$4C // JMP opcode
sta USRPOK sta USRPOK
lda basic_line_number+0 lda LINNUM+0
sta USRADD+0 sta USRADD+0
lda basic_line_number+1 lda LINNUM+1
sta USRADD+1 sta USRADD+1
// Setup the register values // Setup the register values
+75 -1
View File
@@ -1,82 +1,156 @@
//
// Default handler for all not-yet-implemented commands // Default handler for all not-yet-implemented commands
//
// Note: NOPs are here just to make debugging easier!
//
cmd_for: cmd_for:
nop
cmd_next: cmd_next:
nop
cmd_data: cmd_data:
nop
cmd_inputhash: cmd_inputhash:
nop
cmd_input: cmd_input:
nop
cmd_dim: cmd_dim:
nop
cmd_read: cmd_read:
nop
cmd_let: cmd_let:
nop
cmd_if: cmd_if:
nop
cmd_restore: cmd_restore:
nop
cmd_gosub: cmd_gosub:
nop
cmd_return: cmd_return:
nop
// $90-$9F // $90-$9F
cmd_on: cmd_on:
nop
cmd_wait: cmd_wait:
nop
cmd_save: cmd_save:
nop
cmd_verify: cmd_verify:
nop
cmd_def: cmd_def:
nop
cmd_poke: cmd_poke:
nop
cmd_printhash: cmd_printhash:
nop
cmd_print: cmd_print:
nop
cmd_cont: cmd_cont:
nop
cmd_cmd: cmd_cmd:
nop
cmd_open: cmd_open:
nop
// $A0-$AF // $A0-$AF
cmd_close: cmd_close:
nop
cmd_get: cmd_get:
nop
cmd_tab: cmd_tab:
nop
cmd_to: cmd_to:
nop
cmd_fn: cmd_fn:
nop
cmd_spc: cmd_spc:
nop
cmd_then: cmd_then:
nop
cmd_not: cmd_not:
nop
cmd_step: cmd_step:
nop
cmd_plus: cmd_plus:
nop
cmd_minus: cmd_minus:
nop
cmd_mult: cmd_mult:
nop
cmd_div: cmd_div:
nop
cmd_exponent: cmd_exponent:
nop
cmd_and: cmd_and:
nop
// $B0-$BF // $B0-$BF
cmd_or: cmd_or:
nop
cmd_greater: cmd_greater:
nop
cmd_equal: cmd_equal:
nop
cmd_less: cmd_less:
nop
cmd_sgn: cmd_sgn:
nop
cmd_int: cmd_int:
nop
cmd_abs: cmd_abs:
nop
cmd_usr: cmd_usr:
nop
cmd_fre: cmd_fre:
nop
cmd_pos: cmd_pos:
nop
cmd_sqr: cmd_sqr:
nop
cmd_rnd: cmd_rnd:
nop
cmd_log: cmd_log:
nop
cmd_exp: cmd_exp:
nop
cmd_cos: cmd_cos:
nop
cmd_sin: cmd_sin:
nop
// $C0-$CF // $C0-$CF
cmd_tan: cmd_tan:
nop
cmd_atn: cmd_atn:
nop
cmd_peek: cmd_peek:
nop
cmd_len: cmd_len:
nop
cmd_str: cmd_str:
nop
cmd_val: cmd_val:
nop
cmd_asc: cmd_asc:
nop
cmd_chr: cmd_chr:
nop
cmd_left: cmd_left:
nop
cmd_right: cmd_right:
nop
cmd_mid: cmd_mid:
nop
cmd_go: cmd_go:
nop
// Undefined tokens // Undefined tokens
cmd_unimplemented: cmd_unimplemented:
jmp do_NOT_IMPLEMENTED_error jmp do_NOT_IMPLEMENTED_error
+9 -14
View File
@@ -129,8 +129,7 @@ do_basic_error:
// "?" // "?"
txa txa
pha pha
lda #$0d jsr print_return
jsr JCHROUT
lda #$3f lda #$3f
jsr JCHROUT jsr JCHROUT
pla pla
@@ -140,33 +139,29 @@ do_basic_error:
jsr print_packed_message jsr print_packed_message
// A space between error name and word error // A space between error name and word error
lda #$20 jsr print_space
jsr $ffd2
// "ERROR" // "ERROR"
ldx #33 ldx #33
jsr print_packed_message jsr print_packed_message
lda basic_current_line_number+1 lda CURLIN+1
cmp #$ff cmp #$ff
beq !+ beq !+
// We were in a program, so show IN <line> // We were in a program, so show IN <line>
jsr printf // XXX don't use printf, use packed messages ldx #37
.text " IN " jsr print_packed_message
.byte 0
lda basic_current_line_number+1 lda CURLIN+1
ldx basic_current_line_number+0 ldx CURLIN+0
jsr print_integer jsr print_integer
!: !:
// New lines // New lines
lda #$0d jsr print_return
jsr $ffd2
lda #$00 lda #$00
jsr $ffd2 jsr JCHROUT
// XXX - Restore stack depth first? // XXX - Restore stack depth first?
jmp basic_main_loop jmp basic_main_loop
+13
View File
@@ -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()
+9
View File
@@ -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.
+5
View File
@@ -0,0 +1,5 @@
// XXX provide documentation and implementation
INIT:
STUB_IMPLEMENTATION()
+3
View File
@@ -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.
+44
View File
@@ -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
+3
View File
@@ -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.
+3
View File
@@ -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.
+5
View File
@@ -0,0 +1,5 @@
// XXX provide documentation and implementation
RVECT:
STUB_IMPLEMENTATION()
+23 -23
View File
@@ -3,25 +3,25 @@
// Implement by shifting MAC left one bit, // Implement by shifting MAC left one bit,
// and then keeping that value to add on after // and then keeping that value to add on after
// shifting two more bits left. // shifting two more bits left.
// This should be done using basic_fac1_overflow to // This should be done using BITS to
// hold the overflow bits, so that the result can // hold the overflow bits, so that the result can
// be exponent adjusted after, if required. // be exponent adjusted after, if required.
fac1_mul10: fac1_mul10:
lda #$00 lda #$00
sta basic_fac1_overflow sta BITS
// Multiply mantissa by 2 // Multiply mantissa by 2
jsr fac1_mantissa_mul2 jsr fac1_mantissa_mul2
// copy down to BASIC numeric work area at $57 // copy down to BASIC numeric work area at $57
// (basic_numeric_work_area) // (TEMPF1)
// (We copy all 7 bytes off the FAC1, so that we have // (We copy all 7 bytes off the FAC1, so that we have
// the overflow bits, and the copy is as small as possible) // the overflow bits, and the copy is as small as possible)
ldx #7 ldx #7
f1m10_l1: f1m10_l1:
lda basic_fac1_mantissa,x lda FAC1_mantissa,x
sta basic_numeric_work_area,x sta TEMPF1,x
dex dex
bpl f1m10_l1 bpl f1m10_l1
@@ -34,20 +34,20 @@ f1m10_l1:
ldx #0 ldx #0
clc clc
f1m10_l2: f1m10_l2:
lda basic_fac1_mantissa,x lda FAC1_mantissa,x
adc basic_numeric_work_area,x adc TEMPF1,x
sta basic_fac1_mantissa,x sta FAC1_mantissa,x
inx inx
dey dey
bpl f1m10_l2 bpl f1m10_l2
lda basic_fac1_overflow lda BITS
adc basic_numeric_work_area+7 adc TEMPF1+7
sta basic_fac1_overflow sta BITS
// Now shift right and increase exponent until overflow // Now shift right and increase exponent until overflow
// bits = $00 // bits = $00
f1m10_l3: f1m10_l3:
lda basic_fac1_overflow lda BITS
bne !+ bne !+
// All done, return // All done, return
clc clc
@@ -55,8 +55,8 @@ f1m10_l3:
!: !:
// Divide mantissa by two, and increment exponent // Divide mantissa by two, and increment exponent
jsr fac1_mantissa_div2 jsr fac1_mantissa_div2
inc basic_fac1_exponent inc FAC1_exponent
lda basic_fac1_exponent lda FAC1_exponent
bpl f1m10_l3 bpl f1m10_l3
// Exponent has bit 7 set, so has wrapped. // Exponent has bit 7 set, so has wrapped.
// = OVERFLOW ERROR // = OVERFLOW ERROR
@@ -68,30 +68,30 @@ fac1_mantissa_mul2:
clc clc
f1m1_l1: f1m1_l1:
// Multiply mantissa by 2, and store overflow // Multiply mantissa by 2, and store overflow
// in basic_fac1_bits // in FAC1_bits
lda basic_fac1_mantissa,x lda FAC1_mantissa,x
rol rol
sta basic_fac1_mantissa,x sta FAC1_mantissa,x
inx inx
dey dey
bpl f1m1_l1 bpl f1m1_l1
lda basic_fac1_overflow lda BITS
rol rol
sta basic_fac1_overflow sta BITS
rts rts
fac1_mantissa_div2: fac1_mantissa_div2:
// Divide mantissa by 2, including using overflow bits // Divide mantissa by 2, including using overflow bits
clc clc
lda basic_fac1_overflow lda BITS
ror ror
sta basic_fac1_overflow sta BITS
ldy #3 ldy #3
f1md2_l1: f1md2_l1:
lda basic_fac1_mantissa,y lda FAC1_mantissa,y
ror ror
sta basic_fac1_mantissa,y sta FAC1_mantissa,y
dey dey
bpl f1md2_l1 bpl f1md2_l1
rts rts
+9
View File
@@ -0,0 +1,9 @@
init_oldtxt:
lda TXTTAB+0
sta OLDTXT+0
lda TXTTAB+1
sta OLDTXT+1
rts
+19 -22
View File
@@ -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. // 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 // XXX - Remember decimal position and exponent, and apply them
// after to produce normalised floating point number. // after to produce normalised floating point number.
@@ -20,7 +20,7 @@ ij_not_a_digit:
// Look for decimal point // Look for decimal point
cmp #$2e cmp #$2e
bne ij_not_decimal bne ij_not_decimal
lda tokenise_work4 lda __tokenise_work4
cmp #$ff cmp #$ff
beq ij_found_decimal beq ij_found_decimal
// More than one decimal point in a number means we have reached the end of the number // More than one decimal point in a number means we have reached the end of the number
@@ -33,7 +33,7 @@ ij_found_decimal:
// can do the necessary number of divide by 10s on the final // can do the necessary number of divide by 10s on the final
// number. // number.
lda #$00 lda #$00
sta tokenise_work4 sta __tokenise_work4
jmp ij_consider_next_digit jmp ij_consider_next_digit
@@ -48,29 +48,26 @@ injest_number:
// Clear decimal position flag // Clear decimal position flag
lda #$ff lda #$ff
sta tokenise_work4 sta __tokenise_work4
// Check if leading char is a - sign // Check if leading char is a - sign
// Note: the - will have been tokenised to $AB // Note: the - will have been tokenised to $AB
// XXX - implement // XXX - implement
ldy #$00 ldy #$00
lda (basic_current_statement_ptr),y lda (TXTPTR),y
cmp #$AB cmp #$AB
bne ij_not_minus bne ij_loop1 // not minus
// Set sign to negative // Set sign to negative
lda #$ff lda #$ff
sta basic_fac1_sign sta FAC1_sign
// Skip over the minus sign // Skip over the minus sign
jsr basic_consume_character jsr basic_consume_character
ij_not_minus:
ij_loop1: ij_loop1:
ldy #$00 ldy #$00
lda (basic_current_statement_ptr),y lda (TXTPTR),y
cmp #$30 cmp #$30
bcc ij_not_a_digit bcc ij_not_a_digit
cmp #$3a cmp #$3a
@@ -80,7 +77,7 @@ ij_loop1:
// Only add digit if we have not overflowed the accuracy of // Only add digit if we have not overflowed the accuracy of
// the mantissa // the mantissa
lda basic_fac1_exponent lda FAC1_exponent
beq ij_accept_precision beq ij_accept_precision
// We have an extra digit after saturating our precision. // We have an extra digit after saturating our precision.
@@ -89,7 +86,7 @@ ij_loop1:
// If we have seen a decimal point, then we can completely ignore // If we have seen a decimal point, then we can completely ignore
// the digit, as it is contributing not recordable information // the digit, as it is contributing not recordable information
lda tokenise_work4 lda __tokenise_work4
cmp #$ff cmp #$ff
bne ij_seen_decimal_point bne ij_seen_decimal_point
@@ -103,25 +100,25 @@ ij_accept_precision:
// we can add the new digit in // we can add the new digit in
jsr fac1_mul10 jsr fac1_mul10
lda basic_fac1_exponent lda FAC1_exponent
bne ij_consider_next_digit bne ij_consider_next_digit
// Get digit // Get digit
ldy #$00 ldy #$00
lda (basic_current_statement_ptr),y lda (TXTPTR),y
sec sec
sbc #$30 sbc #$30
// Add to FAC1 mantissa // Add to FAC1 mantissa
clc clc
adc basic_fac1_mantissa+0 adc FAC1_mantissa+0
sta basic_fac1_mantissa+0 sta FAC1_mantissa+0
ldx #1 ldx #1
ldy #3 ldy #3
ij_loop2: ij_loop2:
lda basic_fac1_mantissa,x lda FAC1_mantissa,x
adc #$00 adc #$00
sta basic_fac1_mantissa,x sta FAC1_mantissa,x
inx inx
dey dey
bne ij_loop2 bne ij_loop2
@@ -146,10 +143,10 @@ erase_fac1:
lda #$00 lda #$00
ldx #8 ldx #8
!: !:
sta basic_fac1_exponent,x sta FAC1_exponent,x
dex dex
bpl !- bpl !-
sta basic_fac1_mantissa_lob sta FACOV
rts rts
+29 -29
View File
@@ -13,30 +13,30 @@
pack_word: pack_word:
// Inputs: // Inputs:
// X = offset of string to pack. Address is $0200 + X // X = offset of string to pack. Address is $0200 + X
// tokenise_work1 = number of bytes to pack // __tokenise_work1 = number of bytes to pack
// tokenise_work2 = packed length of string // __tokenise_work2 = packed length of string
// Outputs: // Outputs:
// Output is written to $0100 (bottom of stack). // Output is written to $0100 (bottom of stack).
// Memory modified: // Memory modified:
// tokenise_work4 = temporary storage // __tokenise_work4 = temporary storage
// tokenise_work3 = flag for whether we have a nybl prepared or not. // __tokenise_work3 = flag for whether we have a nybl prepared or not.
// (This can also be checked on exit, to know whether the last byte // (This can also be checked on exit, to know whether the last byte
// is incomplete, which is important for searching for abbreviated // is incomplete, which is important for searching for abbreviated
// key words.) // key words.)
// Make sure we have a sane request // Make sure we have a sane request
lda tokenise_work1 lda __tokenise_work1
bne !+ bne !+
sec sec
rts rts
!: !:
// Initialise internal variables // Initialise internal variables
lda #$00 lda #$00
sta tokenise_work2 sta __tokenise_work2
sta tokenise_work3 sta __tokenise_work3
pack_char_loop: pack_char_loop:
@@ -56,13 +56,13 @@ pack_char_loop:
// either $FE or $FF, depending on whether this is the last // either $FE or $FF, depending on whether this is the last
// byte or not // byte or not
lda tokenise_work3 lda __tokenise_work3
bne have_nybl_before_exception_char bne have_nybl_before_exception_char
// No nybl exists before the exception char, so prefix with $FE or $FF // No nybl exists before the exception char, so prefix with $FE or $FF
// based on whether we are at the end of the input string or not // based on whether we are at the end of the input string or not
inx inx
lda tokenise_work1 lda __tokenise_work1
cmp #$01 cmp #$01
beq at_end beq at_end
lda #$FF lda #$FF
@@ -80,11 +80,11 @@ output_exception_byte:
have_nybl_before_exception_char: have_nybl_before_exception_char:
// Or existing byte with #$0F, and clear nybl flag // Or existing byte with #$0F, and clear nybl flag
ldy tokenise_work2 ldy __tokenise_work2
lda $0100,y lda $0100,y
ora #$0f ora #$0f
sta $0100,y sta $0100,y
inc tokenise_work2 inc __tokenise_work2
// FALL THROUGH // FALL THROUGH
@@ -92,7 +92,7 @@ write_literal_and_terminate_if_required:
// Clear have nybl flag // Clear have nybl flag
lda #$00 lda #$00
sta tokenise_work3 sta __tokenise_work3
lda $0200,x lda $0200,x
jsr write_unpacked_char jsr write_unpacked_char
@@ -102,7 +102,7 @@ write_literal_and_terminate_if_required:
end_string_if_required: end_string_if_required:
// Check if X points to last char of string to be packed // Check if X points to last char of string to be packed
inx inx
lda tokenise_work1 lda __tokenise_work1
cmp #$01 cmp #$01
beq !+ beq !+
dex dex
@@ -118,10 +118,10 @@ end_string:
rts rts
write_unpacked_char: write_unpacked_char:
ldy tokenise_work2 ldy __tokenise_work2
sta $0100,y sta $0100,y
iny iny
sty tokenise_work2 sty __tokenise_work2
rts rts
not_exception_char: not_exception_char:
@@ -130,7 +130,7 @@ not_exception_char:
bcs whole_byte_symbol bcs whole_byte_symbol
// Nybl encoded value: Put in upper half or lower half of a byte? // Nybl encoded value: Put in upper half or lower half of a byte?
ldy tokenise_work3 ldy __tokenise_work3
bne store_low_nybl bne store_low_nybl
// Store in high nybl -- so shift it into the hi nybl // Store in high nybl -- so shift it into the hi nybl
@@ -138,26 +138,26 @@ not_exception_char:
asl asl
asl asl
asl asl
ldy tokenise_work2 ldy __tokenise_work2
sta $0100,y sta $0100,y
bne stored_nybl // Must be taken, as A cannot be $00 bne stored_nybl // Must be taken, as A cannot be $00
store_low_nybl: store_low_nybl:
// Low nybl gets added to high nybl already stored in the byte // Low nybl gets added to high nybl already stored in the byte
ldy tokenise_work2 ldy __tokenise_work2
ora $0100,y ora $0100,y
sta $0100,y sta $0100,y
stored_nybl: stored_nybl:
// Now toggle the nybl flag // Now toggle the nybl flag
lda tokenise_work3 lda __tokenise_work3
eor #$ff eor #$ff
sta tokenise_work3 sta __tokenise_work3
// And advance the offset if we filled this byte up // And advance the offset if we filled this byte up
bne consider_next_char // Taken if byte has a nybl free, i.e., don't advance pointer while half byte remains free bne consider_next_char // Taken if byte has a nybl free, i.e., don't advance pointer while half byte remains free
// Count the filled up byte // Count the filled up byte
inc tokenise_work2 inc __tokenise_work2
// Add termination byte if required // Add termination byte if required
// (This re-writes the same byte again, which we don't care about) // (This re-writes the same byte again, which we don't care about)
@@ -168,15 +168,15 @@ whole_byte_symbol:
// But if we have a nybl to flush, then we handle it like // But if we have a nybl to flush, then we handle it like
// a full exception character // a full exception character
ldy tokenise_work3 ldy __tokenise_work3
beq nothing_to_flush beq nothing_to_flush
// Set low nybl to $F to mark next byte as literal // Set low nybl to $F to mark next byte as literal
ldy tokenise_work2 ldy __tokenise_work2
lda $0100,y lda $0100,y
ora #$0f ora #$0f
sta $0100,y sta $0100,y
inc tokenise_work2 inc __tokenise_work2
jmp write_literal_and_terminate_if_required jmp write_literal_and_terminate_if_required
@@ -190,7 +190,7 @@ nothing_to_flush:
consider_next_char: consider_next_char:
// Pack next char // Pack next char
inx inx
dec tokenise_work1 dec __tokenise_work1
beq !+ beq !+
jmp pack_char_loop jmp pack_char_loop
!: !:
@@ -198,18 +198,18 @@ consider_next_char:
// (but leave flag set so the caller knows if the // (but leave flag set so the caller knows if the
// bottom nybl might be different if the string were // bottom nybl might be different if the string were
// longer). // longer).
lda tokenise_work3 lda __tokenise_work3
beq !+ beq !+
inc tokenise_work2 inc __tokenise_work2
rts rts
!: !:
// Last byte was full, so we need at $00 on the end // Last byte was full, so we need at $00 on the end
// (unless a $FE token was written 2 bytes ago) // (unless a $FE token was written 2 bytes ago)
ldy tokenise_work2 ldy __tokenise_work2
iny iny
lda #$00 lda #$00
sta $0100,y sta $0100,y
inc tokenise_work2 inc __tokenise_work2
rts rts
@@ -1,20 +1,34 @@
// Return C=1 if a pointer in BASIC memory space is NULL, else C=0 // Return C=1 if a pointer in BASIC memory space is NULL, else C=0
// X = ZP pointer to check // X = ZP pointer to check
peek_pointer_null_check: peek_line_pointer_null_check:
ldy #$00 ldy #$00
#if CONFIG_MEMORY_MODEL_60K
ldx #<OLDTXT+0
jsr peek_under_roms jsr peek_under_roms
cmp #$00 cmp #$00
#else // CONFIG_MEMORY_MODEL_38K
lda (OLDTXT),y
#endif
bne ptr_not_null bne ptr_not_null
iny iny
#if CONFIG_MEMORY_MODEL_60K
jsr peek_under_roms jsr peek_under_roms
cmp #$00 cmp #$00
#else // CONFIG_MEMORY_MODEL_38K
lda (OLDTXT),y
#endif
bne ptr_not_null bne ptr_not_null
// Pointer is NULL // Pointer is NULL
clc clc
rts rts
ptr_not_null: ptr_not_null:
sec sec
rts rts
+17 -18
View File
@@ -38,8 +38,7 @@ found_message_in_token_stream:
cmp #$ff cmp #$ff
beq !+ beq !+
jsr print_packed_word jsr print_packed_word
lda #$20 jsr print_space
jsr JCHROUT
pla pla
tay tay
iny iny
@@ -57,9 +56,9 @@ print_packed_word:
// Setup pointer to packed words // Setup pointer to packed words
lda #<packed_message_words lda #<packed_message_words
sta temp_string_ptr+0 sta FRESPC+0
lda #>packed_message_words lda #>packed_message_words
sta temp_string_ptr+1 sta FRESPC+1
// Find the word in the list // Find the word in the list
ldy #$ff ldy #$ff
@@ -69,14 +68,14 @@ packed_word_search:
beq found_packed_word beq found_packed_word
// $x0 is an end of work marker // $x0 is an end of work marker
lda (temp_string_ptr),y lda (FRESPC),y
and #$0f and #$0f
cmp #$00 cmp #$00
bne !+ bne !+
dex dex
!: !:
// $FE $xx is an end of work marker // $FE $xx is an end of work marker
lda (temp_string_ptr),y lda (FRESPC),y
cmp #$fe cmp #$fe
bne !+ bne !+
dex dex
@@ -90,7 +89,7 @@ packed_word_search:
// Advance to next page if required // Advance to next page if required
cpy #$ff cpy #$ff
bne packed_word_search bne packed_word_search
inc temp_string_ptr+1 inc FRESPC+1
jmp packed_word_search jmp packed_word_search
found_packed_word: found_packed_word:
@@ -99,11 +98,11 @@ found_packed_word:
// Make sure we don't wrap on a page boundary // Make sure we don't wrap on a page boundary
tya tya
clc clc
adc temp_string_ptr+0 adc FRESPC+0
sta temp_string_ptr+0 sta FRESPC+0
lda temp_string_ptr+1 lda FRESPC+1
adc #$00 adc #$00
sta temp_string_ptr+1 sta FRESPC+1
print_packed_string: print_packed_string:
ldy #$ff ldy #$ff
@@ -113,7 +112,7 @@ next_packed_word_char:
iny iny
// Check for end of word // Check for end of word
lda (temp_string_ptr),y lda (FRESPC),y
cmp #$00 cmp #$00
beq end_of_packed_word beq end_of_packed_word
cmp #$fe cmp #$fe
@@ -124,13 +123,13 @@ next_packed_word_char:
beq end_of_packed_word beq end_of_packed_word
// Check if it is an uncommon char // Check if it is an uncommon char
lda (temp_string_ptr),y lda (FRESPC),y
and #$f0 and #$f0
cmp #$f0 cmp #$f0
beq is_uncommon_char beq is_uncommon_char
// Is not an uncommon char, so get char of upper nybl // Is not an uncommon char, so get char of upper nybl
lda (temp_string_ptr),y lda (FRESPC),y
// Put high nybl into low bits of X // Put high nybl into low bits of X
lsr lsr
@@ -150,7 +149,7 @@ next_packed_word_char:
// See if there is a char in the low nybl to print // See if there is a char in the low nybl to print
pla pla
tay tay
lda (temp_string_ptr),y lda (FRESPC),y
and #$0f and #$0f
beq end_of_packed_word beq end_of_packed_word
cmp #$0f cmp #$0f
@@ -182,7 +181,7 @@ no_lo_nybl_char:
// If current byte has $0F in low nybl, then the next // If current byte has $0F in low nybl, then the next
// byte is a whole byte. // byte is a whole byte.
lda (temp_string_ptr),y lda (FRESPC),y
and #$0f and #$0f
cmp #$0f cmp #$0f
beq next_is_literal_char beq next_is_literal_char
@@ -207,7 +206,7 @@ unpack_literal_char:
iny iny
tya tya
pha pha
lda (temp_string_ptr),y lda (FRESPC),y
jsr JCHROUT jsr JCHROUT
pla pla
tay tay
@@ -216,7 +215,7 @@ unpack_literal_char:
is_uncommon_char: is_uncommon_char:
// Lower nybl has offset into low-frequency part of the table // Lower nybl has offset into low-frequency part of the table
lda (temp_string_ptr),y lda (FRESPC),y
and #$0f and #$0f
clc clc
adc #14 adc #14
-157
View File
@@ -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
+1 -1
View File
@@ -11,7 +11,7 @@ select_device:
// Note: if tape support is introduced here, make sure DOS wedge won't get broken // Note: if tape support is introduced here, make sure DOS wedge won't get broken
ldx current_device_number ldx FA
cpx #$08 cpx #$08
bcs !+ bcs !+
ldx #$08 ldx #$08
+7
View File
@@ -0,0 +1,7 @@
//
// Startup banner, to be displayed durin cold start
//
startup_banner:
TARGET_HOOK_BANNER()
+29 -29
View File
@@ -1,6 +1,6 @@
// Tokenise a line of BASIC // Tokenise a line of BASIC
// Stored at $0200 // Stored at $0200
// Length in tokenise_work1 // Length in __tokenise_work1
tokenise_line: tokenise_line:
@@ -17,9 +17,9 @@ tokenise_line:
lda #$00 lda #$00
sta $0110 sta $0110
sta $0112 sta $0112
sta quote_mode_flag sta QTSW
lda tokenise_work1 lda __tokenise_work1
sta $0113 sta $0113
tokenise_char: tokenise_char:
@@ -32,15 +32,15 @@ tokenise_char:
// End of line reached // End of line reached
// Finished tokenising line // Finished tokenising line
// Update tokenise_work1 and terminate with null // Update __tokenise_work1 and terminate with null
ldx $0112 ldx $0112
lda #$00 lda #$00
sta $0200,x sta $0200,x
stx tokenise_work1 stx __tokenise_work1
// Clear quote mode flag that is also used by KERNAL for screen display // Clear quote mode flag that is also used by KERNAL for screen display
lda #$00 lda #$00
sta quote_mode_flag sta QTSW
rts rts
!: !:
// More to do // More to do
@@ -50,8 +50,8 @@ tokenise_char:
sta $0111 sta $0111
tokenise_char_loop: tokenise_char_loop:
// Pack the word from the start (start = X, raw len = tokenise_work1) // Pack the word from the start (start = X, raw len = __tokenise_work1)
// Returns packed length in tokenise_work2 and writes the packed // Returns packed length in __tokenise_work2 and writes the packed
// word at $0100+ // word at $0100+
ldx $0110 ldx $0110
@@ -60,9 +60,9 @@ tokenise_char_loop:
bne tk_not_quote bne tk_not_quote
// Quote // Quote
lda quote_mode_flag lda QTSW
eor #$ff eor #$ff
sta quote_mode_flag sta QTSW
jmp tk_literal_char jmp tk_literal_char
tk_not_quote: tk_not_quote:
@@ -82,13 +82,13 @@ tk_not_quote:
tk_might_be_keyword: tk_might_be_keyword:
// Don't tokenise in quote mode // Don't tokenise in quote mode
lda quote_mode_flag lda QTSW
bne tk_literal_char bne tk_literal_char
// Pack string // Pack string
ldx $0110 ldx $0110
lda $0111 lda $0111
sta tokenise_work1 sta __tokenise_work1
// XXX - We should implement an optimisation where we // XXX - We should implement an optimisation where we
// trim the last symbol of successively, instead of re-packing the word // trim the last symbol of successively, instead of re-packing the word
@@ -97,7 +97,7 @@ tk_might_be_keyword:
// that are available. // that are available.
jsr pack_word jsr pack_word
lda tokenise_work2 lda __tokenise_work2
cmp #$10 cmp #$10
bcc !+ bcc !+
// Packed string too long // Packed string too long
@@ -137,7 +137,7 @@ found_token_in_line:
// If it is REM, then lock us in quote mode to the end of the line // If it is REM, then lock us in quote mode to the end of the line
cmp #$8f cmp #$8f
bne not_rem bne not_rem
sta quote_mode_flag sta QTSW
not_rem: not_rem:
// Now skip over the length of the token // Now skip over the length of the token
@@ -162,31 +162,31 @@ keyword_search:
// Search for the compressed keyword stored at $0100 in the list // Search for the compressed keyword stored at $0100 in the list
// of compressed keywords // of compressed keywords
// tokenise_work1 = offset in line of input // __tokenise_work1 = offset in line of input
// tokenise_work2 = length of token we are matching // __tokenise_work2 = length of token we are matching
// tokenise_work3 = offset in token list // __tokenise_work3 = offset in token list
// load_or_verify_or_tokenise_work5 = temporary work space // __tokenise_work5 = temporary work space
// X and Y registers used as temporary space. // X and Y registers used as temporary space.
// returns C=1 if no matching token, else C=0 and A=token // returns C=1 if no matching token, else C=0 and A=token
lda #$00 lda #$00
sta tokenise_work1 sta __tokenise_work1
sta tokenise_work3 sta __tokenise_work3
next_kw_offset: next_kw_offset:
// Advance offset in compressed keyword list, to see if a match // Advance offset in compressed keyword list, to see if a match
// BEGINS here // BEGINS here
// Get count of bytes to compare // Get count of bytes to compare
lda tokenise_work2 lda __tokenise_work2
sta load_or_verify_or_tokenise_work5 sta __tokenise_work5
// Load current position // Load current position
ldy tokenise_work3 ldy __tokenise_work3
ldx tokenise_work1 ldx __tokenise_work1
// Advance offset in compressed token list, and stop at the end // Advance offset in compressed token list, and stop at the end
inc tokenise_work3 inc __tokenise_work3
lda tokenise_work3 lda __tokenise_work3
cmp #packed_keyword_table_len cmp #packed_keyword_table_len
bne next_in_match bne next_in_match
jmp done_searching_for_token jmp done_searching_for_token
@@ -198,7 +198,7 @@ next_in_match:
inx inx
iny 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 bne next_in_match
@@ -212,7 +212,7 @@ next_in_match:
// two byte prior is $FE // two byte prior is $FE
// Get offset of first byte of this token // Get offset of first byte of this token
ldx tokenise_work3 ldx __tokenise_work3
dex // pointer points one late, so rewind it dex // pointer points one late, so rewind it
// At start of list? // At start of list?
@@ -233,7 +233,7 @@ next_in_match:
jmp next_kw_offset jmp next_kw_offset
word_boundary: word_boundary:
// Found a token whose offset is in tokenise_work3 // Found a token whose offset is in __tokenise_work3
// Now trace back to the start of the compressed keyword list // Now trace back to the start of the compressed keyword list
// to work out what keyword number we are, so that we can return // to work out what keyword number we are, so that we can return
// the token number. // the token number.
+64 -18
View File
@@ -4,11 +4,13 @@
// in ,aliases.s. // in ,aliases.s.
// Thus those addresses are expressed using formulae. // Thus those addresses are expressed using formulae.
#if CONFIG_MEMORY_MODEL_60K
install_ram_routines: install_ram_routines:
// Copy routines into place // 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 sta tiny_nmi_handler,x
dex dex
bpl !- bpl !-
@@ -21,7 +23,7 @@ install_ram_routines:
rts rts
ram_routines_start: __ram_routines_start:
// XXX - Routine order must match that of the KERNAL version of the file. // XXX - Routine order must match that of the KERNAL version of the file.
// (since it has fewer routines) // (since it has fewer routines)
@@ -64,8 +66,8 @@ memmap_allram_routine:
rts rts
shift_mem_up_routine: shift_mem_up_routine:
// Move memmove_size bytes from memmove_src to memmove_dst, // Move __memmove_size bytes from __memmove_src to __memmove_dst,
// where memmove_dst > memmove_src // where __memmove_dst > __memmove_src
// This means we have to copy from the back end down. // This means we have to copy from the back end down.
// This routine assumes the pointers are already pointed // This routine assumes the pointers are already pointed
// to the end of the areas, and that Y is correctly initialised // to the end of the areas, and that Y is correctly initialised
@@ -73,20 +75,20 @@ shift_mem_up_routine:
php php
jsr memmap_allram jsr memmap_allram
smu1: smu1:
lda (memmove_src),y lda (__memmove_src),y
sta (memmove_dst),y sta (__memmove_dst),y
dey dey
bne smu1 bne smu1
dec memmove_src+1 dec __memmove_src+1
dec memmove_dst+1 dec __memmove_dst+1
dec memmove_size+1 dec __memmove_size+1
bne smu1 bne smu1
plp plp
jmp memmap_normal jmp memmap_normal
shift_mem_down_routine: shift_mem_down_routine:
// Move memmove_size bytes from memmove_src to memmove_dst, // Move __memmove_size bytes from __memmove_src to __memmove_dst,
// where memmove_dst > memmove_src // where __memmove_dst > __memmove_src
// This means we have to copy from the back end down. // This means we have to copy from the back end down.
// This routine assumes the pointers are already pointed // This routine assumes the pointers are already pointed
// to the end of the areas, and that Y is correctly initialised // to the end of the areas, and that Y is correctly initialised
@@ -94,15 +96,59 @@ shift_mem_down_routine:
php php
jsr memmap_allram jsr memmap_allram
smd1: smd1:
lda (memmove_src),y lda (__memmove_src),y
sta (memmove_dst),y sta (__memmove_dst),y
iny iny
bne smd1 bne smd1
inc memmove_src+1 inc __memmove_src+1
inc memmove_dst+1 inc __memmove_dst+1
dec memmove_size+1 dec __memmove_size+1
bne smd1 bne smd1
plp plp
jmp memmap_normal 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
+15 -16
View File
@@ -1,5 +1,5 @@
// START wedge support #if CONFIG_DOS_WEDGE
wedge_dos: wedge_dos:
@@ -16,7 +16,7 @@ wedge_dos:
// Check if user asked for a status // Check if user asked for a status
ldy #$00 ldy #$00
lda (basic_current_statement_ptr), y lda (TXTPTR), y
bne !+ bne !+
jmp wedge_dos_status // XXX try to optimize this, perhaps move 'wedge_dos_status' above? jmp wedge_dos_status // XXX try to optimize this, perhaps move 'wedge_dos_status' above?
!: !:
@@ -31,7 +31,7 @@ wedge_dos:
cmp #$3A cmp #$3A
bcs wedge_dos_command // char code after 9 bcs wedge_dos_command // char code after 9
iny iny
lda (basic_current_statement_ptr), y lda (TXTPTR), y
beq wedge_dos_change_drive // end of buffer beq wedge_dos_change_drive // end of buffer
cmp #$20 cmp #$20
beq wedge_dos_change_drive beq wedge_dos_change_drive
@@ -64,17 +64,17 @@ wedge_dos_change_drive:
// Reuse the line number parser for device number retrieval // Reuse the line number parser for device number retrieval
jsr basic_parse_line_number jsr basic_parse_line_number
lda basic_line_number+1 lda LINNUM+1
beq !+ beq !+
jmp do_ILLEGAL_QUANTITY_error jmp do_ILLEGAL_QUANTITY_error
!: !:
lda basic_line_number+0 lda LINNUM+0
cmp #$08 cmp #$08
bpl !+ bpl !+
bcs !+ bcs !+
jmp do_ILLEGAL_DEVICE_NUMBER_error jmp do_ILLEGAL_DEVICE_NUMBER_error
!: !:
sta current_device_number sta FA
jmp basic_end_of_line jmp basic_end_of_line
wedge_dos_status_get: wedge_dos_status_get:
@@ -139,7 +139,7 @@ wedge_dos_directory:
// First change the secondary address to the one suitable for // First change the secondary address to the one suitable for
// directory loading // directory loading
lda #$00 // logical device number lda #$00 // logical device number
ldx current_device_number ldx FA
ldy #$60 ldy #$60
jsr JSETFLS jsr JSETFLS
@@ -195,10 +195,10 @@ wedge_dos_directory_display:
// Display line // Display line
ldx #<BUF ldx #<BUF
stx basic_current_line_ptr+0 stx OLDTXT+0
ldx #>BUF ldx #>BUF
stx basic_current_line_ptr+1 stx OLDTXT+1
ldx #basic_current_line_ptr ldx #OLDTXT
jsr list_single_line jsr list_single_line
// Read & display next line or quit // Read & display next line or quit
@@ -209,8 +209,7 @@ wedge_dos_directory_display:
wedge_dos_clean_exit: wedge_dos_clean_exit:
jsr JCLALL jsr JCLALL
// Print new line // Print new line
lda #$0D jsr print_return
jsr JCHROUT
jmp basic_end_of_line jmp basic_end_of_line
wedge_dos_basic_error: wedge_dos_basic_error:
@@ -226,13 +225,13 @@ wedge_dos_setnam:
ldy #$FF ldy #$FF
!: !:
iny iny
lda (basic_current_statement_ptr), y lda (TXTPTR), y
bne !- bne !-
// Set the name to open // Set the name to open
tya tya
ldx basic_current_statement_ptr+0 ldx TXTPTR+0
ldy basic_current_statement_ptr+1 ldy TXTPTR+1
jmp JSETNAM jmp JSETNAM
// END wedge support #endif // CONFIG_DOS_WEDGE
-73
View File
@@ -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
@@ -4,10 +4,8 @@
// and ultimate_dos_v1.0.pdf and command_interface_v1.0.pdf by Gideon Zweijtzer // and ultimate_dos_v1.0.pdf and command_interface_v1.0.pdf by Gideon Zweijtzer
// Command interface registers // Command interface registers
.label U64_CONTROL = $DF1C // write .label U64_CONTROL_STATUS = $DF1C // write = CONTROL, read = STATUS
.label U64_STATUS = $DF1C // read .label U64_COMMAND_DATA_IDENTIFY = $DF1D // write = COMMAND_DATA, read = IDENTIFICATION
.label U64_COMMAND_DATA = $DF1D // write
.label U64_IDENTIFICATION = $DF1D // read
.label U64_RESPONSE_DATA = $DF1E // read only .label U64_RESPONSE_DATA = $DF1E // read only
.label U64_STATUS_DATA = $DF1F // read only .label U64_STATUS_DATA = $DF1F // read only
File renamed without changes.
+6
View File
@@ -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
+3
View File
@@ -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
File renamed without changes.
+44
View File
@@ -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 + '$'
File renamed without changes.
+35 -32
View File
@@ -1,15 +1,18 @@
// We have the following variables: // We have the following variables:
// cursor_blink_disable // BLNSW (cursor blink switch)
// cursor_blink_countdown // BLNCT (cursor blink countdown)
// cursor_saved_character // GDBLN (cursor saved character)
// cursor_is_visible // BLNON (if cursor is visible)
// colour_under_cursor // GDCOL (colour under cursor)
// USER (current screen line colour pointer)
// PNT (current screen line pointer)
// PNTR (current screen x position)
show_cursor_if_enabled: show_cursor_if_enabled:
lda cursor_blink_disable lda BLNSW
beq !+ beq !+
rts rts
!: lda cursor_is_visible !: lda BLNON
beq show_cursor beq show_cursor
rts rts
@@ -17,77 +20,77 @@ show_cursor:
// Set cursor as though it had just finished the off phase, // Set cursor as though it had just finished the off phase,
// so that the call to blink_cursor paints it // so that the call to blink_cursor paints it
lda #$00 lda #$00
sta cursor_blink_countdown sta BLNCT
sta cursor_is_visible sta BLNON
jsr blink_cursor jsr blink_cursor
// Then set the timeout to 1 frame, so that the cursor // Then set the timeout to 1 frame, so that the cursor
// blinks under key repeat conditions, like on the original KERNAL // blinks under key repeat conditions, like on the original KERNAL
lda #$01 lda #$01
sta cursor_blink_countdown sta BLNCT
rts rts
blink_cursor: blink_cursor:
// Is the cursor enabled? // Is the cursor enabled?
lda cursor_blink_disable lda BLNSW
bne no_blink_cursor bne no_blink_cursor
// Do we need to redraw things? // Do we need to redraw things?
dec cursor_blink_countdown dec BLNCT
bpl no_blink_cursor bpl no_blink_cursor
// Check if cursor was visible or not, and toggle // Check if cursor was visible or not, and toggle
lda cursor_is_visible lda BLNON
bne undraw_cursor bne undraw_cursor
draw_cursor: draw_cursor:
jsr calculate_screen_line_pointer jsr calculate_screen_line_pointer
ldy current_screen_x ldy PNTR
lda (current_screen_line_ptr),y lda (PNT),y
sta cursor_saved_character sta GDBLN
eor #$80 eor #$80
sta (current_screen_line_ptr),y sta (PNT),y
// Also set cursor colour // Also set cursor colour
lda (current_screen_line_colour_ptr),y lda (USER),y
sta colour_under_cursor sta GDCOL
lda text_colour lda COLOR
sta (current_screen_line_colour_ptr),y sta (USER),y
lda #1 lda #1
sta cursor_is_visible sta BLNON
jmp reset_blink_timer jmp reset_blink_timer
undraw_cursor: undraw_cursor:
jsr calculate_screen_line_pointer jsr calculate_screen_line_pointer
lda cursor_saved_character lda GDBLN
ldy current_screen_x ldy PNTR
sta (current_screen_line_ptr),y sta (PNT),y
lda colour_under_cursor lda GDCOL
sta (current_screen_line_colour_ptr),y sta (USER),y
lda #0 lda #0
sta cursor_is_visible sta BLNON
// Fall through // Fall through
reset_blink_timer: reset_blink_timer:
// Rest blink counter // Rest blink counter
// (Compute's Mapping the 64, p39-40) // (Compute's Mapping the 64, p39-40)
lda #20 lda #20
sta cursor_blink_countdown sta BLNCT
no_blink_cursor: no_blink_cursor:
rts rts
disable_cursor: disable_cursor:
lda #$80 lda #$80
sta cursor_blink_disable sta BLNSW
// FALL THROUGH // FALL THROUGH
hide_cursor_if_visible: hide_cursor_if_visible:
lda cursor_is_visible lda BLNON
bne undraw_cursor bne undraw_cursor
rts rts
enable_cursor: enable_cursor:
lda #$00 lda #$00
sta cursor_blink_disable sta BLNSW
rts rts
+5 -7
View File
@@ -1,15 +1,13 @@
// c64 prg p263 // c64 prg p263
cartridge_check: cartridge_check:
ldx #$04 ldx #$05
cartridge_check_l1: cartridge_check_l1:
lda CART_SIG,x lda CART_SIG-1,x
cmp cartridge_signature,x cmp cartridge_signature-1,x
bne no_cartridge bne no_cartridge
dex dex
bpl cartridge_check_l1 bne cartridge_check_l1
sec // FALLTROUGH
rts
no_cartridge: no_cartridge:
clc
rts rts
+22 -22
View File
@@ -52,18 +52,18 @@ chrin_repeat:
// If so, return the next byte, and clear the flag when we reach the end. // If so, return the next byte, and clear the flag when we reach the end.
// Do we have a line of input waiting? // Do we have a line of input waiting?
lda keyboard_input_ready lda CRSW
beq read_from_keyboard beq read_from_keyboard
// Yes, we have input waiting at (start_of_keyboard_input)+keyboard_input_ready // Yes, we have input waiting at (LXSP)+CRSW
// When keyboard_input_ready = end_of_input_line, then we return a carriage return // When CRSW = INDX, then we return a carriage return
// and clear the flag // and clear the flag
cmp end_of_input_line cmp INDX
bne not_end_of_input bne not_end_of_input
// Return carriage return and clear pending input flag // Return carriage return and clear pending input flag
lda #$00 lda #$00
sta keyboard_input_ready sta CRSW
pla pla
tax tax
clc clc
@@ -75,9 +75,9 @@ not_end_of_input:
tay tay
pla pla
tax tax
lda (start_of_keyboard_input),y lda (LXSP),y
jsr screen_code_to_petscii jsr screen_code_to_petscii
inc keyboard_input_ready inc CRSW
clc clc
rts rts
@@ -87,10 +87,10 @@ read_from_keyboard:
jsr enable_cursor jsr enable_cursor
// Wait for a key // Wait for a key
lda keys_in_key_buffer lda NDX
beq chrin_repeat beq chrin_repeat
lda keyboard_buffer lda KEYD
cmp #$0d cmp #$0d
bne not_enter bne not_enter
@@ -106,10 +106,10 @@ read_from_keyboard:
// (Compute's Mapping the 64, p96) // (Compute's Mapping the 64, p96)
// Set pointer to line of input // Set pointer to line of input
lda current_screen_line_ptr+0 lda PNT+0
sta start_of_keyboard_input+0 sta LXSP+0
lda current_screen_line_ptr+1 lda PNT+1
sta start_of_keyboard_input+1 sta LXSP+1
// Calculate length // Calculate length
jsr get_current_line_logical_length jsr get_current_line_logical_length
@@ -117,18 +117,18 @@ read_from_keyboard:
iny iny
!: dey !: dey
bmi empty_line bmi empty_line
lda (current_screen_line_ptr),y lda (PNT),y
cmp #$20 cmp #$20
beq !- beq !-
iny iny
sty end_of_input_line sty INDX
lda #$01 lda #$01
sta keyboard_input_ready sta CRSW
// Return first char of line // Return first char of line
ldy #$00 ldy #$00
pla pla
tax tax
lda (start_of_keyboard_input),y lda (LXSP),y
jsr screen_code_to_petscii jsr screen_code_to_petscii
clc clc
rts rts
@@ -145,7 +145,7 @@ empty_line:
not_enter: not_enter:
// Print character // Print character
lda keyboard_buffer lda KEYD
jsr CHROUT jsr CHROUT
jsr pop_keyboard_buffer jsr pop_keyboard_buffer
@@ -160,13 +160,13 @@ pop_keyboard_buffer:
sei sei
ldx #$00 ldx #$00
ldy #$01 ldy #$01
!: lda keyboard_buffer,y !: lda KEYD,y
sta keyboard_buffer,x sta KEYD,x
inx inx
iny iny
cpy key_buffer_size cpy XMAX
bne !- bne !-
dec keys_in_key_buffer dec NDX
cli cli
rts rts
+178 -190
View File
@@ -11,7 +11,7 @@
chrout_real: chrout_real:
sta last_printed_character_ascii sta SCHAR
// Save X and Y values // Save X and Y values
// (Confirmed by writing a test program that X and Y // (Confirmed by writing a test program that X and Y
@@ -34,7 +34,7 @@ chrout_real:
chrout_iec: chrout_iec:
lda last_printed_character_ascii lda SCHAR
jsr JCIOUT jsr JCIOUT
bcc chrout_done bcc chrout_done
@@ -77,7 +77,7 @@ chrout_done:
tay tay
pla pla
tax tax
lda last_printed_character_ascii lda SCHAR
clc // indicate success clc // indicate success
rts rts
@@ -88,7 +88,7 @@ chrout_screen:
jsr hide_cursor_if_visible jsr hide_cursor_if_visible
lda last_printed_character_ascii lda SCHAR
tax tax
// Check for special characters // Check for special characters
@@ -110,8 +110,8 @@ not_0a:
bne not_0d bne not_0d
// RETURN clears quote and insert modes // RETURN clears quote and insert modes
lda #$00 lda #$00
sta quote_mode_flag sta QTSW
sta insert_mode sta INSRT
jmp screen_advance_to_next_line jmp screen_advance_to_next_line
not_0d: not_0d:
@@ -125,7 +125,7 @@ not_0d:
cmp #79 cmp #79
bne definitely_not_too_long bne definitely_not_too_long
tay tay
lda (current_screen_line_ptr),y lda (PNT),y
cmp #$20 cmp #$20
beq definitely_not_too_long beq definitely_not_too_long
@@ -135,7 +135,7 @@ not_0d:
definitely_not_too_long: definitely_not_too_long:
// Work out if line needs to be expanded, and if so expand it // Work out if line needs to be expanded, and if so expand it
ldy #39 ldy #39
lda (current_screen_line_ptr),y lda (PNT),y
cmp #$20 cmp #$20
beq no_need_to_extend 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 // though we really don't believe that the routine can be copyrighted
// due to the lack of creativity. // due to the lack of creativity.
dey dey
lda (current_screen_line_colour_ptr),y lda (USER),y
iny iny
sta (current_screen_line_colour_ptr),y sta (USER),y
dey dey
lda (current_screen_line_ptr),y lda (PNT),y
iny iny
sta (current_screen_line_ptr),y sta (PNT),y
dey dey
cpy current_screen_x cpy PNTR
bne !- bne !-
// Increase insert mode count (which causes quote-mode like behaviour) // Increase insert mode count (which causes quote-mode like behaviour)
inc insert_mode inc INSRT
// Put space in the inserted gap // Put space in the inserted gap
lda #$20 lda #$20
sta (current_screen_line_ptr),y sta (PNT),y
jmp chrout_done jmp chrout_done
not_94: not_94:
// DELETE in insert mode embeds control character // DELETE in insert mode embeds control character
ldx insert_mode ldx INSRT
bne not_14 bne not_14
cmp #$14 cmp #$14
bne not_14 bne not_14
// Delete // Delete
ldx current_screen_x ldx PNTR
bne delete_non_zero_column bne delete_non_zero_column
delete_at_column_0: delete_at_column_0:
ldy current_screen_y ldy TBLX
bne not_row_0 bne not_row_0
// delete from row 0, col 0 does nothing // delete from row 0, col 0 does nothing
jmp chrout_done jmp chrout_done
not_row_0: not_row_0:
// Column 0 delete just moves us to the end of the // Column 0 delete just moves us to the end of the
// previous line, without actually deleting anything // previous line, without actually deleting anything
dec current_screen_y dec TBLX
jsr get_current_line_logical_length jsr get_current_line_logical_length
lda logical_line_length lda LNMX
sta current_screen_x sta PNTR
jsr calculate_screen_line_pointer jsr calculate_screen_line_pointer
jmp chrout_done jmp chrout_done
delete_non_zero_column: delete_non_zero_column:
// Copy rest of line down // Copy rest of line down
jsr get_current_line_logical_length jsr get_current_line_logical_length
ldy current_screen_x ldy PNTR
cpy logical_line_length cpy LNMX
beq done_delete beq done_delete
dey dey
!: !:
iny iny
lda (current_screen_line_ptr),y lda (PNT),y
dey dey
sta (current_screen_line_ptr),y sta (PNT),y
iny iny
lda (current_screen_line_colour_ptr),y lda (USER),y
dey dey
sta (current_screen_line_colour_ptr),y sta (USER),y
iny iny
cpy logical_line_length cpy LNMX
bne !- bne !-
// Clear char at end of line // Clear char at end of line
jsr get_current_line_logical_length jsr get_current_line_logical_length
tay tay
lda #$20 lda #$20
sta (current_screen_line_ptr),y sta (PNT),y
done_delete: done_delete:
dec current_screen_x dec PNTR
jmp chrout_done jmp chrout_done
not_14: not_14:
// Check for quote mode // Check for quote mode
ldx quote_mode_flag ldx QTSW
bne is_quote_mode bne is_quote_mode
ldx insert_mode ldx INSRT
bne is_quote_mode bne is_quote_mode
jmp not_quote_mode jmp not_quote_mode
@@ -274,7 +274,7 @@ not_quote_mode:
colour_check_loop: colour_check_loop:
cmp colour_codes,x cmp colour_codes,x
bne !+ bne !+
stx text_colour stx COLOR
jmp chrout_done jmp chrout_done
!: dex !: dex
bpl colour_check_loop bpl colour_check_loop
@@ -283,24 +283,24 @@ colour_check_loop:
cmp #$12 cmp #$12
bne not_12 bne not_12
lda #$80 lda #$80
sta reverse_video_flag sta RVS
jmp chrout_done jmp chrout_done
not_12: not_12:
// Compute's Mapping the 64 p 38 // Compute's Mapping the 64 p 38
cmp #$92 cmp #$92
bne not_92 bne not_92
lda #$00 lda #$00
sta reverse_video_flag sta RVS
jmp chrout_done jmp chrout_done
not_92: not_92:
// Check for cursor movement keys // Check for cursor movement keys
cmp #$11 cmp #$11
bne not_11 bne not_11
lda current_screen_x lda PNTR
clc clc
adc #40 adc #40
sta current_screen_x sta PNTR
// We need to advance the pointer manually, as normalising // We need to advance the pointer manually, as normalising
// now will break things. The pointer update is required // now will break things. The pointer update is required
// so that we can tell if we really are on the bottom phys // so that we can tell if we really are on the bottom phys
@@ -311,22 +311,22 @@ not_92:
not_11: not_11:
cmp #$1d cmp #$1d
bne not_1d bne not_1d
inc current_screen_x inc PNTR
jsr calculate_screen_line_pointer jsr calculate_screen_line_pointer
jmp chrout_done jmp chrout_done
not_1d: not_1d:
cmp #$91 cmp #$91
bne not_91 bne not_91
lda current_screen_x lda PNTR
sec sec
sbc #40 sbc #40
sta current_screen_x sta PNTR
jsr calculate_screen_line_pointer jsr calculate_screen_line_pointer
jmp chrout_done jmp chrout_done
not_91: not_91:
cmp #$9d cmp #$9d
bne not_9d bne not_9d
dec current_screen_x dec PNTR
jsr calculate_screen_line_pointer jsr calculate_screen_line_pointer
jmp chrout_done jmp chrout_done
not_9d: not_9d:
@@ -335,8 +335,8 @@ not_9d:
cmp #$13 cmp #$13
bne not_13 bne not_13
lda #0 lda #0
sta current_screen_x sta PNTR
sta current_screen_y sta TBLX
jsr calculate_screen_line_pointer jsr calculate_screen_line_pointer
jmp chrout_done jmp chrout_done
not_13: not_13:
@@ -365,12 +365,12 @@ not_clearscreen:
bcc !+ bcc !+
and #$7f and #$7f
jmp not_high_char jmp output_literal_char // not high char
!: !:
// Range $20-$3F is unchanged // Range $20-$3F is unchanged
cmp #$40 cmp #$40
bcc not_high_char bcc output_literal_char // not high char
// Unshifted letters and symbols from $40-$5F // Unshifted letters and symbols from $40-$5F
// all end up being -$40 // all end up being -$40
@@ -385,74 +385,70 @@ not_clearscreen:
// Fix shifted chars by adding $20 again // Fix shifted chars by adding $20 again
cmp #$20 cmp #$20
bcc not_high_char bcc output_literal_char // not high char
cmp #$40 cmp #$40
bcs not_high_char bcs output_literal_char // not high char
clc clc
adc #$20 adc #$20
not_high_char:
chrout_l1:
output_literal_char: output_literal_char:
// Write normal character on the screen // Write normal character on the screen
pha pha
ldy current_screen_x ldy PNTR
ora reverse_video_flag // Compute's Mapping the 64 p38 ora RVS // Compute's Mapping the 64 p38
sta (current_screen_line_ptr),y sta (PNT),y
// Decrement number of chars waiting to be inserted // Decrement number of chars waiting to be inserted
lda insert_mode lda INSRT
beq !+ beq !+
dec insert_mode dec INSRT
!: !:
pla pla
cmp #$22 cmp #$22
bne not_quote bne not_quote
// Toggle quote flag if required // Toggle quote flag if required
lda quote_mode_flag lda QTSW
eor #$80 eor #$80
sta quote_mode_flag sta QTSW
not_quote: not_quote:
// Set colour // Set colour
lda text_colour lda COLOR
sta (current_screen_line_colour_ptr),y sta (USER),y
// Advance the column, and scroll screen down if we need // Advance the column, and scroll screen down if we need
// to insert a 2nd line in this logical line. // to insert a 2nd line in this logical line.
// (eg Compute's Mapping the 64 p41) // (eg Compute's Mapping the 64 p41)
ldx current_screen_y ldx TBLX
iny iny
sty current_screen_x sty PNTR
cpy #40 cpy #40
bne !+ bne !+
jsr screen_grow_logical_line jsr screen_grow_logical_line
ldy current_screen_x ldy PNTR
!: !:
cpy #80 cpy #80
bcc no_screen_advance_to_next_line bcc no_screen_advance_to_next_line
lda #0 lda #0
sta current_screen_x sta PNTR
jmp screen_advance_to_next_line jmp screen_advance_to_next_line
no_screen_advance_to_next_line: no_screen_advance_to_next_line:
jmp chrout_done jmp chrout_done
screen_grow_logical_line: screen_grow_logical_line:
ldy current_screen_y ldy TBLX
// Don't grow line if it is already grown // Don't grow line if it is already grown
lda screen_line_link_table,y lda LDTBL,y
bpl !+ bpl !+
jmp done_grow_line jmp not_last_line // doneb grow line
!: !:
lda #$80 lda #$80
sta screen_line_link_table,y sta LDTBL,y
// Now make space for the extra line added. // Now make space for the extra line added.
// If we are on the last physical line of the screen, // If we are on the last physical line of the screen,
@@ -471,11 +467,11 @@ screen_grow_logical_line:
ldy #0 ldy #0
count_rows_loop: count_rows_loop:
dex dex
lda screen_line_link_table,y lda LDTBL,y
bpl !+ bpl !+
dex dex
!: iny !: iny
cpy current_screen_y cpy TBLX
bne count_rows_loop bne count_rows_loop
cpx #0 cpx #0
@@ -493,28 +489,28 @@ count_rows_loop:
lda HIBASE lda HIBASE
clc clc
adc #3 adc #3
sta current_screen_line_ptr+1 sta PNT+1
sta load_or_scroll_temp_pointer+1 sta SAL+1
lda #>$DBC0 lda #>$DBC0
sta load_save_verify_end_address+1 sta EAL+1
sta current_screen_line_colour_ptr+1 sta USER+1
lda #<$03C0 lda #<$03C0
sta current_screen_line_ptr+0 sta PNT+0
sta current_screen_line_colour_ptr+0 sta USER+0
// souce address is line above // souce address is line above
sec sec
sbc #40 sbc #40
sta load_or_scroll_temp_pointer+0 sta SAL+0
sta load_save_verify_end_address+0 sta EAL+0
copy_line_down_loop: copy_line_down_loop:
ldy #39 ldy #39
cl_inner: cl_inner:
lda (load_save_verify_end_address),y lda (EAL),y
sta (current_screen_line_colour_ptr),y sta (USER),y
lda (load_or_scroll_temp_pointer),y lda (SAL),y
sta (current_screen_line_ptr),y sta (PNT),y
dey dey
bpl cl_inner bpl cl_inner
@@ -523,29 +519,29 @@ cl_inner:
// Old source is new destination // Old source is new destination
// Use different registers to minimise byte similarity with C64 KERNAl // Use different registers to minimise byte similarity with C64 KERNAl
ldy load_or_scroll_temp_pointer+1 ldy SAL+1
sty current_screen_line_ptr+1 sty PNT+1
lda load_save_verify_end_address+1 lda EAL+1
ldy load_or_scroll_temp_pointer+0 ldy SAL+0
sta current_screen_line_colour_ptr+1 sta USER+1
sty current_screen_line_ptr+0 sty PNT+0
sty current_screen_line_colour_ptr+0 sty USER+0
// Decrementing source pointers // Decrementing source pointers
lda load_or_scroll_temp_pointer+0 lda SAL+0
sec sec
sbc #<40 sbc #<40
sta load_or_scroll_temp_pointer+0 sta SAL+0
sta load_save_verify_end_address+0 sta EAL+0
lda load_or_scroll_temp_pointer+1 lda SAL+1
sbc #>40 sbc #>40
sta load_or_scroll_temp_pointer+1 sta SAL+1
// convert to screen equivalent // convert to screen equivalent
sec sec
sbc HIBASE sbc HIBASE
clc clc
adc #>$D800 adc #>$D800
sta load_save_verify_end_address+1 sta EAL+1
dex dex
bne copy_line_down_loop bne copy_line_down_loop
@@ -556,17 +552,16 @@ no_copy_down:
// Erase newly inserted line // Erase newly inserted line
ldy #79 ldy #79
!: !:
lda text_colour lda COLOR
sta (current_screen_line_colour_ptr),y sta (USER),y
lda #$20 lda #$20
sta (current_screen_line_ptr),y sta (PNT),y
dey dey
cpy #40 cpy #40
bne !- bne !-
rts rts
done_grow_line:
not_last_line: not_last_line:
rts rts
@@ -575,23 +570,23 @@ scroll_up_if_on_last_line:
// Colour RAM is always in fixed place, so is easiest // Colour RAM is always in fixed place, so is easiest
// to use to check if we are on the last line. // to use to check if we are on the last line.
// The last line is at $D800 + 24*40 = $DBC0 // The last line is at $D800 + 24*40 = $DBC0
lda current_screen_line_colour_ptr+1 lda USER+1
cmp #>$DBC0 cmp #>$DBC0
bne not_last_line bne not_last_line
lda current_screen_line_colour_ptr+0 lda USER+0
cmp #<$DBC0 cmp #<$DBC0
beq is_last_line beq is_last_line
jsr get_current_line_logical_length jsr get_current_line_logical_length
clc clc
adc current_screen_line_colour_ptr+0 adc USER+0
cmp #<$DBE7-1 cmp #<$DBE7-1
bcc not_last_line bcc not_last_line
is_last_line: is_last_line:
dec current_screen_y dec TBLX
// FALL THROUGH // FALL THROUGH
@@ -601,68 +596,68 @@ scroll_screen_up:
// Get pointers to start of screen + colour RAM // Get pointers to start of screen + colour RAM
lda HIBASE lda HIBASE
sta current_screen_line_ptr+1 sta PNT+1
sta load_or_scroll_temp_pointer+1 sta SAL+1
lda #>$D800 lda #>$D800
sta current_screen_line_colour_ptr+1 sta USER+1
sta load_save_verify_end_address+1 sta EAL+1
lda #$00 lda #$00
sta current_screen_line_ptr+0 sta PNT+0
sta current_screen_line_colour_ptr+0 sta USER+0
// Get pointers to screen/colour RAM source // Get pointers to screen/colour RAM source
lda screen_line_link_table+0 lda LDTBL+0
bmi !+ bmi !+
lda #40 lda #40
.byte $2C // BIT $nnnn to skip next instruction .byte $2C // BIT $nnnn to skip next instruction
!: !:
lda #80 lda #80
sta load_or_scroll_temp_pointer+0 sta SAL+0
sta load_save_verify_end_address+0 sta EAL+0
// Copy first three pages // Copy first three pages
ldy #$00 ldy #$00
ldx #3 ldx #3
scroll_copy_loop: scroll_copy_loop:
lda (load_save_verify_end_address),y lda (EAL),y
sta (current_screen_line_colour_ptr),y sta (USER),y
lda (load_or_scroll_temp_pointer),y lda (SAL),y
sta (current_screen_line_ptr),y sta (PNT),y
iny iny
bne scroll_copy_loop bne scroll_copy_loop
inc load_or_scroll_temp_pointer+1 inc SAL+1
inc current_screen_line_ptr+1 inc PNT+1
inc load_save_verify_end_address+1 inc EAL+1
inc current_screen_line_colour_ptr+1 inc USER+1
dex dex
bne scroll_copy_loop bne scroll_copy_loop
// Copy last partial page // Copy last partial page
// We need to copy 1000-(3*256)-line length // We need to copy 1000-(3*256)-line length
// = 232 - line length // = 232 - line length
lda load_or_scroll_temp_pointer+0 lda SAL+0
lda #232 lda #232
sec sec
sbc load_or_scroll_temp_pointer+0 sbc SAL+0
tax tax
scroll_copy_loop2: scroll_copy_loop2:
lda (load_save_verify_end_address),y lda (EAL),y
sta (current_screen_line_colour_ptr),y sta (USER),y
lda (load_or_scroll_temp_pointer),y lda (SAL),y
sta (current_screen_line_ptr),y sta (PNT),y
iny iny
dex dex
bne scroll_copy_loop2 bne scroll_copy_loop2
// Fill in scrolled up area // Fill in scrolled up area
ldx load_or_scroll_temp_pointer+0 ldx SAL+0
scroll_copy_loop3: scroll_copy_loop3:
lda text_colour lda COLOR
sta (current_screen_line_colour_ptr),y sta (USER),y
lda #$20 lda #$20
sta (current_screen_line_ptr),y sta (PNT),y
iny iny
dex dex
bne scroll_copy_loop3 bne scroll_copy_loop3
@@ -671,13 +666,13 @@ scroll_copy_loop3:
ldy #0 ldy #0
ldx #24 ldx #24
link_copy: link_copy:
lda screen_line_link_table+1,y lda LDTBL+1,y
sta screen_line_link_table+0,y sta LDTBL+0,y
iny iny
dex dex
bne link_copy bne link_copy
// Clear line link flag of last line // Clear line link flag of last line
stx screen_line_link_table+24 stx LDTBL+24
// Restore correct line pointers // Restore correct line pointers
jsr calculate_screen_line_pointer jsr calculate_screen_line_pointer
@@ -685,14 +680,14 @@ link_copy:
rts rts
get_current_line_logical_length: get_current_line_logical_length:
ldy current_screen_y ldy TBLX
lda screen_line_link_table,y lda LDTBL,y
bpl line_not_linked_del bpl line_not_linked_del
lda #79 lda #79
.byte $2c // BIT absolute mode, which we use to skip the next two instruction bytes .byte $2c // BIT absolute mode, which we use to skip the next two instruction bytes
line_not_linked_del: line_not_linked_del:
lda #39 lda #39
sta logical_line_length sta LNMX
rts rts
screen_advance_to_next_line: screen_advance_to_next_line:
@@ -701,37 +696,37 @@ screen_advance_to_next_line:
// Go to start of line // Go to start of line
lda #0 lda #0
sta current_screen_x sta PNTR
// Advance line number // Advance line number
ldy current_screen_y ldy TBLX
// Do quick fix to line pointer to work out if it is off // Do quick fix to line pointer to work out if it is off
// the bottom of the screen. // the bottom of the screen.
ldx #40 ldx #40
lda screen_line_link_table,y lda LDTBL,y
bmi !+ bmi !+
.byte $2c .byte $2c
!: ldx #80 !: ldx #80
txa txa
clc clc
adc current_screen_line_ptr+0 adc PNT+0
sta current_screen_line_ptr+0 sta PNT+0
lda current_screen_line_ptr+1 lda PNT+1
adc #0 adc #0
sta current_screen_line_ptr+1 sta PNT+1
inc current_screen_y inc TBLX
// Check if it will trigger scrolling // Check if it will trigger scrolling
// Work out if we have gone off the bottom of the screen? // Work out if we have gone off the bottom of the screen?
// 1040 > 1024, so if high byte of screen pointer is >= (HIBASE+4), // 1040 > 1024, so if high byte of screen pointer is >= (HIBASE+4),
// then we are off the bottom of the screen // then we are off the bottom of the screen
lda current_screen_line_ptr+1 lda PNT+1
sec sec
sbc HIBASE sbc HIBASE
cmp #3 cmp #3
bcc !+ bcc !+
lda current_screen_line_ptr+0 lda PNT+0
cmp #$e7 cmp #$e7
bcc !+ bcc !+
@@ -744,83 +739,82 @@ screen_advance_to_next_line:
jmp chrout_done jmp chrout_done
add_40_to_screen_x: add_40_to_screen_x:
lda current_screen_x lda PNTR
clc clc
adc #40 adc #40
sta current_screen_x sta PNTR
rts rts
normalise_screen_x_y: normalise_screen_x_y:
// Normalise X and Y values // Normalise X and Y values
// If X < 0, then make X = X + 40 (or 80, if previous line is linked) // If X < 0, then make X = X + 40 (or 80, if previous line is linked)
!: lda current_screen_x !: lda PNTR
bpl x_not_negative bpl x_not_negative
dec current_screen_y dec TBLX
// Check that we didn't go backwards off the top of the screen // Check that we didn't go backwards off the top of the screen
bpl !+ bpl !+
lda #0 lda #0
sta current_screen_y sta TBLX
!: jsr add_40_to_screen_x !: jsr add_40_to_screen_x
// Check if line is linked, if so, add 40 again // Check if line is linked, if so, add 40 again
ldy current_screen_y ldy TBLX
lda screen_line_link_table,y lda LDTBL,y
bpl !+ bpl !+
jsr add_40_to_screen_x jsr add_40_to_screen_x
!: !:
x_not_negative: x_not_negative:
// Work out if X is too big // Work out if X is too big
ldy current_screen_y ldy TBLX
lda screen_line_link_table,y lda LDTBL,y
bpl !+ bpl !+
lda #79 lda #79
.byte $2C // BIT $nnnn, used to skip next instruction .byte $2C // BIT $nnnn, used to skip next instruction
!: lda #39 !: lda #39
cmp current_screen_x cmp PNTR
bcs x_not_too_big bcs x_not_too_big
// X value is too big, so subtract 40 and increment Y // X value is too big, so subtract 40 and increment Y
lda current_screen_x lda PNTR
sec sec
sbc #40 sbc #40
sta current_screen_x sta PNTR
inc current_screen_y inc TBLX
x_not_too_big: x_not_too_big:
// Make sure Y isn't negative // Make sure Y isn't negative
lda current_screen_y lda TBLX
bpl !+ bpl !+
lda #0 lda #0
sta current_screen_y sta TBLX
!: !:
// Make sure Y isn't too large for absolute size of // Make sure Y isn't too large for absolute size of
// screen // screen
cmp #24 cmp #24
bcc !+ bcc !+
lda #24 lda #24
sta current_screen_y sta TBLX
!: !:
// Make sure Y isn't too much for the screen, taking // Make sure Y isn't too much for the screen, taking
// into account the line link table // into account the line link table
ldy #24 // max allowable line ldy #24 // max allowable line
ldx #0 ldx #0
link_count_loop: link_count_loop:
lda screen_line_link_table,x lda LDTBL,x
bpl !+ bpl !+
dey dey
!: inx !: inx
cpx #25 cpx #25
bne link_count_loop bne link_count_loop
tya tya
cmp current_screen_y cmp TBLX
bcs y_ok bcs y_ok
sta current_screen_y sta TBLX
y_ok: y_ok:
rts rts
calculate_screen_line_pointer: calculate_screen_line_pointer:
@@ -828,12 +822,12 @@ calculate_screen_line_pointer:
// Reset pointer to start of screen // Reset pointer to start of screen
lda HIBASE lda HIBASE
sta current_screen_line_ptr+1 sta PNT+1
lda #0 lda #0
sta current_screen_line_ptr+0 sta PNT+0
// Add 40 for every line, or 80 if the lines are linked // Add 40 for every line, or 80 if the lines are linked
ldx current_screen_y ldx TBLX
!: !:
// Stop if we have counted enough lines // Stop if we have counted enough lines
@@ -844,18 +838,18 @@ calculate_screen_line_pointer:
ldy #40 ldy #40
// -1 offset is because we count down from N to 1, not // -1 offset is because we count down from N to 1, not
// N-1 to 0. // N-1 to 0.
lda screen_line_link_table-1,x lda LDTBL-1,x
bpl cslp_l1 bpl cslp_l1
ldy #80 ldy #80
cslp_l1: cslp_l1:
// Add computed line length to pointer value // Add computed line length to pointer value
tya tya
clc clc
adc current_screen_line_ptr+0 adc PNT+0
sta current_screen_line_ptr+0 sta PNT+0
lda current_screen_line_ptr+1 lda PNT+1
adc #0 adc #0
sta current_screen_line_ptr+1 sta PNT+1
// Loop back to next line // Loop back to next line
dex dex
@@ -866,36 +860,30 @@ cslp_l1:
update_colour_line_pointer: update_colour_line_pointer:
// Now setup pointer to colour RAM // Now setup pointer to colour RAM
lda current_screen_line_ptr+0 lda PNT+0
sta current_screen_line_colour_ptr+0 sta USER+0
lda current_screen_line_ptr+1 lda PNT+1
sec sec
sbc HIBASE sbc HIBASE
clc clc
adc #>$d800 adc #>$d800
sta current_screen_line_colour_ptr+1 sta USER+1
rts rts
advance_screen_pointer_40_bytes: advance_screen_pointer_40_bytes:
lda current_screen_line_ptr+0 lda PNT+0
clc clc
adc #<40 adc #<40
sta current_screen_line_ptr+0 sta PNT+0
sta current_screen_line_colour_ptr+0 sta USER+0
lda current_screen_line_ptr+1 lda PNT+1
adc #>40 adc #>40
sta current_screen_line_ptr+1 sta PNT+1
sec sec
sbc HIBASE sbc HIBASE
clc clc
adc #>$D800 adc #>$D800
sta current_screen_line_colour_ptr+1 sta USER+1
jmp update_colour_line_pointer 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
+13 -6
View File
@@ -56,13 +56,20 @@ cint_pal:
!: !:
sta TVSFLG sta TVSFLG
// Setup KEYLOG vector - XXX is it proper place?
lda #<setup_keydecode
sta KEYLOG+0
lda #>setup_keydecode
sta KEYLOG+1
cint_brk: // entry for BRK and STOP+RESTORE - XXX, where should it start? cint_brk: // entry for BRK and STOP+RESTORE - XXX, where should it start?
jsr setup_vicii jsr setup_vicii
// Initialise cursor blink flags (Compute's Mapping the 64 p215) // Initialise cursor blink flags (Compute's Mapping the 64 p215)
lda #$00 lda #$00
sta cursor_blink_disable sta BLNSW
// Set keyboard decode vector (Compute's Mapping the 64 p215) // 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 // But require key to be held for ~1/3sec before
// repeating (Compute's Mapping the 64 p58) // repeating (Compute's Mapping the 64 p58)
ldx #22-2 // Fudge factor to match speed ldx #22-2 // Fudge factor to match speed
stx key_first_repeat_delay stx DELAY
// Set current colour for text (Compute's Mapping the 64 p215) // Set current colour for text (Compute's Mapping the 64 p215)
ldx #$01 // default is light blue ($0E), but we use a different one ldx #$01 // default is light blue ($0E), but we use a different one
stx text_colour stx COLOR
// Set maximum keyboard buffer size (Compute's Mapping the 64 p215) // Set maximum keyboard buffer size (Compute's Mapping the 64 p215)
ldx #10 ldx #10
stx key_buffer_size stx XMAX
// Put non-zero value in enable_case_switch // Put non-zero value in MODE to enable case switch
stx enable_case_switch stx MODE
// Set default I/O devices (see SCINIT description at http://sta.c64.org/cbm64krnfunc.html) // Set default I/O devices (see SCINIT description at http://sta.c64.org/cbm64krnfunc.html)
jsr clrchn_reset jsr clrchn_reset
+5
View File
@@ -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&amp%3Bstart=15
https://sys64738.org/2019/05/c64-bedtime-coding-eng-printing-08/
- 'Duotris' game calls $E50C during startup screen initialization
+31
View File
@@ -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&amp%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
+10 -10
View File
@@ -9,7 +9,7 @@ clear_screen:
lda #$00 lda #$00
ldy #24 ldy #24
clearscreen_l1: clearscreen_l1:
sta screen_line_link_table,y sta LDTBL,y
dey dey
bpl clearscreen_l1 bpl clearscreen_l1
@@ -19,35 +19,35 @@ clearscreen_l1:
// We should do this at HIBASE, which annoyingly // We should do this at HIBASE, which annoyingly
// is no ZP, so we need to make a vector // is no ZP, so we need to make a vector
// (Compute's Mapping the 64 p216) // (Compute's Mapping the 64 p216)
// Get pointer to the screen into current_screen_line_ptr // Get pointer to the screen into PNT
// as it is the first appropriate place for it found when // as it is the first appropriate place for it found when
// searching through the ZP allocations listed in // searching through the ZP allocations listed in
// Compute's Mapping the 64 // Compute's Mapping the 64
sta current_screen_line_ptr+0 sta PNT+0
lda HIBASE lda HIBASE
sta current_screen_line_ptr+1 sta PNT+1
ldx #$03 // countdown for pages to update ldx #$03 // countdown for pages to update
iny // Y now = #$00 iny // Y now = #$00
lda #$20 // space character lda #$20 // space character
clearscreen_l2: clearscreen_l2:
sta (current_screen_line_ptr),y sta (PNT),y
iny iny
bne clearscreen_l2 bne clearscreen_l2
// To draw only 1000 bytes, add 250 to address each time // To draw only 1000 bytes, add 250 to address each time
lda current_screen_line_ptr lda PNT
clc clc
adc #<250 adc #<250
sta current_screen_line_ptr sta PNT
lda current_screen_line_ptr+1 lda PNT+1
adc #>250 adc #>250
sta current_screen_line_ptr+1 sta PNT+1
lda #$20 // get space character again lda #$20 // get space character again
dex dex
bpl clearscreen_l2 bpl clearscreen_l2
// Clear colour RAM // Clear colour RAM
// (Compute's Mapping the 64 p216) // (Compute's Mapping the 64 p216)
lda text_colour lda COLOR
clearscreen_l3: clearscreen_l3:
sta $d800,y sta $d800,y
sta $d900,y sta $d900,y
+3 -1
View File
@@ -1,6 +1,8 @@
setup_vicii: setup_vicii:
// XXX there is more to setup within this routine
// Set up default IO values (Compute's Mapping the 64 p215) // Set up default IO values (Compute's Mapping the 64 p215)
lda #$1B // Enable text mode lda #$1B // Enable text mode
sta VIC_SCROLY sta VIC_SCROLY
@@ -17,4 +19,4 @@ setup_vicii:
lda #$00 lda #$00
sta VIC_SPENA sta VIC_SPENA
// FALLTROUGH rts
+2 -2
View File
@@ -13,7 +13,7 @@
GETIN: GETIN:
// Wait for a key // Wait for a key
lda keys_in_key_buffer lda NDX
bne !+ bne !+
// Nothing in keyboard buffer to read // Nothing in keyboard buffer to read
@@ -22,7 +22,7 @@ GETIN:
rts rts
!: !:
lda keyboard_buffer lda KEYD
pha pha
jsr pop_keyboard_buffer jsr pop_keyboard_buffer
+8 -6
View File
@@ -20,7 +20,7 @@ OPEN:
beq !+ beq !+
dey dey
lda LAT, y lda LAT, y
cmp current_logical_filenum cmp LA
bne open_not_yet_open bne open_not_yet_open
jmp kernalerror_FILE_ALREADY_OPEN jmp kernalerror_FILE_ALREADY_OPEN
open_not_yet_open: open_not_yet_open:
@@ -43,11 +43,11 @@ open_has_space:
// LAT / FAT / SAT support implemented according to // LAT / FAT / SAT support implemented according to
// 'Compute's Mapping the Commodore 64', page 52 // 'Compute's Mapping the Commodore 64', page 52
lda current_logical_filenum lda LA
sta LAT, y sta LAT, y
lda current_device_number lda FA
sta FAT, y sta FAT, y
lda current_secondary_address lda SA
sta SAT, y sta SAT, y
iny iny
@@ -58,7 +58,7 @@ open_has_space:
beq open_done_success beq open_done_success
// Check for IEC device // Check for IEC device
lda current_device_number lda FA
jsr iec_check_devnum jsr iec_check_devnum
bcc open_iec bcc open_iec
@@ -75,14 +75,16 @@ open_iec:
bcc !+ bcc !+
jmp kernalerror_DEVICE_NOT_FOUND jmp kernalerror_DEVICE_NOT_FOUND
!: !:
lda current_secondary_address lda SA
jsr iec_cmd_open jsr iec_cmd_open
bcc !+ bcc !+
jmp kernalerror_DEVICE_NOT_FOUND jmp kernalerror_DEVICE_NOT_FOUND
!: !:
#if CONFIG_MEMORY_MODEL_60K
// We need our helpers to get to filenames under ROMs or IO area // We need our helpers to get to filenames under ROMs or IO area
jsr install_ram_routines jsr install_ram_routines
#endif
// Send command ('file name') // Send command ('file name')
jsr lvs_send_file_name jsr lvs_send_file_name
+2
View File
@@ -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.
Loaded 100 of 186 files, more files were not shown because too many files have changed in this diff. Show more