Bläddra i källkod

vim testing

main
Daniel Covington 2 dagar sedan
förälder
incheckning
cd7607e330
12 ändrade filer med 1140 tillägg och 7 borttagningar
  1. +12
    -1
      .claude/settings.local.json
  2. +40
    -0
      samples/kernal-os-skeleton/build_all.bat
  3. +15
    -0
      samples/kernal-os-skeleton/build_vim.bat
  4. +139
    -6
      samples/kernal-os-skeleton/kernal_os.asm
  5. Binär
      samples/kernal-os-skeleton/kernal_os.d64
  6. Binär
      samples/kernal-os-skeleton/kernal_os.o
  7. Binär
      samples/kernal-os-skeleton/kernal_os.prg
  8. +16
    -0
      samples/kernal-os-skeleton/run.bat
  9. +907
    -0
      samples/kernal-os-skeleton/vim.asm
  10. +11
    -0
      samples/kernal-os-skeleton/vim.cfg
  11. Binär
      samples/kernal-os-skeleton/vim.o
  12. Binär
      samples/kernal-os-skeleton/vim.prg

+ 12
- 1
.claude/settings.local.json Visa fil

@@ -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: $?\")"
]
}
}

+ 40
- 0
samples/kernal-os-skeleton/build_all.bat Visa fil

@@ -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

+ 15
- 0
samples/kernal-os-skeleton/build_vim.bat Visa fil

@@ -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

+ 139
- 6
samples/kernal-os-skeleton/kernal_os.asm Visa fil

@@ -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
ldy #>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
ldy #>filename_spec
jsr SETNAM

lda #0
ldx #<EXEC_AREA
ldy #>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
ldy #>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_LO
lda #>EXEC_AREA
sta PTR1_HI
jsr call_indirect
jsr set_os_memory
rts

command_empty:
exec_not_found:
lda #<msg_exec_nf
ldy #>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:


Binär
samples/kernal-os-skeleton/kernal_os.d64 Visa fil


Binär
samples/kernal-os-skeleton/kernal_os.o Visa fil


Binär
samples/kernal-os-skeleton/kernal_os.prg Visa fil


+ 16
- 0
samples/kernal-os-skeleton/run.bat Visa fil

@@ -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%"

+ 907
- 0
samples/kernal-os-skeleton/vim.asm Visa fil

@@ -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
ldy #>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
ldy #>full_fn
jsr SETNAM

jsr OPEN
bcc ds_open_ok
; open error
lda #<msg_disk_err
ldy #>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
ldy #>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
ldy #>msg_saved
jsr show_status_text
rts

ds_no_name:
lda #<msg_need_name
ldy #>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
ldy #>str_normal
jsr write_str_to_status
rts

dstat_ins:
lda #<str_insert
ldy #>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

+ 11
- 0
samples/kernal-os-skeleton/vim.cfg Visa fil

@@ -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;
}

Binär
samples/kernal-os-skeleton/vim.o Visa fil


Binär
samples/kernal-os-skeleton/vim.prg Visa fil


Laddar…
Avbryt
Spara

Powered by TurnKey Linux.