Merge pull request #32 from FeralChild64/master

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

No files matched your search

+4
View File
@@ -1,4 +1,8 @@
# Image which is illegal to distribute - just for extra safety
kernal_hybrid.rom
# Compilation related files
assembler/KickAss*
+107
View File
@@ -0,0 +1,107 @@
# Configuring the build
It's not possible to provide ROM builds that suit everyone needs - therefore configuration files were introduced, separately for each of the hardware targets:
* [`c64/,,config_generic.s`](c64/,,config_generic.s)
* [`c64/,,config_mega65.s`](c64/,,config_mega65.s)
* [`c64/,,config_ultimate64.s`](c64/,,config_ultimate64.s)
Just edit them and recompile the project. To enable particular option - uncomment it by removing leading `//` from before `#define` directive (as you probably guessed, commenting out disables it). Some options are followed by constants - you can change them too to further fine-tune the build.
Note however, that features do not came for free - enabling them needs some additional ROM space (in BASIC segment, in KERNAL segment, or in both), which is VERY limited on the target machines. Some options might be unavailable for speecific targets - read the comments in the configuration files. Some options might also carry compatibility and/or performance hit - so choose wisely.
Sane defaults are already present - different for each target.
## Processor instruction set
### `CONFIG_CPU_MOS_6502`
Choose if your CPU only supports the original MOS Technology 6502 instruction set, like:
* MOS 6510 - used in the Commodore 64
* MOS 8500 - used in the Commodore 64C
* MOS 8502 - used in the Commodore 128
If unsure - select this one.
### `CONFIG_CPU_WDC_65C02`
Choose if your CPU supports the Western Design Center 65C02 instruction set, like:
* WDC 65C02 - used in the Turbo Master accelerator
* CSG 65CE02
* CSG 4510 - used in the Commodore 65 prototypes
It enables some speed/size code optimizations. Warning - this is untested!
### `CONFIG_CPU_WDC_65816`
Choose if your CPU supports the 16-bit Western Design Center 65816 instruction set, like:
* WDC 65C816 - used in the Flash 8 accelerator
* WDC 65C816S - used in the SuperCPU accelerator
It enables some speed/size code optimizations. Warning - this is untested!
## Memory models
Different layouts of memory are possible - but they can be selected at compile time only.
### `CONFIG_MEMORY_MODEL_38K`
Memory model the original machine uses - memory available for BASIC ends at `$9FFF`, just before the first block of ROM. The fastest and the most compatible, but gives the least memory for BASIC. If unsure - select this one.
### `CONFIG_MEMORY_MODEL_46K` and `CONFIG_MEMORY_MODEL_50K`
Planned for the future - not available yet.
### `CONFIG_MEMORY_MODEL_60K`
Uses RAM under BASIC, I/O and KERNAL, takes over `$C000`-`$CFFF` area requires special helper routines installed in `$2A7`-`$2FF` area (normally unused and free for the user). Gives the most free memory for BASIC programs, but it's the slowest and the least compatible model.
Comparing to standard memoryy model, it needs about 180 bytes in BASIC segment and 80 bytes in KERNAL segment - at the moment of doing the test, these values are expected to change often.
## Multiple SID support
The SID is a sound chip - original machine had one installed. However, mods exists to add more of them for improved sound capabilitiee. Emulators and FPGA machines typically allow to simulate more than one too. Unfortunately, there is no standard regarding how these additional chips are visible in the processor address space, and there is no sane way to detect it - thus, it has to be configurable.
The SID support in the ROM is very limited - it only disables the sound during startup or warm restart (when STOP+RESTORE is pressed or BRK assembler instruction is executed).
### `CONFIG_SID_2ND` and `CONFIG_SID_3RD`
Each of them add support for one additional SID - addresses should be given in `CONFIG_SID_2ND_ADDRESS` and `CONFIG_SID_3RD_ADDRESS`, respectively.
Each of these options needs 8 bytes in KERNAL segment.
### `CONFIG_SID_D4XX` and `CONFIG_SID_D5XX`
Cause the system to support SIDs in `$D4xx` and `$D5xx` ranges, respectively.
Each of them needs a couple of bytes in KERNAL segment - but they can share some code, and `$D4xx` range support replaces the standard `$D400` address handling, so exact amount depends on the exact configuration.
## Miscelaneous features
### `CONFIG_DOS_WEDGE`
If enabled, a simple DOS wedge is available from the direct mode - supports `@<drive_number>`, `@<command>`, `@$`, `@$<params>` and `@` commands.
Feature needs about 330 bytes in BASIC segment.
### `CONFIG_BCD_SAFE_INTERRUPTS`
On the most widespread CPUs the D flag is not cleared upon entering interrupts. Since the original Kernal does not clear it either, it's not safe to use BCD processor mode without disabling the interrupts first. This option makes sure the D flag is disabled at the start of the interrupt - this allows some optimizations in the code.
Feature needs 2 bytes in KERNAL segmment (for CPUs needing the patch), but at the same time allows optimizations allowing to gain some more bytes. If unsure - enable.
## Debug options
Options in this section are for debug purposes only. If unsure - disable.
### `CONFIG_DBG_STUBS_BRK`
Replaces `RTS` stubbed routines implementation with one causing a break.
### `CONFIG_DBG_PRINTF`
Makes 'printf' routine available.
+86 -20
View File
@@ -3,7 +3,7 @@
SRCDIR_COMMON = c64/aliases
SRCDIR_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
+105 -50
View File
@@ -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
View File
@@ -4,7 +4,12 @@ Follow these rules, or bad things will happen!
- Don't mix ROMs for different platforms - use generic BASIC with generic KERNAL, Mega65 BASIC with Mega65 KERNAL, etc.
- Don't mix 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.
+28
View File
@@ -0,0 +1,28 @@
//
// Please read CONFIG.md before modifying this file!
//
#define CONFIG_CPU_MOS_6502
// #define CONFIG_CPU_WDC_65C02
// #define CONFIG_CPU_WDC_65816
#define CONFIG_MEMORY_MODEL_38K
// #define CONFIG_MEMORY_MODEL_60K
// #define CONFIG_SID_2ND
.const CONFIG_SID_2ND_ADDRESS = $D420
// #define CONFIG_SID_3RD
.const CONFIG_SID_3RD_ADDRESS = $D440
// #define CONFIG_SID_D4XX
// #define CONFIG_SID_D5XX
#define CONFIG_DOS_WEDGE
#define CONFIG_BCD_SAFE_INTERRUPTS
#define CONFIG_EXTENDED_SCNKEY // for now has to be enabled
// #define CONFIG_DBG_STUBS_BRK
// #define CONFIG_DBG_PRINTF
+28
View File
@@ -0,0 +1,28 @@
//
// Please read CONFIG.md before modifying this file!
//
#define CONFIG_CPU_MOS_6502
// #define CONFIG_CPU_WDC_65C02
// #define CONFIG_CPU_WDC_65816
// #define CONFIG_MEMORY_MODEL_38K
#define CONFIG_MEMORY_MODEL_60K
#define CONFIG_SID_2ND
.const CONFIG_SID_2ND_ADDRESS = $D420
// #define CONFIG_SID_3RD
.const CONFIG_SID_3RD_ADDRESS = $D440
// #define CONFIG_SID_D4XX
// #define CONFIG_SID_D5XX
#define CONFIG_DOS_WEDGE
#define CONFIG_BCD_SAFE_INTERRUPTS
#define CONFIG_EXTENDED_SCNKEY // for now has to be enabled
// #define CONFIG_DBG_STUBS_BRK
// #define CONFIG_DBG_PRINTF
+28
View File
@@ -0,0 +1,28 @@
//
// Please read CONFIG.md before modifying this file!
//
#define CONFIG_CPU_MOS_6502
// #define CONFIG_CPU_WDC_65C02
// #define CONFIG_CPU_WDC_65816
#define CONFIG_MEMORY_MODEL_38K
// #define CONFIG_MEMORY_MODEL_60K
// #define CONFIG_SID_2ND
.const CONFIG_SID_2ND_ADDRESS = $D420
// #define CONFIG_SID_3RD
.const CONFIG_SID_3RD_ADDRESS = $D440
#define CONFIG_SID_D4XX
#define CONFIG_SID_D5XX
#define CONFIG_DOS_WEDGE
#define CONFIG_BCD_SAFE_INTERRUPTS
#define CONFIG_EXTENDED_SCNKEY // for now has to be enabled
// #define CONFIG_DBG_STUBS_BRK
// #define CONFIG_DBG_PRINTF
+83
View File
@@ -0,0 +1,83 @@
// Various configuration dependent aliases/macros/checks
// Check that memory model configuration is correct
{
.var selected = 0;
#if CONFIG_MEMORY_MODEL_38K
.eval selected++
#endif
#if CONFIG_MEMORY_MODEL_60K
.eval selected++
#endif
.if (selected != 1) .error "Please select exactly one CONFIG_MEMORY_MODEL_* option"
}
// Check that processor configuration is correct
{
.var selected = 0;
#if CONFIG_CPU_MOS_6502
.eval selected++
#endif
#if CONFIG_CPU_WDC_65C02
.eval selected++
#endif
#if CONFIG_CPU_WDC_65816
.eval selected++
#endif
.if (selected != 1) .error "Please select exactly one CONFIG_CPU_* option"
}
// Handle processor configuration
#if CONFIG_CPU_WDC_65C02 || CONFIG_CPU_WDC_65816
#define HAS_BCD_SAFE_INTERRUPTS
#define HAS_BCD_SAFE_RESET
.pseudocommand phx { .byte $DA }
.pseudocommand phy { .byte $5A }
.pseudocommand plx { .byte $FA }
.pseudocommand ply { .byte $7A }
#endif
// Handle misc configuration entrues
#if CONFIG_BCD_SAFE_INTERRUPTS
#define HAS_BCD_SAFE_INTERRUPTS
#endif
// Stub configuration
.macro STUB_IMPLEMENTATION_RTS() {
rts
}
.macro STUB_IMPLEMENTATION_BRK() {
.break
brk
brk
jmp *-2
}
.macro STUB_IMPLEMENTATION()
{
#if CONFIG_DBG_STUBS_BRK
STUB_IMPLEMENTATION_BRK()
#else
STUB_IMPLEMENTATION_RTS()
#endif
}
+8
View File
@@ -10,6 +10,8 @@
// VIC-II registers
.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
+109 -22
View File
@@ -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
View File
@@ -1,126 +1,18 @@
// Names of ZP and low memory locations
// (Only those for now that we feel the need to implement initially)
// (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
+13
View File
@@ -0,0 +1,13 @@
// Routines imported from Kernal - our private API
#import "KERNAL_combined.sym"
#if CONFIG_DBG_PRINTF
.label printf = KERNAL.printf
#endif
.label print_hex_byte = KERNAL.print_hex_byte
.label print_return = KERNAL.print_return
.label print_space = KERNAL.print_space
+9
View File
@@ -0,0 +1,9 @@
All the BASIC routines, for which there are vectors in $0300-$030B, have to be available at their original addresses.
Reason: some autostart software (https://codebase64.org/doku.php?id=base:autostarting_disk_files) override these vectors, so that some point
to new locations (usually Kernal related), while others points the original BASIC routines. Different techniques modify different vectors
(while resetting others to original C64 locations), some don't change the vectors at all, but might still put the original
C64 BASIC addresses there.
For various cartridges this just means disabling their extensions (like new commands); for us that would mean improperly functionning BASIC.
+13
View File
@@ -0,0 +1,13 @@
//
// Official BASIC routine, described in:
//
// - [RG64] C64 Programmer's Reference Guide - XXX
// - [CM64] Compute's Mapping the Commodore 64 - page 69, XXX
//
// CPU registers that has to be preserved (see [RG64]): XXX
//
MAIN:
STUB_IMPLEMENTATION()
+13
View File
@@ -0,0 +1,13 @@
//
// Official BASIC routine, described in:
//
// - [RG64] C64 Programmer's Reference Guide - XXX
// - [CM64] Compute's Mapping the Commodore 64 - page 69, XXX
//
// CPU registers that has to be preserved (see [RG64]): XXX
//
CHRNCH:
STUB_IMPLEMENTATION()
+9
View File
@@ -0,0 +1,9 @@
All the BASIC routines, for which there are vectors in $0300-$030B, have to be available at their original addresses.
Reason: some autostart software (https://codebase64.org/doku.php?id=base:autostarting_disk_files) override these vectors, so that some point
to new locations (usually Kernal related), while others points the original BASIC routines. Different techniques modify different vectors
(while resetting others to original C64 locations), some don't change the vectors at all, but might still put the original
C64 BASIC addresses there.
For various cartridges this just means disabling their extensions (like new commands); for us that would mean improperly functionning BASIC.
+3
View File
@@ -0,0 +1,3 @@
This routine is mentionned in the cartridge writing tutorial here: https://codebase64.org/doku.php?id=base:assembling_your_own_cart_rom_image
We have to implement (or at least provide stub), otherwise cartridges will crash.
+5
View File
@@ -0,0 +1,5 @@
// XXX provide documentation and implementation
RUNC:
STUB_IMPLEMENTATION()
+9
View File
@@ -0,0 +1,9 @@
All the BASIC routines, for which there are vectors in $0300-$030B, have to be available at their original addresses.
Reason: some autostart software (https://codebase64.org/doku.php?id=base:autostarting_disk_files) override these vectors, so that some point
to new locations (usually Kernal related), while others points the original BASIC routines. Different techniques modify different vectors
(while resetting others to original C64 locations), some don't change the vectors at all, but might still put the original
C64 BASIC addresses there.
For various cartridges this just means disabling their extensions (like new commands); for us that would mean improperly functionning BASIC.
+13
View File
@@ -0,0 +1,13 @@
//
// Official BASIC routine, described in:
//
// - [RG64] C64 Programmer's Reference Guide - XXX
// - [CM64] Compute's Mapping the Commodore 64 - page 69, XXX
//
// CPU registers that has to be preserved (see [RG64]): XXX
//
QPLOP:
STUB_IMPLEMENTATION()
+3
View File
@@ -0,0 +1,3 @@
This routine is mentionned in the cartridge writing tutorial here: https://codebase64.org/doku.php?id=base:assembling_your_own_cart_rom_image
We have to implement (or at least provide stub), otherwise cartridges will crash.
+5
View File
@@ -0,0 +1,5 @@
// XXX provide documentation and implementation
NEWSTT:
STUB_IMPLEMENTATION()
+13
View File
@@ -0,0 +1,13 @@
//
// Official BASIC routine, described in:
//
// - [RG64] C64 Programmer's Reference Guide - XXX
// - [CM64] Compute's Mapping the Commodore 64 - page 70, XXX
//
// CPU registers that has to be preserved (see [RG64]): XXX
//
GONE:
STUB_IMPLEMENTATION()
+9
View File
@@ -0,0 +1,9 @@
All the BASIC routines, for which there are vectors in $0300-$030B, have to be available at their original addresses.
Reason: some autostart software (https://codebase64.org/doku.php?id=base:autostarting_disk_files) override these vectors, so that some point
to new locations (usually Kernal related), while others points the original BASIC routines. Different techniques modify different vectors
(while resetting others to original C64 locations), some don't change the vectors at all, but might still put the original
C64 BASIC addresses there.
For various cartridges this just means disabling their extensions (like new commands); for us that would mean improperly functionning BASIC.
@@ -1,24 +1,25 @@
// Print string at $YYAA
// 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
+13
View File
@@ -0,0 +1,13 @@
//
// Official BASIC routine, described in:
//
// - [RG64] C64 Programmer's Reference Guide - XXX
// - [CM64] Compute's Mapping the Commodore 64 - page 70, XXX
//
// CPU registers that has to be preserved (see [RG64]): XXX
//
EVAL:
STUB_IMPLEMENTATION()
+9
View File
@@ -0,0 +1,9 @@
All the BASIC routines, for which there are vectors in $0300-$030B, have to be available at their original addresses.
Reason: some autostart software (https://codebase64.org/doku.php?id=base:autostarting_disk_files) override these vectors, so that some point
to new locations (usually Kernal related), while others points the original BASIC routines. Different techniques modify different vectors
(while resetting others to original C64 locations), some don't change the vectors at all, but might still put the original
C64 BASIC addresses there.
For various cartridges this just means disabling their extensions (like new commands); for us that would mean improperly functionning BASIC.
+5
View File
@@ -0,0 +1,5 @@
// XXX provide documentation and implementation
basic_adray1:
STUB_IMPLEMENTATION()
+5
View File
@@ -0,0 +1,5 @@
// XXX provide documentation and implementation
basic_adray2:
STUB_IMPLEMENTATION()
+23 -51
View File
@@ -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
+34 -22
View File
@@ -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
+4 -8
View File
@@ -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
+71 -36
View File
@@ -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
View File
@@ -1,29 +1,41 @@
// Find the BASIC line with number basic_line_number
// Find the BASIC line with number LINNUM
basic_find_line:
// 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
+16 -4
View File
@@ -1,15 +1,27 @@
// Advance basic_current_line_ptr by following the
// Advance OLDTXT by following the
// link to the next line
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
+15 -3
View File
@@ -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
+39 -23
View File
@@ -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
View File
@@ -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
+8 -8
View File
@@ -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
+82 -61
View File
@@ -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
View File
@@ -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
+21
View File
@@ -0,0 +1,21 @@
//
// Default values for BASIC vectors - described in:
//
// - [RG64] C64 Programmer's Reference Guide - pages 68-70
// - [CM64] Compute's Mapping the Commodore 64 - page 318
//
basic_vector_defaults_1:
.word ERROR // IERROR
.word MAIN // IMAIN
.word CHRNCH // ICHRNCH
.word QPLOP // IQPLOP
.word GONE // IGONE
.word EVAL // IEVAL
basic_vector_defaults_2:
.word basic_adray1 // ADRAY1
.word basic_adray2 // ADRAY2
+7 -5
View File
@@ -1,7 +1,11 @@
// Clear screen etc, show READY prompt.
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
+1
View File
@@ -0,0 +1 @@
At least the FB64 (a file browser) uses this routine - but outputting number as ASCI is defintelyy useful routine, certainly much more programs use it.
+10
View File
@@ -0,0 +1,10 @@
//
// Well-known BASIC routine, described in:
//
// - [CM64] Compute's Mapping the Commodore 64 - page 116, XXX
//
LINPRT:
STUB_IMPLEMENTATION()
+13 -15
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
+79 -5
View File
@@ -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
View File
@@ -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
+13
View File
@@ -0,0 +1,13 @@
//
// Official BASIC routine, described in:
//
// - [RG64] C64 Programmer's Reference Guide - XXX
// - [CM64] Compute's Mapping the Commodore 64 - page 69, XXX
//
// CPU registers that has to be preserved (see [RG64]): XXX
//
ERROR:
STUB_IMPLEMENTATION()
+9
View File
@@ -0,0 +1,9 @@
All the BASIC routines, for which there are vectors in $0300-$030B, have to be available at their original addresses.
Reason: some autostart software (https://codebase64.org/doku.php?id=base:autostarting_disk_files) override these vectors, so that some point
to new locations (usually Kernal related), while others points the original BASIC routines. Different techniques modify different vectors
(while resetting others to original C64 locations), some don't change the vectors at all, but might still put the original
C64 BASIC addresses there.
For various cartridges this just means disabling their extensions (like new commands); for us that would mean improperly functionning BASIC.
+5
View File
@@ -0,0 +1,5 @@
// XXX provide documentation and implementation
INIT:
STUB_IMPLEMENTATION()
+3
View File
@@ -0,0 +1,3 @@
This routine is mentionned in the cartridge writing tutorial here: https://codebase64.org/doku.php?id=base:assembling_your_own_cart_rom_image
We have to implement (or at least provide stub), otherwise cartridges will crash.
+44
View File
@@ -0,0 +1,44 @@
//
// Well-known BASIC routine, described in:
//
// - [CM64] Compute's Mapping the Commodore 64 - page 212
//
// Prints the start-up messages
//
INITMSG:
// Print startup banner, up to 255 characters
ldx #$00
!:
lda startup_banner, x
beq !+ // 0 means end of banner
jsr JCHROUT
inx
bne !-
!:
// Print PAL/NTSC
ldx #30 // NTSC
lda TVSFLG
beq !+
ldx #31 // PAL
!:
jsr print_packed_message
// Work out free bytes, display them
jsr basic_do_new
sec
lda MEMSIZ+0
sbc TXTTAB+0
tax
lda MEMSIZ+1
sbc TXTTAB+1
jsr print_integer
jsr print_space
// Print rest of the start up message
ldx #34
jmp print_packed_message
+3
View File
@@ -0,0 +1,3 @@
This routine is mentionned in the cartridge writing tutorial here: https://codebase64.org/doku.php?id=base:assembling_your_own_cart_rom_image
We have to implement (or at least provide stub), otherwise cartridges will crash.
+3
View File
@@ -0,0 +1,3 @@
This routine is mentionned in the cartridge writing tutorial here: https://codebase64.org/doku.php?id=base:assembling_your_own_cart_rom_image
We have to implement (or at least provide stub), otherwise cartridges will crash.
+5
View File
@@ -0,0 +1,5 @@
// XXX provide documentation and implementation
RVECT:
STUB_IMPLEMENTATION()
+24 -24
View File
@@ -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
+9
View File
@@ -0,0 +1,9 @@
init_oldtxt:
lda TXTTAB+0
sta OLDTXT+0
lda TXTTAB+1
sta OLDTXT+1
rts
+19 -22
View File
@@ -1,6 +1,6 @@
// Parse a number from the input buffer at (basic_current_statement_ptr)
// Parse a number from the input buffer at (TXTPTR)
// Result is put into FAC1.
// 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
View File
@@ -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
+17 -18
View File
@@ -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
-157
View File
@@ -1,157 +0,0 @@
// printf()-like routine for simplifying debugging
// Prints the literal zero-terminated string that follows,
// which may also include special tokens that allow
// printing of hex byte and word values stored at the indicated
// addresses.
// .byte 1,$byte = display byte as hex
// .byte 2,$low,$hi = display word as hex
// .byte $f0+n,$low,$hi = display byte at $hi$lo+n as hex
printf:
// Temporary storage is between end of screen at $0400
// and the sprite pointers at $7f8
sta $7f0
stx $7f1
sty $7f2
php
pla
sta $7f3
// Set up read routine
lda #$ad // LDA $nnnn
sta $7f4
lda #$60
sta $7f7 // RTS
// Get PC of caller from the stack, so that
// we can parse through it
pla
clc
adc #$01
sta $7f5
pla
adc #$00
sta $7f6
printf_loop:
jsr $7f4
cmp #$00
bne printf_continues
// Put return address on stack and restore
// registers
lda $7f6
pha
lda $7f5
pha
lda $7f3
pha
lda $7f0
ldx $7f1
ldy $7f2
plp
rts
printf_continues:
cmp #$01
bne not_hexbyte
// Print a hex byte
// Skip the token
jsr printf_advance
// Read the low byte
jsr $7f4
// Print as hex
jsr printf_printhexbyte
jmp printf_nextchar
not_hexbyte:
cmp #$02
bne not_hexword
// Print a hex word
// Skip the token
jsr printf_advance
jsr printf_advance
// Read the high byte
jsr $7f4
// Print as hex
jsr printf_printhexbyte
// Skip the token
jsr printf_retreat
// Read the low byte
jsr $7f4
// Print as hex
jsr printf_printhexbyte
jsr printf_advance
jmp printf_nextchar
not_hexword:
cmp #$f0
bcc not_pointer
// Treat two-byte arg as base address
// and lower 4 bits of token as offset from
// that location.
// Get offset
and #$0f
tay
jsr printf_advance
jsr $7f4
sta $fd
jsr printf_advance
jsr $7f4
sta $fe
lda ($fd),y
jsr printf_printhexbyte
jmp printf_nextchar
not_pointer:
// Print character
jsr JCHROUT
printf_nextchar:
jsr printf_advance
jmp printf_loop
printf_advance:
// Advance pointer to next character
inc $7f5
bne !+
inc $7f6
!:
rts
printf_retreat:
// Retreat pointer to previous char
lda $7f5
sec
sbc #1
sta $7f5
lda $7f6
sbc #0
sta $7f6
rts
printf_printhexbyte:
// Print the hex value in .A as two digits, idea by Haubitze
sed
pha
lsr
lsr
lsr
lsr
cmp #$0A
adc #$30
jsr JCHROUT
pla
and #$0F
cmp #$0A
adc #$30
cld
jmp JCHROUT
+1 -1
View File
@@ -11,7 +11,7 @@ select_device:
// Note: if tape support is introduced here, make sure DOS wedge won't get broken
ldx current_device_number
ldx FA
cpx #$08
bcs !+
ldx #$08
+7
View File
@@ -0,0 +1,7 @@
//
// Startup banner, to be displayed durin cold start
//
startup_banner:
TARGET_HOOK_BANNER()
+32 -32
View File
@@ -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.
+64 -18
View File
@@ -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
View File
@@ -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
-73
View File
@@ -1,73 +0,0 @@
// Names of ZP and low memory locations
// (Only those of relevance for the KERNAL)
// (And only those for now that we feel the need to implement initially)
// (https://www.c64-wiki.com/wiki/Zeropage)
// XXX get rid of this file, use ,aliases_ram_lowmem.s instead
.label kernal_load_or_verify_flag = $93
.label current_file_num = $98
.label input_device_number = DFLTN
.label cassette_buffer_bytes_used = $A6
.label load_or_scroll_temp_pointer = $AC
// We also use the following for temp colour pointer when scrolling
.label load_save_verify_end_address = $AE
.label cassette_buffer_ptr = $B2
.label current_logical_filenum = $B8
.label current_secondary_address = $B9
.label current_device_number = $BA
.label current_filename_ptr = $BB
.label load_save_end_ptr = $C3
.label last_key_matrix_position = $C5
.label keys_in_key_buffer = $C6
.label reverse_video_flag = $C7
.label end_of_input_line = $C8
.label start_of_keyboard_input = $C9
.label current_key_index_entry = $CB
.label cursor_blink_disable = $CC
.label cursor_blink_countdown = $CD
.label cursor_saved_character = $CE
.label cursor_is_visible = $CF
.label keyboard_input_ready = $D0
.label current_screen_line_ptr = $D1
.label current_screen_x = $D3
.label quote_mode_flag = $D4
.label logical_line_length = $D5
.label current_screen_y = $D6
.label last_printed_character_ascii = $D7
.label insert_mode = $D8
// Bits 0 -3 = bits 8-11 of screen line address
// Bit 7 = line spans multiple physical lines
.label screen_line_link_table = $D9
.label current_screen_line_colour_ptr = $F3
.label keyboard_decoding_table_ptr = $F5
// "Compute's Mapping the 64" book
.label keyboard_buffer = $0277
.label text_colour = $0286 // p55
.label colour_under_cursor = $0287 // p56
.label key_buffer_size = $0289 // p57
// 0 = cursor keys, insert, delete and space repeat, but nothing else
// 128 = all keys repeat
// 64 = no keys repeat
.label key_repeat_flags = $028A // p58
// https://www.c64-wiki.com/wiki/Page_2
.label key_repeat_counter = $028B
.label key_first_repeat_delay = $028C
// bit 0 = shift, 1 = Vendor Key, 2 = Control
.label key_bucky_state = $028D
.label key_last_bucky_state = $028E
.label keyboard_decoding_ptr = $028F
.label enable_case_switch = $0291
.label screen_scroll_disable = $0292
// Under-ROM routines
// (BASIC also includes them. XXX - We should de-duplicate them in a safe manner)
.label missed_nmi_flag = $2A7
.label tiny_nmi_handler = $2A8
.label peek_under_roms = tiny_nmi_handler+peek_under_roms_routine-tiny_nmi_handler_routine
.label poke_under_roms = tiny_nmi_handler+poke_under_roms_routine-tiny_nmi_handler_routine
.label memmap_allram = tiny_nmi_handler+memmap_allram_routine-tiny_nmi_handler_routine
.label memmap_normal = tiny_nmi_handler+memmap_normal_routine-tiny_nmi_handler_routine
@@ -4,10 +4,8 @@
// and ultimate_dos_v1.0.pdf and command_interface_v1.0.pdf by Gideon Zweijtzer
// 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.
+6
View File
@@ -0,0 +1,6 @@
// CHR$ codes for the 16 colours
colour_codes:
.byte 144,5,28,159,156,30,31,158
.byte 129,149,150,151,152,153,154,155
+3
View File
@@ -0,0 +1,3 @@
Location of the default Kernal vector values, described in Compute's Mapping the Commodore 64, page 237
It is referenced by GEOS - see https://github.com/mist64/geos/blob/master/inc/c64.inc
File renamed without changes.
+44
View File
@@ -0,0 +1,44 @@
//
// Messages to be prined out by Kernal
//
// Double underscore prevents labels from being passed to VICE (would confuse monitor)
.label __MSG_KERNAL_SEARCHING_FOR = __kernal_message_searching_for - __kernal_messages_start
.label __MSG_KERNAL_LOADING = __kernal_message_loading - __kernal_messages_start
.label __MSG_KERNAL_VERIFYING = __kernal_message_verifying - __kernal_messages_start
.label __MSG_KERNAL_SAVING = __kernal_message_saving - __kernal_messages_start
.label __MSG_KERNAL_FROM_HEX = __kernal_message_from_hex - __kernal_messages_start
.label __MSG_KERNAL_TO_HEX = __kernal_message_to_hex - __kernal_messages_start
__kernal_messages_start:
__kernal_message_searching_for:
.byte $0D
.text "SEARCHING FOR"
.byte $80 + $20 // end of string mark + space
__kernal_message_loading:
.byte $0D
.text "LOADIN"
.byte $80 + $47 // end of string mark + 'G'
__kernal_message_verifying:
.byte $0D
.text "VERIFYIN"
.byte $80 + $47 // end of string mark + 'G'
__kernal_message_saving:
.byte $0D
.text "SAVIN"
.byte $80 + $47 // end of string mark + 'G'
__kernal_message_from_hex:
.text " FROM "
.byte $80 + $24 // end of string mark + '$'
__kernal_message_to_hex:
.text " TO "
.byte $80 + $24 // end of string mark + '$'
File renamed without changes.
+39 -36
View File
@@ -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
+5 -7
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
+5
View File
@@ -0,0 +1,5 @@
The original reason to move PLOT routine into its original position was to provide support for unofficial $E50C address:
- it is well known: https://www.lemon64.com/forum/viewtopic.php?t=3296&amp%3Bstart=15
https://sys64738.org/2019/05/c64-bedtime-coding-eng-printing-08/
- 'Duotris' game calls $E50C during startup screen initialization
+31
View File
@@ -0,0 +1,31 @@
//
// Official Kernal routine, described in:
//
// - [RG64] C64 Programmer's Reference Guide - page 290
// - [CM64] Compute's Mapping the Commodore 64 - page 215
//
// CPU registers that has to be preserved (see [RG64]): none
//
PLOT:
bcs plot_get
// Note: the 'set' part has to start from $E50C, as this is a known address
// - https://www.lemon64.com/forum/viewtopic.php?t=3296&amp%3Bstart=15
// - https://sys64738.org/2019/05/c64-bedtime-coding-eng-printing-08/
// - 'Duotris' game calls $E50C during startup screen initialization
plot_set:
sty TBLX
stx PNTR
// XXX handle cursor blink
// XXX should we update some more variables?
// FALLTROUGH to save one byte on RTS
plot_get:
ldy TBLX
ldx PNTR
rts
+10 -10
View File
@@ -9,7 +9,7 @@ clear_screen:
lda #$00
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
+3 -1
View File
@@ -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
+2 -2
View File
@@ -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
+8 -6
View File
@@ -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
+2
View File
@@ -0,0 +1,2 @@
This is a well-known address of a heavily used Kernal routine, it has to be the same so our ROM is compatible.
Loaded 100 of 186 files, more files were not shown because too many files have changed in this diff. Show more