diff --git a/Makefile b/Makefile index 3efc944..49a4f93 100644 --- a/Makefile +++ b/Makefile @@ -58,6 +58,7 @@ CFLAGS_EXTRA_Z88DK = -Os ######################################## # CoCo customization +LDFLAGS_EXTRA_COCO = --org=0E00 --limit=7C00 AUTOEXEC_COCO = dist.coco/autoexec.bas CFGLOAD_COCO = src/coco/cfgload/cfgload.asm CFGLOAD_BIN = r2r/coco/cfgload.bin diff --git a/src/coco/input.c b/src/coco/input.c index 785e0bb..59d3c08 100644 --- a/src/coco/input.c +++ b/src/coco/input.c @@ -16,6 +16,7 @@ #include "../select_file.h" #include "../set_wifi.h" #include "../select_slot.h" +#include "scroll.h" unsigned char selected_network; extern bool copy_mode; @@ -367,16 +368,20 @@ SFSubState input_select_file_choose(void) char k; unsigned entryType = 0; + scroll_reset(true); + locate(31, 15); while (true) { - k = waitkey(true); + word now = getTimer(); + k = inkey(); switch (k) { case 'C': case 'c': + scroll_reset(false); if (copy_mode == true) { return SF_DONE; @@ -411,6 +416,7 @@ SFSubState input_select_file_choose(void) else return SF_DONE; case KEY_UP_ARROW: // up arrow + scroll_reset(false); if ((bar_get() == 0) && (pos > 0)) return SF_PREV_PAGE; else @@ -422,10 +428,12 @@ SFSubState input_select_file_choose(void) return SF_CHOOSE; } case KEY_SHIFT_UP_ARROW: // shifted up arrow + scroll_reset(false); if (pos > 0) return SF_PREV_PAGE; break; case KEY_DOWN_ARROW: // down arrow + scroll_reset(false); if ((bar_get() == 9) && (dir_eof == false)) return SF_NEXT_PAGE; else @@ -438,11 +446,25 @@ SFSubState input_select_file_choose(void) } break; case KEY_SHIFT_DOWN_ARROW: // shifted down arrow + scroll_reset(false); if (dir_eof == false) return SF_NEXT_PAGE; break; - default: - return SF_CHOOSE; + } + + // Handle idle countdown + timed scroll + if ((word)(now - lastTimer) >= SCROLL_DELAY_TICKS) + { + lastTimer = now; + + if (idleCounter > 0) + { + idleCounter--; + } + else + { + scroll_step(); + } } } diff --git a/src/coco/scroll.c b/src/coco/scroll.c new file mode 100644 index 0000000..4374442 --- /dev/null +++ b/src/coco/scroll.c @@ -0,0 +1,93 @@ +#include +#include +#include +#include "../constants.h" +#include "../globals.h" +#include "../screen.h" +#include "scroll.h" + +word lastTimer; +word idleCounter = IDLE_TIMEOUT_COUNT; +int scrollOffset = 0; +int scrollDir = 1; // 1 = right, -1 = left +byte got_scrolltext; + + +// Draw one line of up to 32 chars from given offset (bounce mode) +void scroll_draw_line_at_y(const char *line, byte y, int offset) +{ + char buf[SCREEN_WIDTH + 1]; + int len = strlen(line); + + memset(buf, ' ', SCREEN_WIDTH); + buf[SCREEN_WIDTH] = 0; + + if (offset < len) + { + int copyLen = len - offset; + if (copyLen > SCREEN_WIDTH) + copyLen = SCREEN_WIDTH; + memcpy(buf, line + offset, copyLen); + } + + locate(0, y+3); // Need to add offset for file choice screen + putstr(buf, SCREEN_WIDTH); + bar_draw(y+3, false); +} + + +// Scroll the currently highlighted line by 1 character (bounce mode) +void scroll_step(void) +{ + byte y = (byte) bar_get(); + if (!got_scrolltext) + { + // Get the full text to scroll + select_get_filename(255); + got_scrolltext = true; + } + + int len = strlen(response); + + if (len <= SCREEN_WIDTH) + return; // no need to scroll + + scrollOffset += scrollDir; + if (scrollOffset < 0) + { + scrollOffset = 0; + scrollDir = 1; + } + else if (scrollOffset > len - SCREEN_WIDTH) + { + scrollOffset = len - SCREEN_WIDTH; + scrollDir = -1; + } + + scroll_draw_line_at_y(response, y, scrollOffset); +} + +// Reset scrolling when user interacts, +// Or initial zetup +void scroll_reset(bool init) +{ + byte y = (byte)bar_get(); + scrollOffset = 0; + scrollDir = 1; + idleCounter = IDLE_TIMEOUT_COUNT; + if (init) + { + lastTimer = 0; + } + else + { + if (got_scrolltext && strlen(response) > SCREEN_WIDTH) + { + // Get the short version of the text again + select_get_filename(DIR_MAX_LEN); + + screen_select_file_display_entry(y, response, 0); + } + } + got_scrolltext = false; +} diff --git a/src/coco/scroll.h b/src/coco/scroll.h new file mode 100644 index 0000000..a8e7424 --- /dev/null +++ b/src/coco/scroll.h @@ -0,0 +1,19 @@ +#ifndef SCROLL_H +#define SCROLL_H +#include +#include +// Timer runs at 60 Hz +#define SCROLL_DELAY_TICKS 30 // 30 ticks = ~0.5 sec +#define IDLE_TIMEOUT_COUNT 10 // 10 × 0.5s = ~5 sec +#define SCREEN_WIDTH 32 + +extern word lastTimer; +extern word idleCounter; +extern int scrollOffset; +extern int scrollDir; // 1 = right, -1 = left + +static void scroll_draw_line_at_y(const char *line, byte y, int offset); +static void scroll_step(void); +void scroll_reset(bool init); + +#endif \ No newline at end of file diff --git a/src/select_file.c b/src/select_file.c index 3961ccd..c9029be 100644 --- a/src/select_file.c +++ b/src/select_file.c @@ -2,6 +2,7 @@ * Select file from Host Slot */ +#include #include "select_file.h" #include "screen.h" #include "constants.h" @@ -150,18 +151,11 @@ void select_display_long_filename(void) #else if ((entry_size[bar_get()] > 30) && (entry_timer == 0)) #endif - { + { if (long_entry_displayed == false) { - fuji_open_directory2(selected_host_slot, path, filter); -#ifdef BUILD_ATARI - fuji_set_directory_position(pos + bar_get() - FILES_START_Y); -#else - fuji_set_directory_position(pos + bar_get()); -#endif - fuji_read_directory(64, 0, response); + select_get_filename(64); screen_select_file_display_long_filename(response); - fuji_close_directory(); long_entry_displayed = true; } } @@ -172,6 +166,21 @@ void select_display_long_filename(void) } } +void select_get_filename(uint8_t len) +{ + fuji_mount_host_slot(selected_host_slot); + + fuji_open_directory2(selected_host_slot, path, filter); + +#ifdef BUILD_ATARI + fuji_set_directory_position(pos + bar_get() - FILES_START_Y); +#else + fuji_set_directory_position(pos + bar_get()); +#endif + fuji_read_directory(len, 0, response); + fuji_close_directory(); +} + void select_next_page(void) { bar_clear(false); diff --git a/src/select_file.h b/src/select_file.h index 6af5765..29fc1a0 100644 --- a/src/select_file.h +++ b/src/select_file.h @@ -5,10 +5,13 @@ #ifndef SELECT_FILE_H #define SELECT_FILE_H +#include + #define ENTRY_TIMER_DUR 128 void select_file(void); void select_display_long_filename(void); +void select_get_filename(uint8_t len); void select_file_set_source_filename(void); unsigned char select_file_is_folder(void); unsigned select_file_entry_type(void);