cx16: added syslib.get_charset()

updated fileselector
This commit is contained in:
Irmen de Jong 2025-01-04 01:02:43 +01:00
parent b7f47d354f
commit a76b8d66ff
3 changed files with 117 additions and 47 deletions

View File

@ -667,6 +667,30 @@ asmsub scnsiz(ubyte width @X, ubyte heigth @Y) clobbers(A,X,Y) {
}} }}
} }
asmsub get_charset() -> ubyte @A {
;Get charset mode. result: 0=unknown, 1=ISO, 2=PETSCII upper case/gfx, 3=PETSCII lowercase.
%asm {{
KERNAL_MODE = $0372 ; internal kernal variable, risky to read it, but it's ben stable for many releases.
lda KERNAL_MODE
beq _end
bit #$40 ;ISO mode flag
beq + ;usually KERNAL_MODE 1 or 6 (| $40)
lda #1
bra _end
+ bit #1 ;PETSCII upper case/graphics
bne + ;usually KERNAL_MODE 2 or 4
lda #2
bra _end
+ lda #3 ;PETSCII upper/lower case
_end:
rts
}}
}
; TODO : implement shims for the remaining extapi calls. ; TODO : implement shims for the remaining extapi calls.

View File

@ -1,6 +1,8 @@
TODO TODO
==== ====
- textio.get_cursor() should just return 2 bytes (rewrite it as asmsub...)
- add paypal donation button as well? - add paypal donation button as well?
- announce prog8 on the 6502.org site? - announce prog8 on the 6502.org site?

View File

@ -1,12 +1,12 @@
%import diskio %import diskio
%import textio %import textio
%import sorting
%import strings %import strings
%zeropage basicsafe %zeropage basicsafe
%option no_sysinit %option no_sysinit
; A "TUI" for an interactive file selector, that scrolls the selection list if it doesn't fit on the screen. ; A "TUI" for an interactive file selector, that scrolls the selection list if it doesn't fit on the screen.
; Returns the name of the selected file. If it is a directory instead, the name will start and end with a slash '/'. ; Returns the name of the selected file. If it is a directory instead, the name will start and end with a slash '/'.
; Functions in PETSCII mode and in ISO mode as well (no case folding in ISO mode!)
; Depends a lot on diskio routines, and uses the drive set in the diskio.drivenumber variable (usually just 8) ; Depends a lot on diskio routines, and uses the drive set in the diskio.drivenumber variable (usually just 8)
; should case folding be done in diskio already? -> no, it doesn't know if you are in iso mode or not. ; should case folding be done in diskio already? -> no, it doesn't know if you are in iso mode or not.
@ -18,10 +18,13 @@
main { main {
sub start() { sub start() {
txt.iso() ; some configuration, optional
fileselector.configure_settings(true, true, 2) fileselector.configure_settings(%00000011, 2)
fileselector.configure_appearance(10, 10, 20, $b3, $d0, true) fileselector.configure_appearance(10, 10, 20, $b3, $d0)
; show all files, using just the * wildcard
uword chosen = fileselector.select("*") uword chosen = fileselector.select("*")
txt.nl() txt.nl()
txt.nl() txt.nl()
if chosen!=0 { if chosen!=0 {
@ -49,28 +52,25 @@ fileselector {
ubyte colors_selected = $d0 ubyte colors_selected = $d0
ubyte buffer_rambank = 1 ; default hiram bank to use for the data buffers ubyte buffer_rambank = 1 ; default hiram bank to use for the data buffers
ubyte show_what = 3 ; dirs and files ubyte show_what = 3 ; dirs and files
bool iso_mode = false ubyte chr_topleft, chr_topright, chr_botleft, chr_botright, chr_horiz_top, chr_horiz_other, chr_vert, chr_jointleft, chr_jointright
ubyte chr_topleft, chr_topright, chr_botleft, chr_botright, chr_horiz, chr_vert, chr_jointleft, chr_jointright
ubyte num_visible_files ubyte num_visible_files
uword name_ptr uword name_ptr
sub configure_settings(bool show_files, bool show_dirs, ubyte rambank) { sub configure_settings(ubyte show_types, ubyte rambank) {
; show_types is a bit mask , bit 0 = show files, bit 1 = show dirs
buffer_rambank = rambank buffer_rambank = rambank
show_what = 0 show_what = show_types
if show_files show_what |= 1
if show_dirs show_what |= 2
set_characters(false) set_characters(false)
} }
sub configure_appearance(ubyte column, ubyte row, ubyte max_entries, ubyte normal, ubyte selected, bool iso_chars) { sub configure_appearance(ubyte column, ubyte row, ubyte max_entries, ubyte normal, ubyte selected) {
dialog_topx = column dialog_topx = column
dialog_topy = row dialog_topy = row
max_lines = max_entries max_lines = max_entries
colors_normal = normal colors_normal = normal
colors_selected = selected colors_selected = selected
iso_mode = iso_chars
} }
sub select(str pattern) -> uword { sub select(str pattern) -> uword {
@ -78,22 +78,20 @@ fileselector {
cx16.rambank(buffer_rambank) cx16.rambank(buffer_rambank)
defer cx16.rambank(old_bank) defer cx16.rambank(old_bank)
; if pattern!=0 and pattern[0]==0
; pattern = 0 ; force pattern to be 0 instead of empty string, to be compatible with prog8 11.0 or older
num_visible_files = 0 num_visible_files = 0
diskio.list_filename[0] = 0 diskio.list_filename[0] = 0
name_ptr = diskio.diskname() name_ptr = diskio.diskname()
if name_ptr==0 or cbm.READST()!=0 if name_ptr==0 or cbm.READST()!=0
return 0 return 0
bool iso_mode = cx16.get_charset()==1
set_characters(iso_mode) set_characters(iso_mode)
txt.color2(colors_normal & 15, colors_normal>>4) txt.color2(colors_normal & 15, colors_normal>>4)
background(0, 3) background(0, 3)
txt.plot(dialog_topx, dialog_topy) txt.plot(dialog_topx, dialog_topy)
txt.chrout(chr_topleft) txt.chrout(chr_topleft)
linepart() linepart(true)
txt.chrout(chr_topright) txt.chrout(chr_topright)
txt.nl() txt.nl()
txt.column(dialog_topx) txt.column(dialog_topx)
@ -121,7 +119,7 @@ fileselector {
construct_name_ptr_array() construct_name_ptr_array()
; sort alphabetically ; sort alphabetically
sorting.shellsort_pointers(filename_ptrs_start, num_files, sorting.string_comparator) sorting.shellsort_pointers(filename_ptrs_start, num_files)
num_visible_files = min(max_lines, num_files) num_visible_files = min(max_lines, num_files)
; initial display ; initial display
@ -140,15 +138,15 @@ fileselector {
txt.nl() txt.nl()
txt.column(dialog_topx) txt.column(dialog_topx)
txt.chrout(chr_vert) txt.chrout(chr_vert)
txt.print(" stop or q to abort ") txt.print(" esc/stop to abort ")
txt.chrout(chr_vert) txt.chrout(chr_vert)
txt.nl() txt.nl()
txt.column(dialog_topx) txt.column(dialog_topx)
txt.chrout(chr_jointleft) txt.chrout(chr_jointleft)
linepart() linepart(false)
txt.chrout(chr_jointright) txt.chrout(chr_jointright)
txt.nl() txt.nl()
print_up_indicator(false) print_scroll_indicator(false, true)
if num_files>0 { if num_files>0 {
for selected_line in 0 to num_visible_files-1 { for selected_line in 0 to num_visible_files-1 {
txt.column(dialog_topx) txt.column(dialog_topx)
@ -167,7 +165,7 @@ fileselector {
txt.chrout(chr_vert) txt.chrout(chr_vert)
txt.nl() txt.nl()
} }
print_down_indicator(false) print_scroll_indicator(false, false)
txt.column(dialog_topx) txt.column(dialog_topx)
footerline() footerline()
selected_line = 0 selected_line = 0
@ -180,7 +178,7 @@ fileselector {
ubyte key = cbm.GETIN2() ubyte key = cbm.GETIN2()
when key { when key {
3, 27, 'q' -> return 0 ; STOP or Q aborts (and ESC?) 3, 27 -> return 0 ; STOP and ESC aborts
'\n',' ' -> { '\n',' ' -> {
if num_files>0 { if num_files>0 {
void strings.copy(peekw(filename_ptrs_start + (top_index+selected_line)*$0002), &diskio.list_filename) void strings.copy(peekw(filename_ptrs_start + (top_index+selected_line)*$0002), &diskio.list_filename)
@ -310,29 +308,19 @@ fileselector {
sub print_up_and_down() { sub print_up_and_down() {
if num_files<=max_lines if num_files<=max_lines
return return
print_up_indicator(top_index>0) print_scroll_indicator(top_index>0, true)
print_down_indicator(top_index + num_visible_files < num_files) print_scroll_indicator(top_index + num_visible_files < num_files, false)
} }
sub print_up_indicator(bool shown) { sub print_scroll_indicator(bool visible, bool up) {
txt.plot(dialog_topx, dialog_topy+5) txt.plot(dialog_topx, dialog_topy + (if up 5 else 6+num_visible_files))
txt.chrout(chr_vert)
txt.column(dialog_topx+26)
if shown
txt.print("(up)")
else
txt.print(" ")
txt.spc()
txt.chrout(chr_vert)
txt.nl()
}
sub print_down_indicator(bool shown) {
txt.plot(dialog_topx, dialog_topy+6+num_visible_files)
txt.chrout(chr_vert) txt.chrout(chr_vert)
txt.column(dialog_topx+24) txt.column(dialog_topx+24)
if shown if visible
txt.print("(down)") if up
txt.print(" (up)")
else
txt.print("(down)")
else else
txt.print(" ") txt.print(" ")
txt.spc() txt.spc()
@ -342,12 +330,15 @@ fileselector {
sub footerline() { sub footerline() {
txt.chrout(chr_botleft) txt.chrout(chr_botleft)
linepart() linepart(false)
txt.chrout(chr_botright) txt.chrout(chr_botright)
} }
sub linepart() { sub linepart(bool top) {
repeat 30 txt.chrout(chr_horiz) cx16.r0L = chr_horiz_other
if top
cx16.r0L = chr_horiz_top
repeat 30 txt.chrout(cx16.r0L)
} }
sub select_line(ubyte line) { sub select_line(ubyte line) {
@ -373,15 +364,18 @@ fileselector {
chr_topright = iso:'ì' chr_topright = iso:'ì'
chr_botleft = iso:'`' chr_botleft = iso:'`'
chr_botright = iso:'\'' chr_botright = iso:'\''
chr_jointleft = chr_jointright = iso:':' chr_jointleft = chr_jointright = iso:'÷'
chr_vert = iso:'|' chr_vert = iso:'|'
chr_horiz = iso:'-' chr_horiz_top = iso:'¯'
chr_horiz_other = iso:'-'
} else { } else {
; PETSCII box symbols
chr_topleft = '┌' chr_topleft = '┌'
chr_topright = '┐' chr_topright = '┐'
chr_botleft = '└' chr_botleft = '└'
chr_botright = '┘' chr_botright = '┘'
chr_horiz = '─' chr_horiz_top = '─'
chr_horiz_other = '─'
chr_vert = '│' chr_vert = '│'
chr_jointleft = '├' chr_jointleft = '├'
chr_jointright = '┤' chr_jointright = '┤'
@ -436,3 +430,53 @@ fileselector {
} }
} }
sorting {
; note: cannot use the sorting library module because that relies on zeropage to be directly available (@requirezp pointer)
; and this code is meant to be able to being used without zeropage as well (except for R0-R15).
sub shellsort_pointers(uword stringpointers_array, ubyte num_elements) {
; Comparefunc must be a routine that accepts 2 pointers in R0 and R1, and must return with Carry=1 if R0<=R1, otherwise Carry=0.
; One such function, to compare strings, is provided as 'string_comparator' below.
cx16.r2 = stringpointers_array ; need zeropage pointer
num_elements--
ubyte gap
for gap in [132, 57, 23, 10, 4, 1] {
ubyte i
for i in gap to num_elements {
cx16.r1 = peekw(cx16.r2+i*$0002)
ubyte @zp j = i
ubyte @zp k = j-gap
while j>=gap {
cx16.r0 = peekw(cx16.r2+k*2)
if string_comparator(cx16.r0, cx16.r1)
break
pokew(cx16.r2+j*2, cx16.r0)
j = k
k -= gap
}
pokew(cx16.r2+j*2, cx16.r1)
}
}
asmsub string_comparator(uword string1 @R0, uword string2 @R1) -> bool @Pc {
; R0 and R1 are the two strings, must return Carry=1 when R0<=R1, else Carry=0
%asm {{
lda cx16.r1L
ldy cx16.r1H
sta P8ZP_SCRATCH_W2
sty P8ZP_SCRATCH_W2+1
lda cx16.r0L
ldy cx16.r0H
jsr prog8_lib.strcmp_mem
cmp #1
bne +
clc
rts
+ sec
rts
}}
}
}
}