Merge pull request #27 from FeralChild64/master

IEC improvements and misc changes
This commit is contained in:
gardners authored and GitHub committed 2019-08-06 10:18:08 +09:30
commit d0de4df1ce
279 files changed
+3890 -966

No files matched your search

+17 -16
View File
@@ -1,17 +1,18 @@
c64/basic/OUT.BIN
c64/basic/combined.s
c64/kernal/OUT.BIN
c64/kernal/combined.s
chargen
newbasic
newc65
newkern
newrom
ophis.bin
padding
src/collect_data
src/compress_text
src/pngprepare
src/preprocess
temp.map
# Compilation related files
temp.s
temp.map
ophis.bin
build/*
# Input to the similarity tool - copyrighted material, we can't check it in!
/basic
/kernal
# Various IDE project files, temporary files, etc.
*project
.*swp
+2
View File
@@ -0,0 +1,2 @@
Although the project itself is LGPL3, I (FeralChild64) allow to redistribute my contributions to this project under any OSI (Open Source Initiative) approved open source license.
+135 -39
View File
@@ -1,61 +1,157 @@
all: Ophis src/collect_data src/preprocess
# Source files
SRC_COMMON = $(wildcard c64/aliases/*.s)
SRC_BASIC_COMMON = $(SRC_COMMON) $(wildcard c64/basic/*.s)
SRC_KERNAL_COMMON = $(SRC_COMMON) $(wildcard c64/kernal/*.s c64/kernal/jumptable/*.s c64/kernal/iec/*.s)
SRC_BASIC_generic = $(SRC_BASIC_COMMON) $(wildcard c64/basic/,target_generic/*.s)
SRC_BASIC_mega65 = $(SRC_BASIC_COMMON) $(wildcard c64/basic/,target_mega65/*.s)
SRC_BASIC_ultimate64 = $(SRC_BASIC_COMMON) $(wildcard c64/basic/,target_ultimate64/*.s)
SRC_KERNAL_generic = $(SRC_KERNAL_COMMON) $(wildcard c64/kernal/,target_generic/*.s)
SRC_KERNAL_mega65 = $(SRC_KERNAL_COMMON) $(wildcard c64/kernal/,target_mega65/*.s)
SRC_KERNAL_ultimate64 = $(SRC_KERNAL_COMMON) $(wildcard c64/kernal/,target_ultimate64/*.s)
# List of tools
TOOL_COLLECT_DATA = build/tools/collect_data
TOOL_COMPRESS_TEXT = build/tools/compress_text
TOOL_PNGPREPARE = build/tools/pngprepare
TOOL_PREPROCESS = build/tools/preprocess
TOOL_SIMILARITY = build/tools/similarity
TOOLS_LIST = $(TOOL_COLLECT_DATA) $(TOOL_COMPRESS_TEXT) $(TOOL_PNGPREPARE) $(TOOL_PREPROCESS) $(TOOL_SIMILARITY)
# Rules - main
.PHONY: all clean updatebin
all: build/chargen build/newkern_generic build/newbasic_generic build/newc65 build/newkern_ultimate64 build/newbasic_ultimate64
Ophis:
git submodule init
git submodule update
src/pngprepare: src/pngprepare.c Makefile
$(CC) $(COPT) -I/usr/local/include -L/usr/local/lib -o src/pngprepare src/pngprepare.c -lpng
clean:
@rm -rf build
@rm -f temp.s
@rm -f temp.map
@rm -f ophis.bin
chargen: src/pngprepare assets/8x8font.png
src/pngprepare charrom assets/8x8font.png chargen
updatebin: build/chargen build/newbasic_generic build/newkern_generic build/newbasic_mega65 build/newkern_mega65 build/newbasic_ultimate64 build/newkern_ultimate64
cp build/chargen bin/chargen.rom
cp build/newbasic_generic bin/basic_generic.rom
cp build/newkern_generic bin/kernal_generic.rom
cp build/newbasic_mega65 bin/basic_mega65.rom
cp build/newkern_mega65 bin/kernal_mega65.rom
cp build/newbasic_ultimate64 bin/basic_ultimate64.rom
cp build/newkern_ultimate64 bin/kernal_ultimate64.rom
src/collect_data: src/collect_data.c Makefile
gcc -Wall -o src/collect_data src/collect_data.c
# Rules - tools
src/preprocess: src/preprocess.c Makefile
gcc -g -Wall -o src/preprocess src/preprocess.c
$(TOOL_COLLECT_DATA): src/collect_data.c Makefile
@mkdir -p build/tools
gcc -Wall -o $(TOOL_COLLECT_DATA) src/collect_data.c
src/similarity: src/similarity.c Makefile
gcc -g -Wall -o src/similarity src/similarity.c
$(TOOL_COMPRESS_TEXT): src/compress_text.c Makefile
@mkdir -p build/tools
gcc -g -Wall -o $(TOOL_COMPRESS_TEXT) src/compress_text.c -lm
src/compress_text: src/compress_text.c Makefile
gcc -g -Wall -o src/compress_text src/compress_text.c -lm
$(TOOL_PNGPREPARE): src/pngprepare.c Makefile
@mkdir -p build/tools
$(CC) $(COPT) -I/usr/local/include -L/usr/local/lib -o $(TOOL_PNGPREPARE) src/pngprepare.c -lpng
newrom: c64/kernal/OUT.BIN c64/basic/OUT.BIN
cat c64/basic/OUT.BIN c64/kernal/OUT.BIN >newrom
$(TOOL_PREPROCESS): src/preprocess.c Makefile
@mkdir -p build/tools
gcc -g -Wall -o $(TOOL_PREPROCESS) src/preprocess.c
newkern: newrom Makefile
dd if=newrom bs=8192 count=1 skip=2 of=newkern
$(TOOL_SIMILARITY): src/similarity.c Makefile
@mkdir -p build/tools
gcc -g -Wall -o $(TOOL_SIMILARITY) src/similarity.c
newbasic: newrom Makefile
dd if=newrom bs=8192 count=1 skip=0 of=newbasic
# Rules - CHARGEN
newc65: newkern newbasic chargen Makefile
dd if=/dev/zero bs=4096 count=10 of=newc65
cat newbasic chargen chargen newkern >>newc65
dd if=/dev/zero bs=65536 count=1 of=padding
cat padding >>newc65
build/chargen: $(TOOL_PNGPREPARE) assets/8x8font.png
$(TOOL_PNGPREPARE) charrom assets/8x8font.png build/chargen
# Dependencies
build/basic_generic/OUT.BIN: Ophis $(TOOLS_LIST) $(SRC_BASIC_generic) build/basic/packed_messages.s
build/kernal_generic/OUT.BIN: Ophis $(TOOLS_LIST) $(SRC_KERNAL_generic)
build/newrom_generic: build/basic_generic/OUT.BIN build/kernal_generic/OUT.BIN
build/newkern_generic: build/newrom_generic Makefile
build/newbasic_generic: build/newrom_generic Makefile
build/basic_mega65/OUT.BIN: Ophis $(TOOLS_LIST) $(SRC_BASIC_mega65) build/basic/packed_messages.s
build/kernal_mega65/OUT.BIN: Ophis $(TOOLS_LIST) $(SRC_KERNAL_mega65)
build/newrom_mega65: build/basic_mega65/OUT.BIN build/kernal_mega65/OUT.BIN
build/newkern_mega65: build/newrom_mega65 Makefile
build/newbasic_mega65: build/newrom_mega65 Makefile
build/basic_ultimate64/OUT.BIN: Ophis $(TOOLS_LIST) $(SRC_BASIC_ultimate64) build/basic/packed_messages.s
build/kernal_ultimate64/OUT.BIN: Ophis $(TOOLS_LIST) $(SRC_KERNAL_ultimate64)
build/newrom_ultimate64: build/basic_ultimate64/OUT.BIN build/kernal_ultimate64/OUT.BIN
build/newkern_ultimate64: build/newrom_ultimate64 Makefile
build/newbasic_ultimate64: build/newrom_ultimate64 Makefile
c64/basic/packed_messages.s: Makefile src/compress_text
src/compress_text > c64/basic/packed_messages.s
# Rules - BASIC and KERNAL
c64/kernal/OUT.BIN: src/preprocess c64/kernal/*.s
src/preprocess -d c64/kernal -l e4d3 -h ffff
build/basic/packed_messages.s: $(TOOL_COMPRESS_TEXT)
@mkdir -p build/basic
$(TOOL_COMPRESS_TEXT) > build/basic/packed_messages.s
c64/basic/OUT.BIN: src/preprocess c64/basic/*.s c64/basic/packed_messages.s
src/preprocess -d c64/basic -l a000 -h e4d2
.PRECIOUS: build/basic_%/OUT.BIN
build/basic_%/OUT.BIN: Ophis $(TOOLS_LIST) $(SRC_BASIC_$*) build/basic/packed_messages.s
@mkdir -p build/basic_$*
@rm -f build/basic_$*/*
@for SRC in $(SRC_BASIC_$*); do \
ln -s ../../$$SRC build/basic_$*/$$(basename $$SRC); \
done
@ln -s ../../build/basic/packed_messages.s build/basic_$*/packed_messages.s
$(TOOL_PREPROCESS) -d build/basic_$* -l a000 -h e4d2
testremote: newkern newbasic
x64 -kernal newkern -basic newbasic -remotemonitor
.PRECIOUS: build/kernal_%/OUT.BIN
build/kernal_%/OUT.BIN: Ophis $(TOOLS_LIST) $(SRC_KERNAL_$*)
@mkdir -p build/kernal_$*
@rm -f build/kernal_$*/*
@for SRC in $(SRC_KERNAL_$*); do \
ln -s ../../$$SRC build/kernal_$*/$$(basename $$SRC); \
done
$(TOOL_PREPROCESS) -d build/kernal_$* -l e4d3 -h ffff
test: newkern newbasic
x64 -kernal newkern -basic newbasic -8 empty.d64
.PRECIOUS: build/newrom_%
build/newrom_%: build/basic_%/OUT.BIN build/kernal_%/OUT.BIN
cat build/basic_$*/OUT.BIN build/kernal_$*/OUT.BIN > build/newrom_$*
testm65: newc65
m65 -b ../mega65-core/bin/mega65r1.bit -k ../mega65-core/bin/KICKUP.M65 -R newc65 -4
.PRECIOUS: build/newkern_%
build/newkern_%: build/newrom_% Makefile
dd if=build/newrom_$* bs=8192 count=1 skip=2 of=build/newkern_$*
testsimilarity: newkern newbasic src/similarity
src/similarity kernal newrom
src/similarity basic newrom
.PRECIOUS: build/newbasic_%
build/newbasic_%: build/newrom_% Makefile
dd if=build/newrom_$* bs=8192 count=1 skip=0 of=build/newbasic_$*
# Rules - platform 'Mega 65' specific
build/newc65: build/newkern_mega65 build/newbasic_mega65 build/chargen Makefile
dd if=/dev/zero bs=4096 count=10 of=build/newc65
cat build/newbasic_mega65 build/chargen build/chargen build/newkern_mega65 >> build/newc65
dd if=/dev/zero bs=65536 count=1 of=build/basic/padding
cat build/basic/padding >> build/newc65
# Rules - tests
test: build/newkern_generic build/newbasic_generic
x64 -kernal build/newkern_generic -basic build/newbasic_generic -8 empty.d64
testremote: build/newkern_generic build/newbasic_generic
x64 -kernal build/newkern-generic -basic build/newbasic-generic -remotemonitor
testm65: build/newc65
m65 -b ../mega65-core/bin/mega65r1.bit -k ../mega65-core/bin/KICKUP.M65 -R build/newc65 -4
testsimilarity: build/newrom_generic $(TOOL_SIMILARITY)
$(TOOL_SIMILARITY) kernal build/newrom_generic
$(TOOL_SIMILARITY) basic build/newrom_generic
+117
View File
@@ -0,0 +1,117 @@
# New features
Here are the features of the Open ROMs not found in the original ROMs from the 80s:
* 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
* extended `LOAD` command
* start/end addresses are displayed, in the Final cartridge style
* command with just the file name tries to use the last device if it's number seems sane; otherwise uses 8
* secondary address over 255 is considered a start address
* DOS wedge (direct mode only) - `@<drive_number>`, `@<command>`, `@$`, `@$<params>`, `@`
NOTE: extra features and their syntax can change in the future!
# Features missing
The following ROM features are currently missing:
* most BASIC commands
* BASIC variables
* BASIC expression parsing
* floating point routines
* tape support
* RS-232 support
* warm start (RUN/STOP + RESTORE) - NMI is not implemented at all
* breaking Kernal routines with RUN/STOP key
Features currently being worked on:
* IEC support needs more testing ang bugfixing; alternative drive ROMs (JiffyDOS, DolphinDOS, etc) usually don't work with current implementation, `@$` leaves the drive led on, most likely other problems can be found
# API status
Status of the various APIs and variables from the original ROMs
## Page 0
TODO
## Pages 2 & 3
TODO
## BASIC
TODO
## 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` | PARTIAL | at least PAL/NTSC detection is missing |
| `$FF84` | `IOINIT` | PARTIAL | at least SID volume handling is missing |
| `$FF87` | `RAMTAS` | DONE | |
| `$FF8A` | `RESTOR` | PARTIAL | CBINV, NMINV, and USRCMD missing |
| `$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` | NOT 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` | PARTIAL | most likely incompleete, @$ doesn't end properly |
| `$FFC6` | `CHKIN` | DONE | |
| `$FFC9` | `CHKOUT` | PARTIAL | |
| `$FFCC` | `CLRCHN` | DONE | |
| `$FFCF` | `CHRIN` | PARTIAL | |
| `$FFD2` | `CHROUT` | PARTIAL | |
| `$FFD5` | `LOAD` | PARTIAL | no VERIFY support yet |
| `$FFD8` | `SAVE` | NOT DONE | |
| `$FFDB` | `SETTIM` | NOT DONE | |
| `$FFDE` | `RDTIM` | NOT DONE | |
| `$FFE1` | `STOP` | PARTIAL | no connection with UDTIM |
| `$FFE4` | `GETIN` | PARTIAL | only some devices supported |
| `$FFE7` | `CLALL` | DONE | |
| `$FFEA` | `UDTIM` | NOT DONE | |
| `$FFED` | `SCREEN` | DONE | |
| `$FFF0` | `PLOT` | NOT DONE | |
| `$FFF3` | `IOBASE` | DONE | |
<br />
### Unofficial Kernal locations
TODO
+14
View File
@@ -0,0 +1,14 @@
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 ROMs from different builds/versions (again, CHARGEN is an exception).
- The generic ROM set should be compatible with any C64-compatible machine; platform-specific ROMs might not work on other platforms.
Have fun!
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
View File
Binary file not shown.
BIN
View File
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
+63
View File
@@ -0,0 +1,63 @@
;; Kernal error codes - returned in the A register
;; Described in 'Commodore 64 Programmer's Reference Guide', page 306
.alias K_ERR_ROUTINE_TERMINATED $00
.alias K_ERR_TOO_MANY_OPEN_FILES $01
.alias K_ERR_FILE_ALREADY_OPEN $02
.alias K_ERR_FILE_NOT_OPEN $03
.alias K_ERR_FILE_NOT_FOUND $04
.alias K_ERR_DEVICE_NOT_FOUND $05
.alias K_ERR_FILE_NOT_INPUT $06
.alias K_ERR_FILE_NOT_OUTPUT $07
.alias K_ERR_FILE_NAME_MISSING $08
.alias K_ERR_ILLEGAL_DEVICE_NUMBER $09
.alias K_ERR_TOP_MEM_RS232 $F0
;; Kernal status codes for READST routine (IOSTATUS)
;; Described in 'Commodore 64 Programmer's Reference Guide', page 292
;; For IEC devices
.alias K_STS_TIMEOUT_WRITE $01
.alias K_STS_TIMEOUT_READ $02
.alias K_STS_EOI $40
.alias K_STS_DEVICE_NOT_FOUND $80
;; For tape deck
.alias K_STS_SHORT_BLOCK $04
.alias K_STS_LONG_BLOCK $08
.alias K_STS_READ_ERROR $10
.alias K_STS_CHECKSUM_ERROR $20
.alias K_STS_END_OF_FILE $40
.alias K_STS_END_OF_TAPE $80
;; BASIC error codes, taken from http://sta.c64.org/cbm64baserr.html
.alias B_ERR_TOO_MANY_FILES $01
.alias B_ERR_FILE_OPEN $02
.alias B_ERR_FILE_NOT_OPEN $03
.alias B_ERR_FILE_NOT_FOUND $04
.alias B_ERR_DEVICE_NOT_PRESENT $05
.alias B_ERR_NOT_INPUT_FILE $06
.alias B_ERR_NOT_OUTPUT_FILE $07
.alias B_ERR_MISSING_FILENAME $08
.alias B_ERR_ILLEGAL_DEVICE_NUMBER $09
.alias B_ERR_NEXT_WITHOUT_FOR $0A
.alias B_ERR_SYNTAX $0B
.alias B_ERR_RETURN_WITHOUT_GOSUB $0C
.alias B_ERR_OUT_OF_DATA $0D
.alias B_ERR_ILLEGAL_QUANTITY $0E
.alias B_ERR_OVERFLOW $0F
.alias B_ERR_OUT_OF_MEMORY $10
.alias B_ERR_UNDEFD_STATEMENT $11
.alias B_ERR_BAD_SUBSCRIPT $12
.alias B_ERR_REDIMD_ARRAY $13
.alias B_ERR_DIVISION_BY_ZERO $14
.alias B_ERR_ILLEGAL_DIRECT $15
.alias B_ERR_TYPE_MISMATCH $16
.alias B_ERR_STRING_TOO_LONG $17
.alias B_ERR_FILE_DATA $18
.alias B_ERR_FORMULA_TOO_COMPLEX $19
.alias B_ERR_CANT_CONTINUE $1A
.alias B_ERR_UNDEFD_FUNCTION $1B
.alias B_ERR_VERIFY $1C
.alias B_ERR_LOAD $1D
.alias B_ERR_BREAK $1E
+154
View File
@@ -0,0 +1,154 @@
;;
;; Names of hardware registers - slightly modified names from C64 Programmer's Reference Guide
;;
;; CPU memory registers
.alias CPU_D6510 $0000
.alias CPU_R6510 $0001
;; VIC-II registers
.alias VIC_SP0X $D000
.alias VIC_SP0Y $D001
.alias VIC_SP1X $D002
.alias VIC_SP1Y $D003
.alias VIC_SP2X $D004
.alias VIC_SP2Y $D005
.alias VIC_SP3X $D006
.alias VIC_SP3Y $D007
.alias VIC_SP4X $D008
.alias VIC_SP4Y $D009
.alias VIC_SP5X $D00A
.alias VIC_SP5Y $D00B
.alias VIC_SP6X $D00C
.alias VIC_SP6Y $D00D
.alias VIC_SP7X $D00E
.alias VIC_SP7Y $D00F
.alias VIC_MSIGX $D010
.alias VIC_SCROLLY $D011
.alias VIC_RASTER $D012
.alias VIC_LPENX $D013
.alias VIC_LPENY $D014
.alias VIC_SPENA $D015
.alias VIC_SCROLX $D016
.alias VIC_YXPAND $D017
.alias VIC_YMCSB $D018
.alias VIC_IRQ $D019
.alias VIC_IRQMSK $D01A
.alias VIC_SPBGPR $D01B
.alias VIC_SPMC $D01C
.alias VIC_XXPAND $D01D
.alias VIC_SPSPCL $D01E
.alias VIC_SPBGCL $D01F
.alias VIC_EXTCOL $D020
.alias VIC_BGCOL0 $D021
.alias VIC_BGCOL1 $D022
.alias VIC_BGCOL2 $D023
.alias VIC_BGCOL3 $D024
.alias VIC_SPMC0 $D025
.alias VIC_SPMC1 $D026
.alias VIC_SP0COL $D027
.alias VIC_SP1COL $D028
.alias VIC_SP2COL $D029
.alias VIC_SP3COL $D02A
.alias VIC_SP4COL $D02B
.alias VIC_SP5COL $D02C
.alias VIC_SP6COL $D02D
.alias VIC_SP7COL $D02E
;; SID #1 registers
.alias SID1_FRELO1 $D400
.alias SID1_FREHI1 $D401
.alias SID1_PWLO1 $D402
.alias SID1_PWHI1 $D403
.alias SID1_VCREG1 $D404
.alias SID1_ATDCY1 $D405
.alias SID1_SUREL1 $D406
.alias SID1_FRELO2 $D407
.alias SID1_FREHI2 $D408
.alias SID1_PWLO2 $D409
.alias SID1_PWHI2 $D40A
.alias SID1_VCREG2 $D40B
.alias SID1_ATDCY2 $D40C
.alias SID1_SUREL2 $D40D
.alias SID1_FRELO3 $D40E
.alias SID1_FREHI3 $D40F
.alias SID1_PWLO3 $D410
.alias SID1_PWHI3 $D411
.alias SID1_VCREG3 $D412
.alias SID1_ATDCY3 $D413
.alias SID1_SUREL3 $D414
.alias SID1_CUTLO $D415
.alias SID1_CUTHI $D416
.alias SID1_RESON $D417
.alias SID1_SIGVOL $D418
.alias SID1_POTX $D419
.alias SID1_POTY $D41A
.alias SID1_RANDOM $D41B
.alias SID1_ENV3 $D41C
;; SID #2, #3, #4 registers
.alias SID2_SIGVOL $D438
.alias SID3_SIGVOL $D458
.alias SID4_SIGVOL $D478
;; CIA #1 registers
.alias CIA1_PRA $DC00
.alias CIA1_PRB $DC01
.alias CIA1_DDRA $DC02
.alias CIA1_DDRB $DC03
.alias CIA1_TIMALO $DC04
.alias CIA1_TIMAHI $DC05
.alias CIA1_TIMBLO $DC06
.alias CIA1_TIMBHI $DC07
.alias CIA1_TODTEN $DC08
.alias CIA1_TODSEC $DC09
.alias CIA1_TODMIN $DC0A
.alias CIA1_TODHRS $DC0B
.alias CIA1_SDR $DC0C
.alias CIA1_ICR $DC0D
.alias CIA1_CRA $DC0E
.alias CIA1_CRB $DC0F
;; CIA #2 registers
.alias CIA2_PRA $DD00 ; VIC bank switching and IEC port
.alias CIA2_PRB $DD01
.alias CIA2_DDRA $DD02
.alias CIA2_DDRB $DD03
.alias CIA2_TIMALO $DD04
.alias CIA2_TIMAHI $DD05
.alias CIA2_TIMBLO $DD06
.alias CIA2_TIMBHI $DD07
.alias CIA2_TODTEN $DD08
.alias CIA2_TODSEC $DD09
.alias CIA2_TODMIN $DD0A
.alias CIA2_TODHRS $DD0B
.alias CIA2_SDR $DD0C
.alias CIA2_ICR $DD0D
.alias CIA2_CRA $DD0E
.alias CIA2_CRB $DD0F
;; CIA #2 helper bits - IEC bus
.alias BIT_CIA2_PRA_ATN_OUT $08 ; 1 - low (pulled), 0 - high (released)
.alias BIT_CIA2_PRA_CLK_OUT $10 ; 1 - low (pulled), 0 - high (released)
.alias BIT_CIA2_PRA_DAT_OUT $20 ; 1 - low (pulled), 0 - high (released)
.alias BIT_CIA2_PRA_CLK_IN $40 ; 0 - low (pulled), 1 - high (released)
.alias BIT_CIA2_PRA_DAT_IN $80 ; 0 - low (pulled), 1 - high (released)
+99
View File
@@ -0,0 +1,99 @@
;;
;; Names of ZP and low memory locations
;; (https://www.c64-wiki.com/wiki/Zeropage)
;;
;; $00-$01 - 6502 CPU registers are here
;;
;; Page 0 - BASIC area ($02-$8F)
;;
.alias TXTTAB $2B
;;
;; Page 0 - Kernal area ($90-$FF)
;;
.alias IOSTATUS $90
.alias STKEY $91 ; Keys down clears bits. STOP - bit 7, C= - bit 6, SPACE - bit 4, CTRL - bit 2
.alias VERCK $93 ; 0 = LOAD, 1 = VERIVY
.alias C3PO $94 ; flag - is BSOUR content valid
.alias BSOUR $95 ; serial bus buffered output byte
.alias LDTND $98 ; number of entries in LAT / FAT / SAT tables
.alias DFLTN $99
.alias DFLTO $9A
.alias MSGFLG $9D ; bit 6 = error messages, bit 7 = control message
.alias TIME $A0 ; $A0-$A2, jiffy clock
.alias IEC_TMP1 $A3 ; temporary variable for tape and IEC
.alias IEC_TMP2 $A4 ; temporary variable for tape and IEC
;; 2-byte location below seems to be a good place for temporary storage,
;; it seems used for timing during tape reads only - see:
;; - 'C64 Programmer's Reference Guide', page 314
;; - 'Compute's Mapping the Commodore 64', page 32
.alias CMP0 $B0 ; $B0-$B1
.alias FNLEN $B7 ; current file name length
.alias FNADDR $BB ; $BB-$BC, current file name pointer
.alias STAL $C1 ; $C1-$C2 LOAD/SAVE start address
;;
;; Other low memory addresses
;;
.alias BUF $200 ; $200-$250 (81 bytes), BASIC line editor input buffer
;; Kernal tables for opened files, 10 entries each
.alias LAT $259 ; logical file numbers
.alias FAT $263 ; device numbers
.alias SAT $26D ; secondary addresses
.alias MEMSTR $281
.alias MEMSIZ $283 ; NOTE: Mapping the 64 erroniously has the hex as $282, while the DEC is correct
.alias HIBASE $288 ; high byte of start of screen
.alias RSSTAT $297 ; RS-232 status
.alias PALNTSC $2A6 ; 0 = NTSC, 1 = PAL
;; Registers for SYS call
.alias SAREG $30C
.alias SXREG $30D
.alias SYREG $30E
.alias SPREG $30F
.alias USRPOK $310 ; JMP instruction
.alias USRADD $311 ; $311 - $312
;; Kernal vectors - interrupts
.alias CINV $314
.alias CBINV $316
.alias NMINV $318
;; Kernal vectors - routines
.alias IOPEN $31A
.alias ICLOSE $31C
.alias ICHKIN $31E
.alias ICKOUT $320
.alias ICLRCH $322
.alias IBASIN $324
.alias IBSOUT $326
.alias ISTOP $328
.alias IGETIN $32A
.alias ICLALL $32C
.alias USRCMD $32E
.alias ILOAD $330
.alias ISAVE $331
.alias TBUFFR $33C ; $33C-$3FB, tape buffer
View File
Whitespace-only changes.
+41
View File
@@ -0,0 +1,41 @@
;; Kernal jump table
.alias JCINT $FF81
.alias JIOINIT $FF84
.alias JRAMTAS $FF87
.alias JRESTOR $FF8A
.alias JVECTOR $FF8D
.alias JSETMSG $FF90
.alias JSECOND $FF93
.alias JTKSA $FF96
.alias JMEMTOP $FF99
.alias JMEMBOT $FF9C
.alias JSCNKEY $FF9F
.alias JSETTMO $FFA2
.alias JACPTR $FFA5
.alias JCIOUT $FFA8
.alias JUNTLK $FFAB
.alias JUNLSN $FFAE
.alias JLISTEN $FFB1
.alias JTALK $FFB4
.alias JREADST $FFB7
.alias JSETFLS $FFBA
.alias JSETNAM $FFBD
.alias JOPEN $FFC0
.alias JCLOSE $FFC3
.alias JCHKIN $FFC6
.alias JCKOUT $FFC9
.alias JCLRCHN $FFCC
.alias JCHRIN $FFCF
.alias JCHROUT $FFD2
.alias JLOAD $FFD5
.alias JSAVE $FFD8
.alias JSETTIM $FFDB
.alias JRDTIM $FFDE
.alias JSTOP $FFE1
.alias JGETIN $FFE4
.alias JCLALL $FFE7
.alias JUDTIM $FFEA
.alias JSCREEN $FFED
.alias JPLOT $FFF0
.alias JIOBASE $FFF3
+3 -24
View File
@@ -52,22 +52,13 @@
.alias memmove_dst $6b
.alias memmove_size $6d
.alias TXTTAB $2B
.alias IOSTATUS $90
; Keys down clears bits. STOP=bit 7, C= bit 6, SPACE bit 4, CTRL bit 2
.alias BUCKYSTATUS $91
.alias load_or_verify_flag $93
.alias current_file_num $98
.alias input_device_number $99
; bit 6 = error messages, bit 7 = control messages
.alias kernal_message_control_flags $9d
.alias jiffy_clock_24bits $a0
.alias cassette_buffer_bytes_used $A6
.alias load_or_scroll_temp_pointer $AC
;; We also use the following for temp colour pointer when scrolling
.alias load_save_verify_end_address $AE
.alias cassette_buffer_ptr $B2
.alias current_filename_length $B7
.alias current_logical_filenum $B8
.alias current_secondary_address $B9
.alias current_device_number $BA
@@ -100,15 +91,12 @@
.alias rs232_rx_buffer_ptr $F7
.alias rs232_tx_buffer_ptr $F9
.alias basic_input_buffer $0200
.alias basic_input_buffer BUF
; "Compute's Mapping the 64" book
.alias keyboard_buffer $0277
.alias MEMSTR $0281
.alias MEMSIZ $0283 ; NOTE: Mapping the 64 erroniously has the hex as $282, while the DEC is correct
.alias text_colour $0286 ; p55
.alias colour_under_cursor $0287 ; p56
.alias HIBASE $0288 ; p56 (high byte of start of screen)
.alias key_buffer_size $0289 ; p57
;; 0 = cursor keys, insert, delete and space repeat, but nothing else
@@ -124,14 +112,6 @@
.alias keyboard_decoding_ptr $028F
.alias enable_case_switch $0291
.alias screen_scroll_disable $0292
.alias pal_or_ntsc $02A6
;; Registers for SYS call
.alias sys_reg_a $30c
.alias sys_reg_x $30d
.alias sys_reg_y $30e
.alias sys_reg_p $30f
.alias sys_jmp $310
;; 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
@@ -144,4 +124,3 @@
.alias poke_under_roms tiny_nmi_handler+poke_under_roms_routine-tiny_nmi_handler_routine
.alias memmap_allram tiny_nmi_handler+memmap_allram_routine-tiny_nmi_handler_routine
.alias memmap_normal tiny_nmi_handler+memmap_normal_routine-tiny_nmi_handler_routine
@@ -0,0 +1,9 @@
;; Target-specific hooks
.macro TARGET_HOOK_BANNER
.byte $05, " OPEN ROMS, ", $00
.macend
+41
View File
@@ -0,0 +1,41 @@
;; Target-specific hooks
.macro TARGET_HOOK_BANNER
;; New banner from Retrofan
.byte $9a, $12, $20, $20, $7f, $a9, $20, $20, $1f, $20, $9a, $20, $20, $20
.byte $20, $1f, $20, $9a, $a9, $20, $20, $20, $92, $a1, $1f, $12, $20, $9a, $a9, $20
.byte $20, $20, $7f, $1f, $20, $20, $9a, $a3, $a3, $a3, $a3, $a3, $a3, $a3, $1f, $20
.byte $20, $20, $20, $05, $92, $4d, $45, $47, $41, $9a, $12, $20, $20, $20, $20, $20
.byte $20, $1f, $20, $9a, $20, $20, $92, $a2, $bb, $1f, $12, $20, $9a, $20, $20, $92
.byte $ac, $a2, $a2, $1f, $12, $20, $9a, $20, $20, $1f, $20, $9a, $20, $20, $1f, $20
.byte $20, $1e, $a3, $a3, $a3, $a3, $a3, $a3, $1f, $20, $20, $20, $20, $05, $92, $42
.byte $41, $53, $49, $43, $9a, $12, $20, $20, $92, $7f, $a9, $12, $20, $20, $1f, $20
.byte $9a, $20, $20, $a2, $92, $be, $1f, $12, $20, $9a, $20, $20, $92, $bc, $12, $20
.byte $20, $1f, $20, $9a, $20, $20, $20, $20, $20, $1f, $20, $20, $9e, $a3, $a3, $a3
.byte $a3, $a3, $1f, $20, $20, $20, $20, $05, $92, $2d, $2d, $2d, $2d, $2d, $2d, $9a
.byte $12, $20, $20, $1f, $20, $20, $9a, $20, $20, $1f, $20, $9a, $20, $20, $20, $20
.byte $1f, $20, $9a, $20, $20, $20, $20, $20, $1f, $20, $9a, $20, $20, $1f, $20, $9a
.byte $20, $20, $1f, $20, $20, $96, $a3, $a3, $a3, $a3, $1f
.byte $92, $0D, $0D, $05, $00
;; Original Deft-supplied banner
;; .byte $9A,$12,$A3,$A3,$A3,$A3,$A3,$A3,$DF,$9B,$92,$20,$05,$12,$A0,$A0
;; .byte $DF,$9B,$92,$20,$05,$12,$A0,$A0,$DF,$9B,$92,$20,$05,$12,$A0,$A0
;; .byte $DF,$9B,$92,$20,$05,$12,$A0,$A0,$DF,$9A,$92,$20,$05,$20,$20,$20
;; .byte $4D,$20,$45,$20,$47,$20,$41,$0D,$99,$12,$A3,$A3,$A3,$A3,$A3,$A3
;; .byte $A3,$DF,$92,$7F,$12,$CD,$CD,$DF,$92,$7F,$12,$DF,$05,$92,$20,$20
;; .byte $99,$7F,$12,$DF,$05,$92,$20,$20,$99,$7F,$12,$DF,$92,$7F,$12,$DF
;; .byte $05,$92,$20,$20,$99,$42,$20,$41,$20,$53,$20,$49,$20,$43,$0D,$9E
;; .byte $12,$A3,$A3,$A3,$A3,$A3,$A3,$A3,$A3,$DF,$9B,$92,$7F,$12,$DF,$92
;; .byte $7F,$12,$DF,$92,$7F,$12,$CD,$05,$92,$20,$20,$9B,$7F,$12,$CD,$92
;; .byte $7F,$12,$DF,$92,$7F,$12,$CD,$92,$7F,$12,$DF,$9A,$92,$20,$05,$20
;; .byte $9A,$2D,$2D,$2D,$2D,$2D,$2D,$2D,$0D,$96,$12,$A3,$A3,$A3,$A3,$A3
;; .byte $A3,$A3,$A3,$A3,$DF,$9A,$92,$7F,$12,$DF,$92,$7F,$9B,$20,$9A,$7F
;; .byte $12,$A0,$A0,$9B,$92,$20,$9A,$7F,$12,$A0,$A0,$9B,$92,$20,$9A,$7F
;; .byte $12,$DF,$92,$7F,$9B,$20,$9A,$20,$9B,"0.2.0.0",$0D
;; .byte $0D,$05,$92,$00
.macend
@@ -0,0 +1,9 @@
;; Target-specific hooks
.macro TARGET_HOOK_BANNER
.byte $05, " OPEN ROMS FOR ULTIMATE 64", $0D, $0D, " ", $00
.macend
+1 -1
View File
@@ -20,7 +20,7 @@ print_string_loop:
lda (temp_string_ptr),y
beq print_string_end
jsr $FFD2 ; KERNAL CHROUT
jsr via_IBSOUT
txa
tay
+2 -36
View File
@@ -15,41 +15,7 @@ basic_cold_start:
; Used 217 bytes
startup_banner:
;; New banner from Retrofan
.byte $9a, $12, $20, $20, $7f, $a9, $20, $20, $1f, $20, $9a, $20, $20, $20
.byte $20, $1f, $20, $9a, $a9, $20, $20, $20, $92, $a1, $1f, $12, $20, $9a, $a9, $20
.byte $20, $20, $7f, $1f, $20, $20, $9a, $a3, $a3, $a3, $a3, $a3, $a3, $a3, $1f, $20
.byte $20, $20, $20, $05, $92, $4d, $45, $47, $41, $9a, $12, $20, $20, $20, $20, $20
.byte $20, $1f, $20, $9a, $20, $20, $92, $a2, $bb, $1f, $12, $20, $9a, $20, $20, $92
.byte $ac, $a2, $a2, $1f, $12, $20, $9a, $20, $20, $1f, $20, $9a, $20, $20, $1f, $20
.byte $20, $1e, $a3, $a3, $a3, $a3, $a3, $a3, $1f, $20, $20, $20, $20, $05, $92, $42
.byte $41, $53, $49, $43, $9a, $12, $20, $20, $92, $7f, $a9, $12, $20, $20, $1f, $20
.byte $9a, $20, $20, $a2, $92, $be, $1f, $12, $20, $9a, $20, $20, $92, $bc, $12, $20
.byte $20, $1f, $20, $9a, $20, $20, $20, $20, $20, $1f, $20, $20, $9e, $a3, $a3, $a3
.byte $a3, $a3, $1f, $20, $20, $20, $20, $05, $92, $2d, $2d, $2d, $2d, $2d, $2d, $9a
.byte $12, $20, $20, $1f, $20, $20, $9a, $20, $20, $1f, $20, $9a, $20, $20, $20, $20
.byte $1f, $20, $9a, $20, $20, $20, $20, $20, $1f, $20, $9a, $20, $20, $1f, $20, $9a
.byte $20, $20, $1f, $20, $20, $96, $a3, $a3, $a3, $a3, $1f
.byte $92, $0D, $0D, $05
.byte $00
;; Original Deft-supplied banner
;; .byte $9A,$12,$A3,$A3,$A3,$A3,$A3,$A3,$DF,$9B,$92,$20,$05,$12,$A0,$A0
;; .byte $DF,$9B,$92,$20,$05,$12,$A0,$A0,$DF,$9B,$92,$20,$05,$12,$A0,$A0
;; .byte $DF,$9B,$92,$20,$05,$12,$A0,$A0,$DF,$9A,$92,$20,$05,$20,$20,$20
;; .byte $4D,$20,$45,$20,$47,$20,$41,$0D,$99,$12,$A3,$A3,$A3,$A3,$A3,$A3
;; .byte $A3,$DF,$92,$7F,$12,$CD,$CD,$DF,$92,$7F,$12,$DF,$05,$92,$20,$20
;; .byte $99,$7F,$12,$DF,$05,$92,$20,$20,$99,$7F,$12,$DF,$92,$7F,$12,$DF
;; .byte $05,$92,$20,$20,$99,$42,$20,$41,$20,$53,$20,$49,$20,$43,$0D,$9E
;; .byte $12,$A3,$A3,$A3,$A3,$A3,$A3,$A3,$A3,$DF,$9B,$92,$7F,$12,$DF,$92
;; .byte $7F,$12,$DF,$92,$7F,$12,$CD,$05,$92,$20,$20,$9B,$7F,$12,$CD,$92
;; .byte $7F,$12,$DF,$92,$7F,$12,$CD,$92,$7F,$12,$DF,$9A,$92,$20,$05,$20
;; .byte $9A,$2D,$2D,$2D,$2D,$2D,$2D,$2D,$0D,$96,$12,$A3,$A3,$A3,$A3,$A3
;; .byte $A3,$A3,$A3,$A3,$DF,$9A,$92,$7F,$12,$DF,$92,$7F,$9B,$20,$9A,$7F
;; .byte $12,$A0,$A0,$9B,$92,$20,$9A,$7F,$12,$A0,$A0,$9B,$92,$20,$9A,$7F
;; .byte $12,$DF,$92,$7F,$9B,$20,$9A,$20,$9B,"0.2.0.0",$0D
;; .byte $0D,$05,$92,$00
`TARGET_HOOK_BANNER
;; Work out free bytes, and display
jsr basic_do_new
@@ -63,7 +29,7 @@ startup_banner:
jsr print_integer
lda #$20
jsr $ffd2
jsr via_IBSOUT
;; Print the rest of the start up message
ldx #34
+5 -5
View File
@@ -7,9 +7,9 @@ basic_do_error:
;; Print ? at start
lda #$0d
jsr $ffd2
jsr via_IBSOUT
lda #$3f
jsr $ffd2
jsr via_IBSOUT
;; Print main part of error message
pla
@@ -18,7 +18,7 @@ basic_do_error:
;; Print ERROR at end
lda #$20
jsr $ffd2
jsr via_IBSOUT
ldx #33
jsr print_packed_message
@@ -27,9 +27,9 @@ basic_do_error:
;; XXX print line number if not in direct mode
lda #$0d
jsr $ffd2
jsr via_IBSOUT
lda #$0d
jsr $ffd2
jsr via_IBSOUT
;; Reset stack, and go back to main loop
ldx #$fe
+22 -5
View File
@@ -29,7 +29,7 @@ no_space_to_skip:
basic_execute_statement:
;; Check for RUN/STOP
lda BUCKYSTATUS
lda STKEY
bpl basic_do_break
;; Skip over any white space and :
@@ -80,9 +80,9 @@ basic_execute_statement:
;; Now consume the character
jsr basic_consume_character
rts
rts
not_a_token:
not_a_token:
;; Space, which we can also just ignore
cmp #$20
beq basic_skip_char
@@ -93,11 +93,28 @@ not_a_token:
cmp #$3a
beq basic_skip_char
;; START wedge support
;; Are we in direct mode?
;; DOS Wedge is a hacky solution (inelegant, but convenient),
;; BASIC programmers should implement communication with drives
;; the standard way, handling channels properly. Besides,
;; current implementation does not support characters under ROM
ldx basic_current_line_number+1
cpx #$ff
bne +
;; We are in direct mode, allow wedge to handle '@' sign
;; XXX Maybe it should be allowed only as the first command?
cmp #$40
bne +
jsr basic_consume_character
jmp wedge_dos
*
;; END wedge support
;; If all else fails, it's a syntax error
jmp do_SYNTAX_error
jmp basic_main_loop
basic_skip_char:
jsr basic_consume_character
jmp basic_execute_statement
+1 -1
View File
@@ -52,7 +52,7 @@ rsl_l1: lda $0200,x
*
;; Do printing of the new line
lda #$0d
jsr $ffd2
jsr via_IBSOUT
;; Ignore empty lines
lda tokenise_work1
+1 -1
View File
@@ -17,7 +17,7 @@ basic_do_break:
*
lda #$0d
jsr $ffd2
jsr via_IBSOUT
cmd_end:
jmp basic_main_loop
+12 -9
View File
@@ -22,10 +22,16 @@ list_loop:
jmp basic_main_loop
list_more_lines:
lda BUCKYSTATUS
lda STKEY
bmi +
jmp basic_do_break
*
jsr list_single_line
;; Now link to the next line
jsr basic_find_next_line
jmp list_loop
list_single_line: ; entry point needed by DOS wedge
;; Print line number
ldy #3
jsr peek_under_roms
@@ -36,7 +42,7 @@ list_more_lines:
pla
jsr print_integer
lda #$20
jsr $ffd2
jsr via_IBSOUT
;; Iterate through printing out the line
;; contents
@@ -105,19 +111,16 @@ list_not_rem:
bne list_print_loop
list_is_literal:
jsr $ffd2
jsr via_IBSOUT
iny
bne list_print_loop
list_end_of_line:
;; Clear reverse flag
lda #$92
jsr $ffd2
jsr via_IBSOUT
;; Print end of line
lda #$0d
jsr $ffd2
jsr via_IBSOUT
rts
;; Now link to the next line
jsr basic_find_next_line
jmp list_loop
+51 -9
View File
@@ -11,9 +11,18 @@ cmd_load:
;; middle of a program. For safety, we do.
jsr basic_do_clr
;; Setup Kernal to print control messages or not
lda #$80 ; display control messages and omit error messages
ldx basic_current_line_number+1
cpx #$FF
beq +
lda #$00 ; direct mode - don't display anything
*
jsr JSETMSG
;; Set filename and length
lda #$00
sta current_filename_length
sta FNLEN
;; Without tape support, LOAD must have a filename
;; (This also skips any leading spaces)
@@ -34,7 +43,7 @@ cmd_load:
;; Now search for end of line or closing quote
;; so that we know the length of the filename
getting_filename:
getting_filename:
jsr basic_fetch_and_consume_character
cmp #$22
beq got_filename
@@ -44,19 +53,52 @@ getting_filename:
jmp got_filename
*
inc current_filename_length
inc FNLEN
jmp getting_filename
got_filename:
got_filename:
;; Try to load an IEC file
lda #0 ; use supplied load address, not the one from the file
;; Now fetch the file number, start from the default one
jsr select_device
stx current_device_number
jsr injest_comma
bcs got_devicenumber
jsr basic_parse_line_number
lda basic_line_number+1
bne do_ILLEGAL_QUANTITY_error
lda basic_line_number+0
sta current_device_number
got_devicenumber:
;; Now fetch the secondary address
lda #$00
sta current_secondary_address
lda #$00 ; LOAD not verify
ldx #<$0801 ; LOAD address = $0801
jsr injest_comma
bcs got_secondaryaddress
jsr basic_parse_line_number
lda basic_line_number+1
bne +
lda basic_line_number+0
sta current_secondary_address
jmp got_secondaryaddress
*
;; Second parameter is above 255, this can't be a secondary address
;; Use it as load address instead
;; XXX temporary syntax, it would be better to use something
;; XXX like 'LOAD"FILE",8 TO 49152'
ldx basic_line_number+0
ldy basic_line_number+1
bne got_loadaddress
got_secondaryaddress:
ldx #<$0801
ldy #>$0801
jsr $ffd5
got_loadaddress:
lda #$00 ; LOAD not verify
jsr via_ILOAD
bcc +
;; A = KERNAL error code, which also almost match
+1 -1
View File
@@ -41,7 +41,7 @@ basic_do_new:
;; (same story), expression value cache?
sec ; Read, not write value
jsr $ff99 ; KERNAL MEMTOP routine
jsr JMEMTOP
cpx #$80
beq +
lda #>$f7ff
+9 -9
View File
@@ -10,22 +10,22 @@ cmd_sys:
jsr basic_parse_line_number
;; setup call
lda #$4c ;JMP
sta sys_jmp
lda #$4C ;JMP
sta USRPOK
lda basic_line_number+0
sta sys_jmp+1
sta USRADD+0
lda basic_line_number+1
sta sys_jmp+2
sta USRADD+1
;; Setup the register values
lda sys_reg_p
lda SPREG
pha
ldy sys_reg_y
ldx sys_reg_x
lda sys_reg_a
ldy SYREG
ldx SXREG
lda SAREG
plp
;; Call the routine.
jsr sys_jmp
jsr USRPOK
jmp basic_execute_statement
+20
View File
@@ -0,0 +1,20 @@
;; Consummes a comma in a BASIC code, C set for no coma found
injest_comma:
jsr basic_fetch_and_consume_character
cmp #$2C ; comma character
beq injest_comma_found
cmp #$20
beq injest_comma ; space, can always be skipped
;; not found
jsr basic_unconsume_character
sec
rts
injest_comma_found:
clc
rts
-126
View File
@@ -1,126 +0,0 @@
packed_message_chars:
.byte $45 ; 'E' = $1 (nybl)
.byte $54 ; 'T' = $2 (nybl)
.byte $4F ; 'O' = $3 (nybl)
.byte $4E ; 'N' = $4 (nybl)
.byte $49 ; 'I' = $5 (nybl)
.byte $52 ; 'R' = $6 (nybl)
.byte $41 ; 'A' = $7 (nybl)
.byte $4C ; 'L' = $8 (nybl)
.byte $53 ; 'S' = $9 (nybl)
.byte $44 ; 'D' = $a (nybl)
.byte $46 ; 'F' = $b (nybl)
.byte $55 ; 'U' = $c (nybl)
.byte $50 ; 'P' = $d (nybl)
.byte $4D ; 'M' = $e (nybl)
.byte $43 ; 'C' = $F1 / $xF $43
.byte $47 ; 'G' = $F2 / $xF $47
.byte $59 ; 'Y' = $F3 / $xF $59
.byte $56 ; 'V' = $F4 / $xF $56
.byte $42 ; 'B' = $F5 / $xF $42
.byte $48 ; 'H' = $F6 / $xF $48
.byte $58 ; 'X' = $F7 / $xF $58
.byte $57 ; 'W' = $F8 / $xF $57
.byte $24 ; '$' = $F9 / $xF $24
.byte $27 ; ''' = $Fa / $xF $27
.byte $0D ; '␍' = $Fb / $xF $0D
.byte $51 ; 'Q' = $Fc / $xF $51
.byte $2E ; '.' = $Fd / $xF $2E
.byte $23 ; '#' = $FE/F + $23
.byte $4B ; 'K' = $FE/F + $4B
.byte $28 ; '(' = $FE/F + $28
.byte $5A ; 'Z' = $FE/F + $5A
.byte $2B ; '+' = $FE/F + $2B
.byte $2D ; '-' = $FE/F + $2D
.byte $2A ; '*' = $FE/F + $2A
.byte $2F ; '/' = $FE/F + $2F
.byte $5E ; '^' = $FE/F + $5E
.byte $3E ; '>' = $FE/F + $3E
.byte $3D ; '=' = $FE/F + $3D
.byte $3C ; '<' = $FE/F + $3C
packed_message_tokens:
.byte $00,$01,$02,$ff,$03,$04,$ff,$03
.byte $05,$04,$ff,$03,$05,$06,$ff,$07
.byte $05,$08,$ff,$05,$09,$03,$ff,$05
.byte $0a,$03,$ff,$0b,$0c,$ff,$0d,$07
.byte $0e,$ff,$0f,$10,$11,$ff,$12,$ff
.byte $13,$10,$14,$ff,$15,$16,$17,$ff
.byte $0d,$18,$ff,$19,$ff,$15,$16,$1a
.byte $ff,$1b,$1c,$ff,$1d,$1e,$ff,$1f
.byte $20,$ff,$21,$22,$23,$ff,$0d,$24
.byte $ff,$25,$26,$ff,$27,$00,$28,$ff
.byte $03,$17,$ff,$29,$00,$2a,$ff,$2b
.byte $2c,$ff,$1b,$2d,$ff,$2e,$ff,$2f
.byte $ff,$30,$ff,$31,$ff,$32,$ff,$33
.byte $ff,$34,$ff,$35,$36,$ff,$1a,$37
.byte $ff
.byte $05
.byte $38
.byte $ff
packed_message_words:
.byte $23,$30,$e7,$4f,$59,$00,$b5,$81
.byte $90,$b5,$81,$00,$3d,$14,$00,$43
.byte $20,$b3,$c4,$a0,$a1,$f4,$5f,$43
.byte $10,$d6,$19,$14,$20,$54,$dc,$20
.byte $3c,$2d,$c2,$00,$e5,$99,$54,$f2
.byte $00,$b5,$81,$47,$e1,$00,$58,$81
.byte $f2,$78,$00,$4c,$ef,$42,$16,$00
.byte $41,$f7,$20,$f8,$52,$f6,$3c,$20
.byte $b3,$60,$9f,$59,$42,$7f,$58,$00
.byte $61,$2c,$64,$00,$f2,$39,$cf,$42
.byte $00,$3c,$20,$3b,$00,$a7,$27,$00
.byte $fc,$c7,$42,$52,$f3,$00,$3f,$56
.byte $16,$b8,$3f,$57,$00,$e1,$e3,$6f
.byte $59,$00,$c4,$a1,$bf,$27,$a0,$92
.byte $72,$1e,$14,$20,$f5,$7a,$00,$9c
.byte $f5,$9f,$43,$65,$d2,$00,$61,$a5
.byte $ef,$27,$a0,$76,$67,$f3,$00,$a5
.byte $f4,$59,$53,$40,$f5,$f3,$00,$ff
.byte $5a,$16,$30,$a5,$61,$f1,$20,$2f
.byte $59,$d1,$00,$e5,$9e,$72,$f1,$f6
.byte $00,$92,$65,$4f,$47,$00,$83,$4f
.byte $47,$00,$b3,$6e,$c8,$70,$f1,$3e
.byte $d8,$1f,$58,$00,$f1,$74,$fa,$20
.byte $f1,$34,$25,$4c,$10,$bc,$4f,$43
.byte $25,$34,$00,$f4,$16,$5b,$f3,$00
.byte $83,$7a,$00,$61,$7a,$f3,$fd,$fb
.byte $00,$83,$7a,$54,$f2,$00,$f4,$16
.byte $5b,$f3,$54,$f2,$00,$97,$f4,$54
.byte $f2,$00,$16,$63,$60,$f5,$f3,$21
.byte $90,$b6,$11,$fd,$fb,$fb,$00,$f1
.byte $36,$6c,$d2,$00,$5e,$d8,$1e,$14
.byte $21
.byte $a0
packed_keywords:
.byte $14,$a0,$b3,$60,$41,$f7,$20,$a7
.byte $27,$00,$54,$dc,$2f,$23,$00,$54
.byte $dc,$20,$a5,$e0,$61,$7a,$00,$81
.byte $20,$f2,$32,$30,$6c,$40,$5b,$00
.byte $61,$92,$36,$10,$f2,$39,$cf,$42
.byte $00,$61,$2c,$64,$00,$61,$e0,$92
.byte $3d,$00,$34,$00,$f8,$75,$20,$83
.byte $7a,$00,$97,$f4,$10,$f4,$16,$5b
.byte $f3,$00,$a1,$b0,$d3,$ff,$4b,$10
.byte $d6,$54,$2f,$23,$00,$d6,$54,$20
.byte $f1,$34,$20,$85,$92,$00,$f1,$86
.byte $00,$f1,$ea,$00,$9f,$59,$90,$3d
.byte $14,$00,$f1,$83,$91,$00,$f2,$12
.byte $00,$41,$f8,$00,$27,$f5,$fe,$28
.byte $23,$00,$b4,$00,$9d,$f1,$fe,$28
.byte $2f,$48,$14,$00,$43,$20,$92,$1d
.byte $00,$fe,$2b,$fe,$2d,$fe,$2a,$fe
.byte $2f,$fe,$5e,$74,$a0,$36,$00,$fe
.byte $3e,$fe,$3d,$fe,$3c,$9f,$47,$40
.byte $54,$20,$7f,$42,$90,$c9,$60,$b6
.byte $10,$d3,$90,$9f,$51,$60,$64,$a0
.byte $83,$f2,$00,$1f,$58,$d0,$f1,$39
.byte $00,$95,$40,$27,$40,$72,$40,$d1
.byte $1f,$4b,$00,$81,$40,$92,$6f,$24
.byte $00,$f4,$78,$00,$79,$f1,$00,$f1
.byte $f6,$6f,$24,$00,$81,$b2,$f9,$00
.byte $65,$f2,$f6,$2f,$24,$00,$e5,$af
.byte $24
.byte $00
.byte $f2
.byte $30
.alias packed_keyword_table_len $DC
+2 -2
View File
@@ -58,7 +58,7 @@ hi_loop:
pha
ldx #4
clc
hi_add_loop:
hi_add_loop:
lda $0100,x
adc number_table_hi,y
sta $0100,x
@@ -115,7 +115,7 @@ found_start_of_number:
;; Print digits
* lda $0100,y
ora #$30
jsr $ffd2
jsr via_IBSOUT
iny
cpy #5
bne -
+6 -6
View File
@@ -38,7 +38,7 @@ found_message_in_token_stream:
beq +
jsr print_packed_word
lda #$20
jsr $ffd2
jsr via_IBSOUT
pla
tay
iny
@@ -47,7 +47,7 @@ found_message_in_token_stream:
pla
;; Rub out space at the end
lda #$14
jsr $ffd2
jsr via_IBSOUT
rts
print_packed_word:
@@ -138,13 +138,13 @@ next_packed_word_char:
lsr
tax
;; Save Y so it doesn't get clobbered by $FFD2
;; Save Y so it doesn't get clobbered by CHROUT
tya
pha
;; X=1-14 = first 14 chars, so subtract one
lda packed_message_chars-1,x
jsr $FFD2
jsr via_IBSOUT
;; See if there is a char in the low nybl to print
pla
@@ -171,7 +171,7 @@ has_nybl:
;; X=1-14 = first 14 chars, so subtract one
lda packed_message_chars-1,x
jsr $FFD2
jsr via_IBSOUT
*
pla
tay
@@ -207,7 +207,7 @@ unpack_literal_char:
tya
pha
lda (temp_string_ptr),y
jsr $ffd2
jsr via_IBSOUT
pla
tay
rts
+3 -3
View File
@@ -112,7 +112,7 @@ not_hexword:
not_pointer:
;; Print character
jsr $ffd2
jsr via_IBSOUT
printf_nextchar:
jsr printf_advance
@@ -148,11 +148,11 @@ printf_printhexbyte:
cmp #$3A
bcc +
adc #6
* jsr $ffd2
* jsr via_IBSOUT
pla
and #$0f
ora #$30
cmp #$3A
bcc +
adc #6
* jmp $ffd2
* jmp via_IBSOUT
+19
View File
@@ -0,0 +1,19 @@
select_device:
;; Take last device number, make sure it's a drive - 8 or above. Above 30,
;; although illegal for IEC we also consider a drive, as they exists
;; drivers assigning these numbers to CBM-DOS capable devices - like some
;; IEEE-488 carts.
;;
;; If current device is not a drive, set device to 8 (first drive number)
;; Device number is left in X, for SETFLS Kernal routine
;; Note: if tape support is introduced here, make sure DOS wedge won't get broken
ldx current_device_number
cpx #$08
bcs +
ldx #$08
*
rts
+42
View File
@@ -0,0 +1,42 @@
;;
;; Helper routines for jumping via vectors, to be used with JSR
;;
;; Note: they are not in the order of low memory vectors, to avoid
;; similarity with the original ROMs
via_ISAVE:
jmp (ISAVE)
via_ILOAD:
jmp (ILOAD)
via_ICLOSE:
jmp (ICLOSE)
via_IOPEN:
jmp (IOPEN)
via_ICHKIN:
jmp (ICHKIN)
via_IBASIN:
jmp (IBASIN)
via_IGETIN:
jmp (IGETIN)
via_ICKOUT:
jmp (ICKOUT)
via_IBSOUT:
jmp (IBSOUT)
via_ICLRCH:
jmp (ICLRCH)
via_ICLALL:
jmp (ICLALL)
via_ISTOP:
jmp (ISTOP)
+230
View File
@@ -0,0 +1,230 @@
;; START wedge support
wedge_dos:
;; Close all the channels, so that wedge has full control
jsr via_ICLALL
;; Set file parameters, channel 15 is a typical one for commands
jsr select_device ; sets X register
lda #$0F
ldy #$0F
jsr JSETFLS
;; Now we have to check what the user wants us to do
;; Check if user asked for a status
ldy #$00
lda (basic_current_statement_ptr), y
beq wedge_dos_status
;; Check if asked for a directory
cmp #$24
beq wedge_dos_directory
*
;; Check if asked to change drive number, or if it is a regular command
cmp #$30
bcc wedge_dos_command ; char code before 0
cmp #$3A
bcs wedge_dos_command ; char code after 9
iny
lda (basic_current_statement_ptr), y
beq wedge_dos_change_drive ; end of buffer
cmp #$20
beq wedge_dos_change_drive
jmp -
wedge_dos_command:
;; Provide command name
jsr wedge_dos_setnam
jsr JSETNAM
jsr via_IOPEN
bcs wedge_dos_basic_error
;; Retrieve status, print it if not OK
jsr via_ICLALL
jsr wedge_dos_status_get
lda BUF+0
cmp #$30 ; '0'
bne wedge_dos_status_print
lda BUF+1
cmp #$30 ; '0'
bne wedge_dos_status_print
;; Clean-up and exit
jmp wedge_dos_clean_exit
wedge_dos_change_drive:
;; Reuse the line number parser for device number retrieval
jsr basic_parse_line_number
lda basic_line_number+1
beq +
jmp do_ILLEGAL_QUANTITY_error
*
lda basic_line_number+0
cmp #$08
bpl +
bcs +
jmp do_ILLEGAL_DEVICE_NUMBER_error
*
sta current_device_number
jmp basic_end_of_line
wedge_dos_status_get:
;; Here the flow is mostly the same as in the example from
;; https://codebase64.org/doku.php?id=base:reading_the_error_channel_of_a_disk_drive
;; Set remaining file parameters, open the channel
lda #$00 ; empty file name
jsr JSETNAM
jsr via_IOPEN
bcs wedge_dos_basic_error
;; Set channel for input
ldx #$0F
jsr via_ICHKIN
bcs wedge_dos_basic_error
ldy #$00
*
cpy #$50 ; buffer overflow protection
beq +
jsr JREADST ; retrieve errors
;; XXX error in case of status != EOF
;; Print out everything retrieved from the drive
bne +
jsr via_IBASIN
bcs wedge_dos_basic_error
sta BUF, y
iny
jmp -
*
rts
wedge_dos_status:
jsr wedge_dos_status_get
;; FALLTROUGH
wedge_dos_status_print:
;; Print buffered status
ldx #$00
*
dey
bmi +
lda BUF, x
jsr via_IBSOUT
inx
bne -
*
;; Clean-up and exit
jmp wedge_dos_clean_exit
wedge_dos_directory:
;; First change the secondary address to the one suitable for
;; directory loading
;; XXX
lda #$00 ; logical device number
ldx current_device_number
ldy #$60
jsr JSETFLS
;; Provide file name
jsr wedge_dos_setnam
;; Open the file
jsr via_IOPEN
bcs wedge_dos_basic_error
;; Set channel for file reading
ldx #$00
jsr via_ICHKIN
bcs wedge_dos_basic_error
;; Ignore start address (2 first bytes) - XXX check for errors
jsr via_IBASIN
bcs wedge_dos_basic_error
jsr via_IBASIN
bcs wedge_dos_basic_error
wedge_dos_directory_line:
;; Load a single line, reuse BASIC input buffer
ldy #$FF
*
iny
jsr via_IBASIN
bcs wedge_dos_basic_error
sta BUF, y
cpy #$50
beq + ; line too long, terminate loading file
jsr JREADST
bne + ; end of file
cpy #$04 ; 2 bytes (pointer to next line) + 2 bytes (line number)
bcc -
lda BUF, y
bne -
;; End of line, but not end of file
beq wedge_dos_directory_display
*
lda #K_STS_END_OF_FILE
sta IOSTATUS ; make sure end of file is marked
;; FALLTROUGH
wedge_dos_directory_display:
cpy #$05 ; protection against malformed directory
bcc wedge_dos_clean_exit
lda #$00 ; extra protection agains buffer overflow
sta BUF, y
;; Display line
ldx #<BUF
stx basic_current_line_ptr+0
ldx #>BUF
stx basic_current_line_ptr+1
ldx #basic_current_line_ptr
jsr list_single_line
;; Read & display next line or quit
lda IOSTATUS
beq wedge_dos_directory_line
;; FALLTROUGH
wedge_dos_clean_exit:
jsr via_ICLALL
;; Print new line
lda #$0D
jsr via_IBSOUT
jmp basic_end_of_line
wedge_dos_basic_error:
pha
jsr via_ICLALL
pla
tax
dex
jmp do_basic_error
wedge_dos_setnam:
;; Now determine the length of the 'file' name
ldy #$FF
*
iny
lda (basic_current_statement_ptr), y
bne -
;; Set the name to open
tya
ldx basic_current_statement_ptr+0
ldy basic_current_statement_ptr+1
jmp JSETNAM
;; END wedge support
+3 -18
View File
@@ -3,27 +3,18 @@
; (And only those for now that we feel the need to implement initially)
; (https://www.c64-wiki.com/wiki/Zeropage)
.alias TXTTAB $2B
.alias IOSTATUS $90
; Keys down clears bits. STOP=bit 7, C= bit 6, SPACE bit 4, CTRL bit 2
.alias BUCKYSTATUS $91
.alias kernal_load_or_verify_flag $93
.alias current_file_num $98
.alias input_device_number $99
; bit 6 = error messages, bit 7 = control messages
.alias kernal_message_control_flags $9d
.alias jiffy_clock_24bits $a0
.alias input_device_number DFLTN
.alias cassette_buffer_bytes_used $A6
.alias load_or_scroll_temp_pointer $AC
;; We also use the following for temp colour pointer when scrolling
.alias load_save_verify_end_address $AE
.alias cassette_buffer_ptr $B2
.alias current_filename_length $B7
.alias current_logical_filenum $B8
.alias current_secondary_address $B9
.alias current_device_number $BA
.alias current_filename_ptr $BB
.alias load_save_start_ptr $C1
.alias load_save_end_ptr $C3
.alias last_key_matrix_position $C5
.alias keys_in_key_buffer $C6
@@ -50,15 +41,11 @@
.alias keyboard_decoding_table_ptr $F5
.alias rs232_rx_buffer_ptr $F7
.alias rs232_tx_buffer_ptr $F9
; "Compute's Mapping the 64" book
.alias keyboard_buffer $0277
.alias MEMSTR $0281
.alias MEMSIZ $0283 ; NOTE: Mapping the 64 erroniously has the hex as $282, while the DEC is correct
.alias text_colour $0286 ; p55
.alias colour_under_cursor $0287 ; p56
.alias HIBASE $0288 ; p56 (high byte of start of screen)
.alias key_buffer_size $0289 ; p57
;; 0 = cursor keys, insert, delete and space repeat, but nothing else
@@ -74,7 +61,6 @@
.alias keyboard_decoding_ptr $028F
.alias enable_case_switch $0291
.alias screen_scroll_disable $0292
.alias pal_or_ntsc $02A6
;; Under-ROM routines
;; (BASIC also includes them. XXX - We should de-duplicate them in a safe manner)
@@ -84,5 +70,4 @@
.alias poke_under_roms tiny_nmi_handler+poke_under_roms_routine-tiny_nmi_handler_routine
.alias memmap_allram tiny_nmi_handler+memmap_allram_routine-tiny_nmi_handler_routine
.alias memmap_normal tiny_nmi_handler+memmap_normal_routine-tiny_nmi_handler_routine
@@ -0,0 +1,6 @@
;; Target-specific hooks
.macro TARGET_HOOK_LOAD
.macend
@@ -0,0 +1,6 @@
;; Target-specific hooks
.macro TARGET_HOOK_LOAD
.macend
@@ -0,0 +1,57 @@
;; Registers according to Ultimate 64 Command Interface description,
;; https://1541u-documentation.readthedocs.io/en/latest/command%20interface.html
;; and ultimate_dos_v1.0.pdf and command_interface_v1.0.pdf by Gideon Zweijtzer
;; Command interface registers
.alias U64_CONTROL $DF1C ; write
.alias U64_STATUS $DF1C ; read
.alias U64_COMMAND_DATA $DF1D ; write
.alias U64_IDENTIFICATION $DF1D ; read
.alias U64_RESPONSE_DATA $DF1E ; read only
.alias U64_STATUS_DATA $DF1F ; read only
;; Constant for U64_IDENTIFICATION register
.alias U64_MAGIC_ID $C9
;; Constants for U64_CONTROL register
.alias U64_CTRL_BIT_PUSH_CMD $01
.alias U64_CTRL_BIT_DATA_ACC $02
.alias U64_CTRL_BIT_ABORT $04
.alias U64_CTRL_BIT_CLR_ERR $08
;; Constants for U64_STATUS register
.alias U64_STAT_BIT_CMD_BUSY $01
.alias U64_STAT_BIT_DATA_ACC $02
.alias U64_STAT_BIT_ABORT_P $04
.alias U64_STAT_BIT_ERROR $08
.alias U64_STAT_MASK_STATE $30 ; two bits!
.alias U64_STAT_BIT_STAT_AV $40
.alias U64_STAT_BIT_DATA_AV $80
;; Interface targets
.alias U64_TARGET_DOS1 $01
.alias U64_TARGET_DOS2 $02
;; DOS command codes
.alias U64_DOS_CMD_IDENTIFY $01
.alias U64_DOS_CMD_OPEN_FILE $02
.alias U64_DOS_CMD_CLOSE_FILE $03
.alias U64_DOS_CMD_READ_DATA $04
.alias U64_DOS_CMD_WRITE_DATA $05
.alias U64_DOS_CMD_FILE_SEEK $06
.alias U64_DOS_CMD_FILE_INFO $07
.alias U64_DOS_CMD_CHANGE_DIR $11
.alias U64_DOS_CMD_GET_PATH $12
.alias U64_DOS_CMD_OPEN_DIR $13
.alias U64_DOS_CMD_READ_DIR $14
.alias U64_DOS_CMD_COPY_UI_PATH $15
.alias U64_DOS_CMD_LOAD_REU $21
.alias U64_DOS_CMD_SAVE_REU $22
.alias U64_DOS_CMD_ECHO $F0
;; DOS file opening constants
.alias U64_FA_READ $01
.alias U64_FA_WRITE $02
.alias U64_FA_CREATE_NEW $03
.alias U64_FA_CREATE_ALWAYS $04
@@ -0,0 +1,9 @@
;; Target-specific hooks
.macro TARGET_HOOK_LOAD
;; XXX disabled for now - the current file opening API is not
;; really suitable for easy usage from Kernal
;; jsr u64_load
.macend
@@ -0,0 +1,130 @@
;;
;; LOAD routine hook for fast loading via UltiDOS
;;
u64_load:
;; First check whether the command interface is enabled
lda U64_IDENTIFICATION
cmp #U64_MAGIC_ID
beq +
u64_load_skip:
rts
*
;; XXX find out which device number softIEC is mapped to
lda current_device_number
cmp #$20 ; for now use device number 32
bne u64_load_skip
;; Takeover the flow completely
pla
pla
;; Display SEARCHING FOR + filename
jsr lvs_display_searching_for
;; Whatever the interface was doing - ask to abort it
jsr u64_load_abort
;; Send a command to open the file
lda #U64_DOS_CMD_OPEN_FILE
jsr u64_load_send_cmd
lda #U64_FA_READ
jsr u64_load_send_cmd
jsr u64_load_send_filename
jsr u64_load_finalize_cmd
;; Check status
jsr u64_load_check_status
bcs lvs_file_not_found_error
;; Load first two bytes to determine start address
;; XXX
jsr printf
.byte "DBG: NOT IMPLEMENTED",$0D,0
jmp lvs_wrap_around_error
rts
u64_load_abort:
lda #U64_CTRL_BIT_ABORT
sta U64_CONTROL
*
lda U64_STATUS
bne -
rts
u64_load_send_cmd:
ldx #U64_TARGET_DOS2
stx U64_COMMAND_DATA ; target
sta U64_COMMAND_DATA ; command code
rts
u64_load_send_filename:
ldy #0
u64_load_send_filename_loop:
cpy FNLEN
bne+
rts
*
ldx #<current_filename_ptr
jsr peek_under_roms
iny
sta U64_COMMAND_DATA
jmp u64_load_send_filename_loop
u64_load_finalize_cmd:
;; Push the command for execution
lda #U64_CTRL_BIT_PUSH_CMD
sta U64_CONTROL
;; Wait till it is complete
*
lda U64_STATUS
and #U64_STAT_BIT_CMD_BUSY
bne -
rts
u64_load_check_status:
;; Wait till status is available
lda U64_STATUS
and #U64_STAT_BIT_STAT_AV
beq u64_load_check_status
;; Status is ready - check the first character
lda U64_STATUS_DATA
jsr JCHROUT ; XXX for test only
cmp #$30 ; '0'
bne u64_load_check_status_wrong
;; Check the second status character
lda U64_STATUS
and #U64_STAT_BIT_STAT_AV
beq u64_load_check_status_ok
lda U64_STATUS_DATA
jsr JCHROUT ; XXX for test only
cmp #$30 ; '0'
beq u64_load_check_status_ok
;; FALLTROUGH
u64_load_check_status_wrong:
sec
bcs +
u64_load_check_status_ok:
clc
*
;; Now empty the status queue
lda U64_STATUS
and #U64_STAT_BIT_STAT_AV
beq +
lda U64_STATUS_DATA
jsr JCHROUT ; XXX for test only
jmp -
*
rts
+14 -2
View File
@@ -1,3 +1,15 @@
; Function defined on pp272-273 of C64 Programmers Reference Guide
;;
;; Official Kernal routine, described in:
;;
;; - [RG64] C64 Programmer's Reference Guide - page 274
;; - [CM64] Compute's Mapping the Commodore 64 - page 224/225
;;
;; CPU registers that has to be preserved (see [RG64]): .Y
;;
acptr:
rts
jsr kernalstatus_reset
jmp iec_rx_byte
-3
View File
@@ -1,3 +0,0 @@
; Function defined on pp272-273 of C64 Programmers Reference Guide
chkin:
rts
+143
View File
@@ -0,0 +1,143 @@
;;
;; Official Kernal routines, described in:
;;
;; - [RG64] C64 Programmer's Reference Guide - page 275 (CHKIN) / 276 (CKOUT)
;; - [CM64] Compute's Mapping the Commodore 64 - page 229
;;
;; CPU registers that has to be preserved (see [RG64]): .Y
;;
;; CHKIN implementation
chkin:
;; Store Y for preservation
tya
pha
;; Reset status
jsr kernalstatus_reset
;; First retrieve the FAT/LAT/SAT table index (and check if file is open)
txa
jsr find_fls
bcs chkinout_file_not_open
;; Now we have table index in Y - first filter out unsuitable devices
lda FAT,Y
cmp #$01
beq chkinout_device_not_present ; tape not implemented
cmp #$02
beq chkinout_device_not_present ; RS-232 not implemented
;; Fail if the file is open for writing (secondary address 1)
lda LAT, Y
cmp #$01
beq chkinout_file_not_input
;; For IEC devices, send TALK + TKSA first
lda FAT,Y
jsr iec_check_devnum
bcs chkin_set_device
jsr talk
bcs chkinout_device_not_present ; don't set DFLTN in case of failure
lda LAT, Y
jsr tksa
bcs chkinout_device_not_present
chkin_set_device:
lda FAT,Y
sta DFLTN
clc ; for success
;; FALLTROUGH
;; Common part for booth CHKIN and CKOUT
chkinout_end:
tax
pla
tay
txa
rts
chkinout_file_not_open:
pla
tay
jmp kernalerror_FILE_NOT_OPEN
chkinout_device_not_present:
pla
tay
jsr kernalstatus_DEVICE_NOT_FOUND
jmp kernalerror_DEVICE_NOT_FOUND
chkinout_file_not_input:
pla
tay
jmp kernalerror_FILE_NOT_INPUT
chkinout_file_not_output:
pla
tay
jmp kernalerror_FILE_NOT_OUTPUT
chkinout_common:
;; CKOUT implementation
ckout:
;; Store Y for preservation
tya
pha
;; Reset status
jsr kernalstatus_reset
;; First retrieve the FAT/LAT/SAT table index (and check if file is open)
txa
jsr find_fls
bcs chkinout_file_not_open
;; Now we have table index in Y - first filter out unsuitable devices
lda FAT,Y
cmp #$01
beq chkinout_device_not_present ; tape not implemented
cmp #$02
beq chkinout_device_not_present ; RS-232 not implemented
cmp #$00
beq chkinout_file_not_output ; cannot output to keyboard - XXX check real ROM behaviour
;; Fail if the file is open for reading (secondary address 0)
lda LAT, Y
beq chkinout_file_not_output
;; For IEC devices, send LISTEN + SECOND first
lda FAT,Y
jsr iec_check_devnum
bcs chkout_set_device
jsr listen
bcs chkinout_device_not_present ; don't set DFLTO in case of failure
lda LAT, Y
jsr second
bcs chkinout_device_not_present
chkout_set_device:
lda FAT,Y
sta DFLTO
clc ; for success
jmp chkinout_end
-3
View File
@@ -1,3 +0,0 @@
; Function defined on pp272-273 of C64 Programmers Reference Guide
chkout:
rts
+48 -9
View File
@@ -1,14 +1,53 @@
; Function defined on pp272-273 of C64 Programmers Reference Guide
;; Compute's Mapping the 64, p228
;; Reads a byte of input, unless from keyboard.
;; If from keyboard, then it gets a whole line of input, and returns the first char.
;; Repeated calls after that read out the successive bytes of the line of input.
;;
;; Official Kernal routine, described in:
;;
;; - [RG64] C64 Programmer's Reference Guide - page 277/278
;; - [CM64] Compute's Mapping the Commodore 64 - page 228
;;
;; CPU registers that has to be preserved (see [RG64]): .Y
;;
;; XXX keyboard part currently does not preserve register Y, to be fixed!
;; Reads a byte of input, unless from keyboard.
;; If from keyboard, then it gets a whole line of input, and returns the first char.
;; Repeated calls after that read out the successive bytes of the line of input.
chrin:
;; Determine the device number
lda DFLTN
beq chrin_keyboard ; #$00 - keyboard
;; XXX add screen support
jsr iec_check_devnum
bcc chrin_iec
jmp lvs_device_not_found_error ; not a supported device
chrin_iec:
jsr JACPTR
bcs chrin_done_fail
;; FALLTROUGH
chrin_done:
clc ; indicate success
rts
chrin_done_fail:
sec ; indicate failure
rts
chrin_keyboard:
;; Save X
txa
pha
chrin_repeat:
chrin_repeat:
;; Do we have a line of input we are currently returning?
;; If so, return the next byte, and clear the flag when we reach the end.
@@ -165,7 +204,7 @@ not_shifted:
clc
adc #$40
;; FALLTROUGH
not_vendor:
rts
not_vendor:
rts
+81 -22
View File
@@ -1,24 +1,96 @@
; Function defined on pp272-273 of C64 Programmers Reference Guide
;;
;; Official Kernal routine, described in:
;;
;; - [RG64] C64 Programmer's Reference Guide - page 278/279
;; - [CM64] Compute's Mapping the Commodore 64 - page 228
;;
;; CPU registers that has to be preserved (see [RG64]): .Y
;;
chrout:
;; Crude implementation of character output
sta last_printed_character_ascii
;; Save X and Y values
;; (Confirmed by writing a test program that X and Y
;; don't get modified, in agreement with C64 PRG's
;; description of CHROUT)
sta last_printed_character_ascii
txa
pha
tya
pha
php
sei
;; Determine the device number
lda DFLTO
cmp #$03 ; screen
beq chrout_screen
jsr iec_check_devnum
bcs chrout_done_unknown_device ; not a supported device
chrout_iec:
lda last_printed_character_ascii
jsr JCIOUT
bcc chrout_done
;; FALLTROUGH
chrout_done_fail:
jsr show_cursor_if_enabled
plp
;; Restore X and Y
pla
tay
pla
tax
sec ; indicate failure
rts
chrout_done_unknown_device:
jsr show_cursor_if_enabled
plp
;; Restore X and Y
pla
tay
pla
tax
;; End wioth error
jmp lvs_device_not_found_error
chrout_done:
jsr show_cursor_if_enabled
plp
;; Restore X and Y
pla
tay
pla
tax
lda last_printed_character_ascii
clc ; indicate success
rts
chrout_screen:
;; Crude implementation of character output
sei ;; XXX why do we need to disable interrupts?
jsr hide_cursor_if_visible
lda last_printed_character_ascii
tax
;; Check for special characters
cmp #$00
@@ -32,7 +104,7 @@ not_00:
bne not_0a
jmp chrout_done
not_0a:
;; Carriage return
cmp #$0d
bne not_0d
@@ -370,20 +442,7 @@ not_quote:
sta current_screen_x
jmp screen_advance_to_next_line
no_screen_advance_to_next_line:
chrout_done:
jsr show_cursor_if_enabled
plp
;; Restore X and Y, set carry to mark success on exit
pla
tay
pla
tax
lda last_printed_character_ascii
clc ; indicate success
rts
jmp chrout_done
screen_grow_logical_line:
ldy current_screen_y
+14 -2
View File
@@ -1,5 +1,14 @@
;; Function defined on pp272-273 of C64 Programmers Reference Guide
;; Compute's Mapping the 64 p215
;;
;; Official Kernal routine, described in:
;;
;; - [RG64] C64 Programmer's Reference Guide - page 280
;; - [CM64] Compute's Mapping the Commodore 64 - page 242
;;
;; CPU registers that has to be preserved (see [RG64]): none
;;
cint:
jsr setup_vicii
@@ -34,6 +43,9 @@ cint:
;; Put non-zero value in enable_case_switch
stx enable_case_switch
;; Set default I/O devices (see SCINIT description at http://sta.c64.org/cbm64krnfunc.html)
jsr clrchn_reset
;; Fallthrough/jump to screen clear routine (Compute's Mapping the 64 p215)
jmp clear_screen
+35 -1
View File
@@ -1,3 +1,37 @@
; Function defined on pp272-273 of C64 Programmers Reference Guide
;;
;; Official Kernal routine, described in:
;;
;; - [RG64] C64 Programmer's Reference Guide - page 279/280
;; - [CM64] Compute's Mapping the Commodore 64 - page 224
;;
;; CPU registers that has to be preserved (see [RG64]): .X, .Y
;;
ciout:
pha
lda C3PO
bne ciout_send_byte
;; Nothing to send - set buffer as valid, store byte there
inc C3PO
;; Clear carry flag to indicate success
clc
ciout_store_in_buffer:
;; Store in the buffer data to be sent next, return
pla
sta BSOUR
rts
ciout_send_byte:
clc ; don't send with EOI
jsr iec_tx_byte
inc C3PO ; iec_tx_byte sets it to 0, but we still have something to send
jmp ciout_store_in_buffer
+38
View File
@@ -0,0 +1,38 @@
;;
;; Official Kernal routine, described in:
;;
;; - [RG64] C64 Programmer's Reference Guide - page 281
;; - [CM64] Compute's Mapping the Commodore 64 - page 230
;;
;; CPU registers that has to be preserved (see [RG64]): .Y
;;
clall:
;; Store .Y register
tya
pha
;; Original routine probably just sets LDTND to 0, but this is not really safe,
;; so we actually close all the channels; at least IDE64 does the same for
;; it's channels, see CLALL description in the IDE64 User's Guide
*
ldy LDTND
beq +
dey
lda LAT, y
jsr close ; XXX jump through ICLOSE?
jmp -
*
;; Restore .Y register
pla
tay
;; 'C64 Programmers Reference Guide', page 281, claims it calls CLRCHN too
jsr clrchn
;; Not sure whether original Kernal does so, but it seems sane to also clear possible errors
jmp kernalstatus_reset
+57 -1
View File
@@ -1,3 +1,59 @@
; Function defined on pp272-273 of C64 Programmers Reference Guide
;;
;; Official Kernal routine, described in:
;;
;; - [RG64] C64 Programmer's Reference Guide - page 281/282
;; - [CM64] Compute's Mapping the Commodore 64 - page 229/230
;; - https://www.pagetable.com/?p=1031, https://github.com/mist64/cbmbus_doc (IEC command)
;;
;; CPU registers that has to be preserved (see [RG64]): none
;;
close:
;; XXX this needs more testing (opening 10 files at once, closing in various orders, etc) once the code is more mature
;; Find the LAT / SAT / FAT entry which LAT corresponds to A
jsr find_fls
bcs close_error_not_found ;; XXX can we report error in IOSTATUS here?
;; We have the entry index in Y - check whether this is IEC device
lda FAT, y
jsr iec_check_devnum
bcs close_remove_from_table
;; IEC device
jsr iec_tx_flush ; make sure no byte is awaiting
*
lda SAT, y ; get secondary address
ora $E0 ; CLOSE command
sta IEC_TMP2
jsr iec_tx_command
bcs close_remove_from_table
jsr iec_tx_command_finalize
close_remove_from_table:
;; Remove channel from the table
iny
cpy #$0A
bpl +
lda LAT, y
sta LAT-1, y
lda FAT, y
sta FAT-1, y
lda SAT, y
sta SAT-1, y
jmp close_remove_from_table
*
;; Decrement the list size variable
dec LDTND
clc ; report success - not sure if original CLOSE does this, but it's nevertheless a good practice
rts
close_error_not_found:
sec ; report success - not sure if original CLOSE does this, but it's nevertheless a good practice
rts
-2
View File
@@ -1,2 +0,0 @@
close_all_files:
rts
+34 -1
View File
@@ -1,3 +1,36 @@
; Function defined on pp272-273 of C64 Programmers Reference Guide
;;
;; Official Kernal routine, described in:
;;
;; - [RG64] C64 Programmer's Reference Guide - page 282
;; - [CM64] Compute's Mapping the Commodore 64 - page 230
;;
;; CPU registers that has to be preserved (see [RG64]): .Y
;;
clrchn:
;; Handle IEC input device
lda DFLTN
jsr iec_check_devnum
bcs +
;; Previous device was IEC one - send UNTALK first
jsr untlk
*
;; Restore output device to default
lda DFLTO
jsr iec_check_devnum
bcs +
;; Handle IEC output device
jsr unlsn
*
clrchn_reset: ;; entry needed by CHRIN
;; Set input device number to keyboard
lda #$00
sta DFLTN
;; Set output device number to screen
lda #$03
sta DFLTO
rts
+84 -2
View File
@@ -1,6 +1,88 @@
;; Kernal error codes are described in 'Commodore 64 Programmer's Reference Guide', page 306
kernalerror_DEVICE_NOT_FOUND:
lda #$05
kernalerror_ROUTINE_TERMINATED: ; by a STOP key
lda #K_ERR_ROUTINE_TERMINATED
sec
rts
kernalerror_TOO_MANY_OPEN_FILES:
lda #K_ERR_TOO_MANY_OPEN_FILES
sec
rts
kernalerror_FILE_ALREADY_OPEN:
lda #K_ERR_FILE_ALREADY_OPEN
sec
rts
kernalerror_FILE_NOT_OPEN:
lda #K_ERR_FILE_NOT_OPEN
sec
rts
kernalerror_FILE_NOT_FOUND:
lda #K_ERR_FILE_NOT_FOUND
sec
rts
kernalerror_DEVICE_NOT_FOUND:
lda #K_ERR_DEVICE_NOT_FOUND
sec
rts
kernalerror_FILE_NOT_INPUT:
lda #K_ERR_FILE_NOT_INPUT
sec
rts
kernalerror_FILE_NOT_OUTPUT:
lda #K_ERR_FILE_NOT_OUTPUT
sec
rts
kernalerror_FILE_NAME_MISSING:
lda #K_ERR_FILE_NAME_MISSING
sec
rts
kernalerror_ILLEGAL_DEVICE_NUMBER:
lda #K_ERR_ILLEGAL_DEVICE_NUMBER
sec
rts
kernalerror_TOP_MEM_RS232:
lda #K_ERR_TOP_MEM_RS232
sec
rts
;; Kernal status codes are described in 'Commodore 64 Programmer's Reference Guide', page 292
kernalstatus_reset:
lda #$00
sta IOSTATUS
rts
kernalstatus_TIMEOUT_WRITE: ;; XXX detect this!
lda IOSTATUS
ora #K_STS_TIMEOUT_WRITE
sta IOSTATUS
rts
kernalstatus_TIMEOUT_READ: ;; XXX detect this!
lda IOSTATUS
ora #K_STS_TIMEOUT_READ
sta IOSTATUS
rts
kernalstatus_EOI:
lda IOSTATUS
ora #K_STS_EOI
sta IOSTATUS
rts
kernalstatus_DEVICE_NOT_FOUND:
lda IOSTATUS
ora #K_STS_DEVICE_NOT_FOUND
sta IOSTATUS
rts
+13 -1
View File
@@ -1,4 +1,13 @@
; Function defined on pp272-273 of C64 Programmers Reference Guide
;;
;; Official Kernal routine, described in:
;;
;; - [RG64] C64 Programmer's Reference Guide - page 285
;; - [CM64] Compute's Mapping the Commodore 64 - page 238
;;
;; CPU registers that has to be preserved (see [RG64]): none
;;
ioinit:
; Set $00/$01 port mode and value
@@ -39,4 +48,7 @@ ioinit:
lda #$3b
sta $dd02
;; Set IEC bus oto its initial idle state
jsr iec_set_idle
rts
-9
View File
@@ -1,9 +0,0 @@
; $FFF3 - Get page of IO devices
; Returns Y=$DC, X=$00
; (http://codebase64.org/doku.php?id=base:kernalreference)
;
; As there is nothing between here and $FFFA, we can just hard code this in place.
LDY #$DC
LDX #$00
RTS
+24
View File
@@ -0,0 +1,24 @@
;; Just a helper routines
;; Find the LAT / SAT / FAT entry index where LAT corresponds to A, returns index in Y
;; Carry flag set means not found
find_fls:
ldy LDTND
beq find_fls_not_found ; table empty
*
dey
bmi find_fls_not_found ; no more entries
cmp LAT, y
bne - ; does not match, try the next one
clc
rts
find_fls_not_found:
sec
rts
-2
View File
@@ -1,2 +0,0 @@
get_screen_size:
rts
+12 -1
View File
@@ -1,4 +1,15 @@
; Function defined on pp272-273 of C64 Programmers Reference Guide
;;
;; Official Kernal routine, described in:
;;
;; - [RG64] C64 Programmer's Reference Guide - page 283
;; - [CM64] Compute's Mapping the Commodore 64 - page 227/228
;;
;; CPU registers that has to be preserved (see [RG64]): .X, .Y
;;
;; XXX currently does not preserve registers, to be fixed!
getin:
;; Wait for a key
+22
View File
@@ -0,0 +1,22 @@
;;
;; Checks whether device number (in .A) is a correct IEC device number
;;
;; Preserves .A, .X and .Y
;;
iec_check_devnum:
;; 0, 1, 2, or 3 are illegal - reserved for non-IEC devices on Commodore
cmp #$04
bcs +
;; FALLTROUGH
iec_check_devnum_failed:
sec ; indicate non-IEC device
rts
*
;; 31 and above are illegal too, due to IEC command encoding scheme,
;; see https://www.pagetable.com/?p=1031
cmp #$1F
bcs iec_check_devnum_failed
;; Carry is clear here - indicates IEC device
rts
+16
View File
@@ -0,0 +1,16 @@
;;
;; Kernal internal IEC routine
;;
;; - https://www.pagetable.com/?p=1031, https://github.com/mist64/cbmbus_doc
;;
iec_cmd_close:
jsr iec_check_channel_openclose
bcc +
jmp kernalerror_FILE_NOT_INPUT
*
ora #$E0
jmp common_open_close_unlsn_second
+42
View File
@@ -0,0 +1,42 @@
;;
;; Kernal internal IEC routine
;;
;; - https://www.pagetable.com/?p=1031, https://github.com/mist64/cbmbus_doc
;;
iec_cmd_open: ; similar to TKSA, but without turnaround
jsr iec_check_channel_openclose
bcc +
jmp kernalerror_FILE_NOT_INPUT
*
ora #$F0
;; FALLTROUGH
common_open_close_unlsn_second: ; common part of several commands
sta IEC_TMP2
jsr iec_tx_command
bcs + ; branch if error
jmp iec_tx_command_finalize
*
rts
iec_check_channel_openclose:
;; Due to OPEN/CLOSE/TKSA/SECOND command encoding (see https://www.pagetable.com/?p=1031),
;; allowed channels are 0-15; report error if out of range
cmp #$10
bcc +
;; Workaround to allow reading executable files and disk directory
;; using OPEN routine - see https://www.pagetable.com/?p=273 for
;; example usage
cmp #$60
beq +
sec ; mark unsuitable channel number
rts
*
clc ; mark suitable channel number
rts
@@ -0,0 +1,15 @@
iec_pull_atn_clk_release_data:
;; Pulled CLK = DATA considered invalid; for extra robustness on non-emulated
;; hardware give some lines few more cycles to stabilize; see page 10 of
;; http://www.zimmers.net/anonftp/pub/cbm/programming/serial-bus.pdf
lda CIA2_PRA
ora #BIT_CIA2_PRA_ATN_OUT ; pull
sta CIA2_PRA
ora #BIT_CIA2_PRA_CLK_OUT ; pull
sta CIA2_PRA
and #$FF - BIT_CIA2_PRA_DAT_OUT ; release
sta CIA2_PRA
rts
@@ -0,0 +1,13 @@
iec_pull_clk_release_data:
;; Pulled CLK = DATA considered invalid; for extra robustness on non-emulated
;; hardware give some lines few more cycles to stabilize; see page 10 of
;; http://www.zimmers.net/anonftp/pub/cbm/programming/serial-bus.pdf
lda CIA2_PRA
ora #BIT_CIA2_PRA_CLK_OUT ; pull
sta CIA2_PRA
and #$FF - BIT_CIA2_PRA_DAT_OUT ; release
sta CIA2_PRA
rts
@@ -0,0 +1,15 @@
iec_pull_data_release_atn_clk:
;; Released CLK = DATA considered valid; for extra robustness on non-emulated
;; hardware give some lines few more cycles to stabilize; see page 10 of
;; http://www.zimmers.net/anonftp/pub/cbm/programming/serial-bus.pdf
lda CIA2_PRA
ora #BIT_CIA2_PRA_DAT_OUT ; pull
sta CIA2_PRA
and #$FF - BIT_CIA2_PRA_CLK_OUT ; release
sta CIA2_PRA
and #$FF - BIT_CIA2_PRA_ATN_OUT ; release
sta CIA2_PRA
rts
+8
View File
@@ -0,0 +1,8 @@
iec_release_atn:
lda CIA2_PRA
and #$FF - BIT_CIA2_PRA_ATN_OUT ; release
sta CIA2_PRA
rts
+16
View File
@@ -0,0 +1,16 @@
iec_release_atn_clk_data:
;; Released CLK = DATA considered valid; for extra robustness on non-emulated
;; hardware give some lines few more cycles to stabilize; see page 10 of
;; http://www.zimmers.net/anonftp/pub/cbm/programming/serial-bus.pdf
lda CIA2_PRA
and #$FF - BIT_CIA2_PRA_ATN_OUT ; release
sta CIA2_PRA
and #$FF - BIT_CIA2_PRA_DAT_OUT ; release
sta CIA2_PRA
and #$FF - BIT_CIA2_PRA_CLK_OUT ; release
sta CIA2_PRA
rts
+13
View File
@@ -0,0 +1,13 @@
iec_release_clk_data:
;; Released CLK = DATA considered valid; for extra robustness on non-emulated
;; hardware give some lines few more cycles to stabilize; see page 10 of
;; http://www.zimmers.net/anonftp/pub/cbm/programming/serial-bus.pdf
lda CIA2_PRA
and #$FF - BIT_CIA2_PRA_DAT_OUT ; release
sta CIA2_PRA
and #$FF - BIT_CIA2_PRA_CLK_OUT ; release
sta CIA2_PRA
rts
@@ -0,0 +1,13 @@
iec_release_clk_pull_data:
;; Released CLK = DATA considered valid; for extra robustness on non-emulated
;; hardware give some lines few more cycles to stabilize; see page 10 of
;; http://www.zimmers.net/anonftp/pub/cbm/programming/serial-bus.pdf
lda CIA2_PRA
ora #BIT_CIA2_PRA_DAT_OUT ; pull
sta CIA2_PRA
and #$FF - BIT_CIA2_PRA_CLK_OUT ; release
sta CIA2_PRA
rts
+38
View File
@@ -0,0 +1,38 @@
;;
;; Helper routines to return with error/success
;;
;; All of them restore X/Y registers from stack,
;; they take care about Carry flag,
;; error return reeset IEC line to default state,
;; take care about .A and IOSTATUS
;;
iec_return_success:
;; BSOUR is certainly not valid anymore
lda #$00
sta C3PO
;; Restore registers
pla
tay
pla
tax
;; Report success
clc
rts
iec_return_DEVICE_NOT_FOUND:
;; Set IEC line to normal idle state
jsr iec_set_idle
;; BSOUR is certainly not valid anymore
lda #$00
sta C3PO
;; Restore registers
pla
tay
pla
tax
;; Report error
jmp kernalerror_DEVICE_NOT_FOUND
+147
View File
@@ -0,0 +1,147 @@
;; Receive a byte from the IEC bus.
;; Implemented based on https://www.pagetable.com/?p=1135, https://github.com/mist64/cbmbus_doc,
;; http://www.zimmers.net/anonftp/pub/cbm/programming/serial-bus.pdf (page 11)
;;
;; Preserves .X and .Y registers
iec_rx_byte:
;; Store .X and .Y on the stack - preserve them
txa
pha
tya
pha
;; Timing is critical here - execute on disabled IRQs
php
sei
;; First, we wait for the talker to release the CLK line
jsr iec_wait_for_clk_release
;; We then release the DATA to signal we are ready
;; We can use this routine, since we weren't pulling CLK anyway
jsr iec_release_clk_data
;; Wait till data line is released (someone else might be holding it)
jsr iec_wait_for_data_release
;; Wait for talker to pull CLK.
;; If over 200 usec (205 cycles on NTSC machine) , then it is EOI.
;; Loop iteraction takes 13 cycles, 17 full iterations are enough
ldx #$11 ; 2 cycles
iec_rx_clk_wait1:
lda CIA2_PRA ; 4 cycles
rol ; 2 cycles, to put CLK in as the last bit
bpl iec_rx_not_eoi ; 2 cycles if not jumped
dex ; 2 cycles
bne iec_rx_clk_wait1 ; 3 cycles if jumped
;; Timeout - either this is the last byte of stream, or the stream is empty at all.
;; Mark end of stream in IOSTATUS
jsr kernalstatus_EOI
iec_rx_not_empty:
;; Pull data for 60 usec to confirm it
jsr iec_release_clk_pull_data
jsr iec_wait60us
jsr iec_release_clk_data
iec_rx_not_eoi:
;; Latch input bits in on rising edge of CLK, eight times for eight bits.
ldx #7
;; Get empty byte to load into.
lda #$00
pha
iec_rx_bit_loop:
;; Wait for CLK to release
jsr iec_wait_for_clk_release
;; (we do this implicitly below, with a tighter routine,
;; so that we don't have timing problems, as the requirements
;; are quite tight. Basically we need to read the clock and data
;; bit from the same byte read.
;; DATA now has the next bit, but inverted (well, except that it turns out not to be).
;; DATA is in bit 7, which is a bit annoying.
;; But we can clock it out with a ROL instruction
;; so that it is in C. We can then ROR it into the
;; partial data byte.
;; We use ROR so that we shift in from the top, so that
;; the first bit we shift in ends up in bit 0 after all
;; 8 bits have been read.
;; ODD: For some reason we don't need to invert the
;; received bits. This is weird, because we invert them
;; on the way out, and everything in the protocol seems
;; to indicate that we sould do so. But experimentation
;; has confirmed the bits don't need inversion on reception.
;; Move data bit into C flag, and loop until bit 6 clears
;; i.e., the clock has been released.
* lda CIA2_PRA
rol
bpl -
;; Pull it into the data byte
pla
ror
pha
;; Wait for CLK to be pulled again, over 300 usec (307 cycles on NTSC)
;; consider this a timeout
ldy #$19 ; 2 cycles
iec_rx_clk_wait2:
lda CIA2_PRA ; 4 cycles
rol ; 2 cycles, to put CLK in as the last bit
bpl + ; 2 cycles if not jumped
dey ; 2 cycles
bne iec_rx_clk_wait2 ; 3 cycles if jumped
;; Timeout
jsr kernalstatus_EOI
pla
plp
;; Restore registers
pla
tay
pla
tax
sec ; XXX confirm that sec is really a way to report timeout here
rts
*
;; More bits?
dex
bpl iec_rx_bit_loop
;; Then we must within 1000 usec acknowledge the frame by
;; pulling DATA. At this point, CLK is pulled by the
;; talker and DATA by us, i.e., we are ready to receive
;; the next byte. (p11).
jsr iec_release_clk_pull_data
;; Retreive the received byte
pla
;; Return no-error
plp
;; Restore registers
sta IEC_TMP2 ; $A4 is a byte buffer according to http://sta.c64.org/cbm64mem.html
pla
tay
pla
tax
lda IEC_TMP2
clc
rts
+7
View File
@@ -0,0 +1,7 @@
iec_set_idle:
lda CIA2_PRA
ora #BIT_CIA2_PRA_CLK_OUT ; pull
and #$FF - BIT_CIA2_PRA_DAT_OUT - BIT_CIA2_PRA_ATN_OUT ; release
sta CIA2_PRA
rts
+38
View File
@@ -0,0 +1,38 @@
;; According to http://www.zimmers.net/anonftp/pub/cbm/programming/serial-bus.pdf
;; pages 7--8.
;; See also https://www.pagetable.com/?p=1135, https://github.com/mist64/cbmbus_doc
iec_turnaround_to_listen:
;; Store .X and .Y on the stack - preserve them
txa
pha
tya
pha
;; Timing is critical here - execute on disabled IRQs
php
sei
;; Pull DATA, release CLK and ATN (we are not sending commands)
jsr iec_pull_data_release_atn_clk
;; Wait for clock line to be pulled by the drive
ldx #$FF ; XXX should we really use that high number?
*
lda CIA2_PRA
rol ; to put BIT_CIA2_PRA_CLK_IN as the last (sign) bit
bpl +
dex
bne -
;; Timeout - XXX what errors do original Kernal report?
plp
jmp iec_return_DEVICE_NOT_FOUND
;; CLK is pulled by the device, OK
*
plp
jmp iec_return_success
+29
View File
@@ -0,0 +1,29 @@
;; According to http://www.zimmers.net/anonftp/pub/cbm/programming/serial-bus.pdf
;; pages 7--8.
;; See also https://www.pagetable.com/?p=1135, https://github.com/mist64/cbmbus_doc
iec_turnaround_to_talk:
;; Store .X and .Y on the stack - preserve them
txa
pha
tya
pha
;; Timing is critical here - execute on disabled IRQs
php
sei
;; First make sure both CLK, DATA and ATN are released at our side
jsr iec_release_atn
jsr iec_release_clk_data
;; Wait till device releases CLK line
jsr iec_wait_for_clk_release
;; Pull CLK line, it should be held by talker
jsr iec_pull_clk_release_data
plp
jmp iec_return_success
+40
View File
@@ -0,0 +1,40 @@
;; Implemented based on https://www.pagetable.com/?p=1135, https://github.com/mist64/cbmbus_doc
;; Expects byte to send in IEC_TMP2 ($A4 is a byte buffer according to http://sta.c64.org/cbm64mem.html)
;; Carry flag set = signal EOI
;;
;; Preserves .X and .Y registers
iec_tx_byte:
;; Store .X and .Y on the stack - preserve them
txa
pha
tya
pha
;; Notify all devices that we are going to send a byte
;; and it is going to be a data byte (released ATN)
jsr iec_release_atn_clk_data
;; Common part of iec_txbyte and iec_tx_common - waits for devices
;; and transmits a byte
jsr iec_tx_common
;; Give device time to tell if they are busy by pulling DATA
;; They should do it within 1ms
ldx #$FF
* lda CIA2_PRA
;; BPL here is checking that bit 7 clears,
;; i.e, that the DATA line is pulled by drive
bpl +
dex
bne -
bpl iec_return_DEVICE_NOT_FOUND
*
jmp iec_return_success
+62
View File
@@ -0,0 +1,62 @@
;; Implemented based on https://www.pagetable.com/?p=1135, https://github.com/mist64/cbmbus_doc
;; Expects byte to send in IEC_TMP2 ($A4 is a byte buffer according to http://sta.c64.org/cbm64mem.html)
;; Carry flag set = signal EOI
;;
;; Preserves .X and .Y registers
iec_tx_command:
;; Store .X and .Y on the stack - preserve them
txa
pha
tya
pha
;; Notify all devices that we are going to send a byte
;; and it is going to be a command (pulled ATN)
jsr iec_pull_atn_clk_release_data
;; Give devices time to respond (response is mandatory!)
jsr iec_wait1ms
;; Did at least one device respond by pulling DATA?
lda CIA2_PRA
and #BIT_CIA2_PRA_DAT_IN ; XXX try to optimize this, move to separate routine
beq +
;; No devices present on the bus, so we can immediately return with device not found
jmp iec_return_DEVICE_NOT_FOUND
*
;; At least one device responded, but they are still allowed to stall
;; (can be busy processing something), we have to wait till they are all
;; ready (or bored with DOS attack...)
;; Release back CLK, keep DATA released - to ask devices for status.
jsr iec_release_clk_data
;; Common part of iec_txbyte and iec_tx_common - waits for devices
;; and transmits a byte
clc ; Carry flag set is used for EOI mark
jsr iec_tx_common
;; According to https://www.pagetable.com/?p=1135 there is some complicated and dangerous
;; flow here, but http://www.zimmers.net/anonftp/pub/cbm/programming/serial-bus.pdf (page 6)
;; advices to just wait 1ms and check the DATA status
jsr iec_wait1ms
lda CIA2_PRA
and #BIT_CIA2_PRA_DAT_IN ; XXX try to optimize this, move to separate routine
beq +
;; XXX possible optimization of the flow above: for many commands it is enough
;; to wait for the DATA being pulled, as confirmation is expected from
;; a single device only - but not sure if it's worth the trouble
jmp iec_return_DEVICE_NOT_FOUND
*
;; Done
jmp iec_return_success
+20
View File
@@ -0,0 +1,20 @@
;; Routine to finalize some IEC commands - which do not end in turnaround and are not followed by others
;; Implemented based on https://www.pagetable.com/?p=1135, https://github.com/mist64/cbmbus_doc
iec_tx_command_finalize:
;; Store .X and .Y on the stack - preserve them
txa
pha
tya
pha
;; Give device some time to complete command reception, release ATN,
;; give it some time again before (possible) next command
jsr iec_wait20us
jsr iec_set_idle
jsr iec_wait20us
jmp iec_return_success
+72
View File
@@ -0,0 +1,72 @@
;; This is a common part of iec_tx_byte and iec_tx_command
;; Implemented based on https://www.pagetable.com/?p=1135, https://github.com/mist64/cbmbus_doc
;; and http://www.zimmers.net/anonftp/pub/cbm/programming/serial-bus.pdf
;; Expects byte to send in IEC_TMP2 ($A4 is a byte buffer according to http://sta.c64.org/cbm64mem.html)
;; Carry flag set = signal EOI
iec_tx_common:
;; Timing is critical here - execute on disabled IRQs
php
sei
;; Wait till all receivers are ready, they should all release DATA
jsr iec_wait_for_data_release
;; At this point a delay 256 usec or more is considered EOI - add waits if necessary
bcc +
jsr iec_wait100us
jsr iec_wait100us
jsr iec_wait60us
;; XXX waits above should be enough - why do we need more waits???
jsr iec_wait100us
jsr iec_wait100us
jsr iec_wait100us
;; Receiver should now acknowledge EOI by pulling data for at least 60 usec
jsr iec_wait60us
jsr iec_wait_for_data_release
*
;; Pull CLK back to indicate that DATA is not valid, keep it for 60us
;; We can use this routine as we don't hold DATA anyway (and its state doesn't even matter)
jsr iec_pull_clk_release_data
jsr iec_wait60us
;; Now, we can start transmission of 8 bits of data
ldx #7
iec_tx_common_sendbit:
;; Is next bit 0 or 1?
lda IEC_TMP2
lsr
sta IEC_TMP2
bcs +
;; Bit is 0
jsr iec_release_clk_pull_data
jmp iec_tx_common_bit_is_sent
*
;; Bit is 1
jsr iec_release_clk_data
iec_tx_common_bit_is_sent:
;; Wait 20us, so that device(s) can pick DATA
jsr iec_wait20us
;; Pull CLK for 20us again, before sending the next bit
;; or performing any other action
jsr iec_pull_clk_release_data
jsr iec_wait20us ; XXX this might be an overkill, there is a lot of code besides this wait here - few NOPs might be enough
;; More bits to send?
dex
bpl iec_tx_common_sendbit
plp
rts ; Flow continues differently for data/command
+15
View File
@@ -0,0 +1,15 @@
;; Flush the IEC output buffer (if not empty) - send byte with EOI
;;
;; Preserves .X, .Y and .A registers
iec_tx_flush:
pha
lda C3PO
beq +
sec ; send it with EOI
jsr iec_tx_byte ; send the command regardless of the status
*
pla
rts
+22
View File
@@ -0,0 +1,22 @@
iec_wait100us:
;; Wait 100usec
;; PAL:
;; - CPU frequency 0.985248 MHz, we need to waste at least 99 cycles
;; NTSC:
;; - CPU frequency 1.022727 MHZ, we need to waste at least 103 cycles
;; Waste cycles in a loop
ldy #$12 ; 2 cycles
* dey ; 2 cycles * 18
bpl - ; 3 cycles * 17 + 2 cycles
rts ; 6 cycles
;; 6 cycles JSR to routine,
;; 97 cycles routine with RTS
;; 1 cycle to fetch next instruction
;; ---
;; 104 cycles
+20
View File
@@ -0,0 +1,20 @@
;;
;; Wait 1 ms (1000 usec)
;;
;; On NTSC this means 1023 cycles (slightly less on PAL, but we have to be sure).
;; We can't count on badlines, as the screen might be disabled.
;; Delay here is implemeented using VIC-II raster register. Since one raster is
;; 63 cycles, we need at least 17 full rasters to be 100% sure we wait enough
iec_wait1ms:
ldx #18 ; we probably won't start with the beginning of raster
lda VIC_RASTER
*
cmp VIC_RASTER
beq -
lda VIC_RASTER
dex
bne -
rts
+22
View File
@@ -0,0 +1,22 @@
iec_wait20us:
;; Wait 20usec
;; PAL:
;; - CPU frequency 0.985248 MHz, we need to waste at least 20 cycles
;; NTSC:
;; - CPU frequency 1.022727 MHZ, we need to waste at least 21 cycles
;; Waste cycles by reading some unimportant memory location
;; in order not to clutter VICE debug logs
ora $03FF ; 4 cycles
ora $03FF ; 4 cycles
rts ; 6 cycles
;; 6 cycles JSR to routine,
;; 14 cycles routine with RTS
;; 1 cycle to fetch next instruction
;; ---
;; 21 cycles
+23
View File
@@ -0,0 +1,23 @@
iec_wait60us:
;; Wait 60usec
;; PAL:
;; - CPU frequency 0.985248 MHz, we need to waste at least 60 cycles
;; NTSC:
;; - CPU frequency 1.022727 MHZ, we need to waste at least 62 cycles
;; Waste cycles in a loop
ldy #$0A ; 2 cycles
* dey ; 2 cycles * 10
bpl - ; 3 cycles * 9 + 2 cycles
rts ; 6 cycles
;; 6 cycles JSR to routine,
;; 57 cycles routine with RTS
;; 1 cycle to fetch next instruction
;; ---
;; 64 cycles
@@ -0,0 +1,7 @@
iec_wait_for_clk_release:
lda CIA2_PRA
and #BIT_CIA2_PRA_CLK_IN
beq iec_wait_for_clk_release
rts
+8
View File
@@ -0,0 +1,8 @@
iec_wait_for_data_pull:
lda CIA2_PRA
;; Check the highest bit, which is DATA IN,
;; (highest bit set = negative value)
bmi iec_wait_for_data_pull
rts
@@ -0,0 +1,8 @@
iec_wait_for_data_release:
lda CIA2_PRA
;; Check the highest bit, which is DATA IN,
;; (highest bit set = negative value)
bpl iec_wait_for_data_release
rts
-5
View File
@@ -1,5 +0,0 @@
iec_assert_atn:
lda $dd00
ora #$08
sta $dd00
rts
-6
View File
@@ -1,6 +0,0 @@
iec_assert_clk_and_data:
lda $dd00
and #$0b
ora #$30
sta $dd00
rts
-6
View File
@@ -1,6 +0,0 @@
iec_assert_clk_release_data:
lda $dd00
and #$0b
ora #$10
sta $dd00
rts
-5
View File
@@ -1,5 +0,0 @@
iec_assert_data:
lda $dd00
ora #$20
sta $dd00
rts
-11
View File
@@ -1,11 +0,0 @@
iec_release_atn:
lda $dd00
and #$f7
sta $dd00
;; Also clear EOI marker
lda IOSTATUS
and #$bf
sta IOSTATUS
rts
-5
View File
@@ -1,5 +0,0 @@
iec_release_clk:
lda $dd00
and #$2b
sta $dd00
rts
-6
View File
@@ -1,6 +0,0 @@
iec_release_clk_and_data:
lda $DD00
and #$0b
sta $DD00
rts
-114
View File
@@ -1,114 +0,0 @@
;; Receive a byte from the IEC bus.
;; reference http://www.zimmers.net/anonftp/pub/cbm/programming/serial-bus.pdf
;; page 11.
iec_rx_byte:
;; First, we wait for the talker to release the CLK line.
jsr iec_wait_for_clock_release
;; We then release the data line
;; (We can use this routine, since we weren't holding CLK, anyway)
jsr iec_release_clk_and_data
;; Wait for talker to assert CLK.
;; If >200usec, then it is EOI and we have to assert the
;; DATA line for 60 usec to tell the TALKER that we have
;; acknowledged the EOI.
ldx #20
iec_rx_clk_wait:
;; Loop takes 11 usec, so ~20 iterations for 200usec timeout
lda $dd00
rol
bpl not_eoi
dex
cpx #$21
bne not_rx_timeout
;; Time out waiting for CLK to assert again.
;; = error
sec
rts
not_rx_timeout:
cpx #$00
bpl iec_rx_clk_wait
;; Remember EOI condition
lda IOSTATUS
ora #$40
sta IOSTATUS
;; EOI timeout: So pulse DATA line for 60 usec
jsr iec_assert_data
jsr iec_wait60us
jsr iec_release_clk_and_data
;; And still wait for CLK to be asserted
;; XXX - This will cause periodic EOI pulses if the sender takes too long.
;; That is probably ok.
ldx #$7f
jmp iec_rx_clk_wait
not_eoi:
;; CLK is now low. Latch input bits in on rising edge
;; of CLK, eight times for eight bits.
ldx #7
;; Get empty byte to load into.
lda #$00
pha
iec_rx_bit_loop:
;; Wait for CLK to release
;; jsr iec_wait_for_clock_release
;; (we do this implicitly below, with a tighter routine,
;; so that we don't have timing problems, as the requirements
;; are quite tight. Basically we need to read the clock and data
;; bit from the same byte read.
;; DATA now has the next bit, but inverted (well, except that it turns out not to be).
;; DATA is in bit7, which is a bit annoying.
;; But we can clock it out with a ROL instruction
;; so that it is in C. We can then ROR it into the
;; partial data byte.
;; We use ROR so that we shift in from the top, so that
;; the first bit we shift in ends up in bit 0 after all
;; 8 bits have been read.
;; ODD: For some reason we don't need to invert the
;; received bits. This is weird, because we invert them
;; on the way out, and everything in the protocol seems
;; to indicate that we sould do so. But experimentation
;; has confirmed the bits don't need inversion on reception.
;; Move data bit into C flag, and loop until bit 6 clears
;; i.e., the clock has been released.
* LDA $DD00
ROL
bpl -
;; Pull it into the data byte
pla
ROR
pha
;; Wait for CLK to re-assert
jsr iec_wait_for_clock_assert
;; More bits?
dex
bpl iec_rx_bit_loop
;; Then we must within 1000usec acknowledge the frame by
;; asserting DATA. At this point, CLK is asserted by the
;; talker and DATA by us, i.e., we are ready to receive
;; the next byte. (p11).
jsr iec_assert_data
;; Retreive the received byte
PLA
;; Return no-error
CLC
RTS
-39
View File
@@ -1,39 +0,0 @@
;; According to http://www.zimmers.net/anonftp/pub/cbm/programming/serial-bus.pdf
;; pages 7--8.
iec_turnaround_to_listen:
;; Assert data and release clock
lda $dd00
and #$ef ; release clock (bit 4)
ora #$20 ; assert data (bit 5)
sta $dd00
;; Wait for clock line to be asserted by the drive
* lda $dd00
and #$40
bne -
;; http://www.zimmers.net/anonftp/pub/cbm/programming/serial-bus.pdf
;; page 8 tells us we should not do anything here after waiting for
;; the clock line to assert.
ldx #$ff
* lda $dd00
and #$40
bne +
dex
bne -
;; jsr printf
;; .byte "TURNAROUND FAILED - FILE NOT FOUND?",$0d,$00
;; ;; Timeout = file not found error
;; ;; (https://www.pagetable.com/?p=1023)
lda #4
sec
rts
*
;; ATN turn around successful
clc
rts
Loaded 100 of 279 files, more files were not shown because too many files have changed in this diff. Show more