mirror of
https://github.com/irmen/prog8.git
synced 2025-02-13 18:31:04 +00:00
cx16 fileselector improvements
This commit is contained in:
parent
3b4b37f16b
commit
b014facbd3
@ -35,6 +35,8 @@
|
||||
; Those are all shared in the different tasks! You HAVE to use a mechanism around the userdata value (pointer?) to keep separate state elsewhere!
|
||||
|
||||
coroutines {
|
||||
%option ignore_unused
|
||||
|
||||
const ubyte MAX_TASKS = 64
|
||||
uword[MAX_TASKS] tasklist
|
||||
uword[MAX_TASKS] userdatas
|
||||
|
@ -161,6 +161,7 @@ io_error:
|
||||
; Files in the buffer are separated by a 0 byte. You can provide an optional pattern to match against.
|
||||
; After the last filename one additional 0 byte is placed to indicate the end of the list.
|
||||
; Returns number of files (it skips 'dir' entries i.e. subdirectories).
|
||||
; Note: NO case-folding is done in this routine! (unlike DOS"$ which does case folding on the basic prompt)
|
||||
; Also sets carry on exit: Carry clear = all files returned, Carry set = directory has more files that didn't fit in the buffer.
|
||||
; Note that no list of pointers of some form is returned, the names are just squashed together.
|
||||
; If you really need a list of pointers to the names, that is pretty straightforward to construct by iterating over the names
|
||||
@ -222,6 +223,7 @@ io_error:
|
||||
; -- retrieve the next entry from an iterative file listing session.
|
||||
; results will be found in list_blocks, list_filename, and list_filetype.
|
||||
; if it returns false though, there are no more entries (or an error occurred).
|
||||
; Note: NO case-folding is done in this routine! (unlike DOS"$ which does case folding on the basic prompt)
|
||||
|
||||
if not iteration_in_progress
|
||||
return false
|
||||
|
@ -484,6 +484,7 @@ extsub $C006 = x16edit_loadfile_options(ubyte firstbank @X, ubyte lastbank @Y, s
|
||||
uword disknumberAndColors @R3, uword headerAndStatusColors @R4) clobbers(A,X,Y)
|
||||
|
||||
; Audio (rom bank 10)
|
||||
; NOTE: because these are auto-banked, you should not call them from an IRQ handler routine (due to jsrfar race condition).
|
||||
extsub @bank 10 $C09F = audio_init() clobbers(A,X,Y) -> bool @Pc ; (re)initialize both vera PSG and YM audio chips
|
||||
extsub @bank 10 $C000 = bas_fmfreq(ubyte channel @A, uword freq @XY, bool noretrigger @Pc) clobbers(A,X,Y) -> bool @Pc
|
||||
extsub @bank 10 $C003 = bas_fmnote(ubyte channel @A, ubyte note @X, ubyte fracsemitone @Y, bool noretrigger @Pc) clobbers(A,X,Y) -> bool @Pc
|
||||
|
@ -1,6 +1,7 @@
|
||||
; **experimental** data sorting routines, API subject to change!!
|
||||
|
||||
sorting {
|
||||
%option ignore_unused
|
||||
|
||||
; GNOME SORT is tiny and extremely fast if the initial values are already almost sorted.
|
||||
; SHELL SORT is quite a bit faster if the initial values are more randomly distributed.
|
||||
|
@ -270,7 +270,7 @@ On the Commander X16 the stack and ringbuffer will use a HiRAM bank instead of s
|
||||
you have to initialize that via the init(bank) routine.
|
||||
|
||||
Read the `buffers source code <https://github.com/irmen/prog8/tree/master/compiler/res/prog8lib/diskio.p8>`_
|
||||
to see what's in there. Note that the init() routines have that extra bank parameter on the cx16.
|
||||
to see what's in there. Note that the init() routines have that extra bank parameter on the X16.
|
||||
|
||||
|
||||
compression (slightly experimental)
|
||||
@ -502,6 +502,8 @@ floats
|
||||
|
||||
.. note::
|
||||
Floating point support is only available on c64, cx16 and virtual targets for now.
|
||||
On the X16, make sure rom bank 4 is still active before doing floationg point operations (it's the bank that contains the fp routines).
|
||||
On the C64, you have to make sure the Basic ROM is still banked in (same reason).
|
||||
|
||||
Provides definitions for the ROM/Kernal subroutines and utility routines dealing with floating point variables.
|
||||
|
||||
@ -599,7 +601,7 @@ Provides definitions for the ROM/Kernal subroutines and utility routines dealing
|
||||
|
||||
gfx_lores and gfx_hires (cx16 only)
|
||||
-----------------------------------
|
||||
Full-screen multicolor bitmap graphics routines, available on the Cx16 machine only.
|
||||
Full-screen multicolor bitmap graphics routines, available on the X16 machine only.
|
||||
|
||||
- gfx_lores: optimized routines for 320x240 256 color bitmap graphics mode. Compatible with X16 screen mode 128.
|
||||
- gfx_hires: optimized routines for 640x480 4 color bitmap graphics mode
|
||||
@ -626,7 +628,7 @@ Bitmap graphics routines:
|
||||
|
||||
This library is available both on the C64 and the cx16.
|
||||
It uses the ROM based graphics routines on the latter, and it is a very small library because of that.
|
||||
On the cx16 there's also various other graphics modules if you want more features and different screen modes. See below for those.
|
||||
On the X16 there's also various other graphics modules if you want more features and different screen modes. See below for those.
|
||||
|
||||
Read the `graphics source code <https://github.com/irmen/prog8/tree/master/compiler/res/prog8lib/c64/graphics.p8>`_
|
||||
to see what's in there. (Note: slight variations for different compiler targets)
|
||||
@ -783,7 +785,7 @@ but perhaps the provided ones can be of service too.
|
||||
|
||||
monogfx (cx16 and virtual)
|
||||
---------------------------
|
||||
Full-screen lores or hires monochrome bitmap graphics routines, available on the Cx16 machine only.
|
||||
Full-screen lores or hires monochrome bitmap graphics routines, available on the X16 machine only.
|
||||
|
||||
- two resolutions: lores 320*240 or hires 640*480 bitmap mode
|
||||
- optimized routines for monochrome (2-color) graphics
|
||||
|
@ -245,7 +245,7 @@ On the c64 and cx16, the rom routines are used for floating point operations,
|
||||
so on both systems the correct rom banks have to be banked in to make this work.
|
||||
Although the C128 shares the same floating point format, Prog8 currently doesn't support
|
||||
using floating point on that system (because the c128 fp routines require the fp variables
|
||||
to be in another ram bank than the program, something Prog8 doesn't do).
|
||||
to be in another ram bank than the program, something Prog8 doesn't support yet).
|
||||
|
||||
Also your code needs to import the ``floats`` library to enable floating point support
|
||||
in the compiler, and to gain access to the floating point routines.
|
||||
@ -258,6 +258,11 @@ You can use underscores to group digits in floating point literals to make long
|
||||
any underscores in the number are ignored by the compiler.
|
||||
For instance ``30_000.999_999`` is a valid floating point number 30000.999999.
|
||||
|
||||
.. attention::
|
||||
On the X16, make sure rom bank 4 is still active before doing floationg point operations (it's the bank that contains the fp routines).
|
||||
On the C64, you have to make sure the Basic ROM is still banked in (same reason).
|
||||
|
||||
|
||||
.. _arrayvars:
|
||||
|
||||
Arrays
|
||||
|
@ -3,22 +3,26 @@
|
||||
%import sorting
|
||||
%import strings
|
||||
%zeropage basicsafe
|
||||
%option no_sysinit
|
||||
|
||||
; 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 '/'.
|
||||
; 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.
|
||||
; TODO use "@$:=p" instead of filtering manually for only dirs use @$:=d , but that needs a change in diskio...
|
||||
; TODO is there a way to detect if iso charset mode is active (not really, except read the kernal variable...)
|
||||
; TODO joystick control? mouse control?
|
||||
; TODO keyboard typing; jump to the first entry that starts with that character? (but 'q' for quit stops working then)
|
||||
; TODO keyboard typing; jump to the first entry that starts with that character? (but 'q' for quit stops working then, plus scrolling with pageup/down is already pretty fast)
|
||||
|
||||
|
||||
main {
|
||||
sub start() {
|
||||
|
||||
fileselector.configure(20, 10, 20, true, 2)
|
||||
txt.iso()
|
||||
fileselector.configure_settings(true, true, 2)
|
||||
fileselector.configure_appearance(10, 10, 20, $b3, $d0, true)
|
||||
uword chosen = fileselector.select("*")
|
||||
txt.nl()
|
||||
txt.print_ub(cx16.getrambank())
|
||||
txt.nl()
|
||||
if chosen!=0 {
|
||||
txt.print("chosen: ")
|
||||
@ -32,27 +36,41 @@ main {
|
||||
}
|
||||
|
||||
fileselector {
|
||||
%option ignore_unused
|
||||
|
||||
const uword filenamesbuffer = $a000 ; use a HIRAM bank
|
||||
const uword filenamesbuf_size = $1e00 ; leaves room for a 256 entry string pointer table at $be00-$bfff
|
||||
const uword filename_ptrs_start = $be00 ; array of 256 string pointers for each of the names in the buffer. ends with $0000.
|
||||
ubyte dialog_topx = 4
|
||||
|
||||
ubyte dialog_topx = 10
|
||||
ubyte dialog_topy = 10
|
||||
ubyte max_lines = 20
|
||||
ubyte colors_normal = $b3
|
||||
ubyte colors_selected = $d0
|
||||
ubyte buffer_rambank = 1 ; default hiram bank to use for the data buffers
|
||||
bool also_directories = true
|
||||
ubyte show_what = 3 ; dirs and files
|
||||
bool iso_mode = false
|
||||
ubyte chr_topleft, chr_topright, chr_botleft, chr_botright, chr_horiz, chr_vert, chr_jointleft, chr_jointright
|
||||
|
||||
str chosen_filename = "?" * 32
|
||||
uword name_ptr
|
||||
ubyte num_visible_files
|
||||
uword name_ptr
|
||||
|
||||
|
||||
sub configure(ubyte column, ubyte row, ubyte max_entries, bool also_dirs, ubyte rambank) {
|
||||
sub configure_settings(bool show_files, bool show_dirs, ubyte rambank) {
|
||||
buffer_rambank = rambank
|
||||
show_what = 0
|
||||
if show_files show_what |= 1
|
||||
if show_dirs show_what |= 2
|
||||
set_characters(false)
|
||||
}
|
||||
|
||||
sub configure_appearance(ubyte column, ubyte row, ubyte max_entries, ubyte normal, ubyte selected, bool iso_chars) {
|
||||
dialog_topx = column
|
||||
dialog_topy = row
|
||||
max_lines = max_entries
|
||||
buffer_rambank = rambank
|
||||
also_directories = also_dirs
|
||||
colors_normal = normal
|
||||
colors_selected = selected
|
||||
iso_mode = iso_chars
|
||||
}
|
||||
|
||||
sub select(str pattern) -> uword {
|
||||
@ -64,26 +82,35 @@ fileselector {
|
||||
; pattern = 0 ; force pattern to be 0 instead of empty string, to be compatible with prog8 11.0 or older
|
||||
|
||||
num_visible_files = 0
|
||||
chosen_filename[0] = 0
|
||||
diskio.list_filename[0] = 0
|
||||
name_ptr = diskio.diskname()
|
||||
if name_ptr==0 or cbm.READST()!=0
|
||||
return 0
|
||||
|
||||
txt.cls()
|
||||
set_characters(iso_mode)
|
||||
txt.color2(colors_normal & 15, colors_normal>>4)
|
||||
background(0, 3)
|
||||
|
||||
txt.plot(dialog_topx, dialog_topy)
|
||||
txt.print("┌")
|
||||
txt.chrout(chr_topleft)
|
||||
linepart()
|
||||
txt.print("┐\n")
|
||||
txt.chrout(chr_topright)
|
||||
txt.nl()
|
||||
txt.column(dialog_topx)
|
||||
txt.print("│ drive ")
|
||||
txt.chrout(chr_vert)
|
||||
txt.print(" drive ")
|
||||
txt.print_ub(diskio.drivenumber)
|
||||
txt.print(": '")
|
||||
txt.print(name_ptr)
|
||||
txt.chrout('\'')
|
||||
txt.column(dialog_topx+31)
|
||||
txt.print("│\n")
|
||||
txt.chrout(chr_vert)
|
||||
txt.nl()
|
||||
txt.column(dialog_topx)
|
||||
txt.print("│ scanning directory... │\n")
|
||||
txt.chrout(chr_vert)
|
||||
txt.print(" scanning directory... ")
|
||||
txt.chrout(chr_vert)
|
||||
txt.nl()
|
||||
txt.column(dialog_topx)
|
||||
footerline()
|
||||
|
||||
@ -95,41 +122,56 @@ fileselector {
|
||||
construct_name_ptr_array()
|
||||
; sort alphabetically
|
||||
sorting.shellsort_pointers(filename_ptrs_start, num_files, sorting.string_comparator)
|
||||
num_visible_files = min(max_lines, num_files)
|
||||
|
||||
; initial display
|
||||
background(5, 3 + num_visible_files -1)
|
||||
txt.plot(dialog_topx+2, dialog_topy+2)
|
||||
txt.print("select file: (")
|
||||
txt.print("select ")
|
||||
if show_what & 1 == 1
|
||||
txt.print("file")
|
||||
else
|
||||
txt.print("directory")
|
||||
txt.print(": (")
|
||||
txt.print_ub(num_files)
|
||||
txt.print(" total)")
|
||||
txt.column(dialog_topx+31)
|
||||
txt.print("│\n")
|
||||
txt.chrout(chr_vert)
|
||||
txt.nl()
|
||||
txt.column(dialog_topx)
|
||||
txt.print("│ stop or q to abort |\n")
|
||||
txt.chrout(chr_vert)
|
||||
txt.print(" stop or q to abort ")
|
||||
txt.chrout(chr_vert)
|
||||
txt.nl()
|
||||
txt.column(dialog_topx)
|
||||
txt.print("├")
|
||||
txt.chrout(chr_jointleft)
|
||||
linepart()
|
||||
txt.print("┤\n")
|
||||
txt.chrout(chr_jointright)
|
||||
txt.nl()
|
||||
print_up_indicator(false)
|
||||
if num_files>0 {
|
||||
for selected_line in 0 to min(max_lines, num_files)-1 {
|
||||
for selected_line in 0 to num_visible_files-1 {
|
||||
txt.column(dialog_topx)
|
||||
txt.print("│ ")
|
||||
txt.chrout(chr_vert)
|
||||
txt.spc()
|
||||
print_filename(peekw(filename_ptrs_start+selected_line*$0002))
|
||||
txt.column(dialog_topx+31)
|
||||
txt.print("│\n")
|
||||
num_visible_files++
|
||||
txt.chrout(chr_vert)
|
||||
txt.nl()
|
||||
}
|
||||
} else {
|
||||
txt.column(dialog_topx)
|
||||
txt.print("│ no matches.")
|
||||
txt.chrout(chr_vert)
|
||||
txt.print(" no matches.")
|
||||
txt.column(dialog_topx+31)
|
||||
txt.print("│\n")
|
||||
txt.chrout(chr_vert)
|
||||
txt.nl()
|
||||
}
|
||||
print_down_indicator(false)
|
||||
txt.column(dialog_topx)
|
||||
footerline()
|
||||
selected_line = 0
|
||||
invert(selected_line)
|
||||
select_line(0)
|
||||
print_up_and_down()
|
||||
|
||||
repeat {
|
||||
@ -141,49 +183,49 @@ fileselector {
|
||||
3, 27, 'q' -> return 0 ; STOP or Q aborts (and ESC?)
|
||||
'\n',' ' -> {
|
||||
if num_files>0 {
|
||||
void strings.copy(peekw(filename_ptrs_start + (top_index+selected_line)*$0002), chosen_filename)
|
||||
return chosen_filename
|
||||
void strings.copy(peekw(filename_ptrs_start + (top_index+selected_line)*$0002), &diskio.list_filename)
|
||||
return diskio.list_filename
|
||||
}
|
||||
return 0
|
||||
}
|
||||
'[',130,157 -> { ; PAGEUP, cursor left
|
||||
; previous page of lines
|
||||
invert(selected_line)
|
||||
unselect_line(selected_line)
|
||||
if selected_line==0
|
||||
repeat max_lines scroll_list_backward()
|
||||
selected_line = 0
|
||||
invert(selected_line)
|
||||
select_line(0)
|
||||
print_up_and_down()
|
||||
}
|
||||
']',2,29 -> { ; PAGEDOWN, cursor right
|
||||
if num_files>0 {
|
||||
; next page of lines
|
||||
invert(selected_line)
|
||||
unselect_line(selected_line)
|
||||
if selected_line == max_lines-1
|
||||
repeat max_lines scroll_list_forward()
|
||||
selected_line = num_visible_files-1
|
||||
invert(selected_line)
|
||||
select_line(selected_line)
|
||||
print_up_and_down()
|
||||
}
|
||||
}
|
||||
17 -> { ; down
|
||||
if num_files>0 {
|
||||
invert(selected_line)
|
||||
unselect_line(selected_line)
|
||||
if selected_line<num_visible_files-1
|
||||
selected_line++
|
||||
else if num_files>max_lines
|
||||
scroll_list_forward()
|
||||
invert(selected_line)
|
||||
select_line(selected_line)
|
||||
print_up_and_down()
|
||||
}
|
||||
}
|
||||
145 -> { ; up
|
||||
invert(selected_line)
|
||||
unselect_line(selected_line)
|
||||
if selected_line>0
|
||||
selected_line--
|
||||
else if num_files>max_lines
|
||||
scroll_list_backward()
|
||||
invert(selected_line)
|
||||
select_line(selected_line)
|
||||
print_up_and_down()
|
||||
}
|
||||
}
|
||||
@ -196,8 +238,14 @@ fileselector {
|
||||
name_ptr = filenamesbuffer
|
||||
repeat num_files {
|
||||
pokew(filename_ptrs, name_ptr)
|
||||
while @(name_ptr)!=0
|
||||
name_ptr++
|
||||
if iso_mode {
|
||||
; no case folding in iso mode
|
||||
while @(name_ptr)!=0
|
||||
name_ptr++
|
||||
} else {
|
||||
; case-folding to avoid petscii shifted characters coming out as symbols TODO should diskio do this already?
|
||||
name_ptr += strings.lower(name_ptr)
|
||||
}
|
||||
name_ptr++
|
||||
filename_ptrs+=2
|
||||
}
|
||||
@ -268,43 +316,88 @@ fileselector {
|
||||
|
||||
sub print_up_indicator(bool shown) {
|
||||
txt.plot(dialog_topx, dialog_topy+5)
|
||||
txt.chrout('│')
|
||||
txt.chrout(chr_vert)
|
||||
txt.column(dialog_topx+26)
|
||||
if shown
|
||||
txt.print("(up) │\n")
|
||||
txt.print("(up)")
|
||||
else
|
||||
txt.print(" │\n")
|
||||
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('│')
|
||||
txt.chrout(chr_vert)
|
||||
txt.column(dialog_topx+24)
|
||||
if shown
|
||||
txt.print("(down) │\n")
|
||||
txt.print("(down)")
|
||||
else
|
||||
txt.print(" │\n")
|
||||
txt.print(" ")
|
||||
txt.spc()
|
||||
txt.chrout(chr_vert)
|
||||
txt.nl()
|
||||
}
|
||||
|
||||
sub footerline() {
|
||||
txt.chrout('└')
|
||||
txt.chrout(chr_botleft)
|
||||
linepart()
|
||||
txt.chrout('┘')
|
||||
txt.chrout(chr_botright)
|
||||
}
|
||||
|
||||
sub linepart() {
|
||||
repeat 30 txt.chrout('─')
|
||||
repeat 30 txt.chrout(chr_horiz)
|
||||
}
|
||||
|
||||
sub invert(ubyte line) {
|
||||
sub select_line(ubyte line) {
|
||||
line_color(line, colors_selected)
|
||||
}
|
||||
|
||||
sub unselect_line(ubyte line) {
|
||||
line_color(line, colors_normal)
|
||||
}
|
||||
|
||||
sub line_color(ubyte line, ubyte colors) {
|
||||
cx16.r1L = dialog_topy+6+line
|
||||
ubyte charpos
|
||||
for charpos in dialog_topx+1 to dialog_topx+30 {
|
||||
txt.setchr(charpos, cx16.r1L, txt.getchr(charpos, cx16.r1L) ^ 128)
|
||||
txt.setclr(charpos, cx16.r1L, colors)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sub set_characters(bool iso_chars) {
|
||||
if iso_chars {
|
||||
chr_topleft = iso:'í'
|
||||
chr_topright = iso:'ì'
|
||||
chr_botleft = iso:'`'
|
||||
chr_botright = iso:'\''
|
||||
chr_jointleft = chr_jointright = iso:':'
|
||||
chr_vert = iso:'|'
|
||||
chr_horiz = iso:'-'
|
||||
} else {
|
||||
chr_topleft = '┌'
|
||||
chr_topright = '┐'
|
||||
chr_botleft = '└'
|
||||
chr_botright = '┘'
|
||||
chr_horiz = '─'
|
||||
chr_vert = '│'
|
||||
chr_jointleft = '├'
|
||||
chr_jointright = '┤'
|
||||
}
|
||||
}
|
||||
|
||||
sub background(ubyte startrow, ubyte numlines) {
|
||||
startrow += dialog_topy
|
||||
repeat numlines {
|
||||
txt.plot(dialog_topx+1, startrow)
|
||||
repeat 30 txt.chrout(' ')
|
||||
txt.nl()
|
||||
startrow++
|
||||
}
|
||||
}
|
||||
|
||||
sub get_filenames(uword pattern_ptr, uword filenames_buffer, uword filenames_buf_size) -> ubyte {
|
||||
uword buffer_start = filenames_buffer
|
||||
ubyte files_found = 0
|
||||
@ -312,9 +405,11 @@ fileselector {
|
||||
if diskio.lf_start_list(pattern_ptr) {
|
||||
while diskio.lf_next_entry() {
|
||||
bool is_dir = diskio.list_filetype=="dir"
|
||||
if is_dir and show_what & 2 == 0
|
||||
continue
|
||||
if not is_dir and show_what & 1 == 0
|
||||
continue
|
||||
if is_dir {
|
||||
if not also_directories
|
||||
continue
|
||||
@(filenames_buffer) = '/' ; directories start with a slash so they're grouped when sorting
|
||||
filenames_buffer++
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user