From cd7607e330bbbcd6ba0bfca4a0ef189b4b18606b Mon Sep 17 00:00:00 2001 From: Daniel Covington Date: Wed, 27 May 2026 07:26:19 -0400 Subject: [PATCH] vim testing --- .claude/settings.local.json | 13 +- samples/kernal-os-skeleton/build_all.bat | 40 + samples/kernal-os-skeleton/build_vim.bat | 15 + samples/kernal-os-skeleton/kernal_os.asm | 145 +++- samples/kernal-os-skeleton/kernal_os.d64 | Bin 0 -> 174848 bytes samples/kernal-os-skeleton/kernal_os.o | Bin 35654 -> 37565 bytes samples/kernal-os-skeleton/kernal_os.prg | Bin 4317 -> 4577 bytes samples/kernal-os-skeleton/run.bat | 16 + samples/kernal-os-skeleton/vim.asm | 907 +++++++++++++++++++++++ samples/kernal-os-skeleton/vim.cfg | 11 + samples/kernal-os-skeleton/vim.o | Bin 0 -> 12932 bytes samples/kernal-os-skeleton/vim.prg | Bin 0 -> 1369 bytes 12 files changed, 1140 insertions(+), 7 deletions(-) create mode 100644 samples/kernal-os-skeleton/build_all.bat create mode 100644 samples/kernal-os-skeleton/build_vim.bat create mode 100644 samples/kernal-os-skeleton/kernal_os.d64 create mode 100644 samples/kernal-os-skeleton/run.bat create mode 100644 samples/kernal-os-skeleton/vim.asm create mode 100644 samples/kernal-os-skeleton/vim.cfg create mode 100644 samples/kernal-os-skeleton/vim.o create mode 100644 samples/kernal-os-skeleton/vim.prg diff --git a/.claude/settings.local.json b/.claude/settings.local.json index 46b187e..4984c7c 100644 --- a/.claude/settings.local.json +++ b/.claude/settings.local.json @@ -2,7 +2,18 @@ "permissions": { "allow": [ "Bash(build.bat)", - "PowerShell(Copy-Item \"c:\\\\Development\\\\Commodore\\\\os Experiments\\\\c64os\\\\samples\\\\cc65-mouse-driver-demo\\\\mousedemo.c\" \"c:\\\\Development\\\\Commodore\\\\os Experiments\\\\c64os\\\\samples\\\\cc65-mouse-driver-demo\\\\mouse_driver_demo.c\" -Force)" + "PowerShell(Copy-Item \"c:\\\\Development\\\\Commodore\\\\os Experiments\\\\c64os\\\\samples\\\\cc65-mouse-driver-demo\\\\mousedemo.c\" \"c:\\\\Development\\\\Commodore\\\\os Experiments\\\\c64os\\\\samples\\\\cc65-mouse-driver-demo\\\\mouse_driver_demo.c\" -Force)", + "PowerShell($f = \"c:\\\\Development\\\\Commodore\\\\os Experiments\\\\c64os\\\\samples\\\\kernal-os-skeleton\\\\kernal_os.prg\"; \\(Get-Item $f\\).Length)", + "PowerShell($output = & \"C:\\\\Program Files\\\\GTK3VICE-3.10-win64\\\\bin\\\\x64sc.exe\" -help 2>&1; $output | Where-Object { $_ -match \"device|fs|drive|disk\" } | Select-Object -First 40)", + "PowerShell(cmd /c \"cd /d `\"c:\\\\Development\\\\Commodore\\\\os Experiments\\\\c64os\\\\samples\\\\kernal-os-skeleton`\" && build_all.bat\" 2>&1)", + "Bash(cmd.exe /c build_all.bat)", + "Bash(cmd.exe /c \"build_all.bat\")", + "Bash(echo \"exit: $?\")", + "Bash(cmd.exe /c \"ca65 kernal_os.asm -o kernal_os.o && ld65 -C kernal_os.cfg kernal_os.o -o kernal_os.prg && echo kernal_os OK\")", + "Bash(ca65 \"c:/Development/Commodore/os Experiments/c64os/samples/kernal-os-skeleton/kernal_os.asm\" -o \"c:/Development/Commodore/os Experiments/c64os/samples/kernal-os-skeleton/kernal_os.o\")", + "Bash(cmd /c build_all.bat)", + "Bash(cmd /c \"build_all.bat && echo BUILD_OK || echo BUILD_FAILED\")", + "Bash(echo \"EXIT: $?\")" ] } } diff --git a/samples/kernal-os-skeleton/build_all.bat b/samples/kernal-os-skeleton/build_all.bat new file mode 100644 index 0000000..7580c71 --- /dev/null +++ b/samples/kernal-os-skeleton/build_all.bat @@ -0,0 +1,40 @@ +@echo off +setlocal + +set "C1541=C:\Program Files\GTK3VICE-3.10-win64\bin\c1541.exe" +set "DISK=kernal_os.d64" + +rem ---- build kernal_os.prg ---- +call build.bat +if errorlevel 1 goto error + +rem ---- build vim.prg ---- +call build_vim.bat +if errorlevel 1 goto error + +rem ---- verify c1541 ---- +if not exist "%C1541%" ( + echo c1541.exe not found at: + echo %C1541% + exit /b 1 +) + +rem ---- create fresh D64 and write both PRGs ---- +"%C1541%" -format "kernal os,01" d64 "%DISK%" +if errorlevel 1 goto error + +"%C1541%" "%DISK%" -write "kernal_os.prg" "kernal_os" +if errorlevel 1 goto error + +"%C1541%" "%DISK%" -write "vim.prg" "vim" +if errorlevel 1 goto error + +echo. +echo built %DISK% (kernal_os + vim) +goto end + +:error +echo build failed. +exit /b 1 + +:end diff --git a/samples/kernal-os-skeleton/build_vim.bat b/samples/kernal-os-skeleton/build_vim.bat new file mode 100644 index 0000000..4adf7a2 --- /dev/null +++ b/samples/kernal-os-skeleton/build_vim.bat @@ -0,0 +1,15 @@ +@echo off + +ca65 vim.asm -o vim.o +if errorlevel 1 goto error + +ld65 -C vim.cfg vim.o -o vim.prg +if errorlevel 1 goto error + +echo built vim.prg successfully. +goto end + +:error +echo build failed. + +:end diff --git a/samples/kernal-os-skeleton/kernal_os.asm b/samples/kernal-os-skeleton/kernal_os.asm index 956da72..712b0ea 100644 --- a/samples/kernal-os-skeleton/kernal_os.asm +++ b/samples/kernal-os-skeleton/kernal_os.asm @@ -34,6 +34,7 @@ CHKOUT = $FFC9 CLRCH = $FFCC BASIN = $FFCF CLALL = $FFE7 +LOAD = $FFD5 ; ------------------------------------------------------------ ; system locations @@ -55,6 +56,7 @@ INPUT_MAX = 64 DISK_DEV = 8 LFN_DIR = 2 LFN_CMD = 15 +EXEC_AREA = $2000 SYS_ENTRY = 2061 ; ------------------------------------------------------------ @@ -1171,12 +1173,137 @@ check_exit: jmp request_exit command_unknown: - lda #msg_unknown + jmp do_exec + +command_empty: + rts + +; ------------------------------------------------------------ +; external program loader +; ------------------------------------------------------------ +; When the typed word does not match any built-in command, +; search the current disk device for a PRG file with that name. +; If found, load it to EXEC_AREA ($2000) and JSR there. +; The external program should end with RTS to return to the shell. +; All external programs must be assembled for address $2000. +; ------------------------------------------------------------ + +do_exec: + jsr build_exec_filename + bcc exec_try_load + jmp exec_not_found + +exec_try_load: + jsr reset_file_state + + lda #LFN_DIR + sta active_lfn + ldx current_device + ldy #1 + jsr SETLFS + + lda filename_len + ldx #filename_spec + jsr SETNAM + + lda #0 + ldx #EXEC_AREA + jsr LOAD + bcc exec_loaded + + jsr reset_file_state + jmp exec_not_found + +exec_loaded: + jsr reset_file_state + jsr set_os_memory + + lda #msg_exec_run jsr print_string + + ldy #0 +exec_print_name: + lda input_buffer,y + beq exec_print_done + cmp #' ' + beq exec_print_done + jsr CHROUT + iny + bne exec_print_name + +exec_print_done: + lda #CR + jsr CHROUT + + lda #EXEC_AREA + sta PTR1_HI + jsr call_indirect + jsr set_os_memory rts -command_empty: +exec_not_found: + lda #msg_exec_nf + jsr print_string + + ldy #0 +exec_nf_name: + lda input_buffer,y + beq exec_nf_done + cmp #' ' + beq exec_nf_done + jsr CHROUT + iny + bne exec_nf_name + +exec_nf_done: + lda #CR + jsr CHROUT + rts + +; JMP (PTR1) — turns a JSR into an indirect call. +; Caller does: JSR call_indirect +; The called code's RTS returns to call_indirect's caller. +call_indirect: + jmp (PTR1_LO) + +; build filename_spec = "{drive}:{cmdname}" from input_buffer word 0 +build_exec_filename: + ldx #0 + lda current_drive + clc + adc #'0' + sta filename_spec,x + inx + lda #':' + sta filename_spec,x + inx + + ldy #0 + +exec_copy_name: + lda input_buffer,y + beq exec_name_done + cmp #' ' + beq exec_name_done + sta filename_spec,x + inx + iny + cpx #35 + bcc exec_copy_name + sec + rts + +exec_name_done: + stx filename_len + lda #0 + sta filename_spec,x + clc rts ; ------------------------------------------------------------ @@ -1958,9 +2085,6 @@ msg_banner: msg_prompt: .byte "OS> ", 0 -msg_unknown: - .byte "UNKNOWN. HELP", CR, 0 - msg_help: .byte CR .byte "HELP MEM INC DUMP ZERO SIGN", CR @@ -1969,6 +2093,7 @@ msg_help: .byte "HEX RUN RENAME COPY", CR .byte "DEVICE DEV DRIVE DEL ERASE", CR .byte "ABOUT EXIT", CR + .byte "OTHER: LOAD+RUN PRG AT $2000", CR .byte CR .byte 0 @@ -2003,6 +2128,8 @@ msg_about: .byte "KERNAL STAYS MAPPED IN.", CR .byte "SHELL CODE STARTS AT $080D.", CR .byte "USE $A000-$BFFF AS WORK RAM.", CR + .byte "EXTERNAL CMDS LOAD AT $2000.", CR + .byte "ASSEMBLE CMDS WITH *=$2000.", CR .byte CR .byte 0 @@ -2178,6 +2305,12 @@ msg_copy: msg_copy_usage: .byte "USAGE: COPY srcname dstname", CR, 0 +msg_exec_run: + .byte "EXEC: ", 0 + +msg_exec_nf: + .byte "? ", 0 + .segment "BSS" workspace_counter: diff --git a/samples/kernal-os-skeleton/kernal_os.d64 b/samples/kernal-os-skeleton/kernal_os.d64 new file mode 100644 index 0000000000000000000000000000000000000000..1a1425aeff1e07c36630ed9234796eeaa69df7f6 GIT binary patch literal 174848 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 literal 0 HcmV?d00001 diff --git a/samples/kernal-os-skeleton/kernal_os.o b/samples/kernal-os-skeleton/kernal_os.o index 0c664a20f34c78d3e78281c0a960c7bb277a1aa7..11d0623a97714ee9f4f6778989fd731c594564f4 100644 GIT binary patch literal 37565 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 diff --git a/samples/kernal-os-skeleton/kernal_os.prg b/samples/kernal-os-skeleton/kernal_os.prg index 5b3d2d443a9cf3843b3df7e9660d898290422bae..2c09c37df7147328c603e1dc3f773328207b4b7b 100644 GIT binary patch literal 4577 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 literal 4317 zcmbVPeQZtl`!)7V_VxH=q9!C#Hhul?hn2Ug%B#1TENg$(7bc* zdoOWGVcnwW-E+^^Js-bwZ&K%L^aa>2)`UAFj4^nn3j3?@!z#R|z*rEr<8R1V;e(AK zcs-Oqr&bmjM-*86ut%ayoXobtuFxBGFxVRjx zFIV_Sbw6xx6`N7#XGA!svdkqF);437qCRt8J@PcqGI*<+_wk%R%i&lRPE;or8GluB z_3$oH*A+bevYPo&h4-tOvix3D^JP`Js8*85!{7WRwXz!5%9_j`Ui@-J&3~v?KF(iO zON&Jv8t3Vy5&<=)LMtMP|17zh3EcCheu_;;|-B_7Ex z#rDB{;>llCb2C|WfddhdX13$#d(G%*^8!a+7wSK=3r-|r*Sw=JoMNjcLzwea>4wZVALW%sXbR=KIo5aa!?t*R-nbu(=0Z1_eg;?W-m#8QurH;UyReYH`5M~^j$$7|>(Jv!5bca!TA0%Bbay%A{{!ylSNuSb8< zBnCX4kb)R?ZEZz-&7+ShVzu)U*>BXX`j@}q)jEe*f&{jTW$_im{^0|JF91C$SJcc^ zHRI!%2+yqHnYA1NpOJS$CdxDGd1hJ_KAahR@@#x3k1w07%T^Z6l>SLOyx!Cz(DoM5 zO+_dXec+0!+EM%P74=O|W2$tEXsLnpYtvE#A6RR0MxDv8mi={N6{ zj*zq;r8(xt;O7(re&=F9daC@GjKRlM`-qR1A1}0$$^mzef%#Dq#gd35#k?S&X<3ON z*2>MPZDKZRi)U(*tr0#-!uf>JYy9(hZJzhKAOxow_df;m#WF@XwP{5$Jn>kuyYOiA zS{PA*S788=5eTR|)^c?R!X(0{N*_?hXo4{5=2@)0k_8WmKj{|$&t^AY9C%thogO+Jw>j*NN_^1IF9|3-PDMU z6F0Ej-JDLQ?-SWJV^`?j8$FMJ#TRKc-o8#Dkg(;SYIuLNqQR?oUb&lPzqwOsLdo=< z(#`3+#_kX~9p`Ydir3Lm1uj=BH;YQ;iDFx2>5*|>-dMN{$6N96SyaNmrG6U9kMm0D z)HoMy&K|X7bk2oGhoHyZ{K#&O^MUWHJhJ64dw8i053QfRJG+}3(;-J*si%rQ$Vi4{l-9L&Bx08f+v&{vyaCX^o2OhJ1%8jb*rn8`tCkA=fw1r3Lx z&rCvmsMk^yW?CD7r4xe*b0pCLBvqKBG^7oIo`^$ldT1ENw4@1^-k(sccv906(5olG zO2txX3zhT~#0^W);sYk6%yfJJQlrBf7-p;&tk@tz^L68So)ZTK`U+>%s#+0`?VCZs3m&L(8u&d|2!A% zVyXB5@%nT_LzK+P(pIb=oly&(-?n}03(xM@3J4O}jyVn{jLnaw$bmLAoEp8K8wUfP zBZax%B|dg;-L+G?Ca}oO28j`Q%ABgi&jJS$Pz$((u$mZ232V%VjSCP=EQP_!6e2Jl zOCd95LQlG{PeTY}4Oc15-N~dnfXXkA>eG`}szYI3UFWJKksEy~vW_w#1QWebPr^DZ zbtH+9>D8@4Fo$u1v}6*E+Z~Rc7$(HKEYl)@GdPhV#m>S_pocS4Q(nHNyL0 zb2pAeI*}j@w8tWNqcBBkJpfhi)PH~b7Ky7Dw!TCwp$Yvyz>dW5;t!saR$E@&=~(>- DfJi0D diff --git a/samples/kernal-os-skeleton/run.bat b/samples/kernal-os-skeleton/run.bat new file mode 100644 index 0000000..e771423 --- /dev/null +++ b/samples/kernal-os-skeleton/run.bat @@ -0,0 +1,16 @@ +@echo off +setlocal + +set "VICE_EXE=C:\Program Files\GTK3VICE-3.10-win64\bin\x64sc.exe" +set "DISK=kernal_os.d64" + +if not exist "%VICE_EXE%" ( + echo VICE x64sc was not found at: + echo %VICE_EXE% + exit /b 1 +) + +call build_all.bat +if errorlevel 1 exit /b 1 + +"%VICE_EXE%" -autostart "%CD%\%DISK%" diff --git a/samples/kernal-os-skeleton/vim.asm b/samples/kernal-os-skeleton/vim.asm new file mode 100644 index 0000000..c74a9bc --- /dev/null +++ b/samples/kernal-os-skeleton/vim.asm @@ -0,0 +1,907 @@ +; +; vim.asm - minimal modal text editor for the kernal-os-skeleton shell +; +; Build: +; ca65 vim.asm -o vim.o +; ld65 -C vim.cfg vim.o -o vim.prg +; +; From the OS shell type: VIM +; All external commands load at $2000 and end with RTS. +; +; Modes +; NORMAL (default) h j k l or cursor keys = move +; i = insert before cursor +; a = append after cursor +; o = open line below +; x = delete char under cursor +; : = enter command mode +; INSERT type text, DEL = backspace, RUN/STOP = back to NORMAL +; COMMAND :q quit :w NAME save to disk +; RUN/STOP = cancel +; +; Text model: the 24x40 text area of screen RAM IS the buffer. +; Row 24 (bottom line) is the status bar. +; + +.setcpu "6502" + +; ---- KERNAL ---- +GETIN = $FFE4 +STOPKEY = $FFE1 +CHROUT = $FFD2 +SETLFS = $FFBA +SETNAM = $FFBD +OPEN = $FFC0 +CLOSE = $FFC3 +CHKOUT = $FFC9 +CLRCH = $FFCC +CLALL = $FFE7 + +; ---- hardware ---- +SCRRAM = $0400 + +; ---- layout ---- +SCR_COLS = 40 +SCR_ROWS = 24 ; rows 0-23 = text, row 24 = status bar + +; ---- modes ---- +MODE_NORMAL = 0 +MODE_INSERT = 1 +MODE_CMD = 2 + +; ---- PETSCII ---- +CR_CH = $0D +DEL_CH = $14 + +; ---- command buffer ---- +CMD_MAX = 20 + +; ---- save LFN ---- +SAVE_LFN = 5 +SAVE_DEV = 8 + +; ---- zero page (user area, safe under OS banking) ---- +ZP_LO = $FB ; general destination pointer lo +ZP_HI = $FC ; general destination pointer hi +STR_LO = $FD ; string source pointer lo +STR_HI = $FE ; string source pointer hi +ZP_TMP = $02 ; scratch byte + +; ================================================================ +; PRG load address header +; ================================================================ +.segment "LOADADDR" + .word $2000 + +; ================================================================ +; CODE +; ================================================================ +.segment "CODE" + +; ---- entry ---- +vim_main: + jsr CLALL ; close any open channels from shell + jsr vim_init + jsr full_redraw + +main_loop: + lda quit_flag + beq ml_no_quit + jmp vim_do_exit +ml_no_quit: + + jsr get_key ; waits for keypress; $FF = RUN/STOP + cmp #$FF + bne ml_key_ok + ; RUN/STOP pressed + lda cur_mode + beq ml_stop_quit ; normal mode: quit + lda #MODE_NORMAL ; other modes: back to normal + sta cur_mode + jsr full_redraw + jmp main_loop +ml_stop_quit: + lda #1 + sta quit_flag + jmp main_loop +ml_key_ok: + sta last_key + lda cur_mode + cmp #MODE_INSERT + bne ml_not_insert + jmp handle_insert +ml_not_insert: + cmp #MODE_CMD + bne ml_not_cmd + jmp handle_cmd +ml_not_cmd: + ; fall through = normal mode + +; ================================================================ +; NORMAL MODE +; ================================================================ +handle_normal: + lda last_key + cmp #'H' + beq nm_left + cmp #$9D ; cursor-left hardware key + beq nm_left + cmp #'L' + beq nm_right + cmp #$1D ; cursor-right hardware key + beq nm_right + cmp #'K' + beq nm_up + cmp #$91 ; cursor-up hardware key + beq nm_up + cmp #'J' + beq nm_down + cmp #$11 ; cursor-down hardware key + beq nm_down + cmp #'I' + beq nm_ins + cmp #'A' + beq nm_app + cmp #'X' + beq nm_del + cmp #'O' + beq nm_open + cmp #':' + beq nm_cmd + jmp nm_done +nm_left: + jsr cursor_left + jmp nm_done +nm_right: + jsr cursor_right + jmp nm_done +nm_up: + jsr cursor_up + jmp nm_done +nm_down: + jsr cursor_down + jmp nm_done +nm_ins: + lda #MODE_INSERT + sta cur_mode + jmp nm_done +nm_app: + jsr cursor_right + lda #MODE_INSERT + sta cur_mode + jmp nm_done +nm_del: + jsr delete_char + jmp nm_done +nm_open: + jsr open_line_below + lda #MODE_INSERT + sta cur_mode + jmp nm_done +nm_cmd: + lda #MODE_CMD + sta cur_mode + lda #0 + sta cmd_len +nm_done: + jsr full_redraw + jmp main_loop + +; ================================================================ +; INSERT MODE +; ================================================================ +handle_insert: + lda last_key + cmp #CR_CH + beq ins_nl + cmp #DEL_CH + beq ins_bs + cmp #$20 ; ignore control chars below $20 + bcc ins_done + cmp #$7F + bcs ins_done + jsr insert_char ; A = PETSCII char to insert + jsr cursor_right + jmp ins_done +ins_nl: + jsr do_newline + jmp ins_done +ins_bs: + jsr backspace_char +ins_done: + jsr full_redraw + jmp main_loop + +; ================================================================ +; COMMAND MODE +; ================================================================ +handle_cmd: + lda last_key + cmp #CR_CH + beq cmd_exec + cmp #DEL_CH + beq cmd_bs + cmp #$20 + bcc cmd_done + cmp #$7F + bcs cmd_done + ldx cmd_len + cpx #CMD_MAX + bcs cmd_done + sta cmd_buf,x + inc cmd_len + jmp cmd_done +cmd_bs: + lda cmd_len + beq cmd_done + dec cmd_len + jmp cmd_done +cmd_exec: + jsr run_cmd +cmd_done: + jsr full_redraw + jmp main_loop + +; ================================================================ +; EXIT +; ================================================================ +vim_do_exit: + jsr restore_cursor ; de-invert cursor char before leaving + rts ; return to kernal-os-skeleton shell + +; ================================================================ +; COMMAND EXECUTION +; ================================================================ +run_cmd: + lda cmd_len + beq rc_cancel + + ; --- :Q quit --- + cmp #1 + bne rc_not_q + lda cmd_buf + cmp #'Q' + bne rc_not_q + lda #1 + sta quit_flag + lda #MODE_NORMAL + sta cur_mode + rts + +rc_not_q: + ; --- :W [NAME] save --- + lda cmd_buf + cmp #'W' + bne rc_unknown + jsr do_save + lda #MODE_NORMAL + sta cur_mode + rts + +rc_unknown: + ; show "?" in status then return to normal + lda #msg_cmd_err + jsr show_status_text +rc_cancel: + lda #MODE_NORMAL + sta cur_mode + rts + +; ================================================================ +; FILE SAVE +; do_save: reads cmd_buf "W NAME" and writes text to disk +; ================================================================ +do_save: + ; need at least "W N" (3 chars: W, space, one char of name) + lda cmd_len + cmp #3 + bcs ds_len_ok + jmp ds_no_name +ds_len_ok: + lda cmd_buf + 1 + cmp #' ' + beq ds_space_ok + jmp ds_no_name +ds_space_ok: + + ; copy filename from cmd_buf[2..] to save_fn + ldy #2 + ldx #0 +ds_copy_name: + lda cmd_buf,y + beq ds_name_done + cmp #' ' + beq ds_name_done + sta save_fn,x + inx + iny + cpx #15 + bcc ds_copy_name +ds_name_done: + stx save_fn_len + lda #0 + sta save_fn,x + + ; build "0:NAME,S,W" in full_fn + jsr build_save_fname + + ; SETLFS + lda #SAVE_LFN + ldx #SAVE_DEV + ldy #2 + jsr SETLFS + + ; SETNAM + lda full_fn_len + ldx #full_fn + jsr SETNAM + + jsr OPEN + bcc ds_open_ok + ; open error + lda #msg_disk_err + jsr show_status_text + rts + +ds_open_ok: + lda #SAVE_LFN + jsr CHKOUT + bcc ds_write_rows + jsr CLRCH + lda #SAVE_LFN + jsr CLOSE + lda #msg_disk_err + jsr show_status_text + rts + +ds_write_rows: + lda #0 + sta save_row + +ds_row_loop: + ldx save_row + lda row_lo,x + sta ZP_LO + lda row_hi,x + sta ZP_HI + + ; find rightmost non-space column + ldy #SCR_COLS - 1 +ds_find_end: + lda (ZP_LO),y + cmp #$20 + bne ds_row_found + tya + beq ds_row_empty + dey + jmp ds_find_end + +ds_row_empty: + ; empty row: just write CR + lda #CR_CH + jsr CHROUT + jmp ds_row_done + +ds_row_found: + ; write cols 0..Y then CR + sty save_col_end + ldy #0 +ds_write_col: + lda (ZP_LO),y + jsr screen_to_petscii + jsr CHROUT + cpy save_col_end + beq ds_write_cr + iny + jmp ds_write_col + +ds_write_cr: + lda #CR_CH + jsr CHROUT + +ds_row_done: + inc save_row + lda save_row + cmp #SCR_ROWS + bne ds_row_loop + + ; close + jsr CLRCH + lda #SAVE_LFN + jsr CLOSE + + lda #msg_saved + jsr show_status_text + rts + +ds_no_name: + lda #msg_need_name + jsr show_status_text + rts + +; builds "0:save_fn,S,W" into full_fn, length into full_fn_len +build_save_fname: + ldx #0 + lda #'0' + sta full_fn,x + inx + lda #':' + sta full_fn,x + inx + ldy #0 +bsf_loop: + lda save_fn,y + beq bsf_suffix + sta full_fn,x + inx + iny + bne bsf_loop +bsf_suffix: + lda #',' + sta full_fn,x + inx + lda #'S' + sta full_fn,x + inx + lda #',' + sta full_fn,x + inx + lda #'W' + sta full_fn,x + inx + stx full_fn_len + lda #0 + sta full_fn,x + rts + +; ================================================================ +; CURSOR MOVEMENT +; ================================================================ +cursor_left: + lda cur_col + beq cl_wrap + dec cur_col + rts +cl_wrap: + lda cur_row + beq cl_top + dec cur_row + lda #SCR_COLS - 1 + sta cur_col +cl_top: rts + +cursor_right: + lda cur_col + cmp #SCR_COLS - 1 + bcs cr_wrap + inc cur_col + rts +cr_wrap: + lda cur_row + cmp #SCR_ROWS - 1 + bcs cr_bot + inc cur_row + lda #0 + sta cur_col +cr_bot: rts + +cursor_up: + lda cur_row + beq cu_top + dec cur_row +cu_top: rts + +cursor_down: + lda cur_row + cmp #SCR_ROWS - 1 + bcs cd_bot + inc cur_row +cd_bot: rts + +; ================================================================ +; TEXT EDITING +; ================================================================ + +; Set ZP_LO/ZP_HI to the screen RAM base for cur_row +row_ptr: + ldx cur_row + lda row_lo,x + sta ZP_LO + lda row_hi,x + sta ZP_HI + rts + +; Insert PETSCII char (in A) at cursor; shift rest of line right (last char lost) +insert_char: + jsr petscii_to_screen + sta ZP_TMP + jsr row_ptr + ldy #SCR_COLS - 1 +ic_shift: + cpy cur_col + beq ic_write + dey + lda (ZP_LO),y + iny + sta (ZP_LO),y + dey + jmp ic_shift +ic_write: + lda ZP_TMP + ldy cur_col + sta (ZP_LO),y + rts + +; Delete char at cursor; shift rest of line left, fill end with space +delete_char: + jsr row_ptr + ldy cur_col +dc_shift: + cpy #SCR_COLS - 1 + beq dc_space + iny + lda (ZP_LO),y + dey + sta (ZP_LO),y + iny + jmp dc_shift +dc_space: + lda #$20 + sta (ZP_LO),y + rts + +; Backspace: move cursor left then delete +backspace_char: + lda cur_col + beq bs_done + jsr cursor_left + jsr delete_char +bs_done:rts + +; RETURN in insert mode: move to col 0 of next row +do_newline: + lda cur_row + cmp #SCR_ROWS - 1 + bcs nl_done + inc cur_row + lda #0 + sta cur_col +nl_done:rts + +; Open new line below: advance row, clear it, col = 0 +open_line_below: + lda cur_row + cmp #SCR_ROWS - 1 + bcs ol_done + inc cur_row + lda #0 + sta cur_col + jsr clear_current_row +ol_done:rts + +clear_current_row: + jsr row_ptr + ldy #0 + lda #$20 +ccr_lp: sta (ZP_LO),y + iny + cpy #SCR_COLS + bne ccr_lp + rts + +; Clear all 24 text rows to spaces +clear_text: + lda #0 + sta ZP_TMP +ct_loop: + ldx ZP_TMP + lda row_lo,x + sta ZP_LO + lda row_hi,x + sta ZP_HI + ldy #0 + lda #$20 +ct_row: sta (ZP_LO),y + iny + cpy #SCR_COLS + bne ct_row + inc ZP_TMP + lda ZP_TMP + cmp #SCR_ROWS + bne ct_loop + rts + +; ================================================================ +; SCREEN RENDERING +; ================================================================ + +; Restore the saved char at (prev_row, prev_col) +restore_cursor: + ldx prev_row + lda row_lo,x + clc + adc prev_col + sta ZP_LO + lda row_hi,x + adc #0 + sta ZP_HI + lda prev_char + ldy #0 + sta (ZP_LO),y + rts + +; Show cursor by inverting char at (cur_row, cur_col); saves old char +show_cursor: + ldx cur_row + lda row_lo,x + clc + adc cur_col + sta ZP_LO + lda row_hi,x + adc #0 + sta ZP_HI + ldy #0 + lda (ZP_LO),y + sta prev_char + ora #$80 ; set bit 7 = reversed character + sta (ZP_LO),y + lda cur_row + sta prev_row + lda cur_col + sta prev_col + rts + +; Draw status bar at row 24 +draw_status: + ; clear status row + lda row_lo + 24 + sta ZP_LO + lda row_hi + 24 + sta ZP_HI + ldy #0 + lda #$20 +dstat_clr: + sta (ZP_LO),y + iny + cpy #SCR_COLS + bne dstat_clr + + lda cur_mode + cmp #MODE_INSERT + beq dstat_ins + cmp #MODE_CMD + beq dstat_cmd + + ; NORMAL + lda #str_normal + jsr write_str_to_status + rts + +dstat_ins: + lda #str_insert + jsr write_str_to_status + rts + +dstat_cmd: + ; write ":" then cmd_buf + lda row_lo + 24 + sta ZP_LO + lda row_hi + 24 + sta ZP_HI + lda #$3A ; screen code for ':' + ldy #0 + sta (ZP_LO),y + iny + ldx #0 +dstat_cmd_lp: + cpx cmd_len + beq dstat_done + lda cmd_buf,x + jsr petscii_to_screen + sta (ZP_LO),y + iny + inx + cpy #SCR_COLS + bcc dstat_cmd_lp +dstat_done: + rts + +; Write null-terminated PETSCII string (A=lo, Y=hi) to status row +write_str_to_status: + sta STR_LO + sty STR_HI + lda row_lo + 24 + sta ZP_LO + lda row_hi + 24 + sta ZP_HI + ldy #0 +wss_lp: + lda (STR_LO),y + beq wss_done + jsr petscii_to_screen + sta (ZP_LO),y + iny + cpy #SCR_COLS + bcc wss_lp +wss_done: + rts + +; Copy a PETSCII string directly to status (no screen-code conversion) +; Used for messages that already have screen codes (msg_saved etc.) +; Actually we just reuse write_str_to_status since it converts +show_status_text: + jsr write_str_to_status + rts + +; Restore cursor, redraw cursor, redraw status bar +full_redraw: + jsr restore_cursor + jsr show_cursor + jsr draw_status + rts + +; ================================================================ +; INIT +; ================================================================ +vim_init: + lda #0 + sta cur_row + sta cur_col + sta prev_row + sta prev_col + sta cur_mode + sta cmd_len + sta quit_flag + sta save_row + sta save_col_end + lda #$20 ; cursor starts on a space + sta prev_char + jsr clear_text + rts + +; ================================================================ +; KEY INPUT +; ================================================================ +get_key: +gk_loop: + jsr STOPKEY + bne gk_getin + lda #$FF ; RUN/STOP = special exit code + rts +gk_getin: + jsr GETIN + beq gk_loop ; no key yet, keep polling + rts + +; ================================================================ +; CHARACTER CONVERSION +; ================================================================ + +; PETSCII → screen code +; $41-$5A (A-Z unshifted) → $01-$1A (subtract $40) +; $61-$7A (a-z lowercase) → $01-$1A (subtract $60) +; $20-$3F (space,nums,punct) → same +; others: pass through +petscii_to_screen: + cmp #$41 + bcc pts_pass + cmp #$5B + bcc pts_upper + cmp #$61 + bcc pts_pass + cmp #$7B + bcc pts_lower +pts_pass: + rts +pts_upper: + sec + sbc #$40 + rts +pts_lower: + sec + sbc #$60 + rts + +; screen code → PETSCII (inverse of above) +; $01-$1A → $41-$5A (add $40) +; $20-$3F → same +; $00 → '@' +; others: return space $20 +screen_to_petscii: + cmp #$01 + bcc stp_at + cmp #$1B + bcc stp_letter + cmp #$20 + bcc stp_space + cmp #$40 + bcc stp_pass +stp_space: + lda #$20 + rts +stp_at: + lda #$40 ; '@' + rts +stp_letter: + clc + adc #$40 + rts +stp_pass: + rts + +; ================================================================ +; RODATA +; ================================================================ +.segment "RODATA" + +str_normal: + .byte "NORMAL (hjkl=move i=ins x=del :=cmd)", 0 + +str_insert: + .byte "INSERT (type text, DEL=bksp, STOP=normal)", 0 + +msg_cmd_err: + .byte "? unknown command", 0 + +msg_saved: + .byte "saved.", 0 + +msg_disk_err: + .byte "disk error.", 0 + +msg_need_name: + .byte "usage: :w filename", 0 + +; Row-base lookup tables (25 entries: rows 0-23 = text, row 24 = status) +row_lo: + .byte <(SCRRAM + 0*40), <(SCRRAM + 1*40), <(SCRRAM + 2*40) + .byte <(SCRRAM + 3*40), <(SCRRAM + 4*40), <(SCRRAM + 5*40) + .byte <(SCRRAM + 6*40), <(SCRRAM + 7*40), <(SCRRAM + 8*40) + .byte <(SCRRAM + 9*40), <(SCRRAM + 10*40), <(SCRRAM + 11*40) + .byte <(SCRRAM + 12*40), <(SCRRAM + 13*40), <(SCRRAM + 14*40) + .byte <(SCRRAM + 15*40), <(SCRRAM + 16*40), <(SCRRAM + 17*40) + .byte <(SCRRAM + 18*40), <(SCRRAM + 19*40), <(SCRRAM + 20*40) + .byte <(SCRRAM + 21*40), <(SCRRAM + 22*40), <(SCRRAM + 23*40) + .byte <(SCRRAM + 24*40) + +row_hi: + .byte >(SCRRAM + 0*40), >(SCRRAM + 1*40), >(SCRRAM + 2*40) + .byte >(SCRRAM + 3*40), >(SCRRAM + 4*40), >(SCRRAM + 5*40) + .byte >(SCRRAM + 6*40), >(SCRRAM + 7*40), >(SCRRAM + 8*40) + .byte >(SCRRAM + 9*40), >(SCRRAM + 10*40), >(SCRRAM + 11*40) + .byte >(SCRRAM + 12*40), >(SCRRAM + 13*40), >(SCRRAM + 14*40) + .byte >(SCRRAM + 15*40), >(SCRRAM + 16*40), >(SCRRAM + 17*40) + .byte >(SCRRAM + 18*40), >(SCRRAM + 19*40), >(SCRRAM + 20*40) + .byte >(SCRRAM + 21*40), >(SCRRAM + 22*40), >(SCRRAM + 23*40) + .byte >(SCRRAM + 24*40) + +; ================================================================ +; BSS (zero-initialised by the OS / KERNAL CINT on cold start; +; vim_init zeros what it cares about explicitly) +; ================================================================ +.segment "BSS" + +cur_row: .res 1 +cur_col: .res 1 +prev_row: .res 1 +prev_col: .res 1 +prev_char: .res 1 ; screen code saved before cursor inversion +cur_mode: .res 1 +cmd_len: .res 1 +cmd_buf: .res CMD_MAX + 1 +last_key: .res 1 +quit_flag: .res 1 +save_row: .res 1 +save_col_end: .res 1 +save_fn: .res 16 ; extracted filename (no path) +save_fn_len: .res 1 +full_fn: .res 24 ; "0:filename,S,W" +full_fn_len: .res 1 diff --git a/samples/kernal-os-skeleton/vim.cfg b/samples/kernal-os-skeleton/vim.cfg new file mode 100644 index 0000000..93b7bfc --- /dev/null +++ b/samples/kernal-os-skeleton/vim.cfg @@ -0,0 +1,11 @@ +MEMORY { + LOADADDR: start = $1FFE, size = $0002, type = ro, file = %O; + MAIN: start = $2000, size = $7FFF, type = rw, file = %O; +} + +SEGMENTS { + LOADADDR: load = LOADADDR, type = ro; + CODE: load = MAIN, type = ro; + RODATA: load = MAIN, type = ro; + BSS: load = MAIN, type = bss, define = yes; +} diff --git a/samples/kernal-os-skeleton/vim.o b/samples/kernal-os-skeleton/vim.o new file mode 100644 index 0000000000000000000000000000000000000000..8719f2057b6f00ed5d055020a0e7ddc683de0cf6 GIT binary patch literal 12932 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 S<#xN=DM_u9TDQi7@BaZuHrdbs literal 0 HcmV?d00001 diff --git a/samples/kernal-os-skeleton/vim.prg b/samples/kernal-os-skeleton/vim.prg new file mode 100644 index 0000000000000000000000000000000000000000..a5ee53c8e36dded4fdf01e882f70e0eff091b684 GIT binary patch literal 1369 zcmY*ZUuauZ7{9$qyQW>&txOvb<;zWuX|bD~ii|*9iw-uuu5%qGUH^FE8rRq+DNWK= z1RY{952oC{&4lFjRP?(N!n;C|=#o!@u9 zf9IU50Q_phsSt!iR-Oot-V=aWh}$*4H9|xyQ_3R*Io$`Wp`0f;mvaOu-ca-C-vd{1 z`U|Wa;pfD&d`Udbb#aP6E>7@Q5HE_S_{)foiEe%#aX+rb#q)eXoaPa6M*j|APLp!M zk<5`_NQu!#h|BE59fuACA1p8xZ7{>py$od*ZQ>DrTy%0U9_8;>I^YLQ`u-i@SWwEw zpj(V<8b(t;nrdkJ#L6hyI$r5q8Y8=-M1L}1jS}J8bRhHw+--0zNagwoEWg7VBmA{m ztJ4>!PgJhNYCf0e@;we}mrThg}!tPOs&b-(uUEHRbUI=mM`ePfmgZ&g<{hutj@t3bHF z_T|2J+bM^#4mbF+!g`lVWSd2#G?iO(L>!W^TKkjrILx3UT^y5m!IZU?2({uEY%`7^ zMnv;wjIeN7YH`BD74NP~@Xku}E>em^p`iy2y|(#}2N&iW^seT?Oi*? zKc*r#R@b{~|4^nB)lb!jntj0iqTW=ohqvjHgKm7N=6ocOvEiRArT`E1|)rSv)UbWOZHITcN3XOjS_XeyHfn2(MprvM_+tLgD><@|-g zvzIQTVg8-zB;=Fx`5t)btR8)HGB@1=gO>*`Ml;!&bYiMoIRk~vWF|Y8fveecI*}Py za*5gG_(^3vm79d*%uIIXq*BNwt|cQ7nS-}dQ^`ysom7;ri}Pkx`1>Y|ueO?d)RW(ddjOcN~)AKgp6W`2YX_ literal 0 HcmV?d00001