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