diff --git a/MEGA65.md b/MEGA65.md new file mode 100644 index 0000000..6296cd1 --- /dev/null +++ b/MEGA65.md @@ -0,0 +1,142 @@ +# CBM-FileBrowser — native MEGA65 / C65 port + +This adds a **native MEGA65 (C65-mode)** target to CBM-FileBrowser, alongside the +existing C64 / C128 / VIC-20 / C16 / DTV builds. It runs in the MEGA65's own +native mode (not GO64/C64 mode): it loads at `$2001` with a BASIC-10 SYS stub and +uses the MEGA65 screen and VIC-III/IV. + +Because the file browser is a KERNAL/IEC client, it is exactly what you want for +driving a **Meatloaf** device over the IEC serial bus. + +## Files added + +| File | Purpose | +|------|---------| +| `sources/mega65.def` | Target configuration (`target = 65`): memory map, colours, keys, default device. | +| `sources/mega65.asm` | Entry point — includes `mega65.def` then the shared `CBM-FileBrowser.asm`. | +| `sources/CBM-FileBrowser.asm` | Shared core — now has `target = 65` branches throughout. | +| `sources/Makefile` | New `fb65.prg` rule. | + +## Building + +You need [ACME](https://sourceforge.net/projects/acme-crossass/) (`brew install acme`). + +```bash +cd sources +make fb65.prg # just the MEGA65 build +# or +make # all targets, including fb65.prg +``` + +Output: `sources/fb65.prg`, load address `$2001`. + +## Running in the Xemu MEGA65 emulator (`xmega65`) + +```bash +xmega65 -prgmode 65 -prg fb65.prg +``` + +`-prgmode 65` forces native C65 mode; `-prg` auto-runs the program. The browser +comes up showing its list frame, the drive number, and the `SORT` / `QUIT` +bottom bar. + +## Configuration (`sources/mega65.def`) + +Key settings you may want to change: + +- **`hwdevicenum = 10`** — the IEC device the browser talks to. This is set to + **10** for a setup where the internal floppy is disabled and **Meatloaf answers + as device 10**. Set to `0` to auto-detect from the last-used device, or to `8` + for a standard internal drive. At runtime, press **`D`** to cycle the active + drive (8..15) regardless of this default. +- Colours (`backcolor` / `bordercolor` / `forecolor` …), key bindings + (`key_*`), and feature toggles (`sortdir`, `fastscrolle`, …) work the same as + the other targets — see the comments in `mega65.def`. +- `tap_support` is **off** for MEGA65 (the ITS tape path uses C64-specific ROM + entry points and tape is not relevant natively). + +## How the MEGA65 target differs from the others + +The C65 KERNAL is derived from the C128 KERNAL, so the portable `$FFxx` KERNAL +jump table (`SETLFS`/`SETNAM`/`OPEN`/`CLOSE`/`LOAD`/`CHKIN`/`CHRIN`/`CHROUT`/ +`PLOT`/`GETIN`/…) is used unchanged. The MEGA65-specific pieces are: + +- **Memory map:** screen `$0800`, colour RAM `$D800`, BASIC text `$2001` + (vs `$0400`/`$D800`/`$0801` on the C64). +- **BASIC-10 SYS stub** at `$2001` (`10 SYS 8205`). +- **No VDC and no C128 MMU** — the C128 target writes the VDC (`$D600/$D601`) and + banks memory via `$FF00`/`$FF68`; neither exists on the MEGA65, so the C65 + target has its own colour/init code and uses the direct-screen-memory drawing + paths. +- **Self-contained print helpers** — the C64 build calls BASIC-ROM routines at + `$AB1E`/`$BDCD`; those addresses are not valid in C65 mode, so `PRNSTR` / + `PRNINT` / `CLEARSCREEN` are reimplemented locally on top of `CHROUT`. +- **Zero page:** `SHFLAG = $D3`, `NDX = $D0`, device `= $BA` (C128-derived), + status `ST = $90`. + +## Two MEGA65-specific fixes (both needed for correct operation) + +1. **LOAD destination bank (`$AF`/`$B0`).** The MEGA65 KERNAL `LOAD` uses a + 32-bit destination pointer in zero page (`$AD`=lo, `$AE`=hi, `$AF`=bank, + `$B0`=megabyte). The C64-compatible relocating `LOAD` sets only `$AD`/`$AE` + from X/Y and leaves the bank byte uninitialised, so the directory/program + would be written into a stray bank (Xemu reports "unhandled memory write for + linear address `$28xxxx`"). The `target = 65` code zeroes `$AF`/`$B0` right + before every `LOAD`. +2. **80-column row stride (`ScreenCols = 80`).** MEGA65 native mode boots into an + 80-column editor, so screen RAM at `$0800` has an 80-byte logical row stride. + The direct-memory list drawing (clearlist / fast-scroll) must use 80, or + scrolled entries land in the wrong half of the screen. Column *positions* + (`listx` etc.) are unchanged, so the UI sits in the left 40 columns. + +## Program launch (the "RUN" step) + +When you select a program the browser does a KERNAL `LOAD` and then launches it. +The C64/C128 targets jump to machine-specific **BASIC-ROM** routines to RUN; the +closed MEGA65 ROM's BASIC internals are undocumented and going back through +BASIC's direct loop dropped into the built-in monitor. So `target = 65` uses a +**ROM-independent launcher** (`m65_run_hook`): it parses the `SYS ` out of +the program's BASIC stub at `$2001` and `JMP`s straight to the machine code. + +This launches machine-language `.prg`s (BASIC `SYS` stub + machine code — games, +demos, tools, and the `fb*` programs themselves — the bulk of the software). See +**Known limitations** below for pure-BASIC programs. + +Finding the launcher took three MEGA65-specific discoveries, all now in the +`target = 65` code: +- `loadrunpos = $0400`: the C64 tape-buffer `$0334` holds live C65 KERNAL + keyboard-decode vectors — copying the loadrun code there corrupted the + keyboard. `$0400-$07FF` (old C64 screen, free in native mode) is safe. +- keyboard buffer `KEYD = $02B0`, `NDX = $D0` (found by disassembling the ROM). +- stop-key flag `$91` (`$7F` = pressed). + +## Known limitations + +- **Program launch is machine-language only.** The launcher parses a program's + `SYS ` BASIC-10 stub and jumps to it, so it runs the ML `.prg`s that are + the bulk of MEGA65 software. A **pure BASIC-10 program** has no `SYS` token, so + it is *not* run: the launcher falls back to a reset, and if the program happens + to contain a stray `$9E` byte early in its first line the parse can jump to a + bad address and drop into the monitor. Launching BASIC programs properly needs + a LOAD-then-RUN hand-off back into BASIC-10, which isn't implemented yet. **The + Commander X16 target shares this limitation.** + +## Verified in `xmega65` (native C65 mode) + +- Boots and runs from the `$2001` BASIC-10 stub. +- Renders the full UI natively — list frame, cursor arrows, disk-name/status + area, colours, and the drive-number / `SORT` / `QUIT` labels. +- **Reads a disk directory via KERNAL `LOAD"$"` and lists the files.** +- **Scrolls the list cleanly** (up/down, page, top/bottom). +- **Selects and launches a program** (`LOAD` + SYS-stub launcher). +- Keyboard/joystick input (CIA1 `$DC00`, C64-compatible on MEGA65). + +Tested against a D81 on the emulated internal drive (device 8). On real +hardware the identical KERNAL path talks to **Meatloaf over IEC (device 10)** — +`hwdevicenum = 10` in `mega65.def`. + +## Cosmetic note + +The browser draws in the left 40 columns of the 80-column MEGA65 screen. +Optionally the MEGA65 could be switched to 40-column mode at startup so it fills +the screen like a C64. diff --git a/X16.md b/X16.md new file mode 100644 index 0000000..7c78867 --- /dev/null +++ b/X16.md @@ -0,0 +1,122 @@ +# CBM-FileBrowser — Commander X16 port + +This adds a **Commander X16** target (`target = 216`) to CBM-FileBrowser, +alongside the existing C64 / C128 / VIC-20 / C16 / DTV / MEGA65 builds. + +The X16 uses a C64-derived KERNAL (standard `$FFxx` jump table, BASIC at +`$0801`, `65C02` CPU), so most of the browser ports cleanly. The one big +difference is **video: the X16 uses VERA**, whose text screen lives in separate +video RAM, *not* in the CPU address space. So this target does **all** drawing +through the KERNAL screen editor (`CHROUT` / `PLOT`) — there is no direct +screen-memory access, and fast-scrolling (which relies on it) is turned off. + +Being a KERNAL/IEC client, it's exactly what you want for driving a **Meatloaf** +over the IEC serial bus. + +## Files added + +| File | Purpose | +|------|---------| +| `sources/x16.def` | Target configuration (`target = 216`): device, colours, keys. | +| `sources/x16.asm` | Entry point — includes `x16.def` then the shared `CBM-FileBrowser.asm`. | +| `sources/CBM-FileBrowser.asm` | Shared core — now has `target = 216` branches throughout. | +| `sources/Makefile` | New `fbx16.prg` rule (also in `all`). | + +## Building + +Needs [ACME](https://sourceforge.net/projects/acme-crossass/) (`brew install acme`). + +```bash +cd sources +make fbx16.prg # just the X16 build +# or +make # all targets, including fbx16.prg +``` + +Output: `sources/fbx16.prg`, load address `$0801`. + +## Running in the emulator (`x16emu`) + +The X16 emulator serves the directory it is launched from as device 8 (HostFS), +so run it from a folder that contains `fbx16.prg` (and any programs to browse): + +```bash +cd /folder/with/fbx16.prg/and/programs +x16emu -prg fbx16.prg -run +``` + +The browser comes up, lists the folder, and you can cursor to a program and +press **Return** to launch it. On real hardware, put `fbx16.prg` on the SD card +(or load it from Meatloaf) and `LOAD"FBX16",8` + `RUN`. + +## Configuration (`sources/x16.def`) + +- **`hwdevicenum = 8`** — the device the browser reads (the X16 SD-card / HostFS + default). Set to `0` to auto-detect from the last-used device, or to the + device your **Meatloaf** answers on. Press **`D`** at runtime to cycle the + active drive. +- Colours / key bindings work like the other targets (see the comments in + `x16.def`). `bordercolor` is ignored (the X16 has no C64-style border); + `fastscrolle` is forced off (VERA has no direct screen RAM); `tap_support` is + off (no tape). + +## How the X16 target differs + +- **Video is VERA** — screen not in CPU RAM. All drawing via `CHROUT`/`PLOT`; + `clearlist` reimplemented with `PLOT`+`CHROUT`; `fastscrolle = 0` (a full + `CHROUT` redraw per move, fast enough on the 8 MHz X16). The browser sets + 40×30 text mode (`screen_mode` `$FF5F`) at startup. +- **SYS-stub launch** — the same ROM-independent SYS-stub launcher as the + MEGA65: parse `SYS ` out of the program's `$0801` BASIC stub and `JMP` + to the machine code. Launches machine-language `.prg`s — see + **Known limitations** below. +- **Zero page / KERNAL vars** — `ST = $0287`, device `= $0292`, `KEYD = $A800`, + `NDX = $A80A`, `STKEY = $A80B`, `SHFLAG = $A80C`. The browser's own zero page + (`$22-$29`, `$57/$58`, `$FB-$FE`) is free on the X16. +- **`loadrunpos = $0400`** — the X16's "golden RAM" (`$0400-$07FF`), free and + below the `$0801` program area. +- **Keyboard-driven** — the joystick read is stubbed to "nothing pressed" so + input falls through to the keyboard (real joystick support via `joystick_get` + `$FF56` is a possible future add). The raster-wait uses a short delay, not a + VERA vsync poll (the KERNAL owns the vsync IRQ, so polling it hangs). +- **ISO mode for mixed-case filenames** — SD-card/HostFS filenames are ASCII, so + the browser switches the X16 to ISO mode at startup (`CHR$15`) so lower- and + upper-case names both render as real letters. Colour/reverse control codes + still work in ISO mode; the one graphic glyph the browser uses (the separator + bar) is drawn with `-` instead of the PETSCII bar `$c0` (which is `A-grave` in + ISO). + +## Known limitations + +- **Program launch is machine-language only.** The launcher parses a program's + `SYS ` BASIC stub and jumps to it, so it runs the ML `.prg`s that are the + bulk of X16 software (games, demos, tools, and the `fb*` browsers themselves). + A **pure BASIC program** has no `SYS` token, so it is *not* run: the launcher + falls back to a reset, and if the program happens to contain a stray `$9E` byte + early in its first line the parse can jump to a bad address and drop into the + monitor. Launching BASIC programs properly needs a LOAD-then-RUN hand-off back + into BASIC, which isn't implemented yet (re-entering X16 BASIC cleanly from the + browser's running state is fiddly). **The MEGA65 target shares this + limitation.** + +## Bug fixed along the way (helps every target) + +`parseext` (the disk-image extension matcher) had a **latent infinite loop**: +its outer loop steps X by the 4-byte slot size and stopped only when +`X == extensions_max`, but the extensions table is not a whole multiple of 4 +(`"tcrt"` is 5 bytes), so X could step *past* `extensions_max` and never match. +It never surfaced on the C64/C128/MEGA65 because CBM disk names have no file +extension (so `parseext` is skipped), but the X16's HostFS reports names like +`GAME.PRG`, which exercises it. Fixed by terminating on `X >= extensions_max` +(`bcs` instead of `beq`) — a safe hardening for all targets. + +## Verified in `x16emu` + +Boot from the `$0801` stub · full UI rendered natively via VERA/CHROUT · +directory read (`LOAD"$"`) and file listing · list scrolling · keyboard +navigation · **selecting and launching a program**. + +## Charset + +The browser runs the X16 in **ISO mode**, so both upper- and lower-case +filenames (from the SD card / HostFS, which are ASCII) render as real letters. diff --git a/programs/fb65 b/programs/fb65 new file mode 100644 index 0000000..39ab6dd Binary files /dev/null and b/programs/fb65 differ diff --git a/programs/fbx16 b/programs/fbx16 new file mode 100644 index 0000000..f0c224e Binary files /dev/null and b/programs/fbx16 differ diff --git a/sources/CBM-FileBrowser.asm b/sources/CBM-FileBrowser.asm index 2da2f91..ba9b442 100644 --- a/sources/CBM-FileBrowser.asm +++ b/sources/CBM-FileBrowser.asm @@ -23,10 +23,27 @@ ScreenCols = 40 ; Number of screen columns } !if target = 128 { -joyport = $dc00 ; change me, joystick port +joyport = $dc00 ; change me, joystick port ScreenCols = 40 ; Number of screen columns } +!if target = 216 { +; Commander X16 - keyboard driven (no CIA joystick port at $dc00; the X16 has a +; joystick_get KERNAL call instead). ScreenCols is only used by the (unused on +; X16) direct-screen paths and the arrow-position check. +ScreenCols = 40 ; the browser sets the X16 to 40x30 text mode at start +} + +!if target = 65 { +joyport = $dc00 ; joystick port 2 ($dc01 for port 1) - CIA1 is C64-compatible on MEGA65 +ScreenCols = 80 ; MEGA65 native mode boots to an 80-column editor: the + ; screen RAM at $0800 uses an 80-byte logical row stride. + ; This is the stride for the direct-memory list drawing + ; (clearlist/scroll); the visible layout still uses the + ; 40-column column positions (listx etc.), leaving the + ; right half of the screen unused. +} + ; - max. length for stored entries entrylen = 17 @@ -52,7 +69,7 @@ MC_LastConfig = $9c0b ; - kernal functions ; -------------------- -!if target = 20 | target = 64 | target = 16 | target = 128 { +!if target = 20 | target = 64 | target = 16 | target = 128 | target = 65 | target = 216 { SETLFS = $ffba ; a = filenr, x = unitnr, y = sec.addr/command (255|1) SETNAM = $ffbd ; a = namelen, x:y->name OPEN = $ffc0 ; Open Vector [F40A] Open File @@ -118,7 +135,38 @@ IOINIT = $ff84 ; IOINIT - $ff84 - Initializes I/O devices SCRTCHF = $8a7b ; scrtch Perform [new] FORCED and return } -!if target = 20 | target = 64 | target = 16 | target = 128 { +!if target = 65 { +; MEGA65 / C65 native mode. The C65 KERNAL keeps the C64/C128-compatible +; $FFxx jump table, so all the shared vectors above (SETLFS/SETNAM/OPEN/...) +; are valid. It has NO C64 BASIC ROM at $A000, so PRNSTR/PRNINT/CLEARSCREEN +; are provided as local routines (see the "target = 65" routine block below). + +CINT = $ff81 ; CINT - Initialize screen editor +IOINIT = $ff84 ; IOINIT - Initialize I/O devices +SETBNK = $ff6b ; SETBNK - a = bank for file DATA, x = bank for FILENAME. + ; MEGA65 LOAD uses a 28-bit destination; call SETBNK #0,#0 so + ; loads/opens target bank 0 (otherwise the bank byte is garbage + ; and LOAD writes to an unmapped bank - see MEGA65.md). + +SHFLAG = $d3 ; shift/CBM/CTRL flag (C128-derived KERNAL, same as C128) + ; ($00 = None, $01 = Shift, $02 = CBM, $04 = CTRL or a sum of them). +} + +!if target = 216 { +; Commander X16 - standard C64-compatible KERNAL jump table plus X16 extensions. +; Screen is VERA-only, so PRNSTR/PRNINT/CLEARSCREEN are provided locally (see the +; "target = 216" routine block below), built on CHROUT. +CHKIN = $ffc6 ; Set Input (after OPEN) +CHRIN = $ffcf ; Input a byte (after OPEN, CHKIN) + +SCREEN_MODE = $ff5f ; X16: a = mode ($00=80x60, $01=40x30 ...), or $ff to query +SCREEN_SET_CHARSET = $ff62 ; X16: a = charset (0 = ISO, 1 = PETSCII upper/gfx, ...) +JOYSTICK_GET = $ff56; X16: read joystick (a=port); returns state in a/x/y + +SHFLAG = $a80c ; X16 shift/ctrl flag (KERNAL var in RAM bank 0) +} + +!if target = 20 | target = 64 | target = 16 | target = 128 | target = 65 | target = 216 { LISTN = $ffb1 ; Command Serial Bus LISTEN UNLSN = $ffae ; Command Serial Bus UNLISTEN } @@ -161,6 +209,15 @@ vicbackgnd = $d021 ; background color register vicraster = $d012 ; raster compare register } +!if target = 65 { +screen = $0800 ; screen address (native C65 40-column default screen) +color = $d800 ; color/attribute ram (VIC-III $D800 window in native mode) +vicborder = $d020 ; border color register (VIC-III, C64-compatible offset) +vicbackgnd = $d021 ; background color register +vicraster = $d012 ; raster compare register (low byte) +m65_txttop = $0380 ; 2-byte scratch for end-of-loaded-program address +} + !if target = 16 { screen = $0C00 ; screen address color = $0800 ; color ram address @@ -186,7 +243,18 @@ output_control = $9a ;Direct=$80/RUN=0 variablesstartaddress_hi = $2e ;Pointer: Start of Basic hi byte } -status_word_st = $90 ; Status word ST +!if target = 216 { +status_word_st = $0287 ; Status word ST (X16 KERNAL var .status) +} else { +status_word_st = $90 ; Status word ST +} + +!if target = 216 { +keybuf = $a800 ; keyboard buffer (X16 KERNAL .keyd, RAM bank 0) +keybuflen = $a80a ; keyboard buffer byte count (X16 .ndx) +lastdevice = $0292 ; current device number (X16 KERNAL .fa) +imain = $0302 ; BASIC main/direct loop vector (JMP (imain) -> READY) +} !if target = 20 | target = 64 { keybuf = $0277 ; keyboard buffer @@ -206,6 +274,15 @@ keybuflen = $d0 ; keyboard buffer byte count lastdevice = $ba ; last used device number } +!if target = 65 { +keybuf = $02b0 ; keyboard buffer (KEYD) - found by disassembling the + ; MEGA65 KERNAL (STA $02B0,X next to STX $D0/NDX) +keybuflen = $d0 ; keyboard buffer byte count (NDX) - PEEK(208) on C65 +lastdevice = $ba ; last used device number (FA) - standard KERNAL zp +imain = $0302 ; indirect BASIC main/direct loop vector (C65 spec) - + ; JMP (imain) returns to the BASIC "READY" input loop +} + @@ -213,7 +290,7 @@ lastdevice = $ba ; last used device number ; - Zero page variables ; -------------------- -!if target = 20 | target = 64 | target = 16 | target = 128 { +!if target = 20 | target = 64 | target = 16 | target = 128 | target = 65 | target = 216 { ; current joystick state (1 = falling edge) curjoy = $22 @@ -244,7 +321,7 @@ prevdirposh = $58 } } -!if target = 20 | target = 64 | target = 128 { +!if target = 20 | target = 64 | target = 128 | target = 65 | target = 216 { ; - pointer to selected entry selected = $fb @@ -535,6 +612,24 @@ entry: !by 0,0,0 ;end } +!if target = 65 { +*=$2001 + +entry: +; MEGA65 / C65 native BASIC 10 stub: "10 SYS 8205" +; layout (12 bytes, code follows at $200d = 8205): +; next-line ptr, line#, SYS token, "8205", eol, end-of-program +!by $0b,$20,$01,$00,$9e,$38,$32,$30,$35,$00,$00,$00 +} + +!if target = 216 { +*=$0801 + +entry: +; Commander X16 BASIC stub: "10 SYS 2061" (code follows at $080d = 2061) +!by $0b,$08,$01,$00,$9e,$32,$30,$36,$31,$00,$00,$00 +} + mlcodeentry: !if target = 20 { @@ -716,6 +811,27 @@ tax ;(for filename, needed now for OPEN and later for LOAD) jsr $ff68 ;set bank } +!if target = 65 { +;MEGA65: make all KERNAL file I/O use bank 0 for both file data and filename. +;Without this the 28-bit LOAD destination bank byte is uninitialised and LOAD +;writes the directory/program into an unmapped bank. +lda #0 ;bank for file data (LOAD/SAVE) +tax ;bank for filename +jsr SETBNK +} + +!if target = 216 { +;Commander X16: switch to the 40x30 text mode for a C64-like layout. +lda #$01 ;mode 1 = 40x30 +jsr SCREEN_MODE +;Use ISO mode so mixed-case (ASCII) filenames from the SD-card/HostFS render as +;real letters instead of PETSCII graphics. CHR$15 is the X16 screen editor's +;"enable ISO mode" control code (CHR$143 would disable it). Colour/reverse +;control codes still work in ISO mode; only graphic glyphs differ (bar char). +lda #15 +jsr CHROUT +} + !if forecolor>4 { lda #forecolor jsr CHROUT @@ -804,6 +920,21 @@ jsr set_custom_fkeys_def_area } +!if target = 65 { +; MEGA65 / C65 native mode: VIC-III border/background at the C64-compatible +; offsets. No VDC (that is a C128-only chip) and no F-key redefinition. + +!if bordercolor<16 { +lda #bordercolor +sta vicborder +} +!if backcolor<16 { +lda #backcolor +sta vicbackgnd +} + +} + !if hwdevicenum = 0 & autodetectm = 0 { @@ -860,10 +991,10 @@ ldy #listx+17 ; col to print sty curpos ; set cursor position and avoid screen scroll } -!if target = 64 | target = 16 | target = 128 { +!if target = 64 | target = 16 | target = 128 | target = 65 | target = 216 { clc ; function: set cursor jsr PLOT ; set cursor position -} +} ldy #>quit_text ; string start point hi-byte lda #= joyrepeat @@ -1068,11 +1216,17 @@ ldy #0 ; reset joyrepeat counter lda #$ff ; reset lastjoy for repeat sta lastjoy -!if target = 20 | target = 64 | target = 128 { +!if target = 20 | target = 64 | target = 128 | target = 65 { ; read joystick + lda joyport ; a = joy } +!if target = 216 { +; X16 is keyboard-driven here: report "nothing pressed" so input falls through +; to GETIN below (real joystick support could use joystick_get $FF56 later). ++ lda #$ff +} + !if target = 16 { ; read joystick @@ -1152,7 +1306,7 @@ pha -!if target = 20 | target = 64 | target = 16 | target = 128 { +!if target = 20 | target = 64 | target = 16 | target = 128 | target = 65 | target = 216 { ;joystick read tax ; save to x eor lastjoy ; a = joy xor lastjoy @@ -1160,7 +1314,7 @@ and lastjoy ; a = a and lastjoy stx lastjoy ; update lastjoy } -!if target = 20 | target = 64 | target = 128 { +!if target = 20 | target = 64 | target = 128 | target = 65 | target = 216 { sta curjoy and #$1f ; test if anything is pressed bne + ; if is, process input @@ -1249,7 +1403,7 @@ jmp menu bne ++ ; jump if not jmp loadprev ; load prev dir -!if (target = 64 | target = 128) & key_quit < 255 { +!if (target = 64 | target = 128 | target = 65 | target = 216) & key_quit < 255 { ++ cpx #key_quit ; check if key_quit bne ++ ; jump if not @@ -1264,12 +1418,21 @@ bne ++ ; jump if not } jsr restore_fkeys_def_area jmp $fa59 ; reset screen then Warm Start Basic (Stop+Restore) -} else { +} +!if target = 64 { jmp $fe66 ; Warm Start Basic [BRK] } +!if target = 65 { +; MEGA65 native: no C64 BASIC ROM to warm-start into, so do a clean CPU reset, +; which returns the machine to the MEGA65 BASIC ready prompt. + jmp ($fffc) ; reset CPU +} +!if target = 216 { + jmp ($fffc) ; X16: clean reset back to BASIC ready +} } -!if (target = 64 | target = 128) & key_reset < 255 { +!if (target = 64 | target = 128 | target = 65 | target = 216) & key_reset < 255 { ++ cpx #key_reset bne ++ ; jump if not ;jmp $FCE2 ; Reset the C64 SYS64738 @@ -1379,7 +1542,7 @@ bcs firepressed ; jump if pressed cpx #key_fire ; check if key_fire beq firepressed ; jump if pressed -!if target = 64 | target = 16 | target = 128 { +!if target = 64 | target = 16 | target = 128 | target = 65 | target = 216 { !if startmode = 1 { cpx #key_fire2 ; check if key_fire2 (CBM+ENTER) @@ -2140,7 +2303,7 @@ rts -!if target = 64 | target = 16 { +!if target = 64 | target = 16 | target = 65 | target = 216 { !if startmode = 0 { ;old method, LOAD"FILE",8,1 + (System auto RUN) @@ -2152,10 +2315,10 @@ ldy #1 ; sec.address (,1) !if startmode = 1 { -LDA SHFLAG ; 1 shift pressed, 2 CBM pressed, 4 CTRL pressed +LDA SHFLAG ; 1 shift pressed, 2 CBM pressed, 4 CTRL pressed and #$02 -cmp #$02 ; check cbm key -beq + ; start mode 2 (LOAD "FILE",8 + RUN) +cmp #$02 ; check cbm key +beq + ; start mode 2 (LOAD "FILE",8 + RUN) ldy #1 ; sec.address (,1) File start address LOAD lda #0 ; start mode 0 (LOAD "FILE",8,1 + RUN) @@ -2389,6 +2552,26 @@ sty variablesstartaddress_hi sty $1211 ;(high) } +!if target = 65 { + lda #0 ;bank byte / MB byte of the 32-bit KERNAL load pointer + sta $af ; ($AD-$B0); zero them so LOAD targets bank 0 (see loadlist) + sta $b0 + lda #0 ;0 = load + ldx #$01 ;relocate target = $2001 (BASIC 10 start), + ldy #$20 ; used by LOAD only when sec.addr = ,0 + jsr LOAD + ; on return X/Y = end-of-load address + stx m65_txttop+0 + sty m65_txttop+1 +} + +!if target = 216 { + lda #0 ;0 = load + ldx #$01 ;relocate target = $0801 (X16 BASIC start), + ldy #$08 ; used by LOAD only when sec.addr = ,0 + jsr LOAD +} + !if target = 64 { @@ -2526,12 +2709,182 @@ jsr CLEARSCREEN jsr $5a81 ;setup RUN mode jmp $4af6 ;advance to next (first) BASIC program line -StartMode0: +StartMode0: jmp ($00ac) ;SYS to load address (bug with old ROMs and non-fast-serial disk drive) } } +!if target = 65 { +; MEGA65 / C65 native mode program launch. +; +; clear screen +!if clearscrena = 1 { + jsr CLEARSCREEN +} + +; restore default background/border/cursor colors (MEGA65 boot look) +!if colorenable = 1 { + lda #6 + sta vicborder ;default border color (blue) + lda #6 + sta vicbackgnd ;default background color (blue) + lda #154 + jsr CHROUT ;default cursor color (light blue) +} + +; --- RUN the freshly LOADed program --------------------------------------- +; ROM-version-independent launch: type "RUN" + RETURN into the keyboard buffer +; and hand control back to BASIC's direct/main loop via the RAM vector at $0302 +; (imain). BASIC then relinks and runs the program that LOAD placed at $2001 +; (both plain BASIC-10 programs and the usual ML programs that carry a "SYS" +; BASIC stub at $2001 launch this way). No undocumented BASIC-ROM addresses. +; This code is relocated to loadrunpos, so it must be position-independent: +; use immediates + fixed addresses only (no absolute refs to labels in-block). +; Launch the just-loaded program. The standard C64/C65 .prg format is a BASIC +; stub at $2001 -- " SYS <0>" -- followed by machine code. +; We parse straight out of the stub and JMP there. This is completely +; ROM-independent (no BASIC internals, no keyboard buffer) and launches every +; ML-with-SYS-stub program (games, demos, tools - the vast majority). +; Uses only immediates / fixed zero page / relative branches (position-indep.). +m65_run_hook: + lda #$05 ;walk pointer = $2005 (past link+line number) + sta $fb + lda #$20 + sta $fc + ldy #0 +m65_findsys: + lda ($fb),y ;scan for the SYS token ($9e) + cmp #$9e + beq m65_foundsys + iny + cpy #16 + bne m65_findsys + jmp ($fffc) ;no SYS stub (e.g. a pure-BASIC program) -> safe reset + ; (the loadrun code was JMPed to, so there is no + ; return address to RTS back to) +m65_foundsys: + iny ;step past $9e +m65_skipsp: + lda ($fb),y ;skip spaces before the number + cmp #$20 + bne m65_num0 + iny + bne m65_skipsp +m65_num0: + lda #0 ;result ($fd/$fe) = 0 + sta $fd + sta $fe +m65_digit: + lda ($fb),y + sec + sbc #$30 ;ascii -> digit + bcc m65_go ;<'0' -> end of number + cmp #10 + bcs m65_go ;>'9' -> end of number + pha ;save digit + ; result = result*10 + asl $fd + rol $fe ;*2 + lda $fd + sta $22 + lda $fe + sta $23 ;$22/$23 = result*2 + asl $fd + rol $fe + asl $fd + rol $fe ;result = result*8 + clc + lda $fd + adc $22 + sta $fd + lda $fe + adc $23 + sta $fe ;result = result*8 + result*2 = result*10 + pla ;add the new digit + clc + adc $fd + sta $fd + bcc + + inc $fe ++ iny + bne m65_digit +m65_go: + jmp ($00fd) ;jump to the parsed SYS address (the ML entry) +} + +!if target = 216 { +; Commander X16 program launch. Same ROM-independent SYS-stub launcher as the +; MEGA65: parse the "SYS " out of the just-loaded program's BASIC stub and +; JMP to the machine code. The X16 stub is at $0801 (link+line, then the SYS +; token at $0805), so the walk pointer starts at $0805. +!if clearscrena = 1 { + jsr CLEARSCREEN +} +x16_run_hook: + lda #$05 ;walk pointer = $0805 (past $0801 link+line number) + sta $fb + lda #$08 + sta $fc + ldy #0 +x16_findsys: + lda ($fb),y ;scan for the SYS token ($9e) + cmp #$9e + beq x16_foundsys + iny + cpy #16 + bne x16_findsys + jmp ($fffc) ;no SYS stub (pure-BASIC program) -> safe reset +x16_foundsys: + iny ;step past $9e +x16_skipsp: + lda ($fb),y ;skip spaces before the number + cmp #$20 + bne x16_num0 + iny + bne x16_skipsp +x16_num0: + lda #0 ;result ($fd/$fe) = 0 + sta $fd + sta $fe +x16_digit: + lda ($fb),y + sec + sbc #$30 ;ascii -> digit + bcc x16_go ;<'0' -> end of number + cmp #10 + bcs x16_go ;>'9' -> end of number + pha ;save digit + asl $fd ;result *= 10 + rol $fe + lda $fd + sta $22 + lda $fe + sta $23 + asl $fd + rol $fe + asl $fd + rol $fe + clc + lda $fd + adc $22 + sta $fd + lda $fe + adc $23 + sta $fe + pla ;+ new digit + clc + adc $fd + sta $fd + bcc + + inc $fe ++ iny + bne x16_digit +x16_go: + jmp ($00fd) ;jump to the parsed SYS address (the ML entry) +} + + loadrunend ; end of code to copy @@ -2607,7 +2960,11 @@ clc ; function: set cursor jsr PLOT ; set place to print ldy #0 -- lda #$c0 ; "-" char +!if target = 216 { +- lda #$2d ; X16 ISO mode: '-' (the PETSCII bar $c0 renders as 'A-grave') +} else { +- lda #$c0 ; "-" (horizontal bar) char +} jsr CHROUT ; print char iny cpy #namelen+6 @@ -2833,7 +3190,26 @@ clearlist: !by $93 ;clear window !by $13, $13 ;full screen !by 0 ;end of string -} else { +} +!if target = 216 { +; X16: no direct screen memory (VERA), so clear the list area with PLOT + CHROUT. +lda #listtopy +sta tmp ;row counter +-- ldx tmp ;row +ldy #listx ;column +clc +jsr PLOT ;position cursor at (row, listx) +ldy #namelen +- lda #listbackgnd ;space +jsr CHROUT +dey +bne - +inc tmp +lda tmp +cmp #listbottomy +bne -- +} +!if target <> 128 & target <> 216 { lda #screen+listtopy*ScreenCols+listx @@ -2842,7 +3218,7 @@ sta clearlistsh ldx #listbottomy-listtopy -- ldy #0 lda #listbackgnd -- +- clearlistsl = *+1 clearlistsh = *+2 sta $1234,y @@ -3227,7 +3603,11 @@ adc #3 ; a->end of filetypes sta extension_limit ; x->filetypes extension_max = *+1 cpx #$12 -beq + ; extension not found +bcs + ; extension not found (>=, not ==: the extensions table is not a + ; whole multiple of the 4-byte slot size - "tcrt" is 5 bytes - so X + ; can step PAST extensions_max; == would loop forever. This only + ; bites when a filename actually has an extension that matches + ; nothing, e.g. "NAME.PRG" from the X16's HostFS.) - lda (tmpptr),y and #%01111111 ; compare shifted chars too, turn off bit 7 (Tap,TAP,tAP etc, all recognized) extension_list = *+1 @@ -3333,6 +3713,16 @@ bne cleardir_loop ldy tmpptrh ; tmpptr:h->load address (Restore Y value) } +!if target = 65 { +; MEGA65: the KERNAL load pointer is 32-bit at $AD-$B0 (lo,hi,bank,MB). The +; C64-compatible relocating LOAD sets $AD/$AE from X/Y but leaves the bank byte +; $AF (and $B0) uninitialised, so the directory would load into a stray bank. +; Zero them here (A stays 0 for LOAD, X/Y still hold the load address). +lda #0 +sta $af ; bank byte (bits 16..23) +sta $b0 ; megabyte byte (bits 24..27) +} + jsr LOAD ; - parse list @@ -3706,6 +4096,120 @@ Default_Color: } +!if target = 65 { +; *** Routines for MEGA65 / C65 native mode *** +; These replace the C64 BASIC-ROM helpers ($AB1E/$BDCD) and the C128 versions +; (which need the VDC and BASIC-low ROM) with self-contained code that uses +; only the portable KERNAL CHROUT ($FFD2). + +CLEARSCREEN: + lda #147 ;PETSCII clear-screen/home + jmp CHROUT + +PRNINT: +; print unsigned integer. A = high byte (callers pass 0), X = low byte. +; Only used to print the device number, so an 8-bit value is sufficient. + txa ;A = value (0..255) + ldx #$ff ;hundreds + sec +- inx + sbc #100 + bcs - + adc #100 ;X = hundreds, A = remainder (0..99) + ldy #$ff ;tens + sec +- iny + sbc #10 + bcs - + adc #10 ;Y = tens, A = ones (0..9) + pha ;save ones + txa ;hundreds + beq + ;suppress leading zero + ora #$30 + jsr CHROUT + tya ;tens always printed once hundreds shown + ora #$30 + jsr CHROUT + jmp ++ ++ tya ;tens + beq ++ ;suppress leading zero + ora #$30 + jsr CHROUT +++ pla ;ones + ora #$30 + jmp CHROUT + +;print 0-terminated string in A (lo) / Y (hi) +PRNSTR: + sta $ce + sty $cf + ldy #0 +- lda ($ce),y + beq + + jsr CHROUT + iny + bne - ++ rts +} + + +!if target = 216 { +; *** Routines for the Commander X16 *** +; The X16 has no C64 BASIC ROM at $A000; screen is VERA-only. These helpers use +; only the portable KERNAL CHROUT ($FFD2), so all drawing goes through the X16 +; screen editor. + +CLEARSCREEN: + lda #147 ;PETSCII clear-screen/home + jmp CHROUT + +PRNINT: +; print unsigned integer. A = high byte (callers pass 0), X = low byte. +; Only used to print the device number, so an 8-bit value is sufficient. + txa ;A = value (0..255) + ldx #$ff ;hundreds + sec +- inx + sbc #100 + bcs - + adc #100 ;X = hundreds, A = remainder (0..99) + ldy #$ff ;tens + sec +- iny + sbc #10 + bcs - + adc #10 ;Y = tens, A = ones (0..9) + pha ;save ones + txa ;hundreds + beq + ;suppress leading zero + ora #$30 + jsr CHROUT + tya + ora #$30 + jsr CHROUT + jmp ++ ++ tya ;tens + beq ++ ;suppress leading zero + ora #$30 + jsr CHROUT +++ pla ;ones + ora #$30 + jmp CHROUT + +;print 0-terminated string in A (lo) / Y (hi) +PRNSTR: + sta $ce + sty $cf + ldy #0 +- lda ($ce),y + beq + + jsr CHROUT + iny + bne - ++ rts +} + + !if target = 64 { !if variant = 2 { diff --git a/sources/Makefile b/sources/Makefile index ae4fb20..4736874 100644 --- a/sources/Makefile +++ b/sources/Makefile @@ -3,7 +3,7 @@ CFLAGS = -v1 --cpu 6502 -f cbm -o .PHONY: all clean -all: fb20-3k.prg fb20-8k.prg fb20-mc.prg fb20.prg fb64.prg fb64dtv.prg fb16.prg fb128.prg +all: fb20-3k.prg fb20-8k.prg fb20-mc.prg fb20.prg fb64.prg fb64dtv.prg fb16.prg fb128.prg fb65.prg fbx16.prg fb20-3k.prg: vic20-3k.asm vic20-3k.def CBM-FileBrowser.asm $(COMPILER) $(CFLAGS) $@ $< @@ -28,5 +28,11 @@ fb16.prg: c16.asm c16.def CBM-FileBrowser.asm fb128.prg: c128.asm c128.def CBM-FileBrowser.asm $(COMPILER) $(CFLAGS) $@ $< + +fb65.prg: mega65.asm mega65.def CBM-FileBrowser.asm + $(COMPILER) $(CFLAGS) $@ $< + +fbx16.prg: x16.asm x16.def CBM-FileBrowser.asm + $(COMPILER) $(CFLAGS) $@ $< clean: rm *.prg diff --git a/sources/mega65.asm b/sources/mega65.asm new file mode 100644 index 0000000..1005811 --- /dev/null +++ b/sources/mega65.asm @@ -0,0 +1,6 @@ + +; - user configuration +!src "mega65.def" + +; - core code +!src "CBM-FileBrowser.asm" diff --git a/sources/mega65.def b/sources/mega65.def new file mode 100644 index 0000000..3c9002a --- /dev/null +++ b/sources/mega65.def @@ -0,0 +1,179 @@ +; --- mega65.def - configuration for the Commodore MEGA65 (native C65 mode) +; +; Native MEGA65 / C65 target for CBM-FileBrowser. +; +; The MEGA65 in its native (C65) mode runs a C128-derived KERNAL, but with a +; different memory map (screen at $0800, BASIC text at $2001) and NO VDC/MMU. +; So this target reuses the portable KERNAL ($FFxx) jump table and the direct +; screen-memory drawing paths, and provides its own small print/colour helpers +; (see the "target = 65" routine block in CBM-FileBrowser.asm). +; +; Build: acme --cpu 6502 -f cbm -o fb65.prg mega65.asm +; Run : xmega65 -prg fb65.prg (auto-detects $2001 -> C65 mode) + +; - CBM target system +target = 65 ; choose the target system + ; 20 = Commodore VIC-20 + ; 64 = Commodore 64 + ; 16 = The Commodore 264 Series (C16, C116, plus/4) + ;128 = Commodore 128 + ; 65 = Commodore MEGA65 / C65 (native mode) + + ; Select a variant according with target system +variant = 0 ; 0 = None, Standard System. + + ; device number +hwdevicenum = 0 ; 0 = autodetect from the last-used device. Set to your drive + ; (e.g. a Meatloaf) to fix it. Press key_drive (D) at runtime + ; to cycle the active drive (8..15) regardless. + +autodetectm = 0 ; Drive auto detect mode if hwdevicenum = 0 + ; 0 = use the current drive (small program size) + ; 1 = detect the first active drive + +drivechange = 1 ; drive change function + ; 0 = do not change drive + ; 1 = change drive by pressing the key_drive + +rootonstart = 0 ; exit to root when start the program or change the drive + ; 0 = do not exit to root on start/drive change + ; 1 = exit to root on start/drive change + +rootentry = 1 ; "exit to root" entry on menu + ; 0 = none + ; 1 = present + +tap_support = 0 ; add tap capability via "XT:" command (ITS Module required) + ; 0 = none + ; 1 = yes + ; (disabled for MEGA65: the ITS tape path reinitialises the + ; machine via C64-specific ROM entry points and tape is not + ; relevant on a native MEGA65.) + +printbars = 1 ; display a top/bottom bar with some key funcions according with current configuration + ; 0 = do not diplay the top/bottom bar + ; 1 = display the the top/bottom bar + +startmode = 1 ; start mode for selected programs (C16/C64 meaning) + ; 0 = fixed LOAD"FILE",8,1 + RUN (old method, small program size) + ; 1 = LOAD"FILE",8,1 + RUN (by pressing key_fire or Joy button) + ; LOAD"FILE",8 + RUN (by holding CBM while pressing key_fire or Joy button) + +; - functionality (0/1) +minimal = 0 ; remove all extra features for smallest prg size +!if minimal = 1 { +rememberpos = 0 +showcursors = 1 +clearscrena = 1 +fastscrolle = 0 +colorenable = 0 +disknameena = 0 +statusenabl = 0 +pleasewaite = 0 +sortdir = 0 +} else { +rememberpos = 1 ; remember position on previous directory +showcursors = 1 ; show cursors +clearscrena = 1 ; enable screen clearing & color setting +fastscrolle = 1 ; enable fast list scrolling +colorenable = 1 ; enable colors +disknameena = 1 ; enable disk name printing +statusenabl = 1 ; enable status printing +pleasewaite = 1 ; enable "please wait" printing +sortdir = 1 ; enable sort dir function by using the key_sort +} + +; - layout/cosmetic/etc +joyrepeat = 15 ; joystick repeat delay +rastercmp = 1 ; raster line to wait for in mainwait + +; list location + +!if printbars = 1 { + +listtopy = 2 ; 0 <= x < listbottomy +listbottomy = 23 ; listtopy < x <= 25 + +} else { + +listtopy = 1 ; 0 <= x < listbottomy +listbottomy = 25 ; listtopy < x <= 25 + +} + +listx = 9 ; 0 <= x <= 24 +listbackgnd = 32 ; char to display in list background + +; disk name location +disknamey = 0 +disknamex = 9 + +; status text location +statusy = listtopy +statusx = listx+namelen+2 + +!if colorenable = 0 { + +backcolor = 255 +bordercolor = 255 +forecolor2 = 255 +forecolor = 0 +arrowcolor = 0 +buttoncolor = 0 + +} else { + +; back & border & fore2 color: +; 0 = black, 1 = white, 2 = red, 3 = cyan, 4 = purple +; 5 = green, 6 = blue, 7 = yellow, 8 = orange, 9 = brown +; 10 = lred, 10 = gray1, 12 = gray2, 13 = lgreen, +; 14 = lblue, 15 = gray3 + +backcolor = 0 ; 0..15, if >15 -> no change +bordercolor = 6 ; 0..15, if >15 -> no change +forecolor2 = 1 ; 0..15 if >15 -> no change + + +; foreground & arrow color: + +; 5 = white, 28 = red, 30 = green, 31 = blue, 129 = orange +; 144 = black, 149 = brown, 150 = lred, 151 = grey1, 152 = grey2 +; 153 = lgreen, 154 = lblue, 155 = grey3, 156 = purple +; 158 = yellow, 159 = black + +forecolor = 5 ; (see table) if <5 -> no change +arrowcolor = 28 ; (see table) if <5 -> forecolor2 +buttoncolor = 28 ; (see table) if <5 -> no change + +} + +; - key settings +key_nexte = 17 ; next entry (cursor down) +key_preve = 145 ; prev entry (cursor up) +key_nextp = 29 ; next page (cursor right) +key_prevp = 157 ; prev page (cursor left) +key_nextp2 = 136 ; next page alt (F7) (255 = none) +key_prevp2 = 135 ; prev page alt (F5) (255 = none) + +key_fire = 13 ; select (enter) +key_fire2 = 141 ; select alt (CBM+enter) (IF startmode = 1, Target=16 or 64 only) +key_top = 139 ; to top (F6) +key_bottom = 140 ; to bottom (F8) +key_exit = 20 ; exit dir (backspc) +key_quit = 81 ; quit to basic (Q) + +key_sort = 83 ; sort dir (S) + +key_drive = 68 ; change drive (D) + +key_reset = 95 ; reset (<- ESC key) + + +; - load&run code position +; A safe RAM area in bank 0 that is not overwritten while KERNAL LOAD runs and +; that survives loading the target program (which loads at $2001 and upward). +; NOTE: the C64 tape-buffer address $0334 is NOT usable on the C65 - it holds +; live KERNAL keyboard-decode vectors ($0334 ctlvec ... $033E decode) and file +; tables ($034C+). The old C64 40-column screen area $0400-$07FF is free in +; native C65 mode (the editor screen lives at $0800), so use that. +loadrunpos = $0400 diff --git a/sources/x16.asm b/sources/x16.asm new file mode 100644 index 0000000..806493a --- /dev/null +++ b/sources/x16.asm @@ -0,0 +1,6 @@ + +; - user configuration +!src "x16.def" + +; - core code +!src "CBM-FileBrowser.asm" diff --git a/sources/x16.def b/sources/x16.def new file mode 100644 index 0000000..9cadf9c --- /dev/null +++ b/sources/x16.def @@ -0,0 +1,123 @@ +; --- x16.def - configuration for the Commander X16 +; +; Commander X16 target (target = 216) for CBM-FileBrowser. +; +; The X16 uses a C64-derived KERNAL (standard $FFxx jump table, BASIC at $0801) +; but its video is VERA: the text screen is in separate video RAM, NOT in the +; CPU address space. So this target does ALL drawing through the KERNAL screen +; editor (CHROUT/PLOT) - there is no direct screen-memory access, and fast +; scrolling (which relies on direct writes) is turned off. +; +; Build: acme --cpu 65c02 -f cbm -o fbx16.prg x16.asm +; Run : x16emu -prg fbx16.prg -run + +; - CBM target system +target = 216 ; 216 = Commander X16 + ; (20=VIC-20, 64=C64, 16=C264, 128=C128, 65=MEGA65) + +variant = 0 + + ; device number: 8 = the X16 SD-card / HostFS default drive +hwdevicenum = 0 ; a device number, 0 = autodetect from the last-used device (X16 SD default is 8) + +autodetectm = 0 + +drivechange = 1 ; change drive by pressing key_drive +rootonstart = 0 +rootentry = 1 +tap_support = 0 ; no tape on the X16 + +printbars = 1 +startmode = 1 + +; - functionality +minimal = 0 +!if minimal = 1 { +rememberpos = 0 +showcursors = 1 +clearscrena = 1 +fastscrolle = 0 +colorenable = 0 +disknameena = 0 +statusenabl = 0 +pleasewaite = 0 +sortdir = 0 +} else { +rememberpos = 1 +showcursors = 1 +clearscrena = 1 +fastscrolle = 0 ; MUST be 0 on the X16 - fast scroll needs direct screen + ; memory access, which VERA does not provide. The browser + ; falls back to a full CHROUT redraw on each move (fast + ; enough on the 8MHz X16). +colorenable = 1 +disknameena = 1 +statusenabl = 1 +pleasewaite = 1 +sortdir = 1 +} + +; - layout/cosmetic/etc +joyrepeat = 15 +rastercmp = 1 ; unused on the X16 (no $d012 raster); kept for the shared code + +; list location +!if printbars = 1 { +listtopy = 2 +listbottomy = 23 +} else { +listtopy = 1 +listbottomy = 25 +} + +listx = 9 +listbackgnd = 32 + +disknamey = 0 +disknamex = 9 + +statusy = listtopy +statusx = listx+namelen+2 + +!if colorenable = 0 { +backcolor = 255 +bordercolor = 255 +forecolor2 = 255 +forecolor = 0 +arrowcolor = 0 +buttoncolor = 0 +} else { +; back & fore2 (0..15). The X16 has no C64-style border, so bordercolor is +; ignored; backcolor is applied through the screen-clear colour. +backcolor = 6 ; blue +bordercolor = 255 ; no border on X16 -> ignore +forecolor2 = 1 ; white + +; foreground & arrow: PETSCII colour codes via CHROUT (same table as the C64) +forecolor = 5 ; white +arrowcolor = 28 ; red +buttoncolor = 28 ; red +} + +; - key settings (PETSCII, same as the C64) +key_nexte = 17 +key_preve = 145 +key_nextp = 29 +key_prevp = 157 +key_nextp2 = 136 +key_prevp2 = 135 + +key_fire = 13 +key_fire2 = 141 +key_top = 139 +key_bottom = 140 +key_exit = 20 +key_quit = 81 +key_sort = 83 +key_drive = 68 +key_reset = 95 + +; - load&run code position +; Golden RAM $0400-$07FF is free on the X16 (the screen is in VERA, not $0400) +; and survives loading a program (programs load at $0801 and upward). +loadrunpos = $0400