diff --git a/CREDITS.md b/CREDITS.md index d4bef889..c1a3082a 100644 --- a/CREDITS.md +++ b/CREDITS.md @@ -5,7 +5,7 @@ * Retrofan - for his Mega65 banner artwork and PXLfont * TWW/CTR - for his keyboard handling code -* Graham - for his PAL/NTSC detection routine +* Graham - for his PAL/NTSC detection code and compact 8x8 multiplication routine * enthusi/Onslaught - for his example Turbo Tape 64 compatible loader * djmips - for fast 8x8 multiplication routine * Verz - for the integer division routine @@ -24,6 +24,11 @@ * silverdr - for the floating point routines [description](https://codebase64.org/doku.php?id=base:kernal_floating_point_mathematics) * the [C64 Wiki](https://www.c64-wiki.com) contributors +## other + +* Gábor Lénárt - for his work on [XEMU Mega65 emulator](https://github.com/lgblgblgb/xemu) +* Mads Nielsen - for the [Kick Assembler](http://www.theweb.dk/KickAssembler/Main.html#frontpage) +
* ... and all the others we forgot diff --git a/Makefile b/Makefile index 7dcd2041..498de7f4 100644 --- a/Makefile +++ b/Makefile @@ -14,14 +14,15 @@ SRCDIR_BASIC = $(SRCDIR_COMMON) \ src/basic/,stubs_math \ src/basic/assets \ src/basic/basic_commands \ - src/basic/basic_commands_CC \ - src/basic/basic_commands_CD \ + src/basic/basic_commands_01 \ + src/basic/basic_commands_02 \ src/basic/basic_operators \ src/basic/basic_functions \ src/basic/board_m65 \ src/basic/board_x16 \ - src/basic/editor \ - src/basic/engine \ + src/basic/engine_editor \ + src/basic/engine_runtime \ + src/basic/engine_variables \ src/basic/init \ src/basic/math \ src/basic/math_consts \ @@ -329,7 +330,7 @@ $(DIR_M65)/OUTK_0.BIN $(DIR_M65)/KERNAL_0_combined.vs $(DIR_M65)/KERNAL_0_combin $(DIR_M65)/basic.seg_1 $(DIR_M65)/BASIC_1_combined.vs $(DIR_M65)/BASIC_1_combined.sym: @mkdir -p $(DIR_M65) @rm -f $@* $(DIR_M65)/basic.seg_1 $(DIR_M65)/BASIC_1* - @$(TOOL_BUILD_SEGMENT) -a ../../$(TOOL_ASSEMBLER) -r M65 -s BASIC_1 -i BASIC_1-mega65 -o basic.seg_1 -d $(DIR_M65) -l 4000 -h 5fff $(CFG_M65) $(GEN_STR_M65) $(SRCDIR_BASIC) $(GEN_BASIC) + @$(TOOL_BUILD_SEGMENT) -a ../../$(TOOL_ASSEMBLER) -r M65 -s BASIC_1 -i BASIC_1-mega65 -o basic.seg_1 -d $(DIR_M65) -l 4000 -h 7fff $(CFG_M65) $(GEN_STR_M65) $(SRCDIR_BASIC) $(GEN_BASIC) $(DIR_M65)/kernal.seg_1 $(DIR_M65)/KERNAL_1_combined.vs $(DIR_M65)/KERNAL_1_combined.sym: @mkdir -p $(DIR_M65) @@ -408,29 +409,27 @@ build/symbols_hybrid.vs: $(DIR_GEN)/KERNAL_combined.vs # Rules - platform 'Mega65' specific -build/padding_08_KB: - dd if=/dev/zero bs=8192 count=1 of=build/padding_08_KB +build/padding_16_KB: + @mkdir -p build + dd if=/dev/zero bs=8192 count=2 of=build/padding_16_KB build/padding_64_KB: + @mkdir -p build dd if=/dev/zero bs=8192 count=8 of=build/padding_64_KB -$(TARGET_M65_x) $(TARGET_M65_x_PXL): build/padding_08_KB build/padding_64_KB $(SEG_LIST_M65) build/chargen_openroms.rom build/chargen_openroms.patched build/chargen_pxlfont.rom build/chargen_pxlfont.patched +$(TARGET_M65_x) $(TARGET_M65_x_PXL): build/padding_16_KB build/padding_64_KB $(SEG_LIST_M65) build/chargen_openroms.rom build/chargen_openroms.patched build/chargen_pxlfont.rom build/chargen_pxlfont.patched @echo - cat build/padding_08_KB > $(TARGET_M65_x) - cat build/padding_08_KB >> $(TARGET_M65_x) + cat build/padding_16_KB > $(TARGET_M65_x) cat $(DIR_M65)/kernal.seg_1 >> $(TARGET_M65_x) cat $(DIR_M65)/basic.seg_1 >> $(TARGET_M65_x) - cat build/padding_08_KB >> $(TARGET_M65_x) cat $(DIR_M65)/basic.seg_0 >> $(TARGET_M65_x) cat build/chargen_openroms.rom >> $(TARGET_M65_x) cat build/chargen_openroms.patched >> $(TARGET_M65_x) cat $(DIR_M65)/kernal.seg_0 >> $(TARGET_M65_x) cat build/padding_64_KB >> $(TARGET_M65_x) @echo - cat build/padding_08_KB > $(TARGET_M65_x_PXL) - cat build/padding_08_KB >> $(TARGET_M65_x_PXL) + cat build/padding_16_KB > $(TARGET_M65_x_PXL) cat $(DIR_M65)/kernal.seg_1 >> $(TARGET_M65_x_PXL) cat $(DIR_M65)/basic.seg_1 >> $(TARGET_M65_x_PXL) - cat build/padding_08_KB >> $(TARGET_M65_x_PXL) cat $(DIR_M65)/basic.seg_0 >> $(TARGET_M65_x_PXL) cat build/chargen_pxlfont.rom >> $(TARGET_M65_x_PXL) cat build/chargen_pxlfont.patched >> $(TARGET_M65_x_PXL) diff --git a/README.md b/README.md index aa1af581..fa697474 100644 --- a/README.md +++ b/README.md @@ -1,14 +1,18 @@ -# open-roms +# Open ROMs + +![screenshot demonstrating some features](./doc/screenshot-demo.png) A project to create unencumbered open-source ROMs for use on selected retro computers. Besides this manifest, the following documents are available: * [implementation status](./STATUS.md) of various APIs and functionalities * [configuration options](./CONFIG.md) for those willing to compile their own, customized ROM set -* [BASIC extensions](doc/Extended-BASIC.md) -* [development guide](./doc/Development.md) for those interested in OpenROMs technical aspects +* [BASIC extensions](./doc/Extended-BASIC.md) +* [development guide](./doc/Development.md) for those interested in technical aspects * [license](./LICENSE) information and list of major contributors * [credits](./CREDITS.md) to people whose work was of great help to us +To download pre-built ROM images, go [here](./bin). + # Problem Statement and Motivation The copyrights of various old computer system ROMs are still alive, and together with trademarks, can present significant diff --git a/STATUS.md b/STATUS.md index 276414db..ed8966a0 100644 --- a/STATUS.md +++ b/STATUS.md @@ -11,6 +11,12 @@ Here are the features of the Open ROMs not found in the original ROMs from the 8 * JiffyDOS and DolphinDOS protocols support * DOS wedge (direct mode only) - `@`, `@`, `@$`, `@$`, `@` * BASIC extensions, see the [documentation](doc/Extended-BASIC.md) +* extended / tweaked `LOAD` / `VERIFY` commands + * 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 + * command without parameters tries to load first file from drive chosen as above +* `LIST` command should never damage the screen if trying to list memory content which is not a BASIC program +* high performance garbage collector * turbo tape load support (as device 7, or using `←L` / `←M`, optionally with a file name), quite sophisticated: up to 250 blocks (can store bytes under I/O), automatically adjusts for tape speed differences * normal tape load error log is limited by free stack space only (no artificial limitation like in original ROMs) @@ -18,12 +24,6 @@ Here are the features of the Open ROMs not found in the original ROMs from the 8 * improved support for tape adapters (for using regular casette players and other audio devices instead of Datasette) and emulators * built-in tape head align tool (only feasible to use on machines with extended memory, like Mega65) -* extended / tweaked `LOAD` / `VERIFY` commands - * 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 - * command without parameters tries to load first file from drive chosen as above -* `LIST` command should never damage the screen if trying to list memory content which is not a BASIC program - * uses RAM under ROM and I/O: 51199 bytes free (up to `$CFFF`) by default, but 61438 is also possible * cold/warm start silences multiple SID chips * warm start due to BRK prints out the instruction address @@ -42,9 +42,8 @@ The following ROM features are currently missing and are not planned due to spac The following ROM features are currently missing: * most BASIC commands -* BASIC variables -* BASIC expression handling -* most floating point routines +* BASIC integer/float variables/arrays (strings work now, with the exception of undefined arrays) +* BASIC expression handling (again, strings should work now) * RS-232 support * NMI handling is incomplete diff --git a/bin/README.txt b/bin/README.txt index 7358db92..806e59cf 100644 --- a/bin/README.txt +++ b/bin/README.txt @@ -22,6 +22,6 @@ Have fun! ------ -PXL font was created by Retrofan, we got a permission to include it with OpenROMs under GNU Lesser General Public License 3.0, see: +PXL font was created by Retrofan, we got a permission to include it with Open ROMs under GNU Lesser General Public License 3.0, see: - https://www.forum64.de/index.php?thread/84000-neuer-c64-systemfont-auch-plus4-c128-atari/&postID=1493383#post1493383 diff --git a/bin/basic_generic.rom b/bin/basic_generic.rom index dc9dba7b..447fd20d 100644 Binary files a/bin/basic_generic.rom and b/bin/basic_generic.rom differ diff --git a/bin/basic_ultimate64.rom b/bin/basic_ultimate64.rom index 804c3705..5ae0f03b 100644 Binary files a/bin/basic_ultimate64.rom and b/bin/basic_ultimate64.rom differ diff --git a/bin/kernal_generic.rom b/bin/kernal_generic.rom index 75684fcc..9a23705a 100644 Binary files a/bin/kernal_generic.rom and b/bin/kernal_generic.rom differ diff --git a/bin/kernal_ultimate64.rom b/bin/kernal_ultimate64.rom index 379d1847..76f62af3 100644 Binary files a/bin/kernal_ultimate64.rom and b/bin/kernal_ultimate64.rom differ diff --git a/bin/mega65.rom b/bin/mega65.rom index c299e1c5..643e1484 100644 Binary files a/bin/mega65.rom and b/bin/mega65.rom differ diff --git a/bin/mega65_pxlfont.rom b/bin/mega65_pxlfont.rom index e496e285..92655da7 100644 Binary files a/bin/mega65_pxlfont.rom and b/bin/mega65_pxlfont.rom differ diff --git a/doc/Development.md b/doc/Development.md index 2a834a22..29655ae6 100644 --- a/doc/Development.md +++ b/doc/Development.md @@ -1,5 +1,5 @@ -# OpenROMs development guide +# Open ROMs development guide NOTE: this document is a preliminary version, definitely incomplete! @@ -10,30 +10,30 @@ NOTE: this document is a preliminary version, definitely incomplete! - [DolphinDOS](./Protocol-DolphinDOS.md) -## Guidelines for software developers for OpenROMs compatibility +## Guidelines for software developers for Open ROMs compatibility -Most important: always test your software on the original ROMs too. If your code works on the OpenROMs, but fails on the original firmware - than something is clearly wrong, and it might stop working once we make OpenROMs more compatible for one reason or another. +Most important: always test your software on the original ROMs too. If your code works on the Open ROMs, but fails on the original firmware - than something is clearly wrong, and it might stop working once we make Open ROMs more compatible for one reason or another. ### Unofficial ROM APIs -Please, do not use any internal/unofficial OpenROMs API. They WILL change in an incompatible way, you may believe me. Using unofficial API of the original ROMs is OK if the routine is marked as supported in the [implementation status](../STATUS.md) document. +Please, do not use any internal/unofficial Open ROMs API. They WILL change in an incompatible way, you may believe me. Using unofficial API of the original ROMs is OK if the routine is marked as supported in the [implementation status](../STATUS.md) document. -### Compatibility with OpenROMs for Mega65 +### Compatibility with Open ROMs for Mega65 -The Mega65 OpenROMs build aims to provide a C64-compatible memory map in range `$00000-$0FFFF`. For `$10000` and above, everything is still subject to change. +The Mega65 Open ROMs build aims to provide a C64-compatible memory map in range `$00000-$0FFFF`. For `$10000` and above, everything is still subject to change. Please note, that certain ROM routines are moved to additional Mega65 ROM area (2x8KB is not enough to implement full ROM functionality and additional features) - original locations contain just short compatibility code which remaps memory, calls the real routine, and restores default mapping (that means all blocks unmapped). This shouldn't be a problem for original C64 software, but can make a difference for Mega65-aware code; thus, please follow these simple rules: - do not call ROM routines with .B set to anything other than 0 (and .B set to 0x40 or above is a receipe for disaster!) - be aware that ROM routines may restore the default memory mapping by means of MAP/EOM -OpenROMs interrupt handlers do not touch the ROM mapping, range `0x4000-0xBFFF` can be freely mapped without disabling IRQ or NMI. The .Z register is mostly safe to use too - some routines might use it, but they will alwayys restore it's previous state. Please be aware, that for maximum compatibility our IRQ/NMI handlers DO NOT store/restore .Z register. +Open ROMs interrupt handlers do not touch the ROM mapping, range `0x4000-0xBFFF` can be freely mapped without disabling IRQ or NMI. The .Z register is mostly safe to use too - some routines might use it, but they will alwayys restore it's previous state. Please be aware, that for maximum compatibility our IRQ/NMI handlers DO NOT store/restore .Z register. ### API extensions #### PETSCII -OpenROMs provides support for several additional PETSCII codes (all compatible with C128 and/or C65): +Open ROMs provides support for several additional PETSCII codes (all compatible with C128 and/or C65): | PETSCII code | description | | :----------: | :-------------------------------------------------- | @@ -69,7 +69,7 @@ Mega65 build starts in legacy mode, which is intended to be reasonably compatibl - Slightly different chargen. On C64 machines pressing C= + G or C= + M key combinations produces the same visual result as C= + H or C= + N, respectively - despite keycap printing suggests they should produce tinner bars. This was intentional change in the C64 ROMs (compared to VIC-20), to prevent colour problems on 80s era TVs. Screen font used in the legacy mode duplicates this change, but the font intended for native mode has this change reverted back. Additionally, the π sign is available for lower/upper case set too. -## Tinkering with OpenROMs +## Tinkering with Open ROMs Make sure to read the main [README](../README.md) first - although any help with the project is always welcome, you need to be aware of the possible legal problems we want to avoid. @@ -77,19 +77,19 @@ Make sure to read the main [README](../README.md) first - although any help with List of the most important make targets: -| target | description | -| :------------------ | :----------------------------------------------------------------------------- | -| `all` | builds all ROMs, places them in 'build' subdirectory | -| `clean` | removes all the compilation results and intermediate files | -| `updatebin` | upates ROMs in 'bin' subdirectory - with embedded version string, for release | -| `testsimilarity` | launches the similarity tool, see [README](../README.md) | -| `test` | builds the 'custom' configuration, launches it using VICE emulator | -| `test_generic` | builds the default ROMs, for generic C64/C128, launches using VICE | -| `test_generic_x128` | as above, but launches C128 emulator instead | -| `test_mega65` | builds the Mega65 ROM, launches it using XEMU emulator | -| `test_ultimate64` | builds the Ultimate 64 configuration, launches it using VICE emulator | -| `test_hybrid` | builds a hybrid ROM (OpenROMs Kernal + original BASIC), launches it using VICE | -| `test_testing` | builds a rather odd testing configuration, launches it using VICE emulator | +| target | description | +| :------------------ | :------------------------------------------------------------------------------ | +| `all` | builds all ROMs, places them in 'build' subdirectory | +| `clean` | removes all the compilation results and intermediate files | +| `updatebin` | upates ROMs in 'bin' subdirectory - with embedded version string, for release | +| `testsimilarity` | launches the similarity tool, see [README](../README.md) | +| `test` | builds the 'custom' configuration, launches it using VICE emulator | +| `test_generic` | builds the default ROMs, for generic C64/C128, launches using VICE | +| `test_generic_x128` | as above, but launches C128 emulator instead | +| `test_mega65` | builds the Mega65 ROM, launches it using XEMU emulator | +| `test_ultimate64` | builds the Ultimate 64 configuration, launches it using VICE emulator | +| `test_hybrid` | builds a hybrid ROM (Open ROMs Kernal + original BASIC), launches it using VICE | +| `test_testing` | builds a rather odd testing configuration, launches it using VICE emulator | ### Code segments and ROM layouts @@ -97,7 +97,7 @@ List of the most important make targets: Currently there are 3 ROM layouts defined: - `STD` - with 2 code segments: `BASIC` (`$A000-$E4D2`, where `$C000-$DFFF` is a skip-gap for RAM and I/O area) and `KERNAL` (`$E4D3 - $FFFF`) -- `M65` - where `BASIC` becames `BASIC_0` and `KERNAL` becames `KERNAL_0`, additional segments might be added to the build system in the future; at the moment of writing this document additional 8KB of ROM is defined as `BASIC_1` segment and additional 8KB of ROM is defined as `KERNAL_1` segment +- `M65` - where `BASIC` becames `BASIC_0` and `KERNAL` becames `KERNAL_0`, additional segments might be added to the build system in the future; at the moment of writing this document additional 16KB of ROM is defined as `BASIC_1` segment and additional 8KB of ROM is defined as `KERNAL_1` segment - `X16` - memory layout for the Commander X16 machine To check for current ROM layout or code segment use KickAssembler preprocessor defines, like `ROM_LAYOUT_STD`, `ROM_LAYOUT_M65`, `SEGMENT_BASIC`, `SEGMENT_KERNAL_1`. diff --git a/doc/Extended-BASIC-TODO.md b/doc/Extended-BASIC-TODO.md new file mode 100644 index 00000000..7f2ce4a7 --- /dev/null +++ b/doc/Extended-BASIC-TODO.md @@ -0,0 +1,65 @@ + +# Planned BASIC features, when V2 compatibility is reached + +Ideas for the future, most of them suitable for Mega65 or other power machines only + +* sound support +* 2D graphics support +* turtle graphics +* sprite support, including collision callback +* custom character set support +* sprite/character design within program, in a way similar to Simons BASIC +* joystick/mouse/lightpen/paddle commands/functions +* matrix operations +* `DISPOSE` with variable/array as parameter should remove the variable/array from memory +* `BLOAD`, `BVERIFY` and `BSAVE` should have syntax compatible with BASIC V7/V10 +* it should be possible to intercept Kernal errors from BASIC (prevent `?FILE NOT FOUND ERROR IN ...`, etc.); `ON ERROR GOTO` ? +* support for numbers in hexadecimal and binary formats +* `CGOTO` and `CGOSUB` - computatiuonal versions, should accept expressions +* `LABEL`, `LGOTO` and `LGOSUB` - jump to label +* some kind of subroutines with local variable namespace, possibly loaded from disc (like in Warsaw Basic 3.2) +* for Mega65 mode, move variables to a separate memory area, consider extending variable name length +* `←V` (verify from tape) - if Kernal is extended to offer this feature +* modulo function or opeerator +* `DPEEK`, `DPOKE`, `QPEEK`, `QPOKE` - 2/4 byte `PEEK` and `POKE` variants +* all the functions/commands accepting memory addresses should be able to access the whole Mega65 memory +* ability to limit memory used by basic to standard 38K or to 46K (memory model switch) +* `XOR` operator +* `AUTO` - line auto numbering +* `RENUMBER` for chanign the line numbers +* `IF ... THEN ... ELSE`, `BEGIN ... BEND` +* consider `BOOT` command +* possibly some commands for creating menus and dialog boxes +* more configurable `INPUT` +* `PRINT USING`, ability to position cursor, ability to print result in the center of the screen +* `CURSOR` command from BASIC V10 +* `RESTORE` should accept lline number as argument +* hex/dec conversion functions +* `DELETE` command to delete several BASIC lines, as in BASIC V10 +* `FOR` loop should accept integer variable as index +* `FETCH`, `STASH`, `SWAP` - REU support +* `DMA` command for Mega65 +* geoRAM support +* `GO 64` / `GO 65` should enable/disable C64 compatibility mode on Mega65 +* `NSYS` for Mega65 - native `SYS` for Mega65, should not switch to C64 compatibilty mode +* `DO ... LOOP`, `DO ... UNTIL`, `DO ... WHILE`, `EXIT` +* `SEEK#` to read-and-forget n bytes +* `RECORD#` command from BASIC V10 +* `GETKEY` from BASIC V10 +* `HELP` command from BASIC V7/V10 +* function to find substring position +* `WINDOW` command from BASIC V7 +* functions to return cursor position +* `TRAP` and `RESUME` +* `SET DEF` and `SET DISK` from BASIC V10 +* `SLEEP` from BASIC V10 +* `TRON` / `TROFF` - program tracing +* `TYPE` command from BASIC V10 +* `RUN` should be able to run program from device, as in BASIC V10 +* `PAGE` and `DELAY` commands from Simons BASIC, or something similar +* `DUMP` command from Simons BASIC, or something similar +* it should be possbile to assign to `TI` special variable +* function to insert a substring starting from given position +* function to generate string of n duplicated characters +* function to retrieve fractional part of a number +* command to fill text screen area with a character, inverse screen area, scroll, or change fg/bg color of screen area diff --git a/doc/Extended-BASIC.md b/doc/Extended-BASIC.md index dd48b323..42765376 100644 --- a/doc/Extended-BASIC.md +++ b/doc/Extended-BASIC.md @@ -7,19 +7,19 @@ NOTE: Command syntax, behaviour details, and tokens are still subject to change! The DOS Wedge commands are only available in direct mode, and they have to start from the first character of the line. -### `@` +### `@` (all) Displays the error/status read from the current drive. Current drive is either the last device used by any I/O command, the one set by DOS Wedge command, or 8 as a fallback. -### `@$` +### `@$` (all) Displays the directory of the current drive. Does not destroy BASIC program in memory. -### `@device_number` +### `@device_number` (all) Changes the current drive number. -### `@command` +### `@command` (all) Sends the DOS command to the current drive. @@ -27,44 +27,67 @@ Sends the DOS command to the current drive. The Tape Wedge commands are only available in direct mode, and they have to start from the first character of the line. -### `←L ["file_name"]` +### `←L ["file_name"]` (all) Loads the file from tape. Depending on the configuration, it tries to load the file in TurboTape 64 format, in the standard CBM format, or autodetects the file format. -### `←M ["file_name"]` +### `←M ["file_name"]` (all) Like above, but merges a BASIC program to the one already stored in memory. -### `←H` +### `←H` (Mega65) -Launches a built-in tape head alignment tool. Destorys program in memory. Press `RUN/STOP` to terminate the tool. +Launches a built-in tape head alignment tool. Destroys program in memory. Press `RUN/STOP` to terminate the tool. -## Additional BASIC commands +## Additional BASIC commands - I/O -### `FAST` - -Tries to switch the machine to turbo mode - details differ depending on the configured machine / motherboard. - -### `SLOW` - -Tries to switch the machine back to 1 MHz operation mode. - -### `OLD` - -Tries to restore program destroyed by `NEW` or a reset. - -### `MERGE "file_name" [, device_number]` +### `MERGE "file_name" [, device_number]` (all) Appends the BASIC program from a storage medium to the one currently present in memory. -### `BLOAD "file_name", device_number, start_address` +### `BLOAD "file_name", device_number, start_address` (all) Loads a binary file starting from the given memory location. Does not clear variables, does not perform BASIC program relinking, etc. NOTE: for now syntax differs from the BASIC V3.5+ - this will be changed once the necessary BASIC infrastructure is implemented. -### `BVERIFY "file_name", device_number, start_address` +### `BVERIFY "file_name", device_number, start_address` (all) Verify operation for the binary data starting from a given addres. NOTE: for now syntax differs from the BASIC V3.5+ - this will be changed once the necessary BASIC infrastructure is implemented. -### `BSAVE "file_name", device_number, start_address, end_address` +### `BSAVE "file_name", device_number, start_address, end_address` (all) Saves the binary data from the given memory area. NOTE: for now syntax differs from the BASIC V3.5+ - this will be changed once the necessary BASIC infrastructure is implemented. + +## Additional BASIC commands - misc + +### `COLD` (Mega65) + +Resets the machine. In direct mode asks for confirmation first. + +### `FAST` (all) + +Tries to switch the machine to turbo mode - details differ depending on the configured machine / motherboard. + +### `SLOW` (all) + +Tries to switch the machine back to 1 MHz operation mode. + +### `OLD` (all) + +Tries to restore program destroyed by the `NEW` command or a reset. + +### `MEM` (Mega65) + +Displays BASIC memory usage information: +* `TEXT` - size of BASIC program text, always at least 2 bytes are used +* `VARS` - bytes occupied by float and integer variables, string variable descriptors, and function descriptors +* `ARRS` - bytes occupied by arrays (note: for string arrays only descriptors are stored here) +* `STRS` - bytes occupied by strings, also the ones belonging to arrays +* `FREE` - unused space + +### `CLEAR` (all) + +Clears the screen content. + +### `DISPOSE` (all) + +Runs the garbage collector - disposes outdated strings. diff --git a/doc/screenshot-demo.png b/doc/screenshot-demo.png new file mode 100644 index 00000000..d9fec2f9 Binary files /dev/null and b/doc/screenshot-demo.png differ diff --git a/src/aliases/,aliases_config.s b/src/aliases/,aliases_config.s index 42c8166b..ae1798de 100644 --- a/src/aliases/,aliases_config.s +++ b/src/aliases/,aliases_config.s @@ -364,3 +364,10 @@ .const CONFIG_COLOR_TXT = $01 #endif + + +// Determine if we need space-savings in BASIC code + +#if !ROM_LAYOUT_M65 +#define HAS_SMALL_BASIC +#endif diff --git a/src/aliases/,aliases_cpu.s b/src/aliases/,aliases_cpu.s index d0f29fad..3cf72b6a 100644 --- a/src/aliases/,aliases_cpu.s +++ b/src/aliases/,aliases_cpu.s @@ -425,3 +425,17 @@ __l: __l: #endif } + + +// +// Near jump, on some CPUs can be substituted with shorter instruction +// + +.pseudocommand jmp_8 dst +{ +#if HAS_OPCODES_65C02 + bra dst +#else + jmp dst +#endif +} diff --git a/src/aliases/,aliases_ram_lowmem.s b/src/aliases/,aliases_ram_lowmem.s index eb492b70..ef37b7ac 100644 --- a/src/aliases/,aliases_ram_lowmem.s +++ b/src/aliases/,aliases_ram_lowmem.s @@ -35,8 +35,8 @@ .label RESHO = $26 // $26-$2A temporary variables, [!] our usage might be different .label TXTTAB = $2B // $2B-$2C start of BASIC code .label VARTAB = $2D // $2D-$2E end of BASIC code, start of variables - .label ARYTAB = $2F // $2F-$30 -- NOT IMPLEMENTED -- - .label STREND = $31 // $31-$32 -- NOT IMPLEMENTED -- + .label ARYTAB = $2F // $2F-$30 pointer to start of array storage + .label STREND = $31 // $31-$32 pointer to start of free RAM .label FRETOP = $33 // $33-$34 pointer to bottom of strings area .label FRESPC = $35 // $35-$36 [!] our implementation uses this as temporary string pointer .label MEMSIZ = $37 // $37-$38 highest address of BASIC memory + 1 @@ -46,14 +46,14 @@ .label DATLIN = $3F // $3F-$40 -- NOT IMPLEMENTED -- .label DATPTR = $41 // $41-$42 pointer for READ/DATA copmmands .label INPPTR = $43 // $43-$44 -- NOT IMPLEMENTED -- - .label VARNAM = $45 // $45-$46 -- NOT IMPLEMENTED -- - .label VARPNT = $47 // $47-$48 -- NOT IMPLEMENTED -- + .label VARNAM = $45 // $45-$46 current variable name + .label VARPNT = $47 // $47-$48 current variable/descriptor pointer .label FORPNT = $49 // $49-$4A -- NOT IMPLEMENTED -- .label OPPTR = $4B // $4B-$4C helper variable for expression computation, [!] our usage details are different .label OPMASK = $4D // -- NOT IMPLEMENTED -- .label DEFPNT = $4E // $4E-$4F -- NOT IMPLEMENTED -- - .label DSCPNT = $50 // $50-$52 -- NOT IMPLEMENTED -- - .label FOUR6 = $53 // -- NOT IMPLEMENTED -- + .label DSCPNT = $50 // $50-$52 temporary area fro string handling, [!] our usage might differ + .label FOUR6 = $53 // size of variable content (float = 5, integer = 2, string descriptor = 3) .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 @@ -71,12 +71,6 @@ .label FAC2_mantissa = $6A // $6A - $6D .label FAC2_sign = $6E - // We re-use FAC2 for memory move pointers, since we cannot be doing calculations while moving memory - .label memmove__src = $69 - .label memmove__dst = $6B - .label memmove__size = $6D - - .label ARISGN = $6F // -- NOT IMPLEMENTED -- .label FACOV = $70 // FAC1 low order mantissa .label FBUFPT = $71 // $71-$72 -- NOT IMPLEMENTED -- diff --git a/src/basic/,imports.s b/src/basic/,imports.s index 8b3c1e45..6af1d667 100644 --- a/src/basic/,imports.s +++ b/src/basic/,imports.s @@ -32,8 +32,11 @@ .label panic = KERNAL().panic #endif +.label vector_reset = KERNAL().vector_reset .label hw_entry_reset = KERNAL().hw_entry_reset +.label clear_screen = KERNAL().clear_screen + #if CONFIG_DBG_PRINTF .label printf = KERNAL().printf #endif diff --git a/src/basic/assets/packed_keywords_V2.s b/src/basic/assets/packed_keywords.s similarity index 100% rename from src/basic/assets/packed_keywords_V2.s rename to src/basic/assets/packed_keywords.s diff --git a/src/basic/assets/packed_keywords_CC.s b/src/basic/assets/packed_keywords_01.s similarity index 69% rename from src/basic/assets/packed_keywords_CC.s rename to src/basic/assets/packed_keywords_01.s index 8cbf9bed..85093d48 100644 --- a/src/basic/assets/packed_keywords_CC.s +++ b/src/basic/assets/packed_keywords_01.s @@ -4,6 +4,6 @@ // #LAYOUT# * * #IGNORE -packed_freq_keywords_CC: +packed_freq_keywords_01: - put_packed_freq_keywords_CC() + put_packed_freq_keywords_01() diff --git a/src/basic/assets/packed_keywords_CD.s b/src/basic/assets/packed_keywords_02.s similarity index 59% rename from src/basic/assets/packed_keywords_CD.s rename to src/basic/assets/packed_keywords_02.s index c474d947..37c9903a 100644 --- a/src/basic/assets/packed_keywords_CD.s +++ b/src/basic/assets/packed_keywords_02.s @@ -3,7 +3,10 @@ // #LAYOUT# X16 BASIC_0 #TAKE // #LAYOUT# * * #IGNORE +#if !HAS_SMALL_BASIC -packed_freq_keywords_CD: +packed_freq_keywords_02: - put_packed_freq_keywords_CD() + put_packed_freq_keywords_02() + +#endif diff --git a/src/basic/assets/table_ti_hi.s b/src/basic/assets/table_ti_hi.s new file mode 100644 index 00000000..e0615a58 --- /dev/null +++ b/src/basic/assets/table_ti_hi.s @@ -0,0 +1,29 @@ +// #LAYOUT# STD * #TAKE +// #LAYOUT# * BASIC_0 #TAKE +// #LAYOUT# * * #IGNORE + +// +// Table to TI$ special variable support +// + +table_TI_hi: + +#if !CONFIG_RS232_UP9600 + + .byte $20 // 10 hours = 2169000 ticks + .byte $03 // 1 hour = 216000 ticks + .byte $00 // 10 minutes = 36000 ticks + .byte $00 // 1 minute = 3600 ticks + .byte $00 // 10 seconds = 600 ticks + .byte $00 // 1 second = 60 ticks + +#else + + .byte $23 // 10 hours = 2304000 ticks + .byte $03 // 1 hour = 230400 ticks + .byte $00 // 10 minutes = 38400 ticks + .byte $00 // 1 minute = 3840 ticks + .byte $00 // 10 seconds = 640 ticks + .byte $00 // 1 second = 64 ticks + +#endif \ No newline at end of file diff --git a/src/basic/assets/table_ti_lo.s b/src/basic/assets/table_ti_lo.s new file mode 100644 index 00000000..4f7ef5ae --- /dev/null +++ b/src/basic/assets/table_ti_lo.s @@ -0,0 +1,29 @@ +// #LAYOUT# STD * #TAKE +// #LAYOUT# * BASIC_0 #TAKE +// #LAYOUT# * * #IGNORE + +// +// Table to TI$ special variable support +// + +table_TI_lo: + +#if !CONFIG_RS232_UP9600 + + .byte $80 // 10 hours = 2169000 ticks + .byte $C0 // 1 hour = 216000 ticks + .byte $A0 // 10 minutes = 36000 ticks + .byte $10 // 1 minute = 3600 ticks + .byte $58 // 10 seconds = 600 ticks + .byte $3C // 1 second = 60 ticks + +#else + + .byte $00 // 10 hours = 2304000 ticks + .byte $00 // 1 hour = 230400 ticks + .byte $00 // 10 minutes = 38400 ticks + .byte $00 // 1 minute = 3840 ticks + .byte $80 // 10 seconds = 640 ticks + .byte $40 // 1 second = 64 ticks + +#endif diff --git a/src/basic/assets/table_ti_mid.s b/src/basic/assets/table_ti_mid.s new file mode 100644 index 00000000..22b38fb8 --- /dev/null +++ b/src/basic/assets/table_ti_mid.s @@ -0,0 +1,29 @@ +// #LAYOUT# STD * #TAKE +// #LAYOUT# * BASIC_0 #TAKE +// #LAYOUT# * * #IGNORE + +// +// Table to TI$ special variable support +// + +table_TI_mid: + +#if !CONFIG_RS232_UP9600 + + .byte $F5 // 10 hours = 2169000 ticks + .byte $4B // 1 hour = 216000 ticks + .byte $8C // 10 minutes = 36000 ticks + .byte $0E // 1 minute = 3600 ticks + .byte $02 // 10 seconds = 600 ticks + .byte $00 // 1 second = 60 ticks + +#else + + .byte $28 // 10 hours = 2304000 ticks + .byte $84 // 1 hour = 230400 ticks + .byte $96 // 10 minutes = 38400 ticks + .byte $0F // 1 minute = 3840 ticks + .byte $02 // 10 seconds = 640 ticks + .byte $00 // 1 second = 64 ticks + +#endif diff --git a/src/basic/basic_commands/cmd__jumptable.s b/src/basic/basic_commands/cmd__jumptable.s index d5f8e1ff..321ebb31 100644 --- a/src/basic/basic_commands/cmd__jumptable.s +++ b/src/basic/basic_commands/cmd__jumptable.s @@ -17,13 +17,13 @@ cmd_data, cmd_inputhash, cmd_input, - cmd_dim, + array_create, // cmd_dim cmd_read, - cmd_let, + assign_variable, // cmd_let cmd_goto, cmd_run, cmd_if, - cmd_restore, + do_restore, // cmd_restore cmd_gosub, cmd_return, cmd_rem, @@ -42,7 +42,7 @@ cmd_print, cmd_cont, cmd_list, - cmd_clr, + do_clr, // cmd_clr cmd_cmd, cmd_sys, cmd_open, diff --git a/src/basic/basic_commands/cmd__unimplemented.s b/src/basic/basic_commands/cmd__unimplemented.s index 6495feb6..18c9fb1c 100644 --- a/src/basic/basic_commands/cmd__unimplemented.s +++ b/src/basic/basic_commands/cmd__unimplemented.s @@ -19,12 +19,8 @@ cmd_inputhash: nop cmd_input: nop -cmd_dim: - nop cmd_read: nop -cmd_let: - nop cmd_if: nop cmd_gosub: diff --git a/src/basic/basic_commands/cmd_clr.s b/src/basic/basic_commands/cmd_clr.s index f944eacc..9305ec00 100644 --- a/src/basic/basic_commands/cmd_clr.s +++ b/src/basic/basic_commands/cmd_clr.s @@ -3,10 +3,6 @@ // #LAYOUT# * * #IGNORE -cmd_clr: +// PLACEHOLDER for completeness - jumptable contains direct address - jsr do_clr - - // CLR command does not stop execution (confirmed on a C64) - - jmp execute_statements +// CLR command does not stop execution (confirmed on a C64) diff --git a/src/basic/basic_commands/cmd_dim.s b/src/basic/basic_commands/cmd_dim.s new file mode 100644 index 00000000..cccb47e2 --- /dev/null +++ b/src/basic/basic_commands/cmd_dim.s @@ -0,0 +1,6 @@ +// #LAYOUT# STD * #TAKE +// #LAYOUT# * BASIC_0 #TAKE +// #LAYOUT# * * #IGNORE + + +// PLACEHOLDER for completeness - jumptable contains direct address diff --git a/src/basic/basic_commands/cmd_let.s b/src/basic/basic_commands/cmd_let.s new file mode 100644 index 00000000..cccb47e2 --- /dev/null +++ b/src/basic/basic_commands/cmd_let.s @@ -0,0 +1,6 @@ +// #LAYOUT# STD * #TAKE +// #LAYOUT# * BASIC_0 #TAKE +// #LAYOUT# * * #IGNORE + + +// PLACEHOLDER for completeness - jumptable contains direct address diff --git a/src/basic/basic_commands/cmd_list.s b/src/basic/basic_commands/cmd_list.s index 3da8ca4f..6d7eecc3 100644 --- a/src/basic/basic_commands/cmd_list.s +++ b/src/basic/basic_commands/cmd_list.s @@ -31,7 +31,7 @@ list_loop: // LIST terminates any running program, // because it has fiddled with the current line pointer. // (Confirmed by testing on a C64) - jmp shell_main_loop + jmp end_of_program list_more_lines: diff --git a/src/basic/basic_commands/cmd_load_verify.s b/src/basic/basic_commands/cmd_load_verify.s index 9a0d59fd..d9fdcda8 100644 --- a/src/basic/basic_commands/cmd_load_verify.s +++ b/src/basic/basic_commands/cmd_load_verify.s @@ -52,7 +52,7 @@ cmd_load_no_error: // For VERIFY - this is it lda VERCKB - bne_16 execute_statements + bne_16 end_of_statement // C64 BASIC apparently does not clear variables after a LOAD in the // middle of a program. For safety, we do. @@ -74,10 +74,9 @@ cmd_load_no_error: ldx CURLIN+1 inx - beq cmd_load_end // branch if direct mode + beq_16 end_of_program // branch if direct mode + + pha + pha jmp execute_line - -cmd_load_end: - - jmp shell_main_loop diff --git a/src/basic/basic_commands/cmd_new.s b/src/basic/basic_commands/cmd_new.s index e7d7189f..c726b527 100644 --- a/src/basic/basic_commands/cmd_new.s +++ b/src/basic/basic_commands/cmd_new.s @@ -9,4 +9,4 @@ cmd_new: // NEW command terminates execution (confirmed on a C64) - jmp shell_main_loop + jmp end_of_program diff --git a/src/basic/basic_commands/cmd_print.s b/src/basic/basic_commands/cmd_print.s index 66443f4c..1110c46a 100644 --- a/src/basic/basic_commands/cmd_print.s +++ b/src/basic/basic_commands/cmd_print.s @@ -8,7 +8,7 @@ cmd_print: // First check if we have anything to print - jsr end_of_statement_check + jsr is_end_of_statement bcs cmd_print_new_line_done jsr fetch_character @@ -19,14 +19,19 @@ cmd_print: cmd_print_loop: +#if !HAS_OPCODES_65CE02 jsr unconsume_character +#else + dew TXTPTR +#endif // FALLTROUGH cmd_print_after_comma: - // Now evaluate the expression + // Now evaluate the expression and check what to print + jsr tmpstr_free_all jsr FRMEVL lda VALTYP bpl cmd_print_float @@ -37,42 +42,45 @@ cmd_print_string: // Print a string value +#if CONFIG_MEMORY_MODEL_46K || CONFIG_MEMORY_MODEL_50K + + jsr helper_print_string + jmp_8 cmd_print_next_arg + +#else // CONFIG_MEMORY_MODEL_38K || CONFIG_MEMORY_MODEL_60K + ldy #$00 !: cpy __FAC1 + 0 beq cmd_print_next_arg #if CONFIG_MEMORY_MODEL_60K - ldx #<(__FAC1 + 1) jsr peek_under_roms - -#elif CONFIG_MEMORY_MODEL_46K || CONFIG_MEMORY_MODEL_50K - - jsr peek_under_roms_via_FAC1_PLUS_1 - #else // CONFIG_MEMORY_MODEL_38K - lda (__FAC1 + 1), y - #endif jsr JCHROUT iny - jmp !- + bpl !- + +#endif cmd_print_float: // XXX probably we should also check INTFLG here // XXX provide implementation + jmp do_NOT_IMPLEMENTED_error + // FALLTROUGH cmd_print_next_arg: // Look for the next argument - jsr end_of_statement_check + jsr is_end_of_statement bcs cmd_print_new_line_done cmp #$2C // comma XXX on C64 behavior is more complicated, fix it @@ -89,4 +97,6 @@ cmd_print_new_line_done: cmd_print_done: - jmp execute_statements + // Execute next statement + + rts diff --git a/src/basic/basic_commands/cmd_rem.s b/src/basic/basic_commands/cmd_rem.s index 1e5c113d..3247ab0f 100644 --- a/src/basic/basic_commands/cmd_rem.s +++ b/src/basic/basic_commands/cmd_rem.s @@ -7,4 +7,6 @@ cmd_rem: + pha + pha jmp execute_statements_end_of_line diff --git a/src/basic/basic_commands/cmd_restore.s b/src/basic/basic_commands/cmd_restore.s index 034db54e..6e67271e 100644 --- a/src/basic/basic_commands/cmd_restore.s +++ b/src/basic/basic_commands/cmd_restore.s @@ -3,10 +3,6 @@ // #LAYOUT# * * #IGNORE -cmd_restore: +// PLACEHOLDER for completeness - jumptable contains direct address - jsr do_restore - - // RESTORE command does not stop execution (confirmed on a C64) - - jmp execute_statements +// RESTORE command does not stop execution (confirmed on a C64) diff --git a/src/basic/basic_commands/cmd_run_goto.s b/src/basic/basic_commands/cmd_run_goto.s index 4282ca1c..043862c3 100644 --- a/src/basic/basic_commands/cmd_run_goto.s +++ b/src/basic/basic_commands/cmd_run_goto.s @@ -4,24 +4,80 @@ cmd_run: + // RUN clears all variables + jsr do_clr -cmd_goto: - // Disable Kernal messages + + // Initialize OLDTXT pointer, disable Kernal messages + + jsr init_oldtxt lda #$00 jsr JSETMSG - // Reset line pointer to first line of program. - jsr init_oldtxt + // Check if we have any paramenters - jsr end_of_statement_check - bcs !+ + jsr is_end_of_statement + bcs cmd_run_goto_launch - jsr basic_parse_line_number - jsr find_line - bcc !+ - // Line does not exist, so report error - jmp do_UNDEFD_STATEMENT_error + // FALLTROUGH + +cmd_goto: + + // GOTO requires line number + + jsr fetch_line_number + bcs_16 do_SYNTAX_error + + // Check for direct mode + + lda CURLIN+1 + bmi cmd_goto_direct + + // Not a direct mode - compare desired line number (LINNUM) with the current one (CURLIN) + + lda LINNUM+1 + cmp CURLIN+1 + bne !+ + lda LINNUM+0 + cmp CURLIN+0 !: + // If desired line number is lower - search line number from start + + bcc cmd_goto_from_start + + // Else - search from the current line + + jsr find_line_from_current + jmp_8 cmd_goto_check + +cmd_goto_direct: + + // Disable Kernal messages + + lda #$00 + jsr JSETMSG + + // FALLTROUGH + +cmd_goto_from_start: + + // Direct mode - find the line from the beginning + + jsr find_line_from_start + + // FALLTROUGH + +cmd_goto_check: + + bcs_16 do_UNDEFD_STATEMENT_error + + // FALLTROUGH + +cmd_run_goto_launch: + // Run it! + + pha + pha jmp execute_line diff --git a/src/basic/basic_commands/cmd_save.s b/src/basic/basic_commands/cmd_save.s index 5ced4b27..faee06a5 100644 --- a/src/basic/basic_commands/cmd_save.s +++ b/src/basic/basic_commands/cmd_save.s @@ -38,6 +38,6 @@ cmd_save_do: // entry point for BSAVE jsr JSAVE bcs_16 do_kernal_error - // The end + // Execute next statement - jmp execute_statements + rts diff --git a/src/basic/basic_commands/cmd_stop_end.s b/src/basic/basic_commands/cmd_stop_end.s index 3cf6f64c..2c87a33a 100644 --- a/src/basic/basic_commands/cmd_stop_end.s +++ b/src/basic/basic_commands/cmd_stop_end.s @@ -27,4 +27,4 @@ cmd_stop: cmd_end: - jmp shell_main_loop + jmp end_of_program diff --git a/src/basic/basic_commands/cmd_sys.s b/src/basic/basic_commands/cmd_sys.s index 8dd3f5a7..01dcf833 100644 --- a/src/basic/basic_commands/cmd_sys.s +++ b/src/basic/basic_commands/cmd_sys.s @@ -5,7 +5,7 @@ cmd_sys: - jsr end_of_statement_check + jsr is_end_of_statement bcc !+ // SYS requires an argument @@ -41,7 +41,9 @@ cmd_sys_hack_not_needed: // XXX End of hack // - jsr basic_parse_line_number + lda #IDX__EV2_0B // 'SYNTAX ERROR' + jsr fetch_uint16 + bcs_16 do_SYNTAX_error cmd_sys_setup_call: lda #$4C // JMP opcode @@ -60,10 +62,7 @@ cmd_sys_setup_call: plp // Call the routine. - jsr USRPOK - - jmp execute_statements - + jmp USRPOK // // XXX Temporary ugly hack to support 'SYS PI*656' diff --git a/src/basic/basic_commands/helper_load_fetch_filename.s b/src/basic/basic_commands/helper_load_fetch_filename.s index d93a4055..367b4cbf 100644 --- a/src/basic/basic_commands/helper_load_fetch_filename.s +++ b/src/basic/basic_commands/helper_load_fetch_filename.s @@ -11,7 +11,7 @@ helper_load_fetch_filename: // Check if end of statement - jsr end_of_statement_check + jsr is_end_of_statement bcs !+ // Call the expression parser, make sure it returned a string diff --git a/src/basic/basic_commands/helper_print_string_46K_50K.s b/src/basic/basic_commands/helper_print_string_46K_50K.s new file mode 100644 index 00000000..4902509e --- /dev/null +++ b/src/basic/basic_commands/helper_print_string_46K_50K.s @@ -0,0 +1,27 @@ +// #LAYOUT# STD * #TAKE-HIGH +// #LAYOUT# * BASIC_0 #TAKE-HIGH +// #LAYOUT# * * #IGNORE + +// This has to go $E000 or above - routine below banks out the main BASIC ROM! + +#if CONFIG_MEMORY_MODEL_46K || CONFIG_MEMORY_MODEL_50K + +helper_print_string: + + // Unmap BASIC lower ROM + + lda #$26 + sta CPU_R6510 + + // Print the string + + ldy #$00 +!: + cpy __FAC1 + 0 + beq_16 remap_BASIC // branch if end of the string + lda (__FAC1 + 1), y + jsr JCHROUT + iny + bpl !- + +#endif diff --git a/src/basic/basic_commands_01/cmd__jumptable_01.s b/src/basic/basic_commands_01/cmd__jumptable_01.s new file mode 100644 index 00000000..6e3f4f61 --- /dev/null +++ b/src/basic/basic_commands_01/cmd__jumptable_01.s @@ -0,0 +1,49 @@ +// #LAYOUT# STD * #TAKE +// #LAYOUT# * BASIC_0 #TAKE +// #LAYOUT# * * #IGNORE + +// +// Jumptable for BASIC commands with tokens prefixed by $01 +// + + +.const command_01_list = List().add( + + cmd_slow, + cmd_fast, + cmd_old, + + // NOTE! These commands are temporarily placed here, they should be a part of list 02! + + cmd_merge, + + cmd_bload, + cmd_bsave, + cmd_bverify, + + cmd_clear, + varstr_garbage_collect // cmd_dispose +) + + +#if !HAS_OPCODES_65C02 + + +command_01_jumptable_lo: + + put_jumptable_lo(command_01_list) + + +command_01_jumptable_hi: + + put_jumptable_hi(command_01_list) + + +#else // HAS_OPCODES_65C02 + +command_01_jumptable: + + // Note: 65C02 has the page boundary vector bug fixed! + put_jumptable(command_01_list) + +#endif diff --git a/src/basic/basic_commands_CD/cmd_fast_slow.s b/src/basic/basic_commands_01/cmd_fast_slow.s similarity index 86% rename from src/basic/basic_commands_CD/cmd_fast_slow.s rename to src/basic/basic_commands_01/cmd_fast_slow.s index 79fcb6ae..e8b9ed5d 100644 --- a/src/basic/basic_commands_CD/cmd_fast_slow.s +++ b/src/basic/basic_commands_01/cmd_fast_slow.s @@ -20,8 +20,8 @@ cmd_fast: lda #$41 sta CPU_D6510 + rts - jmp execute_statements #elif CONFIG_MB_ULTIMATE_64 @@ -30,12 +30,12 @@ cmd_fast: cmd_slow: sta SCPU_SPEED_NORMAL - jmp execute_statements + rts cmd_fast: sta SCPU_SPEED_TURBO - jmp execute_statements + rts #elif CONFIG_PLATFORM_COMMODORE_64 @@ -60,14 +60,13 @@ cmd_fast: lda #$01 !: sta VIC_CLKRATE - - jmp execute_statements + rts #else cmd_slow: - nop // to prevent double label + nop // just to prevent double label // FALLTROUGH diff --git a/src/basic/basic_commands_CC/cmd_old.s b/src/basic/basic_commands_01/cmd_old.s similarity index 94% rename from src/basic/basic_commands_CC/cmd_old.s rename to src/basic/basic_commands_01/cmd_old.s index 9b816edf..1eeca8e9 100644 --- a/src/basic/basic_commands_CC/cmd_old.s +++ b/src/basic/basic_commands_01/cmd_old.s @@ -21,4 +21,4 @@ cmd_old: // Quit - jmp shell_main_loop + jmp end_of_program diff --git a/src/basic/basic_commands_02/cmd__jumptable_02.s b/src/basic/basic_commands_02/cmd__jumptable_02.s new file mode 100644 index 00000000..f554611f --- /dev/null +++ b/src/basic/basic_commands_02/cmd__jumptable_02.s @@ -0,0 +1,51 @@ +// #LAYOUT# STD * #TAKE +// #LAYOUT# * BASIC_0 #TAKE +// #LAYOUT# * * #IGNORE + +// +// Jumptable for BASIC commands with tokens prefixed by $02 +// + +#if !HAS_SMALL_BASIC + +.const command_02_list = List().add( + + // NOTE! These commands are temporarily placed in list 01! + + // cmd_merge, + + // cmd_bload, + // cmd_bsave, + // cmd_bverify, + + // cmd_clear, + // varstr_garbage_collect, // cmd_dispose + + cmd_cold, + cmd_mem +) + + +#if !HAS_OPCODES_65C02 + + +command_02_jumptable_lo: + + put_jumptable_lo(command_02_list) + + +command_02_jumptable_hi: + + put_jumptable_hi(command_02_list) + + +#else // HAS_OPCODES_65C02 + +command_02_jumptable: + + // Note: 65C02 has the page boundary vector bug fixed! + put_jumptable(command_02_list) + +#endif + +#endif diff --git a/src/basic/basic_commands_CC/cmd_bload_bverify.s b/src/basic/basic_commands_02/cmd_bload_bverify.s similarity index 90% rename from src/basic/basic_commands_CC/cmd_bload_bverify.s rename to src/basic/basic_commands_02/cmd_bload_bverify.s index 2b6db9fb..149e7caa 100644 --- a/src/basic/basic_commands_CC/cmd_bload_bverify.s +++ b/src/basic/basic_commands_02/cmd_bload_bverify.s @@ -37,6 +37,6 @@ cmd_bload: jsr JLOAD bcs_16 do_kernal_error - // XXX when number parsing is done, change to continue execution + // Execute next statement - jmp shell_main_loop + rts diff --git a/src/basic/basic_commands_CC/cmd_bsave.s b/src/basic/basic_commands_02/cmd_bsave.s similarity index 100% rename from src/basic/basic_commands_CC/cmd_bsave.s rename to src/basic/basic_commands_02/cmd_bsave.s diff --git a/src/basic/basic_commands_02/cmd_clear.s b/src/basic/basic_commands_02/cmd_clear.s new file mode 100644 index 00000000..ef71e4ff --- /dev/null +++ b/src/basic/basic_commands_02/cmd_clear.s @@ -0,0 +1,10 @@ +// #LAYOUT# STD * #TAKE +// #LAYOUT# * BASIC_0 #TAKE +// #LAYOUT# * * #IGNORE + + +cmd_clear: + + // XXX in the future add separate implementation for graphics screen + + jmp clear_screen diff --git a/src/basic/basic_commands_02/cmd_cold.s b/src/basic/basic_commands_02/cmd_cold.s new file mode 100644 index 00000000..21f9cc05 --- /dev/null +++ b/src/basic/basic_commands_02/cmd_cold.s @@ -0,0 +1,18 @@ +// #LAYOUT# STD * #TAKE +// #LAYOUT# * BASIC_0 #TAKE +// #LAYOUT# * * #IGNORE + + +#if !HAS_SMALL_BASIC + +cmd_cold: + + jsr helper_ask_if_sure + bcs !+ + + jsr JCLALL // for extra safety + jmp (vector_reset) // hardware CPU vector +!: + rts + +#endif diff --git a/src/basic/basic_commands_02/cmd_dispose.s b/src/basic/basic_commands_02/cmd_dispose.s new file mode 100644 index 00000000..cccb47e2 --- /dev/null +++ b/src/basic/basic_commands_02/cmd_dispose.s @@ -0,0 +1,6 @@ +// #LAYOUT# STD * #TAKE +// #LAYOUT# * BASIC_0 #TAKE +// #LAYOUT# * * #IGNORE + + +// PLACEHOLDER for completeness - jumptable contains direct address diff --git a/src/basic/basic_commands_02/cmd_mem.s b/src/basic/basic_commands_02/cmd_mem.s new file mode 100644 index 00000000..debd0e0c --- /dev/null +++ b/src/basic/basic_commands_02/cmd_mem.s @@ -0,0 +1,149 @@ +// #LAYOUT# STD * #TAKE +// #LAYOUT# M65 * #TAKE +// #LAYOUT# X16 BASIC_0 #TAKE +// #LAYOUT# * * #IGNORE + + +#if !HAS_SMALL_BASIC + +#if (!ROM_LAYOUT_M65 || SEGMENT_BASIC_0) + +cmd_mem: + + // First perform the garbage collection - to be able to determine real values + + jsr varstr_garbage_collect + +#endif // ROM layout + +#if (ROM_LAYOUT_M65 && SEGMENT_BASIC_0) + + jsr map_BASIC_1 + jsr_ind VB1__cmd_mem_cont + jmp map_NORMAL + +#else + +#if (ROM_LAYOUT_M65 && SEGMENT_BASIC_1) + +cmd_mem_cont: + +#endif + + // Print header + + lda #$12 + jsr JCHROUT + ldx #IDX__STR_MEM_HDR + jsr print_packed_misc_str + + // Print all the information, in a loop, in reverse order + + ldy #$04 + + // FALLTROUGH + +cmd_mem_loop: + + // First print the information string + + ldx helper_mem_tab_str, y + phy_trash_a + jsr print_packed_misc_str + + // Print start address + + ldx #IDX__STR_MEM_1 + jsr print_packed_misc_str + +#if HAS_OPCODES_65C02 + ply + phy +#else + pla + pha + tay +#endif + ldx helper_mem_tab_y, y + lda $01, x + jsr print_hex_byte + +#if HAS_OPCODES_65C02 + ply + phy +#else + pla + pha + tay +#endif + ldx helper_mem_tab_y, y + lda $00, x + jsr print_hex_byte + + + ldx #IDX__STR_MEM_2 + jsr print_packed_misc_str + + // Fetch addresses of zeropage variables + +#if HAS_OPCODES_65C02 + ply + phy +#else + pla + pha + tay +#endif + + ldx helper_mem_tab_x, y + lda helper_mem_tab_y, y + tay + + // Print difference between two zeropage variables + + sec + lda $00, x + sbc $0000, y + pha + inx + iny + lda $00, x + sbc $0000, y + +#if HAS_OPCODES_65C02 + plx +#else + tay + pla + tax + tya +#endif + + // Before printing, make sure the result is not negative + + bcs !+ + lda #$3F + jsr JCHROUT + jmp_8 cmd_mem_next + +!: + jsr print_integer + + // FALLTROUGH + +cmd_mem_next: + + // Check if more iterations needed + + ply_trash_a + dey + bpl cmd_mem_loop + + // Finish + + jmp print_return + + +#endif // ROM layout + +#endif // !HAS_SMALL_BASIC diff --git a/src/basic/basic_commands_CC/cmd_merge.s b/src/basic/basic_commands_02/cmd_merge.s similarity index 79% rename from src/basic/basic_commands_CC/cmd_merge.s rename to src/basic/basic_commands_02/cmd_merge.s index 42f3b1ed..dab2f34f 100644 --- a/src/basic/basic_commands_CC/cmd_merge.s +++ b/src/basic/basic_commands_02/cmd_merge.s @@ -42,10 +42,6 @@ cmd_merge_got_params: cmd_merge_no_error: - // Relink loaded program, clear variables + // Relink loaded program, clear variables, execute next statement - jsr update_LINKPRG_VARTAB_do_clr - - // XXX when number parsing is done, change to continue execution - - jmp shell_main_loop + jmp update_LINKPRG_VARTAB_do_clr diff --git a/src/basic/basic_commands_02/helper_ask_if_sure.s b/src/basic/basic_commands_02/helper_ask_if_sure.s new file mode 100644 index 00000000..e274b38e --- /dev/null +++ b/src/basic/basic_commands_02/helper_ask_if_sure.s @@ -0,0 +1,81 @@ +// #LAYOUT# STD * #TAKE +// #LAYOUT# M65 BASIC_1 #TAKE +// #LAYOUT# * BASIC_0 #TAKE +// #LAYOUT# * * #IGNORE + +// +// For direct mode, asks the user if he is sure (sets Carry if not); +// otherwise returns with Carry clear +// + + +#if !HAS_SMALL_BASIC + +helper_ask_if_sure: + +#if (ROM_LAYOUT_M65 && SEGMENT_BASIC_0) + + jsr map_BASIC_1 + jsr_ind VB1__helper_ask_if_sure + jmp map_NORMAL + +#else + + // First check, if we are in direct mode,; if not, do not ask + + ldx CURLIN+1 + inx + bne helper_ask_if_sure_ok // branch if not direct mode + + // Not direct mode - display the question + + ldx #IDX__STR_IF_SURE + jsr print_packed_misc_str + + // Clear the keyboard queue + + lda #$00 + sta NDX + + // Enable cursor, fetch the answer + + lda #$00 + sta BLNSW +!: + jsr JGETIN + cmp #$00 + beq !- + + // Check if 'Y' + + cmp #$59 + beq !+ + + lda #$4E // 'N' + jsr JCHROUT + + sec + rts +!: + // Display 'Y' and wait a short moment for a better user experience + + jsr JCHROUT + + clc + lda TIME+2 + adc #$0C +!: + cmp TIME+2 + bne !- + + // FALLTROUGH + +helper_ask_if_sure_ok: + + clc + rts + + +#endif // ROM layout + +#endif // !HAS_SMALL_BASIC diff --git a/src/basic/basic_commands_CC/helper_bload_fetch_address.s b/src/basic/basic_commands_02/helper_bload_fetch_address.s similarity index 78% rename from src/basic/basic_commands_CC/helper_bload_fetch_address.s rename to src/basic/basic_commands_02/helper_bload_fetch_address.s index f5fca8f6..e4a28e6d 100644 --- a/src/basic/basic_commands_CC/helper_bload_fetch_address.s +++ b/src/basic/basic_commands_02/helper_bload_fetch_address.s @@ -12,7 +12,9 @@ helper_bload_fetch_address: jsr injest_comma bcs_16 do_SYNTAX_error - jsr basic_parse_line_number // XXX detect errors here + lda #IDX__EV2_0B // 'SYNTAX ERROR' + jsr fetch_uint16 + bcs_16 do_SYNTAX_error ldx LINNUM+0 ldy LINNUM+1 diff --git a/src/basic/basic_commands_CC/helper_bload_fetch_filename.s b/src/basic/basic_commands_02/helper_bload_fetch_filename.s similarity index 100% rename from src/basic/basic_commands_CC/helper_bload_fetch_filename.s rename to src/basic/basic_commands_02/helper_bload_fetch_filename.s diff --git a/src/basic/basic_commands_02/helper_mem_tab_str.s b/src/basic/basic_commands_02/helper_mem_tab_str.s new file mode 100644 index 00000000..8bf56176 --- /dev/null +++ b/src/basic/basic_commands_02/helper_mem_tab_str.s @@ -0,0 +1,20 @@ +// #LAYOUT# STD * #TAKE +// #LAYOUT# M65 BASIC_1 #TAKE +// #LAYOUT# X16 BASIC_0 #TAKE +// #LAYOUT# * * #IGNORE + +// +// Helper table for 'MEM' command - list of strings to print +// + +#if !HAS_SMALL_BASIC + +helper_mem_tab_str: + + .byte IDX__STR_MEM_FREE + .byte IDX__STR_MEM_STRS + .byte IDX__STR_MEM_ARRS + .byte IDX__STR_MEM_VARS + .byte IDX__STR_MEM_TEXT + +#endif \ No newline at end of file diff --git a/src/basic/basic_commands_02/helper_mem_tab_x.s b/src/basic/basic_commands_02/helper_mem_tab_x.s new file mode 100644 index 00000000..ec74d04a --- /dev/null +++ b/src/basic/basic_commands_02/helper_mem_tab_x.s @@ -0,0 +1,20 @@ +// #LAYOUT# STD * #TAKE +// #LAYOUT# M65 BASIC_1 #TAKE +// #LAYOUT# X16 BASIC_0 #TAKE +// #LAYOUT# * * #IGNORE + +// +// Helper table for 'MEM' command - list of minuend zeropage variables +// + +#if !HAS_SMALL_BASIC + +helper_mem_tab_x: + + .byte FRETOP + .byte MEMSIZ + .byte STREND + .byte ARYTAB + .byte VARTAB + +#endif diff --git a/src/basic/basic_commands_02/helper_mem_tab_y.s b/src/basic/basic_commands_02/helper_mem_tab_y.s new file mode 100644 index 00000000..d8a02f22 --- /dev/null +++ b/src/basic/basic_commands_02/helper_mem_tab_y.s @@ -0,0 +1,20 @@ +// #LAYOUT# STD * #TAKE +// #LAYOUT# M65 BASIC_1 #TAKE +// #LAYOUT# X16 BASIC_0 #TAKE +// #LAYOUT# * * #IGNORE + +// +// Helper table for 'MEM' command - list of subtrahend zeropage variables +// + +#if !HAS_SMALL_BASIC + +helper_mem_tab_y: + + .byte STREND + .byte FRETOP + .byte ARYTAB + .byte VARTAB + .byte TXTTAB + +#endif diff --git a/src/basic/basic_commands_CC/cmd__jumptable_CC.s b/src/basic/basic_commands_CC/cmd__jumptable_CC.s deleted file mode 100644 index 52a9cb50..00000000 --- a/src/basic/basic_commands_CC/cmd__jumptable_CC.s +++ /dev/null @@ -1,51 +0,0 @@ -// #LAYOUT# STD * #TAKE -// #LAYOUT# * BASIC_0 #TAKE -// #LAYOUT# * * #IGNORE - -// -// Jumptable for BASIC commands with tokens prefixed by $CC -// - - -.const command_CC_list = List().add( - - cmd_merge, - - cmd_bload, - cmd_bsave, - cmd_bverify, - - cmd_old -) - - -#if !HAS_OPCODES_65C02 - - -command_CC_jumptable_lo: - - put_jumptable_lo(command_CC_list) - - -command_CC_jumptable_hi: - - put_jumptable_hi(command_CC_list) - - -#else // HAS_OPCODES_65C02 - - -__before_command_CC_jumptable: - -.if (mod(*, $2) == 1) { brk } // align code so that vector never crosses page boundary - -command_CC_jumptable: - - put_jumptable(command_CC_list) - - // Make sure routine size is always the same - build system limitation - -.if (__before_command_CC_jumptable == command_CC_jumptable) { brk } - - -#endif diff --git a/src/basic/basic_commands_CD/cmd__jumptable_CD.s b/src/basic/basic_commands_CD/cmd__jumptable_CD.s deleted file mode 100644 index 9cfa0c9a..00000000 --- a/src/basic/basic_commands_CD/cmd__jumptable_CD.s +++ /dev/null @@ -1,46 +0,0 @@ -// #LAYOUT# STD * #TAKE -// #LAYOUT# * BASIC_0 #TAKE -// #LAYOUT# * * #IGNORE - -// -// Jumptable for BASIC commands with tokens prefixed by $CD -// - - -.const command_CD_list = List().add( - - cmd_slow, - cmd_fast -) - - -#if !HAS_OPCODES_65C02 - - -command_CD_jumptable_lo: - - put_jumptable_lo(command_CD_list) - - -command_CD_jumptable_hi: - - put_jumptable_hi(command_CD_list) - - -#else // HAS_OPCODES_65C02 - - -__before_command_CD_jumptable: - -.if (mod(*, $2) == 1) { brk } // align code so that vector never crosses page boundary - -command_CD_jumptable: - - put_jumptable(command_CD_list) - - // Make sure routine size is always the same - build system limitation - -.if (__before_command_CD_jumptable == command_CD_jumptable) { brk } - - -#endif diff --git a/src/basic/basic_functions/fun__jumptable.s b/src/basic/basic_functions/fun__jumptable.s index 266ff347..d5b47811 100644 --- a/src/basic/basic_functions/fun__jumptable.s +++ b/src/basic/basic_functions/fun__jumptable.s @@ -55,18 +55,9 @@ function_jumptable_hi: #else // HAS_OPCODES_65C02 - -__before_function_jumptable: - -.if (mod(*, $2) == 1) { brk } // align code so that vector never crosses page boundary - function_jumptable: + // Note: 65C02 has the page boundary vector bug fixed! put_jumptable(function_list) - // Make sure routine size is always the same - build system limitation - -.if (__before_function_jumptable == function_jumptable) { brk } - - #endif diff --git a/src/basic/basic_operators/oper_add.s b/src/basic/basic_operators/oper_add.s index 2670de2e..e663af97 100644 --- a/src/basic/basic_operators/oper_add.s +++ b/src/basic/basic_operators/oper_add.s @@ -9,8 +9,8 @@ oper_add: // First check whether arguments match and then choose the variant pla - cmp VALTYP - bne_16 do_TYPE_MISMATCH_error + eor VALTYP + bmi_16 do_TYPE_MISMATCH_error lda VALTYP bmi oper_add_strings @@ -36,13 +36,18 @@ oper_add_strings: pla sta __FAC2+0 - beq oper_add_strings_end // if string 2 is empty, we have nothing to do + + // If string 2 is empty, release it and quit + + beq oper_add_strings_end // If string 1 is empty, just copy the metadata lda __FAC1+0 bne !+ + jsr tmpstr_free_FAC1 + lda __FAC2+0 sta __FAC1+0 lda __FAC2+1 @@ -52,21 +57,105 @@ oper_add_strings: jmp FRMEVL_continue !: - // Allocate memory for concatenated string + // Allocate memory for the concatenated string clc adc __FAC2+0 bcs_16 do_STRING_TOO_LONG_error - jsr alloc_temp_string + jsr tmpstr_alloc -.break + // Copy the temporary string pointer to INDEX + ldy #$01 + lda (VARPNT), y + sta INDEX+0 + iny + lda (VARPNT), y + sta INDEX+1 + // Perform the concatenation - // XXX finish the implementation +#if CONFIG_MEMORY_MODEL_60K + + // Copy data from the first string + ldy #$00 +!: + ldx #<(__FAC2+1) + jsr peek_under_roms + ldx #BUF sta TXTPTR+1 - jsr basic_parse_line_number + jsr fetch_line_number // Get pointer to next char lda TXTPTR+0 @@ -156,12 +169,12 @@ shell_add_delete_line: jsr update_VARTAB_do_clr // Check if line already present - jsr find_line + jsr find_line_from_start bcs !+ // Line already present - delete it jsr delete_line - jsr find_line // refresh OLDTXT + jsr find_line_from_start // refresh OLDTXT !: // Insert new line if non-zero length, i.e., that // we are not just deleting the line. diff --git a/src/basic/editor/shift_txt_down.s b/src/basic/engine_editor/shift_txt_down.s similarity index 100% rename from src/basic/editor/shift_txt_down.s rename to src/basic/engine_editor/shift_txt_down.s diff --git a/src/basic/editor/shift_txt_up.s b/src/basic/engine_editor/shift_txt_up.s similarity index 100% rename from src/basic/editor/shift_txt_up.s rename to src/basic/engine_editor/shift_txt_up.s diff --git a/src/basic/editor/tk_cut_away.s b/src/basic/engine_editor/tk_cut_away.s similarity index 100% rename from src/basic/editor/tk_cut_away.s rename to src/basic/engine_editor/tk_cut_away.s diff --git a/src/basic/editor/tk_pack.s b/src/basic/engine_editor/tk_pack.s similarity index 96% rename from src/basic/editor/tk_pack.s rename to src/basic/engine_editor/tk_pack.s index 26114fde..56d3db31 100644 --- a/src/basic/editor/tk_pack.s +++ b/src/basic/engine_editor/tk_pack.s @@ -142,8 +142,14 @@ tk_pack_loop_next: lda tk__len_unpacked cmp #TK__MAX_KEYWORD_LEN - bne tk_pack_loop + beq !+ // if max length reached - quit + // Check for characters that can only end the keyword + + lda BUF-1, x + cmp #$41 + bcs tk_pack_loop +!: rts tk_pack_1n_new_byte: diff --git a/src/basic/editor/tk_search.s b/src/basic/engine_editor/tk_search.s similarity index 100% rename from src/basic/editor/tk_search.s rename to src/basic/engine_editor/tk_search.s diff --git a/src/basic/editor/tk_shorten.s b/src/basic/engine_editor/tk_shorten.s similarity index 96% rename from src/basic/editor/tk_shorten.s rename to src/basic/engine_editor/tk_shorten.s index 916a8f41..977b0c02 100644 --- a/src/basic/editor/tk_shorten.s +++ b/src/basic/engine_editor/tk_shorten.s @@ -91,11 +91,7 @@ tk_shorten_3n_byte_nibble: // tk__nibble_flag = $00, both nibbles fr // Reuse 'tk_shorten_1n_hi' sty tk__byte_offset -#if HAS_OPCODES_65C02 - bra tk_shorten_1n_hi -#else - jmp tk_shorten_1n_hi -#endif + jmp_8 tk_shorten_1n_hi tk_shorten_3n_2bytes: // tk__nibble_flag = $FF, only the high nibble is free diff --git a/src/basic/editor/tokenise_line.s b/src/basic/engine_editor/tokenise_line.s similarity index 89% rename from src/basic/editor/tokenise_line.s rename to src/basic/engine_editor/tokenise_line.s index 960d5a92..06ddf755 100644 --- a/src/basic/editor/tokenise_line.s +++ b/src/basic/engine_editor/tokenise_line.s @@ -80,31 +80,31 @@ tokenise_line_loop: // Check for extended tokens - lda #packed_freq_keywords_CC + lda #>packed_freq_keywords_01 sta FRESPC+1 jsr tk_search - bcc tokenise_line_keyword_CC // branch if keyword identified + bcc tokenise_line_keyword_01 // branch if keyword identified - lda #packed_freq_keywords_CD + lda #>packed_freq_keywords_02 sta FRESPC+1 jsr tk_search - bcc tokenise_line_keyword_CD // branch if keyword identified + bcc tokenise_line_keyword_02 // branch if keyword identified + +#endif // Shorten packed keyword candidate and try again jsr tk_shorten -#if HAS_OPCODES_65C02 - bra !- -#else - jmp !- -#endif + jmp_8 !- tokenise_line_keyword_V2: @@ -173,20 +173,24 @@ tokenise_line_char: // Support for extended keyword lists -tokenise_line_keyword_CC: +#if !HAS_SMALL_BASIC + +tokenise_line_keyword_02: // Store the token list index - lda #$CC + lda #$02 skip_2_bytes_trash_nvz // FALLTROUGH -tokenise_line_keyword_CD: +#endif + +tokenise_line_keyword_01: // Store the token list index - lda #$CD + lda #$01 ldy tk__offset sta BUF, y diff --git a/src/basic/editor/update_vartab_do_clr.s b/src/basic/engine_editor/update_vartab_do_clr.s similarity index 100% rename from src/basic/editor/update_vartab_do_clr.s rename to src/basic/engine_editor/update_vartab_do_clr.s diff --git a/src/basic/engine_runtime/ad9e.frmevl.jmp.s b/src/basic/engine_runtime/ad9e.frmevl.jmp.s new file mode 100644 index 00000000..5f01cd7b --- /dev/null +++ b/src/basic/engine_runtime/ad9e.frmevl.jmp.s @@ -0,0 +1,8 @@ +// #LAYOUT# STD * #TAKE +// #LAYOUT# X16 BASIC_0 #TAKE-OFFSET 2000 +// #LAYOUT# * BASIC_0 #TAKE +// #LAYOUT# * * #IGNORE + +// Just a compatibility jump - our routine is longer than original one + + jmp FRMEVL diff --git a/src/basic/engine/ad9e.interop b/src/basic/engine_runtime/ad9e.interop similarity index 100% rename from src/basic/engine/ad9e.interop rename to src/basic/engine_runtime/ad9e.interop diff --git a/src/basic/engine_runtime/check_stack_space.s b/src/basic/engine_runtime/check_stack_space.s new file mode 100644 index 00000000..9cbd5aa1 --- /dev/null +++ b/src/basic/engine_runtime/check_stack_space.s @@ -0,0 +1,16 @@ +// #LAYOUT# STD * #TAKE +// #LAYOUT# * BASIC_0 #TAKE +// #LAYOUT# * * #IGNORE + + +check_stack_space: + + phx_trash_a + + tsx + cpx #$60 // XXX is this a safe threshold? + bcc_16 do_FORMULA_TOO_COMPLEX_error + + plx_trash_a + + rts diff --git a/src/basic/engine_runtime/convert_PETSCII_to_digit.s b/src/basic/engine_runtime/convert_PETSCII_to_digit.s new file mode 100644 index 00000000..97f7c335 --- /dev/null +++ b/src/basic/engine_runtime/convert_PETSCII_to_digit.s @@ -0,0 +1,21 @@ +// #LAYOUT# STD * #TAKE +// #LAYOUT# * BASIC_0 #TAKE +// #LAYOUT# * * #IGNORE + +// +// Tries to convert PETSCII in .A to a digit (0-9 values), sets Carry to indicate failure +// + +convert_PETSCII_to_digit: + + sec + sbc #$30 + bcc convert_PETSCII_to_digit_fail + + cmp #$0A + rts + +convert_PETSCII_to_digit_fail: + + sec + rts diff --git a/src/basic/engine/do_error.s b/src/basic/engine_runtime/do_error.s similarity index 91% rename from src/basic/engine/do_error.s rename to src/basic/engine_runtime/do_error.s index e4979e86..a3d64f63 100644 --- a/src/basic/engine/do_error.s +++ b/src/basic/engine_runtime/do_error.s @@ -1,4 +1,5 @@ // #LAYOUT# STD * #TAKE +// #LAYOUT# M65 BASIC_1 #TAKE // #LAYOUT# * BASIC_0 #TAKE // #LAYOUT# * * #IGNORE @@ -43,9 +44,13 @@ do_kernal_error: // .A = KERNAL error code, also almost ma beq do_BREAK_error // XXX is 0 really a proper error code? dex +#if (ROM_LAYOUT_M65 && SEGMENT_BASIC_1) + jmp do_basic_error +#else bpl do_basic_error // branch always +#endif - // Error messages specific to OpenROMs BASIC dialect + // Error messages specific to Open ROMs BASIC dialect do_MEMORY_CORRUPT_error: .byte $E6 @@ -138,6 +143,16 @@ do_FILE_OPEN_error: do_TO_MANY_FILES_error: .byte $EA +#if (ROM_LAYOUT_M65 && SEGMENT_BASIC_1) + + jmp do_error_fetch + +#else + + // FALLTROUGH + +do_error_fetch: + // Now get the error id and restore $E6 to its correct value lda $E6 @@ -162,9 +177,15 @@ do_TO_MANY_FILES_error: do_basic_error: // error code in .X - // "?" +#if ROM_LAYOUT_M65 + // Make sure we are back with normal memory map + jsr map_NORMAL +#endif + + // Clear all temporary variables, print "?" phx_trash_a + jsr tmpstr_free_all ldx #IDX__STR_RET_QM jsr print_packed_misc_str plx_trash_a @@ -197,3 +218,5 @@ do_basic_error: // error code in .X txs jmp shell_main_loop + +#endif // ROM layout diff --git a/src/basic/engine/do_new_clr_restore.s b/src/basic/engine_runtime/do_new_clr_restore.s similarity index 91% rename from src/basic/engine/do_new_clr_restore.s rename to src/basic/engine_runtime/do_new_clr_restore.s index 3a249d2a..28fbfed7 100644 --- a/src/basic/engine/do_new_clr_restore.s +++ b/src/basic/engine_runtime/do_new_clr_restore.s @@ -51,7 +51,7 @@ do_clr: // See Computes Mapping the Commodore 64 - page 96 - // XXX check on real ROMs that it is being done too when entering new line + // XXX check if original ROM does this too jsr JCLALL lda MEMSIZ+0 @@ -69,6 +69,10 @@ do_clr: sta ARYTAB+1 sta STREND+1 + // This is a good place to reset the temporary string stack + + jsr tmpstr_free_all_reset + // FALLTROUGH (confirmed on real C64 that CLR indeed resets DATPTR) do_restore: diff --git a/src/basic/engine_runtime/end_of_statement.s b/src/basic/engine_runtime/end_of_statement.s new file mode 100644 index 00000000..8216d144 --- /dev/null +++ b/src/basic/engine_runtime/end_of_statement.s @@ -0,0 +1,23 @@ +// #LAYOUT# STD * #TAKE +// #LAYOUT# * BASIC_0 #TAKE +// #LAYOUT# * * #IGNORE + +// +// Executes the next command - after previous got finished +// + + +end_of_statement: + + jsr tmpstr_free_all + jsr fetch_character_skip_spaces + + cmp #$3A // check for colon + beq_16 execute_statements + + cmp #$00 // check for end of the line + beq_16 execute_statements_end_of_line + + // Unexpected character + + jmp do_SYNTAX_error diff --git a/src/basic/engine/execute_line_statements.s b/src/basic/engine_runtime/execute_line_statements.s similarity index 72% rename from src/basic/engine/execute_line_statements.s rename to src/basic/engine_runtime/execute_line_statements.s index 51f34df4..17624201 100644 --- a/src/basic/engine/execute_line_statements.s +++ b/src/basic/engine_runtime/execute_line_statements.s @@ -16,9 +16,7 @@ execute_statements: // Skip over any white spaces and colons (':') !: - jsr fetch_character - cmp #$20 // space, can be skipped - beq !- + jsr fetch_character_skip_spaces cmp #$3A // colon, can be skipped beq !- @@ -29,27 +27,40 @@ execute_statements: // Not end of the line - it seems we actually have something to execute - // Initialize temporary string stack - just about any statement might need it - // XXX original C64 ROM initializes this during the startup too - not sure where to put this + // Move token code to .X + tax - ldx #$16 - stx LASTPT - ldx #$19 - stx TEMPPT + // Push the 'end_of_statement' address for RTS + + lda #>(end_of_statement - 1) + pha + lda #<(end_of_statement - 1) + pha // Check if token is valid for execution - cmp #$7F - bcc_16 execute_statements_var_assign // not a token - try variable assign +#if HAS_SMALL_BASIC - cmp #$A6 - bcs execute_statements_extended + cpx #$01 + beq execute_statements_01 + +#else + + cpx #$03 + bcc execute_statements_extended + +#endif + + cpx #$CB + beq_16 cmd_go // // 'GO' command has a strange token, placed after function tokens + + cpx #$7F + bcc_16 execute_statements_var_assign // not a token - try variable assign #if !HAS_OPCODES_65C02 // Get the jump table entry for it, push it on the stack, and then RTS to start it. - tax lda command_jumptable_hi - $80, x pha lda command_jumptable_lo - $80, x @@ -61,31 +72,32 @@ execute_statements: // Use jumptable to go to the command routine + txa asl tax jmp (command_jumptable, x) #endif +#if !HAS_SMALL_BASIC execute_statements_extended: // Support for extended BASIC commands - cmp #$CC - beq execute_statements_CC - cmp #$CD - beq execute_statements_CD + // XXX consider jumpable here - // 'GO' command has a strange token, it is placed after function tokens + cpx #$01 + beq execute_statements_01 - cmp #$CB - beq_16 cmd_go + cpx #$02 + beq execute_statements_02 jmp do_SYNTAX_error +#endif -execute_statements_CC: +execute_statements_01: // Get the sub-token, check that it is valid @@ -93,7 +105,7 @@ execute_statements_CC: cmp #$00 beq_16 do_SYNTAX_error - cmp #(TK__MAXTOKEN_keywords_CC+1) + cmp #(TK__MAXTOKEN_keywords_01+1) bcs_16 do_SYNTAX_error // Execute command @@ -103,9 +115,9 @@ execute_statements_CC: // Get the jump table entry for it, push it on the stack, and then RTS to start it. tax - lda command_CC_jumptable_hi - 1, x + lda command_01_jumptable_hi - 1, x pha - lda command_CC_jumptable_lo - 1, x + lda command_01_jumptable_lo - 1, x pha rts @@ -116,12 +128,13 @@ execute_statements_CC: asl tax - jmp (command_CC_jumptable - 2, x) + jmp (command_01_jumptable - 2, x) #endif +#if !HAS_SMALL_BASIC -execute_statements_CD: +execute_statements_02: // Get the sub-token, check that it is valid @@ -129,7 +142,7 @@ execute_statements_CD: cmp #$00 beq_16 do_SYNTAX_error - cmp #(TK__MAXTOKEN_keywords_CD+1) + cmp #(TK__MAXTOKEN_keywords_02+1) bcs_16 do_SYNTAX_error // Execute command @@ -139,9 +152,9 @@ execute_statements_CD: // Get the jump table entry for it, push it on the stack, and then RTS to start it. tax - lda command_CD_jumptable_hi - 1, x + lda command_02_jumptable_hi - 1, x pha - lda command_CD_jumptable_lo - 1, x + lda command_02_jumptable_lo - 1, x pha rts @@ -152,10 +165,11 @@ execute_statements_CD: asl tax - jmp (command_CD_jumptable - 2, x) + jmp (command_02_jumptable - 2, x) #endif +#endif // !HAS_SMALL_BASIC execute_statements_end_of_line: @@ -189,9 +203,8 @@ execute_line: // Check if pointer is null, if so, we are at the end of the program - ldy #0 - jsr peek_line_pointer_null_check - bcc_16 shell_main_loop // branch if end of program reached + jsr is_line_pointer_null + beq_16 shell_main_loop // branch if end of program reached // Skip pointer and line number to get address of first statement @@ -232,17 +245,22 @@ execute_line: execute_statements_var_assign: - // XXX here we should handle variable assignments, probably in a separate file - // Prevent wedges from being executed within a program #if CONFIG_TAPE_WEDGE - cmp #$40 + cpx #$40 beq_16 do_DIRECT_MODE_ONLY_error #endif #if CONFIG_DOS_WEDGE - cmp #$5F + cpx #$5F beq_16 do_DIRECT_MODE_ONLY_error #endif - jmp do_SYNTAX_error + // Try variable assignment - execute as LET command + +#if !HAS_OPCODES_65CE02 + jsr unconsume_character +#else + dew TXTPTR +#endif + jmp assign_variable diff --git a/src/basic/engine_runtime/fetch_line_number.s b/src/basic/engine_runtime/fetch_line_number.s new file mode 100644 index 00000000..2078f296 --- /dev/null +++ b/src/basic/engine_runtime/fetch_line_number.s @@ -0,0 +1,21 @@ +// #LAYOUT# STD * #TAKE +// #LAYOUT# * BASIC_0 #TAKE +// #LAYOUT# * * #IGNORE + +// +// Fetches line number, stores it in LINNUM, sets Carry to indicate failure (not a number) +// +// Preserves both .X and .Y +// + +fetch_line_number: + + lda #IDX__EV7_26 // 'LINE NUMBER TOO LARGE' + jsr fetch_uint16 + bcs_16 do_SYNTAX_error + + lda LINNUM+1 + cmp #$FF + beq_16 do_LINE_NUMBER_TOO_LARGE_error + + rts diff --git a/src/basic/engine/fetch_operator.s b/src/basic/engine_runtime/fetch_operator.s similarity index 91% rename from src/basic/engine/fetch_operator.s rename to src/basic/engine_runtime/fetch_operator.s index 26a260f6..c428ec6c 100644 --- a/src/basic/engine/fetch_operator.s +++ b/src/basic/engine_runtime/fetch_operator.s @@ -41,7 +41,11 @@ fetch_operator_success: fetch_operator_failed: +#if !HAS_OPCODES_65CE02 jsr unconsume_character +#else + dew TXTPTR +#endif sec rts @@ -57,7 +61,11 @@ fetch_operator_try_gteq: // This is a '>' +#if !HAS_OPCODES_65CE02 jsr unconsume_character +#else + dew TXTPTR +#endif lda #$07 bne fetch_operator_success // branch always !: @@ -79,7 +87,11 @@ fetch_operator_try_lteq_neq: // This is a '<' +#if !HAS_OPCODES_65CE02 jsr unconsume_character +#else + dew TXTPTR +#endif lda #$09 bne fetch_operator_success // branch always !: diff --git a/src/basic/engine_runtime/fetch_uint16.s b/src/basic/engine_runtime/fetch_uint16.s new file mode 100644 index 00000000..6a960a4a --- /dev/null +++ b/src/basic/engine_runtime/fetch_uint16.s @@ -0,0 +1,124 @@ +// #LAYOUT# STD * #TAKE +// #LAYOUT# * BASIC_0 #TAKE +// #LAYOUT# * * #IGNORE + +// +// Fetches unsigned 16-bit integer, stores it in LINNUM, sets Carry to indicate failure (not a number) +// +// If value above 65535, error depends on .A opn entry +// +// Preserves both .X and .Y +// + +fetch_uint16: + + // Push the error code to stack + + pha + + // Fetch the first character (skip spaces), check if 0-9 + + jsr fetch_character_skip_spaces + + jsr convert_PETSCII_to_digit + bcs fetch_uint16_rts + + // First character seems to be correct - store it + + sta LINNUM+0 + lda #$00 + sta LINNUM+1 + + // FALLTROUGH + +fetch_uint16_loop: + + // Try to fetch another digit + + jsr fetch_character + jsr convert_PETSCII_to_digit + bcs fetch_uint16_end + + // We got another digit - store it + + pha + + // Multiply current LINNUM by 10 (x * 10 = (x * 2) + (x * 2) * 4) + + jsr fetch_uint16_mul_LINNUM_2 + bcs fetch_uint16_1PLA_error + + lda LINNUM+1 + pha + lda LINNUM+0 + pha + + jsr fetch_uint16_mul_LINNUM_2 + bcs fetch_uint16_3PLA_error + jsr fetch_uint16_mul_LINNUM_2 + bcs fetch_uint16_3PLA_error + + clc + pla + adc LINNUM+0 + sta LINNUM+0 + pla + adc LINNUM+1 + sta LINNUM+1 + bcs fetch_uint16_1PLA_error + + // Add the new digit to LINNUM + + pla + clc + adc LINNUM+0 + sta LINNUM+0 + lda LINNUM+1 + adc #$00 + sta LINNUM+1 + bcs fetch_uint16_error + + // Next iteration + + jmp_8 fetch_uint16_loop + +fetch_uint16_end: + +#if !HAS_OPCODES_65CE02 + jsr unconsume_character +#else + dew TXTPTR +#endif + clc + + // FALLTROUGH + +fetch_uint16_rts: + + pla + rts + +fetch_uint16_mul_LINNUM_2: + + asl LINNUM+0 + rol LINNUM+1 + + rts + +fetch_uint16_3PLA_error: + + pla + pla + + // FALLTROUGH + +fetch_uint16_1PLA_error: + + pla + + // FALLTROUGH + +fetch_uint16_error: + + plx_trash_a + jmp do_basic_error diff --git a/src/basic/engine/fetch_uint8.s b/src/basic/engine_runtime/fetch_uint8.s similarity index 74% rename from src/basic/engine/fetch_uint8.s rename to src/basic/engine_runtime/fetch_uint8.s index 1637b056..75d8c685 100644 --- a/src/basic/engine/fetch_uint8.s +++ b/src/basic/engine_runtime/fetch_uint8.s @@ -16,8 +16,9 @@ fetch_coma_uint8: fetch_uint8: - jsr injest_spaces - jsr basic_parse_line_number // XXX detect errors here + lda #IDX__EV2_0E // 'ILLEGAL QUANTITY ERROR' + jsr fetch_uint16 + bcs !+ lda LINNUM+1 bne_16 do_ILLEGAL_QUANTITY_error lda LINNUM+0 diff --git a/src/basic/engine/follow_link_to_next_line.s b/src/basic/engine_runtime/follow_link_to_next_line.s similarity index 100% rename from src/basic/engine/follow_link_to_next_line.s rename to src/basic/engine_runtime/follow_link_to_next_line.s diff --git a/src/basic/engine/ad9e.frmevl.s b/src/basic/engine_runtime/frmevl.s similarity index 86% rename from src/basic/engine/ad9e.frmevl.s rename to src/basic/engine_runtime/frmevl.s index 71b1ccb7..c2b24bdd 100644 --- a/src/basic/engine/ad9e.frmevl.s +++ b/src/basic/engine_runtime/frmevl.s @@ -1,5 +1,4 @@ // #LAYOUT# STD * #TAKE -// #LAYOUT# X16 BASIC_0 #TAKE-OFFSET 2000 // #LAYOUT# * BASIC_0 #TAKE // #LAYOUT# * * #IGNORE @@ -19,7 +18,7 @@ // in a correct order // -// XXX finish the implementation: invoking functions, fetcching PI, fetching float, fetching variables +// XXX finish the implementation: invoking functions, fetching floats FRMEVL: @@ -41,7 +40,7 @@ FRMEVL_loop: // Check if end of statement, fetch the character - jsr end_of_statement_check + jsr is_end_of_statement bcs_16 do_SYNTAX_error jsr fetch_character @@ -68,17 +67,53 @@ FRMEVL_loop: // $7F has to be a function cmp #$80 // check for a token - bcc FRMEVL_execute_function + bcs FRMEVL_execute_function - // There are 2 possibilities left - a floating point value or a variable + // Check for a variable +#if !HAS_OPCODES_65CE02 + jsr unconsume_character +#else + dew TXTPTR +#endif + jsr fetch_variable + bcs FRMEVL_fetch_float - // XXX implement this part + // Found the variable - copy descriptor to FAC1 +#if CONFIG_MEMORY_MODEL_60K + + ldx #const_PI + jsr mov_MEM_FAC1 - jmp do_NOT_IMPLEMENTED_error + jmp_8 FRMEVL_got_value_float // // This subroutine fetches the floating point value from the 'outside world' @@ -142,6 +179,14 @@ FRMEVL_fetch_float: jmp do_NOT_IMPLEMENTED_error + // FALLTROUGH + +FRMEVL_got_value_float: + + lda #$00 + sta VALTYP + beq FRMEVL_got_value + // // This subroutine fetches the string value from the 'outside world' // @@ -178,7 +223,11 @@ FRMEVL_fetch_string: !: // No closing quote, but end of the data +#if !HAS_OPCODES_65CE02 jsr unconsume_character +#else + dew TXTPTR +#endif // FALLTROUGH @@ -196,7 +245,7 @@ FRMEVL_fetch_string: FRMEVL_got_value: - jsr end_of_statement_check + jsr is_end_of_statement bcs FRMEVL_compute_all // compute the stack if expression ended // FALLTROUGH @@ -274,9 +323,7 @@ FRMEVL_push_operator_address: // Check if there is enough stack space; this could not have been done earlier, // as this is the place where unary operator support calls - tsx - cpx #$40 // XXX is this a safe threshold? - bcc_16 do_FORMULA_TOO_COMPLEX_error + jsr check_stack_space // Push the operator address to stack, in a form // suitable for RTS diff --git a/src/basic/engine_runtime/helper_frmevl_strdesccpy_46K_50K.s b/src/basic/engine_runtime/helper_frmevl_strdesccpy_46K_50K.s new file mode 100644 index 00000000..249dbb7d --- /dev/null +++ b/src/basic/engine_runtime/helper_frmevl_strdesccpy_46K_50K.s @@ -0,0 +1,44 @@ +// #LAYOUT# STD * #TAKE-HIGH +// #LAYOUT# * BASIC_0 #TAKE-HIGH +// #LAYOUT# * * #IGNORE + +// This has to go $E000 or above - routines below banks out the main BASIC ROM! + +// +// Helper routine to copy string descriptor, for expression evaluator +// + + +#if CONFIG_MEMORY_MODEL_46K || CONFIG_MEMORY_MODEL_50K + +helper_frmevl_strdesccpy: + + // Unmap BASIC lower ROM + + lda #$26 + sta CPU_R6510 + + // Copy string descriptor + + ldy #$00 + lda (VARPNT),y + sta __FAC1+0 + iny + lda (VARPNT),y + sta __FAC1+1 + iny + lda (VARPNT),y + sta __FAC1+2 + + // FALLTROUGH + +remap_BASIC: + + // Restore default memory mapping + + lda #$27 + sta CPU_R6510 + + rts + +#endif diff --git a/src/basic/engine/init_oldtxt.s b/src/basic/engine_runtime/init_oldtxt.s similarity index 100% rename from src/basic/engine/init_oldtxt.s rename to src/basic/engine_runtime/init_oldtxt.s diff --git a/src/basic/engine_runtime/injest_assign.s b/src/basic/engine_runtime/injest_assign.s new file mode 100644 index 00000000..56456299 --- /dev/null +++ b/src/basic/engine_runtime/injest_assign.s @@ -0,0 +1,16 @@ +// #LAYOUT# STD * #TAKE +// #LAYOUT# * BASIC_0 #TAKE +// #LAYOUT# * * #IGNORE + +// +// Consummes assign operator in a BASIC code, triggers error if not found +// + + +injest_assign: + + jsr fetch_character_skip_spaces + cmp #$B2 // assign operator character + bne_16 do_SYNTAX_error + + rts diff --git a/src/basic/engine/injest_comma.s b/src/basic/engine_runtime/injest_comma.s similarity index 77% rename from src/basic/engine/injest_comma.s rename to src/basic/engine_runtime/injest_comma.s index 8997ee2a..ff712d0e 100644 --- a/src/basic/engine/injest_comma.s +++ b/src/basic/engine_runtime/injest_comma.s @@ -9,14 +9,17 @@ injest_comma: - jsr fetch_character + jsr fetch_character_skip_spaces cmp #$2C // comma character beq injest_comma_found - cmp #$20 // space, can always be skipped - beq injest_comma // Not found + +#if !HAS_OPCODES_65CE02 jsr unconsume_character +#else + dew TXTPTR +#endif sec rts diff --git a/src/basic/engine_runtime/is_alphanumeric.s b/src/basic/engine_runtime/is_alphanumeric.s new file mode 100644 index 00000000..fa85c4c5 --- /dev/null +++ b/src/basic/engine_runtime/is_alphanumeric.s @@ -0,0 +1,39 @@ +// #LAYOUT# STD * #TAKE +// #LAYOUT# M65 BASIC_1 #TAKE +// #LAYOUT# * BASIC_0 #TAKE +// #LAYOUT# * * #IGNORE + +// +// Check .A content, if within 0-9, A-Z ranges, sets Carry if check fails +// + + +is_09_AZ: + + jsr is_AZ + bcs is_09 + rts + + +is_09: + + cmp #$30 // if below '0' - check failed + bcc is_alphanumeric_fail + + cmp #$3A // if above '9' - check failed + rts + + +is_AZ: + + cmp #$41 // if below 'A' - check failed + bcc is_alphanumeric_fail + + cmp #$7B // if above 'Z' - check failed + rts + + +is_alphanumeric_fail: + + sec + rts diff --git a/src/basic/engine_runtime/is_end_of_statement.s b/src/basic/engine_runtime/is_end_of_statement.s new file mode 100644 index 00000000..32cbfcb0 --- /dev/null +++ b/src/basic/engine_runtime/is_end_of_statement.s @@ -0,0 +1,39 @@ +// #LAYOUT# STD * #TAKE +// #LAYOUT# * BASIC_0 #TAKE +// #LAYOUT# * * #IGNORE + +// +// Check for end of statement, sets Carry if so. Injests all spaces. +// + + +is_end_of_statement: + + jsr fetch_character_skip_spaces + + cmp #$00 + beq !+ + cmp #$3A + beq !+ + + // Not end of statement + +#if !HAS_OPCODES_65CE02 + jsr unconsume_character +#else + dew TXTPTR +#endif + + clc + rts +!: + // End of statement + +#if !HAS_OPCODES_65CE02 + jsr unconsume_character +#else + dew TXTPTR +#endif + + sec + rts diff --git a/src/basic/engine_runtime/is_line_pointer_null_38K_60K.s b/src/basic/engine_runtime/is_line_pointer_null_38K_60K.s new file mode 100644 index 00000000..5ca5b151 --- /dev/null +++ b/src/basic/engine_runtime/is_line_pointer_null_38K_60K.s @@ -0,0 +1,37 @@ +// #LAYOUT# STD * #TAKE +// #LAYOUT# * BASIC_0 #TAKE +// #LAYOUT# * * #IGNORE + +// Return pointer in BASIC memory space status in Z flag + + +#if CONFIG_MEMORY_MODEL_38K || CONFIG_MEMORY_MODEL_60K + +is_line_pointer_null: + + // Check the pointer + + ldy #$01 // for non-NULL pointer, high byte is almost certainly not NULL + +#if CONFIG_MEMORY_MODEL_60K + ldx #(assign_variable_arr_ret-1) + pha + lda #<(assign_variable_arr_ret-1) + pha + + // Store FOUR6 on tha stack + + lda FOUR6 + pha + + // Retrieve all the coordinates + + ldx #$00 +!: + inx + jsr helper_fetch_arr_coord + + lda LINNUM+1 + pha + lda LINNUM+0 + pha + + // Check if more dimensions are given + + cpy #$00 + beq !- + + // Store number of dimensions on the stack + + phx_trash_a + + // Fetch assignment operator and continue + + jsr injest_assign + + lda #$FF // force DIMFLG to be array + jmp_8 assign_variable_common_1 + +assign_variable_not_array_1: + + // Require assignment operator + + jsr injest_assign + + // Check for special variables + + jsr is_var_TI_string + beq_16 assign_variable_TI_string + + jsr is_var_TI + beq_16 do_SYNTAX_error + + jsr is_var_ST + beq_16 do_SYNTAX_error + + // Push the DIMFLG and VARNAM to the stack - it might get overridden + + lda DIMFLG + + // FALLTROUGH + +assign_variable_common_1: + + pha + lda VARNAM+0 + pha + lda VARNAM+1 + pha + + // Evaluate the expression + + jsr FRMEVL + + // Restore VARNAM and DIMFLG + + pla + sta VARNAM+1 + pla + sta VARNAM+0 + pla + sta DIMFLG // XXX is it needed? + + // Check if array + + bpl assign_variable_not_array_2 + + // Yes, this is an array - preserve FAC1 values which might get overwritten + // XXX adapt this for floats! + + ldx #$04 +!: + lda __FAC1,x + sta __FAC2,x + dex + bpl !- + + // Get array address + + jsr find_array + bcc !+ + + // Array does not exist - we will have to create one with default parameters + + // XXX implement this + + jmp do_NOT_IMPLEMENTED_error +!: + // Fetch the number of dimensions + + pla + sta __FAC1+0 + tax + + // Fetch the address of the variable + + jmp fetch_variable_arr_calc_pos // RTS goes to assign_variable_arr_ret + +assign_variable_arr_ret: + + // Restore FAC1 values + // XXX adapt this for floats! + + ldx #$04 +!: + lda __FAC2,x + sta __FAC1,x + dex + bpl !- + bmi assign_variable_common_2 // branch always + +assign_variable_not_array_2: + + // Retrieve the variable address + + jsr fetch_variable_find_addr + + // FALLTROUGH + +assign_variable_common_2: + + // Determine variable type + + lda #$00 + clc + bit VARNAM+0 + bpl !+ + adc #$01 +!: + bit VARNAM+1 + bpl !+ + adc #$80 +!: + // Determine what to assign + + bmi assign_string + beq assign_float + + // FALLTROUGH + + // XXX integer and float probably have much in common + +assign_integer: + + lda VALTYP + bmi_16 do_TYPE_MISMATCH_error + +#if CONFIG_MEMORY_MODEL_60K + + // XXX + // XXX: implement this + // XXX + +#elif CONFIG_MEMORY_MODEL_46K || CONFIG_MEMORY_MODEL_50K + // XXX consider optimized version without multiple JSRs + + // XXX + // XXX: implement this + // XXX + +#else // CONFIG_MEMORY_MODEL_38K + + // XXX + // XXX: implement this + // XXX + +#endif + + jmp do_NOT_IMPLEMENTED_error + +assign_float: + + lda VALTYP + bmi_16 do_TYPE_MISMATCH_error + +#if CONFIG_MEMORY_MODEL_60K + + // XXX + // XXX: implement this + // XXX + +#elif CONFIG_MEMORY_MODEL_46K || CONFIG_MEMORY_MODEL_50K + // XXX consider optimized version without multiple JSRs + + // XXX + // XXX: implement this + // XXX + +#else // CONFIG_MEMORY_MODEL_38K + + // XXX + // XXX: implement this + // XXX + +#endif + + jmp do_NOT_IMPLEMENTED_error + +assign_string: + + // Check if value type matches + + lda VALTYP + bpl_16 do_TYPE_MISMATCH_error + + // Copy the string descriptor to DSCPNT + + jsr helper_strdesccpy + + // First special case - check if the new string has size 0 + + lda __FAC1+0 + bne assign_string_not_empty + + // Yes, it is empty - free the old one + + jsr varstr_free + + // Set the new variable as empty string + + ldy #$00 + lda #$00 + +#if CONFIG_MEMORY_MODEL_60K + ldx #= 7) + + sec + lda FRETOP+0 + sbc STREND+0 + pha + lda FRETOP+1 + sbc STREND+1 + bne !+ // branch if high byte of result > 0 + + pla + cmp #$07 + bcs fetch_variable_alocate_space_OK + + jmp do_OUT_OF_MEMORY_error +!: + pla + + // FALLTROUGH + +fetch_variable_alocate_space_OK: + + // If arrays exist, we need to move them upwards + + sec + lda STREND+0 + sta memmove__src+0 + sbc ARYTAB+0 + sta memmove__size+0 + lda STREND+1 + sta memmove__src+1 + sbc ARYTAB+1 + sta memmove__size+1 + + ora memmove__size+0 + beq fetch_variable_alocate_adjust_vars + + // Indeed, there are arrays - adjust size, calculate the destination and perform copying + + inc memmove__size+0 + bne !+ + inc memmove__size+1 +!: + + clc + lda memmove__src+0 + adc #$07 + sta memmove__dst+0 + lda memmove__src+1 + adc #$00 + sta memmove__dst+1 + + jsr shift_mem_up + + // FALLTROUGH + +fetch_variable_alocate_adjust_vars: + + // Adjust ARYTAB and STREND + + clc + lda STREND+0 + adc #$07 + sta STREND+0 + bcc !+ + inc STREND+1 +!: + + clc + lda ARYTAB+0 + adc #$07 + sta ARYTAB+0 + bcc !+ + inc ARYTAB+1 +!: + // VARPNT already points to the start of the variable descriptor + + // We need to recreate the back-pointers to string arrays + + jsr helper_array_refresh_bptrs + + // Fill-in the new variable name and descriptor (it is enough to zero first 2 bytes of content) + + ldy #$00 + +#if CONFIG_MEMORY_MODEL_60K + + ldx # 0, then we certainly have enough space + + lda INDEX+3 + bne helper_array_create_checkmem_success + + // We have very little memory left - we need at least number of dimensions*2 + 5 bytes + + lda __FAC1+0 + asl + clc + adc #$04 + + cmp INDEX+2 + bcs helper_array_create_checkmem_fail + + // FALLTROUGH + +helper_array_create_checkmem_success: + + rts + +helper_array_create_checkmem_fail: + + jmp do_OUT_OF_MEMORY_error diff --git a/src/basic/engine_variables/helper_array_create_mul.s b/src/basic/engine_variables/helper_array_create_mul.s new file mode 100644 index 00000000..fca065b5 --- /dev/null +++ b/src/basic/engine_variables/helper_array_create_mul.s @@ -0,0 +1,76 @@ +// #LAYOUT# STD * #TAKE +// #LAYOUT# * BASIC_0 #TAKE +// #LAYOUT# * * #IGNORE + +// 16-bit multiplication, INDEX+0/+1 = __FAC1+1/+2 * __FAC1+3/+4; __FAC1+1/+2 = INDEX+0/+1 +// uses INDEX+2/+3 (for helper routine) as work area + + +helper_array_create_mul: // preserves .X and .Y + + phx_trash_a + + // We will reuse 8x8 multiplication routine used by floating point operations + + // __FAC1+1 (lo byte) * __FAC1+3 (lo byte) + + lda __FAC1+1 + sta INDEX+3 + lda __FAC1+3 + jsr mul_FAC2_FAC1_8x8 // this preserves .Y + + sta INDEX+0 // result - lo byte + stx INDEX+1 // result - hi byte + + // __FAC1+1 (lo byte) * __FAC1+4 (hi byte) + + lda __FAC1+1 + sta INDEX+3 + lda __FAC1+4 + jsr helper_array_create_mul_8x8_add // multiply and add to high byte of the result + + // __FAC1+2 (hi byte) * __FAC1+3 (lo byte) + + lda __FAC1+2 + sta INDEX+3 + lda __FAC1+3 + jsr helper_array_create_mul_8x8_add // multiply and add to high byte of the result + + // __FAC1+2 (hi byte) * __FAC1+4 (hi byte) has to be 0, + // otherwise the result would be out of range + // do not calculate + + lda __FAC1+2 + beq helper_array_create_mul_success + lda __FAC1+4 + beq helper_array_create_mul_success + + // FALLTROUGH + +helper_array_create_mul_error: + + jmp do_OUT_OF_MEMORY_error + +helper_array_create_mul_success: + + lda INDEX+0 + sta __FAC1+1 + lda INDEX+1 + sta __FAC1+2 + + plx_trash_a + rts + +helper_array_create_mul_8x8_add: + + jsr mul_FAC2_FAC1_8x8 + + cpx #$00 + bne helper_array_create_mul_error + + clc + adc INDEX+1 + bcs helper_array_create_mul_error + sta INDEX+1 + + rts diff --git a/src/basic/engine_variables/helper_array_fetch_dimension_46K_50K.s b/src/basic/engine_variables/helper_array_fetch_dimension_46K_50K.s new file mode 100644 index 00000000..c53efb9e --- /dev/null +++ b/src/basic/engine_variables/helper_array_fetch_dimension_46K_50K.s @@ -0,0 +1,32 @@ +// #LAYOUT# STD * #TAKE-HIGH +// #LAYOUT# * BASIC_0 #TAKE-HIGH +// #LAYOUT# * * #IGNORE + +// This has to go $E000 or above - routine below banks out the main BASIC ROM! + +#if CONFIG_MEMORY_MODEL_46K || CONFIG_MEMORY_MODEL_50K + +helper_array_fetch_dimension: + + // Unmap BASIC lower ROM + + lda #$26 + sta CPU_R6510 + + // Fetch the dimension + + lda (VARPNT), y + sta __FAC1+4 + iny + lda (VARPNT), y + sta __FAC1+3 + iny + + // Restore default memory mapping + + lda #$27 + sta CPU_R6510 + + rts + +#endif diff --git a/src/basic/engine_variables/helper_array_refresh_bptrs.s b/src/basic/engine_variables/helper_array_refresh_bptrs.s new file mode 100644 index 00000000..616ed146 --- /dev/null +++ b/src/basic/engine_variables/helper_array_refresh_bptrs.s @@ -0,0 +1,198 @@ +// #LAYOUT# STD * #TAKE +// #LAYOUT# * BASIC_0 #TAKE +// #LAYOUT# * * #IGNORE + +// +// Refresh back-pointer to arrays +// + +helper_array_refresh_bptrs: + + // Refresh back-pointers to arrays + + lda ARYTAB+0 + sta INDEX+0 + lda ARYTAB+1 + sta INDEX+1 + + // FALLTROUGH + +helper_array_refresh_bptrs_loop_1: + + // Check if we reached end of arays + + lda INDEX+1 + cmp STREND+1 + bne !+ + lda INDEX+0 + cmp STREND+0 + bne !+ + rts +!: + // Calculate start address of the next array, store it in INDEX+2/+3 + +#if CONFIG_MEMORY_MODEL_60K + + ldx # STREND, Carry set if not + + lda STREND+1 + cmp FRETOP+1 + beq !+ + rts +!: + lda STREND+0 + cmp FRETOP+0 + rts diff --git a/src/basic/engine_variables/helper_fretop_up.s b/src/basic/engine_variables/helper_fretop_up.s new file mode 100644 index 00000000..de5ee2b2 --- /dev/null +++ b/src/basic/engine_variables/helper_fretop_up.s @@ -0,0 +1,19 @@ +// #LAYOUT# STD * #TAKE +// #LAYOUT# * BASIC_0 #TAKE +// #LAYOUT# * * #IGNORE + +// +// Helper routine for FRETOP handling +// + + +helper_FRETOP_up: // DSCPNT+0 - bytes to increment FRETO + + clc + lda FRETOP+0 + adc DSCPNT+0 + sta FRETOP+0 + bcc !+ + inc FRETOP+1 +!: + rts diff --git a/src/basic/engine_variables/helper_gc_fetch_backpointer_46K_50K.s b/src/basic/engine_variables/helper_gc_fetch_backpointer_46K_50K.s new file mode 100644 index 00000000..1b72c7cd --- /dev/null +++ b/src/basic/engine_variables/helper_gc_fetch_backpointer_46K_50K.s @@ -0,0 +1,32 @@ +// #LAYOUT# STD * #TAKE-HIGH +// #LAYOUT# * BASIC_0 #TAKE-HIGH +// #LAYOUT# * * #IGNORE + +// This has to go $E000 or above - routine below banks out the main BASIC ROM! + +#if CONFIG_MEMORY_MODEL_46K || CONFIG_MEMORY_MODEL_50K + +helper_gc_fetch_backpointer: + + // Unmap BASIC lower ROM + + lda #$26 + sta CPU_R6510 + + // Copy the back-pointer to OLDTXT, check if it is NULL + + ldy #$00 + lda (TXTPTR),y + sta OLDTXT+0 + + iny + lda (TXTPTR),y + sta OLDTXT+1 + + ora OLDTXT+0 + + // Restore default memory mapping + + jmp remap_BASIC_preserve_P + +#endif diff --git a/src/basic/engine_variables/helper_gc_misc_46K_50K.s b/src/basic/engine_variables/helper_gc_misc_46K_50K.s new file mode 100644 index 00000000..503df2aa --- /dev/null +++ b/src/basic/engine_variables/helper_gc_misc_46K_50K.s @@ -0,0 +1,54 @@ +// #LAYOUT# STD * #TAKE-HIGH +// #LAYOUT# * BASIC_0 #TAKE-HIGH +// #LAYOUT# * * #IGNORE + +// This has to go $E000 or above - routines below bank out the main BASIC ROM! + +#if CONFIG_MEMORY_MODEL_46K || CONFIG_MEMORY_MODEL_50K + +helper_gc_set_memmove_src: + + // Unmap BASIC lower ROM + + lda #$26 + sta CPU_R6510 + + // Set memmove__src + + lda (OLDTXT),y + sta memmove__src+0 + iny + lda (OLDTXT),y + sta memmove__src+1 + + // Restore default memory mapping + + jmp_8 helper_gc_misc_end + +helper_gc_increase_oldtxt: + + // Unmap BASIC lower ROM + + lda #$26 + sta CPU_R6510 + + // Increase OLDTXT accordingly + + lda (OLDTXT),y + clc + adc INDEX+0 + sta (OLDTXT),y + iny + lda (OLDTXT),y + adc INDEX+1 + sta (OLDTXT),y + + // FALLTROUGH + +helper_gc_misc_end: + + // Restore default memory mapping + + jmp remap_BASIC + +#endif diff --git a/src/basic/engine_variables/helper_index_up_a_38K_60K.s b/src/basic/engine_variables/helper_index_up_a_38K_60K.s new file mode 100644 index 00000000..54198e25 --- /dev/null +++ b/src/basic/engine_variables/helper_index_up_a_38K_60K.s @@ -0,0 +1,24 @@ +// #LAYOUT# STD * #TAKE +// #LAYOUT# * BASIC_0 #TAKE +// #LAYOUT# * * #IGNORE + +// +// Helper routine, used in several places +// + +#if CONFIG_MEMORY_MODEL_38K || CONFIG_MEMORY_MODEL_60K + +helper_INDEX_up_A: // .A - bytes to increase INDEX, uses DSCPNT+0 + + sta DSCPNT+0 + + clc + lda INDEX+0 + adc DSCPNT+0 + sta INDEX+0 + bcc !+ + dec INDEX+1 +!: + rts + +#endif diff --git a/src/basic/engine_variables/helper_index_up_a_46K_50K.s b/src/basic/engine_variables/helper_index_up_a_46K_50K.s new file mode 100644 index 00000000..38ede00c --- /dev/null +++ b/src/basic/engine_variables/helper_index_up_a_46K_50K.s @@ -0,0 +1,26 @@ +// #LAYOUT# STD * #TAKE-HIGH +// #LAYOUT# * BASIC_0 #TAKE-HIGH +// #LAYOUT# * * #IGNORE + +// This has to go $E000 or above - it can be used by routines which bank out the main BASIC ROM! + +// +// Helper routine, used in several places +// + +#if CONFIG_MEMORY_MODEL_46K || CONFIG_MEMORY_MODEL_50K + +helper_INDEX_up_A: // .A - bytes to increase INDEX, uses DSCPNT+0 + + sta DSCPNT+0 + + clc + lda INDEX+0 + adc DSCPNT+0 + sta INDEX+0 + bcc !+ + dec INDEX+1 +!: + rts + +#endif diff --git a/src/basic/engine_variables/helper_strconcat_46K_50K.s b/src/basic/engine_variables/helper_strconcat_46K_50K.s new file mode 100644 index 00000000..e44ea918 --- /dev/null +++ b/src/basic/engine_variables/helper_strconcat_46K_50K.s @@ -0,0 +1,53 @@ +// #LAYOUT# STD * #TAKE-HIGH +// #LAYOUT# * BASIC_0 #TAKE-HIGH +// #LAYOUT# * * #IGNORE + +// This has to go $E000 or above - routines below banks out the main BASIC ROM! + +// +// Helper routine for string concatenation +// + + +#if CONFIG_MEMORY_MODEL_46K || CONFIG_MEMORY_MODEL_50K + +helper_strconcat: + + // Unmap BASIC lower ROM + + lda #$26 + sta CPU_R6510 + + // Copy data from the first string + + ldy #$00 +!: + lda (__FAC2+1),y + sta (INDEX),y + iny + cpy __FAC2+0 + bne !- + + // Increase INDEX pointer by the size of the 1st string + + tya + jsr helper_INDEX_up_A + + // Copy data from the second string + + ldy #$00 +!: + lda (__FAC1+1),y + sta (INDEX),y + iny + cpy __FAC1+0 + bne !- + + // Restore default memory mapping + + lda #$27 + sta CPU_R6510 + + rts + +#endif diff --git a/src/basic/engine_variables/helper_strdesccpy_38K.s b/src/basic/engine_variables/helper_strdesccpy_38K.s new file mode 100644 index 00000000..04870841 --- /dev/null +++ b/src/basic/engine_variables/helper_strdesccpy_38K.s @@ -0,0 +1,26 @@ +// #LAYOUT# STD * #TAKE +// #LAYOUT# * BASIC_0 #TAKE +// #LAYOUT# * * #IGNORE + +// +// Helper routine to copy string descriptor +// + + +#if CONFIG_MEMORY_MODEL_38K + +helper_strdesccpy: + + ldy #$00 + lda (VARPNT), y + sta DSCPNT+0 + iny + lda (VARPNT), y + sta DSCPNT+1 + iny + lda (VARPNT), y + sta DSCPNT+2 + + rts + +#endif diff --git a/src/basic/engine_variables/helper_strdesccpy_46K_50K.s b/src/basic/engine_variables/helper_strdesccpy_46K_50K.s new file mode 100644 index 00000000..df7d4172 --- /dev/null +++ b/src/basic/engine_variables/helper_strdesccpy_46K_50K.s @@ -0,0 +1,40 @@ +// #LAYOUT# STD * #TAKE-HIGH +// #LAYOUT# * BASIC_0 #TAKE-HIGH +// #LAYOUT# * * #IGNORE + +// This has to go $E000 or above - routine below banks out the main BASIC ROM! + +// +// Helper routine to copy string descriptor +// + + +#if CONFIG_MEMORY_MODEL_46K || CONFIG_MEMORY_MODEL_50K + +helper_strdesccpy: + + // Unmap BASIC lower ROM + + lda #$26 + sta CPU_R6510 + + // Retrieve pointer to destination + + ldy #$00 + lda (VARPNT), y + sta DSCPNT+0 + iny + lda (VARPNT), y + sta DSCPNT+1 + iny + lda (VARPNT), y + sta DSCPNT+2 + + // Restore default memory mapping + + lda #$27 + sta CPU_R6510 + + rts + +#endif diff --git a/src/basic/engine_variables/helper_strdesccpy_60K.s b/src/basic/engine_variables/helper_strdesccpy_60K.s new file mode 100644 index 00000000..9e627a18 --- /dev/null +++ b/src/basic/engine_variables/helper_strdesccpy_60K.s @@ -0,0 +1,28 @@ +// #LAYOUT# STD * #TAKE +// #LAYOUT# * BASIC_0 #TAKE +// #LAYOUT# * * #IGNORE + +// +// Helper routine to copy string descriptor +// + + +#if CONFIG_MEMORY_MODEL_60K + +helper_strdesccpy: + + ldx # 0 +// +// Output: +// - VARPNT points to the newly alocated descriptor +// + +tmpstr_alloc: + + tax + + // First we need to find a free temporary string descriptor + + lda TEMPPT + cmp #$22 + bcs tmpstr_alloc_try_reuse + + tay + sta LASTPT + clc + adc #$03 + sta TEMPPT + + // FALLTROUGH + +tmpstr_alloc_found: + + // Store desired string length + + stx $00, y + + // Store descriptor address + + sty VARPNT+0 + lda #$00 + sta VARPNT+1 + + // Jump to alocation routine + + jmp varstr_alloc + +tmpstr_alloc_try_reuse: + + // It seems there is no space left - try to find empty entry + + ldy #$19 + + // FALLTROUGH + +tmpstr_alloc_try_reuse_loop: + + lda $00, y + beq tmpstr_alloc_found // branch if free entry found + + iny + iny + iny + cpy #$22 + bne tmpstr_alloc_try_reuse_loop + + // Everything failed - give up + + jmp do_FORMULA_TOO_COMPLEX_error diff --git a/src/basic/engine_variables/tmpstr_free.s b/src/basic/engine_variables/tmpstr_free.s new file mode 100644 index 00000000..14d41291 --- /dev/null +++ b/src/basic/engine_variables/tmpstr_free.s @@ -0,0 +1,94 @@ +// #LAYOUT# STD * #TAKE +// #LAYOUT# * BASIC_0 #TAKE +// #LAYOUT# * * #IGNORE + +// +// Frees the string if it belongs to temporary string stack +// +// Input: +// - DSCPNT+1/+2 - pointer to string (depending on the call addres, can fetch from FAC1/FAC2) +// + + +tmpstr_free_FAC1: + + lda __FAC1+1 + sta DSCPNT+1 + lda __FAC1+2 + + jmp_8 !+ + + +tmpstr_free_FAC2: + + lda __FAC2+1 + sta DSCPNT+1 + lda __FAC2+2 +!: + sta DSCPNT+2 + + // FALLTROUGH + +tmpstr_free: + + // First find the descriptor matching the given string + + ldx #$19 + + //FALLTROUGH + +tmpstr_free_loop: + + cpx TEMPPT + bne !+ + rts // quit if not found +!: + // First fetch the string size - if 0, do not even try to compare + + ldy $00, x + beq tmpstr_free_next_3 + + // Check if current string + + inx + lda $00, x + cmp DSCPNT+1 + bne tmpstr_free_next_2 + + inx + lda $00, x + cmp DSCPNT+2 + bne tmpstr_free_next_1 + + // This is the string we need to free + + sty DSCPNT+0 + phx_trash_a + jsr varstr_free_no_checks + plx_trash_a + + // Mark empty string as free and quit + + dex + dex + lda #$00 + sta $00, x + + rts + +tmpstr_free_next_3: + + inx + + // FALLTROUGH + +tmpstr_free_next_2: + + inx + + // FALLTROUGH + +tmpstr_free_next_1: + + inx + bne tmpstr_free_loop diff --git a/src/basic/engine_variables/tmpstr_free_all.s b/src/basic/engine_variables/tmpstr_free_all.s new file mode 100644 index 00000000..bd0f3067 --- /dev/null +++ b/src/basic/engine_variables/tmpstr_free_all.s @@ -0,0 +1,48 @@ +// #LAYOUT# STD * #TAKE +// #LAYOUT# * BASIC_0 #TAKE +// #LAYOUT# * * #IGNORE + + +tmpstr_free_all: + + // Go through all the temporary descriptors and free everything + + ldx #$19 + + //FALLTROUGH + +tmpstr_free_all_loop: + + // Free all the temporary strings, one by one + + cpx TEMPPT + beq tmpstr_free_all_reset + + lda $00, x + beq !+ + + sta DSCPNT+0 + lda $01, x + sta DSCPNT+1 + lda $02, x + sta DSCPNT+2 + + phx_trash_a + jsr varstr_free_no_checks + plx_trash_a +!: + inx + inx + inx + bne tmpstr_free_all_loop // branch always + +tmpstr_free_all_reset: // entry point for CLR + + // RESET TEMPPT and LASTPT to default values + + lda #$19 + sta TEMPPT + lda #$16 + sta LASTPT + + rts diff --git a/src/basic/engine_variables/varstr_alloc.s b/src/basic/engine_variables/varstr_alloc.s new file mode 100644 index 00000000..371116ef --- /dev/null +++ b/src/basic/engine_variables/varstr_alloc.s @@ -0,0 +1,141 @@ +// #LAYOUT# STD * #TAKE +// #LAYOUT# * BASIC_0 #TAKE +// #LAYOUT# * * #IGNORE + +// +// Allocates memory for string - lowers FRETOP (but not below STREND) +// +// Note: We are not going to use the C64-style memory management here, as it implies +// a very slow garbage collector. Instead, we are using a scheme similar to used in +// BASIC V3.5 and later, with 'back-pointers' after each string, telling about the +// location of the string descriptor. +// +// See: +// - https://www.c64-wiki.com/wiki/Memory_(BASIC) +// - https://sites.google.com/site/h2obsession/CBM/basic/variable-format +// +// Input: +// - VARPNT - pointer to string descriptor, first pointed byte should contain desired length +// Output: +// - fills-in pointer in the string descriptor +// + +// NOTE: if FAC1 or FAC2 contains a value (not a string descriptor - these are going to be updated +// if garbage collector starts), then preserve __FAC1+1/+2 and __FAC2+1/+2 somewhere, as there +// is a small chance they'll get damaged! + +varstr_alloc: + + // Mark garbage collector as not run yet + + lda #$00 + + // FALLTROUGH + +varstr_alloc_retry: + + sta GARBFL // Computes Mapping the Commodore 64, page 10 + + // Backup FRETOP in case of alocation problems + + lda FRETOP+0 + sta INDEX+0 + lda FRETOP+1 + sta INDEX+1 + + // Lower FRETOP to make space for the back-pointer + +#if !HAS_OPCODES_65CE02 + + lda #$02 + jsr helper_FRETOP_down_A + +#else // HAS_OPCODES_65CE02 - this time code is slightly longer, but faster + + dew FRETOP + dew FRETOP + + jsr helper_FRETOP_check + +#endif + + bcs varstr_alloc_fail + + // Create the back-pointer to the string descriptor + + ldy #$00 + lda VARPNT+0 + +#if CONFIG_MEMORY_MODEL_60K + ldx # $FF + jsr varstr_garbage_collect + + jmp_8 varstr_alloc_retry diff --git a/src/basic/engine_variables/varstr_free.s b/src/basic/engine_variables/varstr_free.s new file mode 100644 index 00000000..b4815d7a --- /dev/null +++ b/src/basic/engine_variables/varstr_free.s @@ -0,0 +1,103 @@ +// #LAYOUT# STD * #TAKE +// #LAYOUT# * BASIC_0 #TAKE +// #LAYOUT# * * #IGNORE + +// +// Releases back memory used by string +// +// Input: +// - DSCPNT+0 - string size +// - DSCPNT+1, DSCPNT+2 - pointer to string +// + + +varstr_free: + + // Check the string size - do not do anything if 0 + + lda DSCPNT+0 + bne !+ + rts +!: + // Check if string is above FRETOP (in string area) + + jsr helper_cmp_fretop + bcs varstr_free_no_checks + + // No, it does not belong to string area - quit + + rts + +varstr_free_no_checks: // entry point to be used when it is clear that string is not empty and above FRETOP + + // Check if this is the lowest string + + bne varstr_free_inside + + // This is the lowest string - so just increase FRETOP, this way + // the garbage collector will not be needed that quickly + + jsr helper_FRETOP_up // free the string data + +#if !HAS_OPCODES_65CE02 + + lda #$02 // free the back-pointer + sta DSCPNT+0 + jmp helper_FRETOP_up + +#else // HAS_OPCODES_65CE02 + + inw FRETOP // free the back-pointer + inw FRETOP + + rts + +#endif + +varstr_free_inside: + + // This is not the lowest string; mark it as free + // First preserve the string size, it will make it easier for the garbage collector + + // Increase DSCPNT+1/+2 to point to the back-pointer minus 1 + + dec DSCPNT+0 + + clc + lda DSCPNT+1 + adc DSCPNT+0 + sta DSCPNT+1 + bcc !+ + inc DSCPNT+2 +!: + // Put the size-1, garbage collector will make use of this value + + lda DSCPNT+0 + ldy #$00 + +#if CONFIG_MEMORY_MODEL_60K + ldx # memmove__src @@ -95,11 +33,7 @@ shift_mem_up_internal: dec memmove__size+1 bne !- -#if HAS_OPCODES_65C02 - bra shift_mem_internal_finalize -#else - jmp shift_mem_internal_finalize -#endif + jmp_8 shift_mem_internal_finalize shift_mem_down_internal: diff --git a/src/basic/peek_line_pointer_null_check.s b/src/basic/peek_line_pointer_null_check.s deleted file mode 100644 index a73351d4..00000000 --- a/src/basic/peek_line_pointer_null_check.s +++ /dev/null @@ -1,44 +0,0 @@ -// #LAYOUT# STD * #TAKE -// #LAYOUT# * BASIC_0 #TAKE -// #LAYOUT# * * #IGNORE - -// Return C=1 if a pointer in BASIC memory space is NULL, else C=0 -// X = ZP pointer to check - -peek_line_pointer_null_check: - - ldy #$00 - -#if CONFIG_MEMORY_MODEL_60K - ldx #1 + .byte >10 + .byte >100 + .byte >1000 + .byte >10000 diff --git a/src/basic/print/print_integer_tab_lo.s b/src/basic/print/print_integer_tab_lo.s new file mode 100644 index 00000000..47fef0ec --- /dev/null +++ b/src/basic/print/print_integer_tab_lo.s @@ -0,0 +1,15 @@ +// #LAYOUT# STD * #TAKE +// #LAYOUT# * BASIC_0 #TAKE +// #LAYOUT# * * #IGNORE + +// +// Helper power of 10s table (low buytes) for 'print_integer' +// + +print_integer_tab_lo: + + .byte <1 + .byte <10 + .byte <100 + .byte <1000 + .byte <10000 diff --git a/src/basic/print/print_packed_freq_string.s b/src/basic/print/print_packed_freq_string.s index a936a675..cc5d36c9 100644 --- a/src/basic/print/print_packed_freq_string.s +++ b/src/basic/print/print_packed_freq_string.s @@ -39,18 +39,22 @@ print_packed_misc_str: // .X - misc string index #endif -print_packed_keyword_CC: // .X - token number +print_packed_keyword_01: // .X - token number - lda #packed_freq_keywords_CC + lda #packed_freq_keywords_01 bne print_freq_packed_string // branch always -print_packed_keyword_CD: // .X - token number +#if !HAS_SMALL_BASIC - lda #packed_freq_keywords_CD +print_packed_keyword_02: // .X - token number + + lda #packed_freq_keywords_02 bne print_freq_packed_string // branch always +#endif + print_packed_keyword_V2: // .X - token number lda #(BUF+1) - sta TXTPTR+1 - - lda #$FF - sta CURLIN+1 + jsr prepare_direct_execution + jsr fetch_character // Now we have to check what the user wants us to do // Check if user asked for a status + ldy #$00 lda (TXTPTR), y - bne !+ - jmp wedge_dos_status // XXX try to optimize this, perhaps move 'wedge_dos_status' above? -!: + beq_16 wedge_dos_status + // Check if asked for a directory + cmp #$24 - bne !+ - jmp wedge_dos_directory -!: + beq_16 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 (TXTPTR), y - beq wedge_dos_change_drive // end of buffer - cmp #$20 - beq wedge_dos_change_drive - jmp !- + + jsr is_09 + bcc wedge_dos_change_drive + + // FALLTROUGH wedge_dos_command: +#if !HAS_SMALL_BASIC + + // Check if command needs confirmation + + ldy #$00 + lda (TXTPTR), y + + cmp #$52 // 'R' - because 'RD' is a directory removal command + bne !+ + + iny + lda (TXTPTR), y + cmp #$44 // 'D' + bne wedge_dos_command_confirmed + beq wedge_dos_command_ask +!: + cmp #$4E // 'N' - for the disk format + beq !+ + cmp #$53 // 'S' - for the file scratch + bne wedge_dos_command_confirmed +!: + // This is probably a dangerous command - check further the syntax, + // if 'N:', 'S:', 'Nx:' or 'Sx:' (where 'x' is a digit) - ask for confirmation first + + iny + lda (TXTPTR), y + cmp #$3A // ':' - colon + beq wedge_dos_command_ask + + jsr is_09 + bcs wedge_dos_command_confirmed + + iny + lda (TXTPTR), y + cmp #$3A // ':' - colon + bne wedge_dos_command_confirmed + + // FALLTROUGH + +wedge_dos_command_ask: + + jsr helper_ask_if_sure + bcs_16 wedge_dos_clean_exit + + // FALLTROUGH + +wedge_dos_command_confirmed: + +#endif // !HAS_SMALL_BASIC + // Provide command name + jsr wedge_dos_setnam jsr JSETNAM jsr JOPEN - bcc !+ - jmp wedge_dos_basic_error // XXX combine with other such jumps -!: + bcs_16 wedge_dos_basic_error + // Retrieve status, print it if not OK + jsr JCLALL - jsr wedge_dos_status_get + jsr wedge_dos_status_get_no_new_line + lda BUF+0 cmp #$30 // '0' bne wedge_dos_status_print - lda BUF+1 - cmp #$30 // '0' + + eor BUF+1 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 LINNUM+1 - beq !+ - jmp do_ILLEGAL_QUANTITY_error -!: - lda LINNUM+0 + // Fetch new drive number, make sure this is the last part of the command + + jsr fetch_uint8 + pha + jsr fetch_character_skip_spaces + cmp #$00 + bne_16 do_SYNTAX_error + pla + + // Check if device number is valid for IEC drive + cmp #$08 - bpl !+ - bcs !+ - jmp do_ILLEGAL_DEVICE_NUMBER_error -!: + bcc_16 do_ILLEGAL_DEVICE_NUMBER_error + + // Store new device number and return to shell + sta FA jmp shell_main_loop @@ -104,41 +161,57 @@ wedge_dos_status_get: jsr print_return + // FALLTROUGH + +wedge_dos_status_get_no_new_line: + // 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 JOPEN - bcc !+ - jmp wedge_dos_basic_error // XXX combine with other such jumps -!: + bcs_16 wedge_dos_basic_error // Set channel for input + ldx #$0F jsr JCHKIN - bcc !+ - jmp wedge_dos_basic_error // XXX combine with other such jumps -!: + bcs_16 wedge_dos_basic_error + + // Fetch the drive status 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 JCHRIN - bcc wedge_dos_x1 - jmp wedge_dos_basic_error // XXX try to optimize this -wedge_dos_x1: + // FALLTROUGH + +wedge_dos_status_get_loop: + + // Check for buffer overflow + + cpy #$50 + beq_16 do_OVERFLOW_error + + // Check for EOF + + jsr JREADST + // XXX check for transfer errors + bne wedge_dos_status_get_done + + // Retrieve a byte and put it into the buffer + + jsr JCHRIN + bcs_16 wedge_dos_basic_error + sta BUF, y iny - jmp !- -!: + + bne wedge_dos_status_get_loop // branch always + +wedge_dos_status_get_done: + // Strip ending RETURN dey @@ -147,11 +220,18 @@ wedge_dos_x1: wedge_dos_status: jsr wedge_dos_status_get - // FALLTROUGH + jmp_8 wedge_dos_status_print_no_new_line wedge_dos_status_print: + jsr print_return + + // FALLTROUGH + +wedge_dos_status_print_no_new_line: + // Print buffered status + ldx #$00 !: dey @@ -162,38 +242,44 @@ wedge_dos_status_print: bne !- !: // Clean-up and exit - jmp wedge_dos_clean_exit + + jmp_8 wedge_dos_clean_exit wedge_dos_directory: - // First change the secondary address to the one suitable for - // directory loading - lda #$00 // logical device number + // First change the secondary address to the one suitable for directory loading + + lda #$00 // logical device number ldx FA ldy #$60 jsr JSETFLS // Provide file name + jsr wedge_dos_setnam - // Open the file + // Open the file, set channel for reading + jsr JOPEN bcs wedge_dos_basic_error - // Set channel for file reading ldx #$00 jsr JCHKIN bcs wedge_dos_basic_error // Ignore start address (2 first bytes) - XXX check for errors + jsr JCHRIN bcs wedge_dos_basic_error jsr JCHRIN bcs wedge_dos_basic_error + // FALLTROUGH + wedge_dos_directory_line: // Load a single line, reuse BASIC input buffer + ldy #$FF !: iny @@ -201,29 +287,33 @@ wedge_dos_directory_line: bcs wedge_dos_basic_error sta BUF, y cpy #$50 - beq !+ // line too long, terminate loading file + beq_16 do_OVERFLOW_error // branch if line too long 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 + cpy #$05 // protection against malformed directory bcc wedge_dos_clean_exit - lda #$00 // extra protection agains buffer overflow + lda #$00 // extra protection agains buffer overflow sta BUF, y // Display line + ldx #BUF @@ -232,22 +322,28 @@ wedge_dos_directory_display: jsr list_single_line // Read & display next line or quit + lda IOSTATUS beq wedge_dos_directory_line + // FALLTROUGH wedge_dos_clean_exit: + jsr JCLALL jmp shell_main_loop wedge_dos_basic_error: + pha jsr JCLALL pla jmp do_kernal_error wedge_dos_setnam: + // Now determine the length of the 'file' name + ldy #$FF !: iny @@ -255,9 +351,14 @@ wedge_dos_setnam: bne !- // Set the name to open + tya ldx TXTPTR+0 ldy TXTPTR+1 + jmp JSETNAM + +#endif // ROM layout + #endif // CONFIG_DOS_WEDGE diff --git a/src/basic/wedge/wedge_tape.s b/src/basic/wedge/wedge_tape.s index 951ced7e..e90c6c4e 100644 --- a/src/basic/wedge/wedge_tape.s +++ b/src/basic/wedge/wedge_tape.s @@ -37,8 +37,7 @@ wedge_arrow_H: // Make sure the syntax is correct - jsr injest_spaces - jsr fetch_character + jsr fetch_character_skip_spaces cmp #$00 bne_16 do_SYNTAX_error diff --git a/src/basic/wedge/wedge_tape_prepare_load.s b/src/basic/wedge/wedge_tape_prepare_load.s index cac50b40..b31f0aa3 100644 --- a/src/basic/wedge/wedge_tape_prepare_load.s +++ b/src/basic/wedge/wedge_tape_prepare_load.s @@ -13,9 +13,8 @@ wedge_tape_prepare_load: // Make sure the syntax is correct - jsr injest_spaces - jsr fetch_character - + jsr fetch_character_skip_spaces + cmp #$00 beq wedge_tape_prepare_load_no_filename // branch if no file name given cmp #$22 diff --git a/src/kernal/assets/irq_timing_hi.s b/src/kernal/assets/irq_timing_hi.s index b884d60b..69547d41 100644 --- a/src/kernal/assets/irq_timing_hi.s +++ b/src/kernal/assets/irq_timing_hi.s @@ -22,5 +22,21 @@ irq_timing_hi: // high bytes +#if !CONFIG_RS232_UP9600 + .byte >17045 // NTSC .byte >16421 // PAL + +#else + +// +// Timer values needed by UP9600 +// +// Original driver code by Daniel Dallman with Bo Zimmerman adaptations, +// these causes the tick to be generated 64 times per second +// + + .byte $42 // NTSC + .byte $40 // PAL + +#endif \ No newline at end of file diff --git a/src/kernal/assets/irq_timing_lo.s b/src/kernal/assets/irq_timing_lo.s index 5043d2ba..3760f444 100644 --- a/src/kernal/assets/irq_timing_lo.s +++ b/src/kernal/assets/irq_timing_lo.s @@ -22,5 +22,21 @@ irq_timing_lo: // low bytes +#if !CONFIG_RS232_UP9600 + .byte <17045 // NTSC .byte <16421 // PAL + +#else + +// +// Timer values needed by UP9600 +// +// Original driver code by Daniel Dallman with Bo Zimmerman adaptations, +// these causes the tick to be generated 64 times per second +// + + .byte $95 // NTSC + .byte $25 // PAL + +#endif \ No newline at end of file diff --git a/src/kernal/board_m65/4000.mega65_vectable_kernal_1.s b/src/kernal/board_m65/4000.mega65_vectable_kernal_1.s index 9accb56b..95d310e5 100644 --- a/src/kernal/board_m65/4000.mega65_vectable_kernal_1.s +++ b/src/kernal/board_m65/4000.mega65_vectable_kernal_1.s @@ -21,7 +21,7 @@ #else - // Vector table (OpenROMs private!) + // Vector table (Open ROMs private!) .word IOINIT .word RAMTAS diff --git a/src/kernal/board_x16/cx16_stubs.s b/src/kernal/board_x16/cx16_stubs.s index da530dd6..2407b0e5 100644 --- a/src/kernal/board_x16/cx16_stubs.s +++ b/src/kernal/board_x16/cx16_stubs.s @@ -39,6 +39,3 @@ setup_pal_ntsc: wait_x_bars: STUB_IMPLEMENTATION() - -udtim_keyboard: - STUB_IMPLEMENTATION() diff --git a/src/kernal/init/fffc.vector_reset.s b/src/kernal/init/fffc.vector_reset.s index c8322445..32fb6c03 100644 --- a/src/kernal/init/fffc.vector_reset.s +++ b/src/kernal/init/fffc.vector_reset.s @@ -6,4 +6,6 @@ // $FFFC - CPU Reset Vector // Uncontrovertial, as it is a CPU requirement, and nothing else. +vector_reset: + .word hw_entry_reset diff --git a/src/kernal/interrupts/fffa.vector_nmi.s b/src/kernal/interrupts/fffa.vector_nmi.s index c33c2602..16089345 100644 --- a/src/kernal/interrupts/fffa.vector_nmi.s +++ b/src/kernal/interrupts/fffa.vector_nmi.s @@ -6,4 +6,6 @@ // $FFFA - CPU NMI Hanlder // Uncontrovertial as this is also a CPU requirement. +vector_nmi: + .word hw_entry_nmi diff --git a/src/kernal/interrupts/fffe.vector_irq.s b/src/kernal/interrupts/fffe.vector_irq.s index 755e9c57..ba5a1f6f 100644 --- a/src/kernal/interrupts/fffe.vector_irq.s +++ b/src/kernal/interrupts/fffe.vector_irq.s @@ -7,4 +7,6 @@ // This is non-controvertial, as it is a 6502 CPU requirement, and we just have to point // it to whatever IRQ routine we make. +vector_irq: + .word hw_entry_irq diff --git a/src/kernal/interrupts/hw_entry_irq.s b/src/kernal/interrupts/hw_entry_irq.s index 8177de7c..0424705a 100644 --- a/src/kernal/interrupts/hw_entry_irq.s +++ b/src/kernal/interrupts/hw_entry_irq.s @@ -29,8 +29,8 @@ hw_entry_irq: bne irq_handler_brk // Not caused by BRK - call interrupt routine (only if initialised) - lda CINV - ora CINV+1 + // Routine on zeropage = assuming not initialized + lda CINV+1 beq !+ jmp (CINV) !: diff --git a/src/kernal/keyboard/scnkey.s b/src/kernal/keyboard/scnkey.s index ae1421ff..c48f847b 100644 --- a/src/kernal/keyboard/scnkey.s +++ b/src/kernal/keyboard/scnkey.s @@ -147,7 +147,19 @@ scnkey_bucky_loop: // Set KEYTAB vector - jsr via_keylog // XXX for some CPUs we have indirect jsr + lda KEYLOG+1 + bne !+ + jsr scnkey_set_keytab // KEYLOG routine on zeropage? most likely vector not set + jmp_8 scnkey_keytab_set_done + +!: +#if HAS_OPCODES_65CE02 + jsr_ind KEYLOG +#else + jsr scnkey_via_keylog +#endif + +scnkey_keytab_set_done: #if CONFIG_JOY2_CURSOR @@ -315,7 +327,11 @@ scnkey_got_key: // .Y should now contain the key offset in matrix pointed by KEY // // Besides - since I am the one who writes the code, I will make the values exactly how I like them :D +#if !CONFIG_RS232_UP9600 lda #$16 +#else + lda #$18 +#endif sta DELAY // FALLTROUGH @@ -483,8 +499,4 @@ scnkey_early_repeat: rts -via_keylog: - jmp (KEYLOG) - - #endif // no CONFIG_LEGACY_SCNKEY diff --git a/src/kernal/keyboard/scnkey_set_keytab.s b/src/kernal/keyboard/scnkey_set_keytab.s index 77ad45aa..5299b0b8 100644 --- a/src/kernal/keyboard/scnkey_set_keytab.s +++ b/src/kernal/keyboard/scnkey_set_keytab.s @@ -38,8 +38,8 @@ scnkey_set_keytab: cmp #$FF bne scnkey_valid_offset - // $FF means we shouldn't decode anything, mark this by setting high byte - // of KEYTAB to 0 (I don't think anyone would put keyboard decoding table + // $FF means we should not decode anything, mark this by setting high byte + // of KEYTAB to 0 (I do not think anyone would put keyboard decoding table // at zeropage) lda #$00 beq !+ // branch always diff --git a/src/kernal/keyboard/scnkey_via_keylog.s b/src/kernal/keyboard/scnkey_via_keylog.s new file mode 100644 index 00000000..d23f27d1 --- /dev/null +++ b/src/kernal/keyboard/scnkey_via_keylog.s @@ -0,0 +1,14 @@ +// #LAYOUT# STD * #TAKE +// #LAYOUT# X16 * #IGNORE +// #LAYOUT# * KERNAL_0 #TAKE +// #LAYOUT# * * #IGNORE + +// Short helper jump-via-vector routine, to set the keyboard matrix + +#if !HAS_OPCODES_65CE02 + +scnkey_via_keylog: + + jmp (KEYLOG) + +#endif diff --git a/src/kernal/keyboard/udtim_keyboard.s b/src/kernal/keyboard/udtim_keyboard.s deleted file mode 100644 index d1c8c74e..00000000 --- a/src/kernal/keyboard/udtim_keyboard.s +++ /dev/null @@ -1,54 +0,0 @@ -// #LAYOUT# STD * #TAKE -// #LAYOUT# X16 * #IGNORE -// #LAYOUT# * KERNAL_0 #TAKE -// #LAYOUT# * * #IGNORE - -// -// Keyboard part of the UDTIM routine, has to preserve .Y -// - - -udtim_keyboard: - - // According to [CM64], page 27, the action we have to perform is to copy - // the last row of keyboard to RAM, so that various routines can detect the STOP - // key press. But something as simple as this would have created warm restart - // with M+N+SPACE+RESTORE due to ghosting - so the original ROM has to provide - // some protection here. I do not know what the mechanism there exactly does, - // but I hope the mechanism below will be compatible enough. - - lda #$80 - sta CIA1_PRA // select all the rows except the last one -#if CONFIG_KEYBOARD_C128 - ldx #$00 - stx VIC_XSCAN // connect all the extra C128 keys -#endif -#if CONFIG_KEYBOARD_C65 - ldx #$00 - stx C65_EXTKEYS_PR // connect all the extra C65 keys -#endif - - lda CIA1_PRB // read the keys - eor #$FF - sta STKEY // store reversed state - to filter out anything vulnerable to ghosting - -#if CONFIG_KEYBOARD_C128 - dex // puts $FF - stx VIC_XSCAN // disconnect the extra C128 keys -#endif -#if CONFIG_KEYBOARD_C65 - dex // puts $FF - stx C65_EXTKEYS_PR // disconnect the extra C65 keys -#endif - lda #$7F - sta CIA1_PRA // select the last row (bit to 0) - - lda CIA1_PRB // read the row - ora STKEY // filter out what might be the reason of ghosting - sta STKEY - - // Leave the CIA configured this way. It would be far better to disconnect - // the keyboard at this point, but certain software (mainly intros) is - // unable to, for example, read the space bar status. - - rts diff --git a/src/kernal/memory/under_rom_routines_46k_50k.s b/src/kernal/memory/under_rom_46k_50k.s similarity index 83% rename from src/kernal/memory/under_rom_routines_46k_50k.s rename to src/kernal/memory/under_rom_46k_50k.s index 0db1dc6b..04ef9714 100644 --- a/src/kernal/memory/under_rom_routines_46k_50k.s +++ b/src/kernal/memory/under_rom_46k_50k.s @@ -53,11 +53,7 @@ peek_under_roms_via_FNADDR: // Continue using common code -#if HAS_OPCODES_65C02 - bra peek_under_roms_finalize -#else - jmp peek_under_roms_finalize -#endif + jmp_8 peek_under_roms_finalize peek_under_roms_via_EAL: @@ -75,11 +71,7 @@ peek_under_roms_via_EAL: // Continue using common code -#if HAS_OPCODES_65C02 - bra peek_under_roms_finalize -#else - jmp peek_under_roms_finalize -#endif + jmp_8 peek_under_roms_finalize #endif diff --git a/src/kernal/memory/under_rom_routines_60k.s b/src/kernal/memory/under_rom_60k.s similarity index 100% rename from src/kernal/memory/under_rom_routines_60k.s rename to src/kernal/memory/under_rom_60k.s diff --git a/src/kernal/rs232/rs232_count_channels.s b/src/kernal/rs232/rs232_count_channels.s index 49379a81..c4f17976 100644 --- a/src/kernal/rs232/rs232_count_channels.s +++ b/src/kernal/rs232/rs232_count_channels.s @@ -16,13 +16,13 @@ rs232_count_channels: ldy LDTND !: dey - bmi close_rs232_search_done + bmi !+ lda FAT, y cmp #$02 bne !- inx bpl !- // branch always - +!: rts diff --git a/src/kernal/rs232/up9600_ihitab.s b/src/kernal/rs232/up9600_ihitab.s deleted file mode 100644 index 43b53bd7..00000000 --- a/src/kernal/rs232/up9600_ihitab.s +++ /dev/null @@ -1,21 +0,0 @@ -// #LAYOUT# STD * #TAKE -// #LAYOUT# * KERNAL_0 #TAKE -// #LAYOUT# * * #IGNORE - -// -// Timer values for PAL/NTSC - high bytes -// - -// Based on UP9600 code by Daniel Dallman with Bo Zimmerman adaptations - - -#if CONFIG_RS232_UP9600 - - -up9600_ihitab: - - .byte $42 - .byte $40 - - -#endif // CONFIG_RS232_UP9600 diff --git a/src/kernal/rs232/up9600_ilotab.s b/src/kernal/rs232/up9600_ilotab.s deleted file mode 100644 index 5492bedf..00000000 --- a/src/kernal/rs232/up9600_ilotab.s +++ /dev/null @@ -1,21 +0,0 @@ -// #LAYOUT# STD * #TAKE -// #LAYOUT# * KERNAL_0 #TAKE -// #LAYOUT# * * #IGNORE - -// -// Timer values for PAL/NTSC - low bytes -// - -// Based on UP9600 code by Daniel Dallman with Bo Zimmerman adaptations - - -#if CONFIG_RS232_UP9600 - - -up9600_ilotab: - - .byte $95 - .byte $25 - - -#endif // CONFIG_RS232_UP9600 diff --git a/src/kernal/screen/chrout_screen_jumptable_codes.s b/src/kernal/screen/chrout_screen_jumptable_codes.s index 1f4fe7b3..07d30cd4 100644 --- a/src/kernal/screen/chrout_screen_jumptable_codes.s +++ b/src/kernal/screen/chrout_screen_jumptable_codes.s @@ -83,18 +83,9 @@ chrout_screen_jumptable_hi: #else // HAS_OPCODES_65C02 - -__before_chrout_screen_jumptable: - -.if (mod(*, $2) == 1) { brk } // align code so that vector never crosses page boundary - chrout_screen_jumptable: + // Note: 65C02 has the page boundary vector bug fixed! put_jumptable(chrout_list) - // Make sure routine size is always the same - build system limitation - -.if (__before_chrout_screen_jumptable == chrout_screen_jumptable) { brk } - - #endif diff --git a/src/kernal/time/udtim.s b/src/kernal/time/udtim.s index 9c75406f..44913c57 100644 --- a/src/kernal/time/udtim.s +++ b/src/kernal/time/udtim.s @@ -17,32 +17,95 @@ UDTIM: // (24 hours * 60 minutes * 60 seconds * 60 jiffies), // after this time we have to reset the clock. -#if !HAS_OPCODES_65CE02 - inc TIME+0 - bne udtim_time_done // done with clock - inc TIME+1 -#else - inw TIME+0 -#endif - bne udtim_clock_rollover inc TIME+2 + bne udtim_rollover_check + inc TIME+1 + bne udtim_rollover_check + inc TIME+0 // FALLTROUGH -udtim_time_done: +udtim_rollover_check: - jmp udtim_keyboard - -udtim_clock_rollover: - - // At this point TIME+0 contains 0 - lda TIME+1 - cmp #$1A - bne udtim_time_done // done with clock - lda TIME+2 + lda TIME+0 +#if !CONFIG_RS232_UP9600 cmp #$4F - bne udtim_time_done // done with clock +#else + cmp #$54 +#endif + bcc udtim_keyboard + lda TIME+1 +#if !CONFIG_RS232_UP9600 + cmp #$1A +#else + cmp #$60 +#endif + bcc udtim_keyboard + + // FALLTROUGH + +udtim_clock_reset: + lda #$00 - sta TIME+2 + sta TIME+0 sta TIME+1 - beq udtim_time_done // done with clock - will always jump + sta TIME+2 + + // FALLTROUGH + +// +// Keyboard part of the UDTIM routine, has to preserve .Y +// + +udtim_keyboard: + +#if CONFIG_PLATFORM_COMMANDER_X16 + + STUB_IMPLEMENTATION() + +#else + + // According to [CM64], page 27, the action we have to perform is to copy + // the last row of keyboard to RAM, so that various routines can detect the STOP + // key press. But something as simple as this would have created warm restart + // with M+N+SPACE+RESTORE due to ghosting - so the original ROM has to provide + // some protection here. I do not know what the mechanism there exactly does, + // but I hope the mechanism below will be compatible enough. + + lda #$80 + sta CIA1_PRA // select all the rows except the last one +#if CONFIG_KEYBOARD_C128 + ldx #$00 + stx VIC_XSCAN // connect all the extra C128 keys +#endif +#if CONFIG_KEYBOARD_C65 + ldx #$00 + stx C65_EXTKEYS_PR // connect all the extra C65 keys +#endif + + lda CIA1_PRB // read the keys + eor #$FF + sta STKEY // store reversed state - to filter out anything vulnerable to ghosting + +#if CONFIG_KEYBOARD_C128 + dex // puts $FF + stx VIC_XSCAN // disconnect the extra C128 keys +#endif +#if CONFIG_KEYBOARD_C65 + dex // puts $FF + stx C65_EXTKEYS_PR // disconnect the extra C65 keys +#endif + lda #$7F + sta CIA1_PRA // select the last row (bit to 0) + + lda CIA1_PRB // read the row + ora STKEY // filter out what might be the reason of ghosting + sta STKEY + + // Leave the CIA configured this way. It would be far better to disconnect + // the keyboard at this point, but certain software (mainly intros) is + // unable to, for example, read the space bar status. + + rts + +#endif diff --git a/strings/00000003 b/strings/00000003 new file mode 100644 index 00000000..4870347c --- /dev/null +++ b/strings/00000003 @@ -0,0 +1,4 @@ +couple of 0's followed by $03 + +In original ROMs this is a part of floating point constant, in OpenROMs, it can even by a result of code not filling-in the ROM completely. Trivial - not copyrightable. + diff --git a/strings/00E6A2D006E6A1D002E6A0 b/strings/00E6A2D006E6A1D002E6A0 new file mode 100644 index 00000000..7044c8af --- /dev/null +++ b/strings/00E6A2D006E6A1D002E6A0 @@ -0,0 +1,3 @@ +$00 + INC $A2 + BNE (address matches) + INC $A1 + BNE (address matches) + INC $A0 + +Incrementing 24-bit zeropage variable (TIME) by 1 (+ one byte from another instruction) - trivial, not copyrightable. diff --git a/strings/018562B0 b/strings/018562B0 new file mode 100644 index 00000000..95692b87 --- /dev/null +++ b/strings/018562B0 @@ -0,0 +1,3 @@ +$01 + STA $62 + BCS (offset does not match) + +Instruction + some parts - trivial, not copyrightable. diff --git a/strings/026090051C9F9C1E1F9E8195969798999A9B b/strings/026090051C9F9C1E1F9E8195969798999A9B new file mode 100644 index 00000000..79d39cad --- /dev/null +++ b/strings/026090051C9F9C1E1F9E8195969798999A9B @@ -0,0 +1,3 @@ +$02 + RTS + PETSCII color table + +Part of some instruction (just one byte) + a list of facts - not copyrightable. diff --git a/strings/02852DA52C6900852E20 b/strings/02852DA52C6900852E20 new file mode 100644 index 00000000..61b695ca --- /dev/null +++ b/strings/02852DA52C6900852E20 @@ -0,0 +1,3 @@ +$02 + STA $2D + LDA $2C + ADC #$00 + STA $2E + JSR (address does not match) + +Part of the NEW command implementation resetting various pointers to default values - not creative, not copyrightable. diff --git a/strings/06142615 b/strings/06142615 new file mode 100644 index 00000000..59e554e2 --- /dev/null +++ b/strings/06142615 @@ -0,0 +1,3 @@ +ASL $14 + ROL $15 + +Multiplication of 16-bit zeropage variable by 2 - trivial, not copyrightable. diff --git a/strings/148514A5 b/strings/148514A5 new file mode 100644 index 00000000..4e1b0ad9 --- /dev/null +++ b/strings/148514A5 @@ -0,0 +1,3 @@ +$14 + STA $14 + LDA (zeropage address does not match) + +Instruction + some parts - trivial, not copyrightable. diff --git a/strings/1548A51448 b/strings/1548A51448 new file mode 100644 index 00000000..56c58455 --- /dev/null +++ b/strings/1548A51448 @@ -0,0 +1,3 @@ +$15 + PHA + LDA $14 + PHA + +Part of code stroing some zeropage variables on the stack, not even in the same order - trivial, not copyrightable. diff --git a/strings/1548A5144820 b/strings/1548A5144820 new file mode 100644 index 00000000..93061cbb --- /dev/null +++ b/strings/1548A5144820 @@ -0,0 +1,3 @@ +$15 + PHA + LDA $14 + PHA + JSR (address does not match) + +Part of code storing some zeropage variables on the stack, not even in the same order (+ a part of another instruction) - trivial, not copyrightable. diff --git a/strings/18652285 b/strings/18652285 new file mode 100644 index 00000000..a8291728 --- /dev/null +++ b/strings/18652285 @@ -0,0 +1,3 @@ +CLC + ADC $22 + STA (zeropage address does not match) + +Subtracting two zeropage variables (not even the same ones) - trivial, not copyrightable. diff --git a/strings/1865228524 b/strings/1865228524 new file mode 100644 index 00000000..d0919e3f --- /dev/null +++ b/strings/1865228524 @@ -0,0 +1,3 @@ +CLC + ADC $22 + STA $24 + +Adding two zeropage variables - trivial, not copyrightable. diff --git a/strings/2033A54C b/strings/2033A54C new file mode 100644 index 00000000..88782adf --- /dev/null +++ b/strings/2033A54C @@ -0,0 +1,3 @@ +JSR $A533 (relink program) + JMP (address does not match) + +Call of a well-known subroutine + part of another instruction. Trivial - not copyrightable. diff --git a/strings/20B9ED20 b/strings/20B9ED20 new file mode 100644 index 00000000..84d9467a --- /dev/null +++ b/strings/20B9ED20 @@ -0,0 +1,3 @@ +JSR $EDB9 (LISTEN) + JSR (address does not match) + +Call of a well-known subroutine + part of another instruction. Trivial - not copyrightable. diff --git a/strings/20BAFF20 b/strings/20BAFF20 new file mode 100644 index 00000000..e1ab3c0a --- /dev/null +++ b/strings/20BAFF20 @@ -0,0 +1,3 @@ +JSR $FFBA (SETLFS) + JSR (address does not match) + +Call of a well-known subroutine + part of another instruction. Trivial - not copyrightable. diff --git a/strings/25A000B1 b/strings/25A000B1 new file mode 100644 index 00000000..b6a5fbfe --- /dev/null +++ b/strings/25A000B1 @@ -0,0 +1,4 @@ + $25 + LDY #$00 + LDA (zeropage address does not match),Y + + Instruction + some parts - trivial, not copyrightable. + diff --git a/strings/3020D2FF b/strings/3020D2FF new file mode 100644 index 00000000..80ff7548 --- /dev/null +++ b/strings/3020D2FF @@ -0,0 +1,3 @@ +$30 + JSR $FFD2 (CHROUT) + +Instruction (call of a well-known routine) + some part. Trivial - not copyrightable. diff --git a/strings/38A533E5 b/strings/38A533E5 new file mode 100644 index 00000000..b35d7953 --- /dev/null +++ b/strings/38A533E5 @@ -0,0 +1,3 @@ +SEC + LDA $33 + SBC (zeropage address does not match) + +Subtracting two zeropage variables (not even both the same ones) - trivial, not copyrightable. diff --git a/strings/38A533E531 b/strings/38A533E531 new file mode 100644 index 00000000..7f590ec5 --- /dev/null +++ b/strings/38A533E531 @@ -0,0 +1,3 @@ +SEC + LDA $33 + SBC $31 + +Subtracting two zeropage variables - trivial, not copyrightable. diff --git a/strings/46C954D0 b/strings/46C954D0 new file mode 100644 index 00000000..40330ac8 --- /dev/null +++ b/strings/46C954D0 @@ -0,0 +1,3 @@ +$46 + CMP #$54 + BNE (offset does not match) + +Instruction + some parts. Trivial - not copyrightable. diff --git a/strings/488A4820 b/strings/488A4820 new file mode 100644 index 00000000..d3b130ef --- /dev/null +++ b/strings/488A4820 @@ -0,0 +1,3 @@ +PHA + TXA + PHA + JSR (address does not match) + +Part of code storing registers on the stack (+ a part of another instruction) - trivial, not copyrightable. diff --git a/strings/48A51448 b/strings/48A51448 new file mode 100644 index 00000000..60fec655 --- /dev/null +++ b/strings/48A51448 @@ -0,0 +1,3 @@ +PHA + LDA $14 + PHA + +Part of code retrieving values from stack - trivial, not copyrightable. diff --git a/strings/48A54548 b/strings/48A54548 new file mode 100644 index 00000000..61b91bdf --- /dev/null +++ b/strings/48A54548 @@ -0,0 +1,3 @@ +PHA + LDA $45 + PHA + +Part of code storing some zeropage variables on the stack, not even in the same order - trivial, not copyrightable. diff --git a/strings/48A54648 b/strings/48A54648 new file mode 100644 index 00000000..4ecdbdbe --- /dev/null +++ b/strings/48A54648 @@ -0,0 +1,3 @@ +PHA + LDA $46 + PHA + +Part of code storing some zeropage variables on the stack, not even in the same order - trivial, not copyrightable. diff --git a/strings/48A56248A5 b/strings/48A56248A5 new file mode 100644 index 00000000..3fe300a3 --- /dev/null +++ b/strings/48A56248A5 @@ -0,0 +1,3 @@ +PHA + LDA $62 + PHA + LDA (zeropage address does not match) + +Part of code storing some zeropage variables on the stack, not even in the same order - trivial, not copyrightable. diff --git a/strings/48A57B48A5 b/strings/48A57B48A5 new file mode 100644 index 00000000..4d0b7853 --- /dev/null +++ b/strings/48A57B48A5 @@ -0,0 +1,3 @@ +PHA + LDA $7B + PHA + LDA (zeropage address does not match) + +Part of code storing some zeropage variables on the stack, not even in the same order - trivial, not copyrightable. diff --git a/strings/60A561F0FB b/strings/60A561F0FB new file mode 100644 index 00000000..4cfa30ac --- /dev/null +++ b/strings/60A561F0FB @@ -0,0 +1,3 @@ +RTS + LDA $61 + BEQ (offset matches) + +End of previous subroutine + beginning of a new one, performing different action depending whether zeropage variable is 0 or not. Trivial - not copyrightable. diff --git a/strings/62666366646665667060A5 b/strings/62666366646665667060A5 new file mode 100644 index 00000000..a6e4874f --- /dev/null +++ b/strings/62666366646665667060A5 @@ -0,0 +1,3 @@ +$62 + ROR $63 + ROR $64 + ROR $65 + ROR $70 + RTS + LDA (zeropage addres does not match) + +Part of code multiplying by 2 a well-known multibyte zeropage variable + a part of another instruction. Not creative - not copyrightable. diff --git a/strings/64A90085 b/strings/64A90085 new file mode 100644 index 00000000..5ab38b51 --- /dev/null +++ b/strings/64A90085 @@ -0,0 +1,3 @@ +$64 + LDA #$00 + STA (zeropage address does not match) + +Instruction + some parts - trivial, not copyrightable. diff --git a/strings/65148514 b/strings/65148514 new file mode 100644 index 00000000..17a51e64 --- /dev/null +++ b/strings/65148514 @@ -0,0 +1,3 @@ +ADC $14 + STA $14 + +Adding a value to a zeropage variable - trivial, not copyrightable. diff --git a/strings/65148514A5 b/strings/65148514A5 new file mode 100644 index 00000000..33e55d20 --- /dev/null +++ b/strings/65148514A5 @@ -0,0 +1,3 @@ +ADC $14 + STA $14 + LDA (zeropage address does not match) + +Adding a value to a zeropage variable + some part of another instruction - trivial, not copyrightable. diff --git a/strings/65158515 b/strings/65158515 new file mode 100644 index 00000000..f51f4475 --- /dev/null +++ b/strings/65158515 @@ -0,0 +1,3 @@ +ADC $15 + STA $15 + +Adding a value to a zeropage variable - trivial, not copyrightable. diff --git a/strings/65228522 b/strings/65228522 new file mode 100644 index 00000000..d98ad093 --- /dev/null +++ b/strings/65228522 @@ -0,0 +1,3 @@ +ADC $22 + STA $22 + +Adding a value to a zeropage variable - trivial, not copyrightable. diff --git a/strings/65228524 b/strings/65228524 new file mode 100644 index 00000000..2ffbe09e --- /dev/null +++ b/strings/65228524 @@ -0,0 +1,3 @@ +ADC $22 + STA $24 + +Adding a zeropage value to .A, storing result in another zeropage location - trivial, not copyrightable. diff --git a/strings/65338533 b/strings/65338533 new file mode 100644 index 00000000..9fe74632 --- /dev/null +++ b/strings/65338533 @@ -0,0 +1,3 @@ +ADC $33 + STA $33 + +Adding a value to a zeropage variable - trivial, not copyrightable. diff --git a/strings/686868AA b/strings/686868AA new file mode 100644 index 00000000..cc4b6c84 --- /dev/null +++ b/strings/686868AA @@ -0,0 +1,3 @@ +PLA + PLA + PLA + TAX + +Drop 2 values from the stack, fetch the next one into .X register - trivial, not copyrightable. diff --git a/strings/6885456885 b/strings/6885456885 new file mode 100644 index 00000000..37afe558 --- /dev/null +++ b/strings/6885456885 @@ -0,0 +1,3 @@ +PLA + STA $45 + PLA + STA (zeropage address does not match) + +Part of code retrieving zeropage variables from the stack (not even exactly the same ones) - trivial, not copyrightable. diff --git a/strings/68854668 b/strings/68854668 new file mode 100644 index 00000000..ffb6c888 --- /dev/null +++ b/strings/68854668 @@ -0,0 +1,3 @@ +PLA + STA $46 + PLA + +Part of code retrieving values from the stack - trivial, not copyrightable. diff --git a/strings/7A48A57B b/strings/7A48A57B new file mode 100644 index 00000000..1e29c3d5 --- /dev/null +++ b/strings/7A48A57B @@ -0,0 +1,3 @@ +$7A + PHA + LDA $7B + +Small part of code storing zeropage variables on the stack - trivial, not copyrightable. diff --git a/strings/810000000020 b/strings/810000000020 new file mode 100644 index 00000000..c8e599eb --- /dev/null +++ b/strings/810000000020 @@ -0,0 +1,3 @@ +floating point value 1.0 + $20 byte + +A trivial floating point value + some part - not creative, not copyrightable. diff --git a/strings/85228623 b/strings/85228623 new file mode 100644 index 00000000..3584674c --- /dev/null +++ b/strings/85228623 @@ -0,0 +1,3 @@ +STA $22 + STX $23 + +Storing two registers in a 16-bit zeropage variable - trivial, not copyrightable. diff --git a/strings/85229002 b/strings/85229002 new file mode 100644 index 00000000..3bdcc5fe --- /dev/null +++ b/strings/85229002 @@ -0,0 +1,3 @@ +STA $22 + BCC (offset matches) + +Storing .A in zeropage variable + conditional jump - trivial; not copyrightable. diff --git a/strings/85339002E634 b/strings/85339002E634 new file mode 100644 index 00000000..5c192acf --- /dev/null +++ b/strings/85339002E634 @@ -0,0 +1,3 @@ +STA $33 + BCC (offset matches) + INC $34 + +Small part of the code to add .A to a 16 bit seropage variable - trivial, not copyrightable. diff --git a/strings/85628563 b/strings/85628563 new file mode 100644 index 00000000..b4687a55 --- /dev/null +++ b/strings/85628563 @@ -0,0 +1,3 @@ +STA $62 + STA $63 + +Storing accumulator in two zeropage locations - trivial, not copyrightable. diff --git a/strings/8562C8B1 b/strings/8562C8B1 new file mode 100644 index 00000000..476fdb7b --- /dev/null +++ b/strings/8562C8B1 @@ -0,0 +1,3 @@ +STA $62 + INY + LDA (zeropage address does not match),Y + +Store value on zeropage, fetch new from memory location determined by pointer (not even the same one) - not creative, not copyrightable. diff --git a/strings/856385648565 b/strings/856385648565 new file mode 100644 index 00000000..1c1f884c --- /dev/null +++ b/strings/856385648565 @@ -0,0 +1,3 @@ +STA $63 + STA $64 + STA $65 + +Storing a value (0) in a multibyte zeropage variable - trivial, not copyrightable. diff --git a/strings/86706020 b/strings/86706020 new file mode 100644 index 00000000..abd1ad3b --- /dev/null +++ b/strings/86706020 @@ -0,0 +1,3 @@ +STX $70 + RTS + JSR (addres does not match) + +Routine ending by storing .X to zeropage variable + one byte (start of the instruction) of the next one - trivial, not copyrightable. diff --git a/strings/8810F820 b/strings/8810F820 new file mode 100644 index 00000000..54c6c4ce --- /dev/null +++ b/strings/8810F820 @@ -0,0 +1,3 @@ +DEY + BPL (offset matches) + JSR (address does not match) + +Small part of the loop by .Y register - trivial and not creative, not copyrightable. diff --git a/strings/A0006891 b/strings/A0006891 new file mode 100644 index 00000000..be6d0aaf --- /dev/null +++ b/strings/A0006891 @@ -0,0 +1,3 @@ +LDY #$00 + PLA + STA (zeropage address does not match),Y + +Store value from the stack on the location determined by pointer (not even the same one) - not creative, not copyrightable. diff --git a/strings/A000A54591 b/strings/A000A54591 new file mode 100644 index 00000000..8e706b98 --- /dev/null +++ b/strings/A000A54591 @@ -0,0 +1,3 @@ +LDY #$00 + LDA $45 + STA (zeropage address does not match),Y + +Copying value from zeropage variablle to memory location determined by pointer (not even the same one) - trivial, not copyrightable. diff --git a/strings/A51548A51448 b/strings/A51548A51448 new file mode 100644 index 00000000..8ca219eb --- /dev/null +++ b/strings/A51548A51448 @@ -0,0 +1,3 @@ +LDA $15 + PHA + LDA $14 + PHA + +Store 16-bit zeropage value on the stack - trivial, not copyrightable. diff --git a/strings/A533E531 b/strings/A533E531 new file mode 100644 index 00000000..ece3131f --- /dev/null +++ b/strings/A533E531 @@ -0,0 +1,3 @@ +LDA $33 + SBC $31 + +Subtraction of two zeropage variables - trivial, not copyrightable. diff --git a/strings/A534E532 b/strings/A534E532 new file mode 100644 index 00000000..56808cf9 --- /dev/null +++ b/strings/A534E532 @@ -0,0 +1,3 @@ +LDA $34 + SBC $32 + +Subtracting two zeropage variables - trivial, not copyrightable. diff --git a/strings/A54648A54548 b/strings/A54648A54548 new file mode 100644 index 00000000..e7ef4095 --- /dev/null +++ b/strings/A54648A54548 @@ -0,0 +1,3 @@ +LDA $46 + PHA + LDA $45 + PHA + +Store 16-bit zeropage value on the stack - trivial, not copyrightable. diff --git a/strings/A57A48A5 b/strings/A57A48A5 new file mode 100644 index 00000000..c4f8b4ae --- /dev/null +++ b/strings/A57A48A5 @@ -0,0 +1,3 @@ +LDA $7A + PHA + LDA (zeropage address does not match) + +Part of code storing some zeropage variables on the stack, not even in the same order - trivial, not copyrightable. diff --git a/strings/A57B48A5 b/strings/A57B48A5 new file mode 100644 index 00000000..5cde415f --- /dev/null +++ b/strings/A57B48A5 @@ -0,0 +1,3 @@ +LDA $7B + PHA + LDA (zeropage address does not match) + +Part of code storing some zeropage variables on the stack, not even in the same order - trivial, not copyrightable. diff --git a/strings/A9A8A0AE20 b/strings/A9A8A0AE20 new file mode 100644 index 00000000..ef4c0734 --- /dev/null +++ b/strings/A9A8A0AE20 @@ -0,0 +1,3 @@ +LDA #$A8 + LDY #$AE + JSR (address does not match) + +A small piece of code calling a subroutine to fetch PI value - trivial, not copyrightable. diff --git a/strings/B1474888 b/strings/B1474888 new file mode 100644 index 00000000..0cad4280 --- /dev/null +++ b/strings/B1474888 @@ -0,0 +1,3 @@ +LDA ($47),Y + PHA + DEY + +Small part of a code pushing memory to stack - not creative, not copyrightable. diff --git a/strings/B1B2C905 b/strings/B1B2C905 new file mode 100644 index 00000000..89b22fea --- /dev/null +++ b/strings/B1B2C905 @@ -0,0 +1,3 @@ +LDA ($B2),Y + CMP (value does not match) + +Instruction + some part. Trivial - not copyrightable. diff --git a/strings/C8A54691 b/strings/C8A54691 new file mode 100644 index 00000000..afc36c82 --- /dev/null +++ b/strings/C8A54691 @@ -0,0 +1,3 @@ +INY + LDA $46 + STA (zeropage address does not match),Y + +Copy zeopage value to a memory location determined by pointer (not even the same one) - trivial, not copyrightable. diff --git a/strings/C8B12265 b/strings/C8B12265 new file mode 100644 index 00000000..ca315950 --- /dev/null +++ b/strings/C8B12265 @@ -0,0 +1,3 @@ +INY + LDA ($22),Y + ADC (zeropage address does not match) + +Fetch value determined by pointer, add content of zeropage variable (not even the same one) - trivial, not copyrightable. diff --git a/strings/C8C006D0 b/strings/C8C006D0 new file mode 100644 index 00000000..c2916d5a --- /dev/null +++ b/strings/C8C006D0 @@ -0,0 +1,3 @@ +INY + CPY #$06 + BNE (offset does not match) + +Ending part of the loop by .Y, counting to 6 - not creative, not copyrightable. diff --git a/strings/C922F056 b/strings/C922F056 new file mode 100644 index 00000000..91498fac --- /dev/null +++ b/strings/C922F056 @@ -0,0 +1,3 @@ +CMP #$22 ('"') + BEQ (offset matches) + +Decision based on accumulator value - trivial, not copyrightable. diff --git a/strings/C929F006 b/strings/C929F006 new file mode 100644 index 00000000..a06a9194 --- /dev/null +++ b/strings/C929F006 @@ -0,0 +1,3 @@ +CMP #$29 + BEQ (offset matches) + +Decision based on accumulator value - trivial, not copyrightable. diff --git a/strings/E7FFA537 b/strings/E7FFA537 new file mode 100644 index 00000000..c059fa0c --- /dev/null +++ b/strings/E7FFA537 @@ -0,0 +1,3 @@ +$FFE7 + LDA $37 + +Address of a well-known routine (CLALL) + a single instruction. Trivial - not copyrightable. diff --git a/testsuite/testdisk.d64 b/testsuite/testdisk.d64 index a455d2ee..5cb877cf 100644 Binary files a/testsuite/testdisk.d64 and b/testsuite/testdisk.d64 differ diff --git a/tools/build_segment.cc b/tools/build_segment.cc index d160f055..ab6c41ed 100644 --- a/tools/build_segment.cc +++ b/tools/build_segment.cc @@ -874,10 +874,26 @@ void BinningProblem::placeHighRoutines(DualStream &logOutput) while (!floatingRoutines.empty()) { - // Try to find any high routine + // Find the largest high routine - auto iterRoutine = floatingRoutines.begin(); - while (iterRoutine != floatingRoutines.end() && !(*iterRoutine)->high) iterRoutine++; + auto iterRoutine = floatingRoutines.end(); + + for (auto iter = floatingRoutines.begin(); iter < floatingRoutines.end(); iter++) + { + if (!(*iter)->high) continue; + + if (iterRoutine == floatingRoutines.end() || + (*iterRoutine)->codeLength < (*iter)->codeLength) + { + iterRoutine = iter; + continue; + } + + if ((*iterRoutine)->codeLength < (*iter)->codeLength) + { + iterRoutine = iter; + } + } if (iterRoutine == floatingRoutines.end()) break; diff --git a/tools/generate_strings.cc b/tools/generate_strings.cc index bfbd08e0..e54a6ef3 100644 --- a/tools/generate_strings.cc +++ b/tools/generate_strings.cc @@ -173,72 +173,39 @@ const StringEntryList GLOBAL_Keywords_V2 = { ListType::KEYWORDS, "keywords_V2", { true, true, true, true, "KV2_CB", "GO", 0 }, // https://en.wikipedia.org/wiki/Goto } }; -// extended BASIC keywords - reserved for generic (hardware independent) BASIC commands +// extended BASIC keywords - list reserved for small BASIC commands, suitable for inclusion in non-extended ROMs -const StringEntryList GLOBAL_Keywords_CC = { ListType::KEYWORDS, "keywords_CC", +const StringEntryList GLOBAL_Keywords_01 = { ListType::KEYWORDS, "keywords_01", { // STD M65 U64 X16 - { true, true, true, true, "KCC_01", "MERGE", }, // OpenROMs specific, not present in CBM BASIC dialects - { true, true, true, true, "KCC_02", "BLOAD", }, // http://www.antonis.de/qbebooks/gwbasman/bload.html - { true, true, true, true, "KCC_03", "BSAVE", }, // http://www.antonis.de/qbebooks/gwbasman/bsave.html - { true, true, true, true, "KCC_04", "BVERIFY", }, - { true, true, true, true, "KCC_05", "OLD", }, // OpenROMs specific, not present in CBM BASIC dialects + { true, true, true, true, "K01_01", "SLOW", }, // https://en.wikipedia.org/wiki/Sinclair_BASIC - ZX81 variant + { true, true, true, true, "K01_02", "FAST", }, // https://en.wikipedia.org/wiki/Sinclair_BASIC - ZX81 variant + { true, true, true, true, "K01_03", "OLD", }, // Not present in CBM BASIC dialects, but common to some extensions (*) + + // (*) see https://sourceforge.net/p/vice-emu/code/HEAD/tree/trunk/vice/src/petcat.c + + // NOTE! These commands are temporarily placed here, they should be a part of list 02! + + { true, true, true, true, "K02_01", "MERGE", }, // Not present in CBM BASIC dialects, but common to some extensions (*) + { true, true, true, true, "K02_02", "BLOAD", }, // http://www.antonis.de/qbebooks/gwbasman/bload.html + { true, true, true, true, "K02_03", "BSAVE", }, // http://www.antonis.de/qbebooks/gwbasman/bsave.html + { true, true, true, true, "K02_04", "BVERIFY", }, + { true, true, true, true, "K02_05", "CLEAR", }, // Not present in CBM BASIC dialects, Open ROMs specific + { true, true, true, true, "K02_06", "DISPOSE", }, // Not present in CBM BASIC dialects, Open ROMs specific } }; -// extended BASIC keywords - reserved for BASIC commands likely making sense on most C64-compatible machines +// extended BASIC keywords - list reserved for generic (mostly hardware independent) BASIC commands -const StringEntryList GLOBAL_Keywords_CD = { ListType::KEYWORDS, "keywords_CD", +const StringEntryList GLOBAL_Keywords_02 = { ListType::KEYWORDS, "keywords_02", { // STD M65 U64 X16 - { true, true, true, true, "KCD_01", "SLOW", }, // https://en.wikipedia.org/wiki/Sinclair_BASIC - ZX81 variant - { true, true, true, true, "KCD_02", "FAST", }, // https://en.wikipedia.org/wiki/Sinclair_BASIC - ZX81 variant + + { false, true, false, false, "K02_07", "COLD", }, // Not present in CBM BASIC dialects, but common to some extensions (*) + { false, true, false, false, "K02_08", "MEM", }, // Not present in CBM BASIC dialects, Open ROMs specific + + // (*) see https://sourceforge.net/p/vice-emu/code/HEAD/tree/trunk/vice/src/petcat.c } }; -// extended BASIC keywords - reserved for board-specific BASIC commands - -const StringEntryList GLOBAL_Keywords_CE = { ListType::KEYWORDS, "keywords_CE", -{ - // STD M65 U64 X16 - { false, false, false, false, "KCE_01", "TESTCMD", }, -} }; - -const StringEntryList GLOBAL_Keywords_CF = { ListType::KEYWORDS, "keywords_CF", -{ - // STD M65 U64 X16 - { false, false, false, false, "KCF_01", "TESTCMD", }, -} }; - -// extended BASIC keywords - reserved for generic (hardware independent) BASIC functions - -const StringEntryList GLOBAL_Keywords_D0 = { ListType::KEYWORDS, "keywords_D0", -{ - // STD M65 U64 X16 - { false, false, false, false, "KD0_01", "TESTFUN", }, -} }; - -// extended BASIC keywords - reserved for BASIC functions likely making sense on most C64-compatible machines - -const StringEntryList GLOBAL_Keywords_D1 = { ListType::KEYWORDS, "keywords_D1", -{ - // STD M65 U64 X16 - { false, false, false, false, "KD1_01", "TESTFUN", }, -} }; - -// extended BASIC keywords - reserved for board-specific BASIC functions - -const StringEntryList GLOBAL_Keywords_D2 = { ListType::KEYWORDS, "keywords_D2", -{ - // STD M65 U64 X16 - { false, false, false, false, "KD2_01", "TESTFUN", }, -} }; - -const StringEntryList GLOBAL_Keywords_D3 = { ListType::KEYWORDS, "keywords_D3", -{ - // STD M65 U64 X16 - { false, false, false, false, "KD3_01", "TESTFUN", }, -} }; - - // BASIC errors - all dialects /* @@ -292,11 +259,11 @@ const StringEntryList GLOBAL_Errors = { ListType::STRINGS_BASIC, "errors", { false, false, false, false, "EV7_23", "NO GRAPHICS AREA" }, // not used for now { false, false, false, false, "EV7_24", "BAD DISK" }, // not used for now { false, false, false, false, "EV7_25", "BEND NOT FOUND" }, // not used for now - { false, false, false, false, "EV7_26", "LINE NUMBER TOO LARGE" }, // not used for now + { true, true, true, true, "EV7_26", "LINE NUMBER TOO LARGE" }, { false, false, false, false, "EV7_27", "UNRESOLVED REFERENCE" }, // not used for now { true, true, true, true, "EV7_28", "NOT IMPLEMENTED" }, // this message actually differs from the CBM one { false, false, false, false, "EV7_29", "FILE READ" }, // not used for now - // STD M65 U64 X16 --- error strings specific to OpenROMs, not present in CBM BASIC dialects + // STD M65 U64 X16 --- error strings specific to Open ROMs, not present in CBM BASIC dialects { true, true, true, true, "EOR_2A", "MEMORY CORRUPT" }, } }; @@ -305,13 +272,23 @@ const StringEntryList GLOBAL_Errors = { ListType::STRINGS_BASIC, "errors", const StringEntryList GLOBAL_MiscStrings = { ListType::STRINGS_BASIC, "misc", { // STD M65 U64 X16 --- misc strings as on CBM machines - { true, true, true, true, "STR_RET_QM", "\r?" }, - { true, true, true, true, "STR_BYTES", " BASIC BYTES FREE" }, // https://github.com/stefanhaustein/expressionparser - { true, true, true, true, "STR_READY", "\rREADY.\r" }, // https://www.ibm.com/support/knowledgecenter/zosbasics/com.ibm.zos.zconcepts/zconc_whatistsonative.htm https://github.com/stefanhaustein/expressionparser - { true, true, true, true, "STR_ERROR", " ERROR" }, // simply the word error that is attached to the other parts of messages https://fjkraan.home.xs4all.nl/comp/apple2faq/app2asoftfaq.html - { true, true, true, true, "STR_IN", " IN " }, - // STD M65 U64 X16 --- misc strings specific to OpenROMs, not present in CBM ROMs - { true, true, true, true, "STR_BRK_AT", "\rBRK AT $" }, + { true, true, true, true, "STR_RET_QM", "\r?" }, + { true, true, true, true, "STR_BYTES", " BASIC BYTES FREE" }, // https://github.com/stefanhaustein/expressionparser + { true, true, true, true, "STR_READY", "\rREADY.\r" }, // https://www.ibm.com/support/knowledgecenter/zosbasics/com.ibm.zos.zconcepts/zconc_whatistsonative.htm https://github.com/stefanhaustein/expressionparser + { true, true, true, true, "STR_ERROR", " ERROR" }, // simply the word error that is attached to the other parts of messages https://fjkraan.home.xs4all.nl/comp/apple2faq/app2asoftfaq.html + { true, true, true, true, "STR_IN", " IN " }, + { false, true, false, false, "STR_IF_SURE", "\rARE YOU SURE? " }, // https://docs.microsoft.com/en-us/windows/win32/uxguide/mess-confirm + // STD M65 U64 X16 --- misc strings specific to Open ROMs, not present in CBM ROMs + { true, true, true, true, "STR_BRK_AT", "\rBRK AT $" }, + { false, true, false, false, "STR_MEM_HDR", "\r\x12 AREA START SIZE \r" }, + { false, true, false, false, "STR_MEM_1", " $" }, + { false, true, false, false, "STR_MEM_2", " " }, + { false, true, false, false, "STR_MEM_TEXT", "\r TEXT" }, + { false, true, false, false, "STR_MEM_VARS", "\r VARS" }, + { false, true, false, false, "STR_MEM_ARRS", "\r ARRS" }, + { false, true, false, false, "STR_MEM_STRS", "\r STRS" }, + { false, true, false, false, "STR_MEM_FREE", "\r\r FREE" }, + // Note: depending on configuration, additional strings will be added here } }; @@ -1766,8 +1743,7 @@ void writeStrings() // Add input data to computation objects dataSetX16.addStrings(GLOBAL_Keywords_V2); - dataSetX16.addStrings(GLOBAL_Keywords_CC); - dataSetX16.addStrings(GLOBAL_Keywords_CD); + dataSetX16.addStrings(GLOBAL_Keywords_01); dataSetX16.addStrings(GLOBAL_Errors); dataSetX16.addStrings(GLOBAL_MiscStrings); @@ -1782,8 +1758,8 @@ void writeStrings() // Add input data to computation objects dataSetM65.addStrings(GLOBAL_Keywords_V2); - dataSetM65.addStrings(GLOBAL_Keywords_CC); - dataSetM65.addStrings(GLOBAL_Keywords_CD); + dataSetM65.addStrings(GLOBAL_Keywords_01); + dataSetM65.addStrings(GLOBAL_Keywords_02); dataSetM65.addStrings(GLOBAL_Errors); dataSetM65.addStrings(GLOBAL_MiscStrings); @@ -1798,8 +1774,7 @@ void writeStrings() // Add input data to computation objects dataSetU64.addStrings(GLOBAL_Keywords_V2); - dataSetU64.addStrings(GLOBAL_Keywords_CC); - dataSetU64.addStrings(GLOBAL_Keywords_CD); + dataSetU64.addStrings(GLOBAL_Keywords_01); dataSetU64.addStrings(GLOBAL_Errors); dataSetU64.addStrings(GLOBAL_MiscStrings); @@ -1814,8 +1789,7 @@ void writeStrings() // Add input data to computation objects dataSetSTD.addStrings(GLOBAL_Keywords_V2); - dataSetSTD.addStrings(GLOBAL_Keywords_CC); - dataSetSTD.addStrings(GLOBAL_Keywords_CD); + dataSetSTD.addStrings(GLOBAL_Keywords_01); dataSetSTD.addStrings(GLOBAL_Errors); dataSetSTD.addStrings(GLOBAL_MiscStrings); diff --git a/tools/pngprepare.c b/tools/pngprepare.c index 7c5b245c..8b5c6b5c 100644 --- a/tools/pngprepare.c +++ b/tools/pngprepare.c @@ -108,13 +108,16 @@ void abort_(const char * s, ...) void read_png_file(char* file_name) { unsigned char header[8]; // 8 is the maximum size that can be checked + size_t readResult; /* open file and test for it being a png */ infile = fopen(file_name, "rb"); if (infile == NULL) abort_("[read_png_file] File %s could not be opened for reading", file_name); - fread(header, 1, 8, infile); + readResult = fread(header, 1, 8, infile); + if (readResult != 8) + abort_("[read_png_file] File %s could not be read", file_name); if (png_sig_cmp(header, 0, 8)) abort_("[read_png_file] File %s is not recognized as a PNG file", file_name);