From 74181b0d0f806db92cea89f775ceaa73a7c06d09 Mon Sep 17 00:00:00 2001 From: Paul Gardner-Stephen Date: Sat, 14 Jun 2025 01:45:30 +0930 Subject: [PATCH 01/29] add start of files for shared resources API #70 --- include/mega65/shres.h | 26 ++++++++++++++++++++++++++ src/cc65/shres_asm.s | 24 ++++++++++++++++++++++++ src/shres.c | 32 ++++++++++++++++++++++++++++++++ 3 files changed, 82 insertions(+) create mode 100644 include/mega65/shres.h create mode 100644 src/cc65/shres_asm.s create mode 100644 src/shres.c diff --git a/include/mega65/shres.h b/include/mega65/shres.h new file mode 100644 index 0000000..d9177d2 --- /dev/null +++ b/include/mega65/shres.h @@ -0,0 +1,26 @@ +/* + MEGA65 SYSPART Shared Resources Access API + +*/ + +extern unsigned char *shres_regs; + +#define MAX_RES_NAME_LEN 256 +#define SEEK_SET 1 +#define SEEK_CUR 2 +#define SEEK_END 3 +struct shared_resource { + char name[MAX_RES_NAME_LEN]; + unsigned long long flags; + unsigned long long length; + unsigned long long first_sector; + unsigned long long position; +}; + +#define shared_resource_dir unsigned int + +char shopen(char *resource_name,unsigned long long required_flags, struct shared_resource *file_handle); +char shread(unsigned char *ptr, unsigned int count, struct shared_resource *file_handle); +char shseek(struct shared_resource *,unsigned long long offset, unsigned char whence); +shared_resource_dir shdopen(); +char sddread(unsigned long long required_flags, shared_resource_dir *directory_handle, struct shared_resource *dirent); diff --git a/src/cc65/shres_asm.s b/src/cc65/shres_asm.s new file mode 100644 index 0000000..161d37d --- /dev/null +++ b/src/cc65/shres_asm.s @@ -0,0 +1,24 @@ + + .setcpu "65C02" + .export _shres_trap + +.SEGMENT "CODE" + + .p4510 + + ;; closedir takes file descriptor as argument (appears in A) +_shres_trap: + LDQ _shres_regs + STA $D645 + NOP + STQ _shres_regs + PHP + PLA + STA _shres_regs+4 + LDX #$00 + TAX + RTS + +_shres_regs: + .dword 0 ; regs + .byte 0 ; processor flags diff --git a/src/shres.c b/src/shres.c new file mode 100644 index 0000000..bab0211 --- /dev/null +++ b/src/shres.c @@ -0,0 +1,32 @@ +#include "shres.h" + +/* Open SYSPART Shared Resource area. + Return 0 if success, or non-zero if error. +*/ +char shopen(char *resource_name,unsigned long long required_flags, struct shared_resource *file_handle) +{ + return 1; +} + +/* Read bytes from a SYSPART shared resource. + Return 0 if success, or non-zero if error. + */ +char shread(unsigned char *ptr, unsigned int count, struct shared_resource *file_handle) +{ + return 1; +} + +char shseek(struct shared_resource *,unsigned long long offset, unsigned char whence) +{ + return 1; +} + +shared_resource_dir shdopen() +{ + return 0xffff; +} + +char sddread(unsigned long long required_flags, shared_resource_dir *directory_handle, struct shared_resource *dirent) +{ + return 1; +} From 9857ede384aa6ae88306fa0d445170714a51c595 Mon Sep 17 00:00:00 2001 From: Paul Gardner-Stephen Date: Sat, 14 Jun 2025 02:00:39 +0930 Subject: [PATCH 02/29] get shres code building with cc65 #70 --- include/mega65/shres.h | 17 +++++++---------- src/cc65/shres_asm.s | 10 +++++++--- src/shres.c | 8 ++++---- 3 files changed, 18 insertions(+), 17 deletions(-) diff --git a/include/mega65/shres.h b/include/mega65/shres.h index d9177d2..8ecc4e1 100644 --- a/include/mega65/shres.h +++ b/include/mega65/shres.h @@ -6,21 +6,18 @@ extern unsigned char *shres_regs; #define MAX_RES_NAME_LEN 256 -#define SEEK_SET 1 -#define SEEK_CUR 2 -#define SEEK_END 3 struct shared_resource { char name[MAX_RES_NAME_LEN]; - unsigned long long flags; - unsigned long long length; - unsigned long long first_sector; - unsigned long long position; + unsigned long flags; + unsigned long length; + unsigned long first_sector; + unsigned long position; }; #define shared_resource_dir unsigned int -char shopen(char *resource_name,unsigned long long required_flags, struct shared_resource *file_handle); +char shopen(char *resource_name,unsigned long required_flags, struct shared_resource *file_handle); char shread(unsigned char *ptr, unsigned int count, struct shared_resource *file_handle); -char shseek(struct shared_resource *,unsigned long long offset, unsigned char whence); +char shseek(struct shared_resource *,unsigned long offset, unsigned char whence); shared_resource_dir shdopen(); -char sddread(unsigned long long required_flags, shared_resource_dir *directory_handle, struct shared_resource *dirent); +char sddread(unsigned long required_flags, shared_resource_dir *directory_handle, struct shared_resource *dirent); diff --git a/src/cc65/shres_asm.s b/src/cc65/shres_asm.s index 161d37d..31f6db0 100644 --- a/src/cc65/shres_asm.s +++ b/src/cc65/shres_asm.s @@ -8,10 +8,14 @@ ;; closedir takes file descriptor as argument (appears in A) _shres_trap: - LDQ _shres_regs + NEG ; Prefix instructions to make LDA -> LDQ + NEG + LDA _shres_regs STA $D645 NOP - STQ _shres_regs + NEG ; Prefix instructions to make STA -> STQ + NEG + STA _shres_regs PHP PLA STA _shres_regs+4 @@ -19,6 +23,6 @@ _shres_trap: TAX RTS -_shres_regs: +_shres_regs: .dword 0 ; regs .byte 0 ; processor flags diff --git a/src/shres.c b/src/shres.c index bab0211..2ad84cf 100644 --- a/src/shres.c +++ b/src/shres.c @@ -1,9 +1,9 @@ -#include "shres.h" +#include "mega65/shres.h" /* Open SYSPART Shared Resource area. Return 0 if success, or non-zero if error. */ -char shopen(char *resource_name,unsigned long long required_flags, struct shared_resource *file_handle) +char shopen(char *resource_name,unsigned long required_flags, struct shared_resource *file_handle) { return 1; } @@ -16,7 +16,7 @@ char shread(unsigned char *ptr, unsigned int count, struct shared_resource *file return 1; } -char shseek(struct shared_resource *,unsigned long long offset, unsigned char whence) +char shseek(struct shared_resource *,unsigned long offset, unsigned char whence) { return 1; } @@ -26,7 +26,7 @@ shared_resource_dir shdopen() return 0xffff; } -char sddread(unsigned long long required_flags, shared_resource_dir *directory_handle, struct shared_resource *dirent) +char sddread(unsigned long required_flags, shared_resource_dir *directory_handle, struct shared_resource *dirent) { return 1; } From 85d82cc0946cea3682643fbb2148b175ea3e99ad Mon Sep 17 00:00:00 2001 From: Paul Gardner-Stephen Date: Sat, 14 Jun 2025 02:02:33 +0930 Subject: [PATCH 03/29] fix typo in symbol name #70 --- include/mega65/shres.h | 2 +- src/shres.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/include/mega65/shres.h b/include/mega65/shres.h index 8ecc4e1..7e69a1d 100644 --- a/include/mega65/shres.h +++ b/include/mega65/shres.h @@ -20,4 +20,4 @@ char shopen(char *resource_name,unsigned long required_flags, struct shared_reso char shread(unsigned char *ptr, unsigned int count, struct shared_resource *file_handle); char shseek(struct shared_resource *,unsigned long offset, unsigned char whence); shared_resource_dir shdopen(); -char sddread(unsigned long required_flags, shared_resource_dir *directory_handle, struct shared_resource *dirent); +char shdread(unsigned long required_flags, shared_resource_dir *directory_handle, struct shared_resource *dirent); diff --git a/src/shres.c b/src/shres.c index 2ad84cf..dea8ff6 100644 --- a/src/shres.c +++ b/src/shres.c @@ -26,7 +26,7 @@ shared_resource_dir shdopen() return 0xffff; } -char sddread(unsigned long required_flags, shared_resource_dir *directory_handle, struct shared_resource *dirent) +char shdread(unsigned long required_flags, shared_resource_dir *directory_handle, struct shared_resource *dirent) { return 1; } From 7e1b1f30f5325a4de1d4d7a1ffbee210c8b646c4 Mon Sep 17 00:00:00 2001 From: Paul Gardner-Stephen Date: Sat, 14 Jun 2025 02:26:01 +0930 Subject: [PATCH 04/29] Implement shdopen() #70 --- include/mega65/shres.h | 8 ++++++- src/cc65/shres_asm.s | 4 ++-- src/shres.c | 54 +++++++++++++++++++++++++++++++++++++++++- 3 files changed, 62 insertions(+), 4 deletions(-) diff --git a/include/mega65/shres.h b/include/mega65/shres.h index 7e69a1d..4ae067e 100644 --- a/include/mega65/shres.h +++ b/include/mega65/shres.h @@ -3,7 +3,13 @@ */ -extern unsigned char *shres_regs; +extern void shres_trap(void); +extern unsigned char shres_regs[5]; + +#define SHRES_FLAG_FONT 1 +// Flags with meaning only if FLAG_FONT set +#define SHRES_FLAG_16x16 2 +#define SHRES_FLAG_UNICODE 4 #define MAX_RES_NAME_LEN 256 struct shared_resource { diff --git a/src/cc65/shres_asm.s b/src/cc65/shres_asm.s index 31f6db0..7a03296 100644 --- a/src/cc65/shres_asm.s +++ b/src/cc65/shres_asm.s @@ -1,13 +1,13 @@ .setcpu "65C02" - .export _shres_trap + .export _shres_trap,_shres_regs .SEGMENT "CODE" .p4510 ;; closedir takes file descriptor as argument (appears in A) -_shres_trap: +_shres_trap: NEG ; Prefix instructions to make LDA -> LDQ NEG LDA _shres_regs diff --git a/src/shres.c b/src/shres.c index dea8ff6..423cf71 100644 --- a/src/shres.c +++ b/src/shres.c @@ -1,4 +1,43 @@ +#include + #include "mega65/shres.h" +#include "mega65/memory.h" + +unsigned char magic_string[]={ + 0x4d,0x45,0x47,0x41,'6','5', // MEGA65 + 0x53,0x48,0x41,0x52,0x45,0x44, // SHARED + 0x52,0x45,0x53,0x4f,0x55,0x52,0x43,0x45,0x53, // RESOURCES + 0x00}; + +void sdcard_busy_wait(void) +{ + while (PEEK(0xD680)&0x03) continue; +} + +char do_shres_trap(unsigned long arg) +{ + // Fail if SD card is busy + if (PEEK(0xD680)&0x03) { + printf("SD card is busy\n"); + return 1; + } + + printf("SD card was idle\n"); + + shres_regs[0] = (arg>>0)&0xff; + shres_regs[1] = (arg>>8)&0xff; + shres_regs[2] = (arg>>16)&0xff; + shres_regs[3] = (arg>>24)&0xff; + shres_trap(); + + printf("Trap A=0x%02x\n",shres_regs[0]); + + // Check trap response in A + return shres_regs[0]; + +} + + /* Open SYSPART Shared Resource area. Return 0 if success, or non-zero if error. @@ -23,7 +62,20 @@ char shseek(struct shared_resource *,unsigned long offset, unsigned char whence) shared_resource_dir shdopen() { - return 0xffff; + char i; + if (do_shres_trap(0)) return 0xffff; + + sdcard_busy_wait(); + + // Make sure the magic string is present in the shared resource area + for(i=0;magic_string[i];i++) { + if (lpeek(0xffd6e00L + i) != magic_string[i]) break; + } + if (magic_string[i]) return 0xffff; + + // It's valid, so return sector number of the first entry in the shared resource + // table. + return 1; } char shdread(unsigned long required_flags, shared_resource_dir *directory_handle, struct shared_resource *dirent) From 3fac544bb2381bb9b57962fc57a56248d89ff6da Mon Sep 17 00:00:00 2001 From: Paul Gardner-Stephen Date: Sat, 14 Jun 2025 03:42:53 +0930 Subject: [PATCH 05/29] more work on SHRES API #70 --- include/mega65/shres.h | 16 +++++++++++----- src/shres.c | 29 ++++++++++++++++++++++++----- 2 files changed, 35 insertions(+), 10 deletions(-) diff --git a/include/mega65/shres.h b/include/mega65/shres.h index 4ae067e..e03f5d3 100644 --- a/include/mega65/shres.h +++ b/include/mega65/shres.h @@ -11,13 +11,19 @@ extern unsigned char shres_regs[5]; #define SHRES_FLAG_16x16 2 #define SHRES_FLAG_UNICODE 4 -#define MAX_RES_NAME_LEN 256 +#define MAX_RES_NAME_LEN 240 struct shared_resource { - char name[MAX_RES_NAME_LEN]; - unsigned long flags; - unsigned long length; + // Matches sector format: unsigned long first_sector; - unsigned long position; + unsigned long length_in_sectors; + unsigned long length; + unsigned long flags; + char name[MAX_RES_NAME_LEN]; + + // Internal state for tracking file once opened: + // (i.e., fields not stored on disk) + unsigned long position; + }; #define shared_resource_dir unsigned int diff --git a/src/shres.c b/src/shres.c index 423cf71..c9cc78d 100644 --- a/src/shres.c +++ b/src/shres.c @@ -22,7 +22,7 @@ char do_shres_trap(unsigned long arg) return 1; } - printf("SD card was idle\n"); + printf("SD card was idle, &shres_regs=0x%04x\n",&shres_regs[0]); shres_regs[0] = (arg>>0)&0xff; shres_regs[1] = (arg>>8)&0xff; @@ -30,10 +30,10 @@ char do_shres_trap(unsigned long arg) shres_regs[3] = (arg>>24)&0xff; shres_trap(); - printf("Trap A=0x%02x\n",shres_regs[0]); + printf("Trap C=%d\n",shres_regs[4]&1); - // Check trap response in A - return shres_regs[0]; + // Check trap response in P + return (shres_regs[4]&0x01) ^0x01; } @@ -80,5 +80,24 @@ shared_resource_dir shdopen() char shdread(unsigned long required_flags, shared_resource_dir *directory_handle, struct shared_resource *dirent) { - return 1; + + // Scan shared resources file for the next matching file, or until we reach + // the end of the shared resources directory. + do { + // The directory handle is really just the sector number in the shared resources area. + if (do_shres_trap(*directory_handle)) return 1; + sdcard_busy_wait(); + + // Check for end of directory (first byte of filename is null) + if (!lpeek(0xffd6e10)) return 1; + + // Copy directory entry to dirent + lcopy(0xffd6e00L,(unsigned long)dirent,256); + dirent->position = 0L; + + (*directory_handle) ++; + } + while ((dirent->flags & required_flags) == required_flags); + + return 0; } From 05da1b5226ced88488934bbe85377ef1cf33600c Mon Sep 17 00:00:00 2001 From: Paul Gardner-Stephen Date: Sat, 14 Jun 2025 13:04:40 +0930 Subject: [PATCH 06/29] work on implementing shread() and shopen() #70 --- include/mega65/shres.h | 5 +++-- src/shres.c | 45 +++++++++++++++++++++++++++++++++++++++--- 2 files changed, 45 insertions(+), 5 deletions(-) diff --git a/include/mega65/shres.h b/include/mega65/shres.h index e03f5d3..9524f3d 100644 --- a/include/mega65/shres.h +++ b/include/mega65/shres.h @@ -18,7 +18,8 @@ struct shared_resource { unsigned long length_in_sectors; unsigned long length; unsigned long flags; - char name[MAX_RES_NAME_LEN]; + unsigned char name_len; + char name[MAX_RES_NAME_LEN+1]; // Internal state for tracking file once opened: // (i.e., fields not stored on disk) @@ -29,7 +30,7 @@ struct shared_resource { #define shared_resource_dir unsigned int char shopen(char *resource_name,unsigned long required_flags, struct shared_resource *file_handle); -char shread(unsigned char *ptr, unsigned int count, struct shared_resource *file_handle); +unsigned int shread(unsigned char *ptr, unsigned int count, struct shared_resource *f); char shseek(struct shared_resource *,unsigned long offset, unsigned char whence); shared_resource_dir shdopen(); char shdread(unsigned long required_flags, shared_resource_dir *directory_handle, struct shared_resource *dirent); diff --git a/src/shres.c b/src/shres.c index c9cc78d..7d11a36 100644 --- a/src/shres.c +++ b/src/shres.c @@ -1,4 +1,5 @@ #include +#include #include "mega65/shres.h" #include "mega65/memory.h" @@ -44,15 +45,53 @@ char do_shres_trap(unsigned long arg) */ char shopen(char *resource_name,unsigned long required_flags, struct shared_resource *file_handle) { + unsigned int d; + d = shdopen(); + if (d==0xffff) return 1; + + while (!shdread(required_flags, &d,file_handle)) { + printf("File: '%s'\n",file_handle->name); + if (!strcmp(resource_name,file_handle->name)) return 0; + } + return 1; } /* Read bytes from a SYSPART shared resource. - Return 0 if success, or non-zero if error. + Returns number of bytes read. */ -char shread(unsigned char *ptr, unsigned int count, struct shared_resource *file_handle) +unsigned int shread(unsigned char *ptr, unsigned int count, struct shared_resource *f) { - return 1; + unsigned int read_bytes = 0; + + if (!f) return 0; + + // EOF + if ( f->position >= f->length ) return 0; + + if (count > (f->length - f->position)) count = (f->length - f->position); + + while(count > 0) { + // Work out how many bytes we can read from the current sector + unsigned int bytes = 512 - (f->position & 511); + if (bytes > count) bytes = count; + + // Read the sector in which our bytes are to be found + do_shres_trap(f->position >> 9); + + lcopy(0xffd6e00L + (f->position & 511),(unsigned long)ptr, bytes); + + // Advance output pointer and file offset pointer + ptr += bytes; + f->position += bytes; + + // And reduce the number of bytes we need. + count -= bytes; + + read_bytes += bytes; + } + + return read_bytes; } char shseek(struct shared_resource *,unsigned long offset, unsigned char whence) From 485f8f9d3a1ce5a9287e06a7feb480fbadc9d69a Mon Sep 17 00:00:00 2001 From: Paul Gardner-Stephen Date: Sat, 14 Jun 2025 13:10:45 +0930 Subject: [PATCH 07/29] fix shread() sector offset. Remove debug output #70 --- src/shres.c | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/src/shres.c b/src/shres.c index 7d11a36..2529451 100644 --- a/src/shres.c +++ b/src/shres.c @@ -19,20 +19,15 @@ char do_shres_trap(unsigned long arg) { // Fail if SD card is busy if (PEEK(0xD680)&0x03) { - printf("SD card is busy\n"); return 1; } - printf("SD card was idle, &shres_regs=0x%04x\n",&shres_regs[0]); - shres_regs[0] = (arg>>0)&0xff; shres_regs[1] = (arg>>8)&0xff; shres_regs[2] = (arg>>16)&0xff; shres_regs[3] = (arg>>24)&0xff; shres_trap(); - printf("Trap C=%d\n",shres_regs[4]&1); - // Check trap response in P return (shres_regs[4]&0x01) ^0x01; @@ -63,7 +58,7 @@ char shopen(char *resource_name,unsigned long required_flags, struct shared_reso unsigned int shread(unsigned char *ptr, unsigned int count, struct shared_resource *f) { unsigned int read_bytes = 0; - + if (!f) return 0; // EOF @@ -77,7 +72,7 @@ unsigned int shread(unsigned char *ptr, unsigned int count, struct shared_resour if (bytes > count) bytes = count; // Read the sector in which our bytes are to be found - do_shres_trap(f->position >> 9); + do_shres_trap(f->first_sector + (f->position >> 9) ); lcopy(0xffd6e00L + (f->position & 511),(unsigned long)ptr, bytes); From 7755d42822603d6f511f6afc924459ec4e9a1dcd Mon Sep 17 00:00:00 2001 From: Paul Gardner-Stephen Date: Sat, 14 Jun 2025 13:36:42 +0930 Subject: [PATCH 08/29] get shopen() file search working etc #70 --- src/shres.c | 28 ++++++++++++++++++++++------ 1 file changed, 22 insertions(+), 6 deletions(-) diff --git a/src/shres.c b/src/shres.c index 2529451..d9d5859 100644 --- a/src/shres.c +++ b/src/shres.c @@ -40,14 +40,28 @@ char do_shres_trap(unsigned long arg) */ char shopen(char *resource_name,unsigned long required_flags, struct shared_resource *file_handle) { + unsigned char r; unsigned int d; d = shdopen(); if (d==0xffff) return 1; - while (!shdread(required_flags, &d,file_handle)) { - printf("File: '%s'\n",file_handle->name); + printf("sdhopen() success\n"); + + while (! (r=shdread(required_flags, &d,file_handle))) { + printf("File: '%s'%d vs '%s'%d (%d)\n", + file_handle->name,strlen(file_handle->name), + resource_name,strlen(resource_name), + strcmp(resource_name,file_handle->name)); + { + unsigned char i; + for(i=0;resource_name[i];i++) { + printf("[%02x vs %02x] ", + file_handle->name[i], resource_name[i]); + } + } if (!strcmp(resource_name,file_handle->name)) return 0; } + printf("r=%d\n",r); return 1; } @@ -118,12 +132,14 @@ char shdread(unsigned long required_flags, shared_resource_dir *directory_handle // Scan shared resources file for the next matching file, or until we reach // the end of the shared resources directory. do { - // The directory handle is really just the sector number in the shared resources area. + // The directory handle is really just the sector number in the shared resources area. + printf("directory sector = %d\n",*directory_handle); + if (do_shres_trap(*directory_handle)) return 1; sdcard_busy_wait(); - // Check for end of directory (first byte of filename is null) - if (!lpeek(0xffd6e10)) return 1; + // Check for end of directory (length of filename is 0) + if (!lpeek(0xffd6e10L)) return 2; // Copy directory entry to dirent lcopy(0xffd6e00L,(unsigned long)dirent,256); @@ -131,7 +147,7 @@ char shdread(unsigned long required_flags, shared_resource_dir *directory_handle (*directory_handle) ++; } - while ((dirent->flags & required_flags) == required_flags); + while ((dirent->flags & required_flags) != required_flags); return 0; } From 3672bb4219c7bcdfc6a5b1ae3a6e9260ec906a78 Mon Sep 17 00:00:00 2001 From: Paul Gardner-Stephen Date: Sat, 14 Jun 2025 13:37:54 +0930 Subject: [PATCH 09/29] remove debug output #70 --- src/shres.c | 18 +----------------- 1 file changed, 1 insertion(+), 17 deletions(-) diff --git a/src/shres.c b/src/shres.c index d9d5859..3740bc6 100644 --- a/src/shres.c +++ b/src/shres.c @@ -40,28 +40,13 @@ char do_shres_trap(unsigned long arg) */ char shopen(char *resource_name,unsigned long required_flags, struct shared_resource *file_handle) { - unsigned char r; unsigned int d; d = shdopen(); if (d==0xffff) return 1; - printf("sdhopen() success\n"); - - while (! (r=shdread(required_flags, &d,file_handle))) { - printf("File: '%s'%d vs '%s'%d (%d)\n", - file_handle->name,strlen(file_handle->name), - resource_name,strlen(resource_name), - strcmp(resource_name,file_handle->name)); - { - unsigned char i; - for(i=0;resource_name[i];i++) { - printf("[%02x vs %02x] ", - file_handle->name[i], resource_name[i]); - } - } + while (! shdread(required_flags, &d,file_handle)) { if (!strcmp(resource_name,file_handle->name)) return 0; } - printf("r=%d\n",r); return 1; } @@ -133,7 +118,6 @@ char shdread(unsigned long required_flags, shared_resource_dir *directory_handle // the end of the shared resources directory. do { // The directory handle is really just the sector number in the shared resources area. - printf("directory sector = %d\n",*directory_handle); if (do_shres_trap(*directory_handle)) return 1; sdcard_busy_wait(); From 24e2695c7cd7acf8dac2e3dd067d48c0b83eb81a Mon Sep 17 00:00:00 2001 From: Paul Gardner-Stephen Date: Sat, 14 Jun 2025 13:44:16 +0930 Subject: [PATCH 10/29] implement shseek() #70 --- include/mega65/shres.h | 2 +- src/shres.c | 19 +++++++++++++++++-- 2 files changed, 18 insertions(+), 3 deletions(-) diff --git a/include/mega65/shres.h b/include/mega65/shres.h index 9524f3d..7afa284 100644 --- a/include/mega65/shres.h +++ b/include/mega65/shres.h @@ -31,6 +31,6 @@ struct shared_resource { char shopen(char *resource_name,unsigned long required_flags, struct shared_resource *file_handle); unsigned int shread(unsigned char *ptr, unsigned int count, struct shared_resource *f); -char shseek(struct shared_resource *,unsigned long offset, unsigned char whence); +char shseek(struct shared_resource *,long offset, unsigned char whence); shared_resource_dir shdopen(); char shdread(unsigned long required_flags, shared_resource_dir *directory_handle, struct shared_resource *dirent); diff --git a/src/shres.c b/src/shres.c index 3740bc6..212d367 100644 --- a/src/shres.c +++ b/src/shres.c @@ -88,9 +88,24 @@ unsigned int shread(unsigned char *ptr, unsigned int count, struct shared_resour return read_bytes; } -char shseek(struct shared_resource *,unsigned long offset, unsigned char whence) +char shseek(struct shared_resource *f,long offset, unsigned char whence) { - return 1; + if (!f) return 1; + switch(whence) { + case SEEK_CUR: + f->position += offset; + break; + case SEEK_END: + f->position = f->length + offset; + break; + case SEEK_SET: + default: + f->position = offset; + } + + if (f->position<0) { f->position=0; return 1;} + if (f->position>f->length) { f->position = f->length; return 1; } + } shared_resource_dir shdopen() From 6eb8edfed15f427d6f18fab313e9b669eff60bc8 Mon Sep 17 00:00:00 2001 From: Paul Gardner-Stephen Date: Sat, 14 Jun 2025 13:51:49 +0930 Subject: [PATCH 11/29] run clang-format on shres files #70 --- include/mega65/shres.h | 36 ++++--- src/shres.c | 234 +++++++++++++++++++++++------------------ 2 files changed, 151 insertions(+), 119 deletions(-) diff --git a/include/mega65/shres.h b/include/mega65/shres.h index 7afa284..a2fee66 100644 --- a/include/mega65/shres.h +++ b/include/mega65/shres.h @@ -13,24 +13,26 @@ extern unsigned char shres_regs[5]; #define MAX_RES_NAME_LEN 240 struct shared_resource { - // Matches sector format: - unsigned long first_sector; - unsigned long length_in_sectors; - unsigned long length; - unsigned long flags; - unsigned char name_len; - char name[MAX_RES_NAME_LEN+1]; - - // Internal state for tracking file once opened: - // (i.e., fields not stored on disk) - unsigned long position; - -}; + // Matches sector format: + unsigned long first_sector; + unsigned long length_in_sectors; + unsigned long length; + unsigned long flags; + unsigned char name_len; + char name[MAX_RES_NAME_LEN + 1]; + + // Internal state for tracking file once opened: + // (i.e., fields not stored on disk) + unsigned long position; +}; #define shared_resource_dir unsigned int -char shopen(char *resource_name,unsigned long required_flags, struct shared_resource *file_handle); -unsigned int shread(unsigned char *ptr, unsigned int count, struct shared_resource *f); -char shseek(struct shared_resource *,long offset, unsigned char whence); +char shopen(char* resource_name, unsigned long required_flags, + struct shared_resource* file_handle); +unsigned int shread( + unsigned char* ptr, unsigned int count, struct shared_resource* f); +char shseek(struct shared_resource*, long offset, unsigned char whence); shared_resource_dir shdopen(); -char shdread(unsigned long required_flags, shared_resource_dir *directory_handle, struct shared_resource *dirent); +char shdread(unsigned long required_flags, + shared_resource_dir* directory_handle, struct shared_resource* dirent); diff --git a/src/shres.c b/src/shres.c index 212d367..22cfb42 100644 --- a/src/shres.c +++ b/src/shres.c @@ -4,149 +4,179 @@ #include "mega65/shres.h" #include "mega65/memory.h" -unsigned char magic_string[]={ - 0x4d,0x45,0x47,0x41,'6','5', // MEGA65 - 0x53,0x48,0x41,0x52,0x45,0x44, // SHARED - 0x52,0x45,0x53,0x4f,0x55,0x52,0x43,0x45,0x53, // RESOURCES - 0x00}; +unsigned char magic_string[] = { 0x4d, 0x45, 0x47, 0x41, '6', '5', // MEGA65 + 0x53, 0x48, 0x41, 0x52, 0x45, 0x44, // SHARED + 0x52, 0x45, 0x53, 0x4f, 0x55, 0x52, 0x43, 0x45, 0x53, // RESOURCES + 0x00 }; void sdcard_busy_wait(void) { - while (PEEK(0xD680)&0x03) continue; + while (PEEK(0xD680) & 0x03) { + continue; + } } char do_shres_trap(unsigned long arg) { - // Fail if SD card is busy - if (PEEK(0xD680)&0x03) { - return 1; - } - - shres_regs[0] = (arg>>0)&0xff; - shres_regs[1] = (arg>>8)&0xff; - shres_regs[2] = (arg>>16)&0xff; - shres_regs[3] = (arg>>24)&0xff; - shres_trap(); - - // Check trap response in P - return (shres_regs[4]&0x01) ^0x01; - + // Fail if SD card is busy + if (PEEK(0xD680) & 0x03) { + return 1; + } + + shres_regs[0] = (arg >> 0) & 0xff; + shres_regs[1] = (arg >> 8) & 0xff; + shres_regs[2] = (arg >> 16) & 0xff; + shres_regs[3] = (arg >> 24) & 0xff; + shres_trap(); + + // Check trap response in P + return (shres_regs[4] & 0x01) ^ 0x01; } - - /* Open SYSPART Shared Resource area. Return 0 if success, or non-zero if error. */ -char shopen(char *resource_name,unsigned long required_flags, struct shared_resource *file_handle) +char shopen(char* resource_name, unsigned long required_flags, + struct shared_resource* file_handle) { - unsigned int d; - d = shdopen(); - if (d==0xffff) return 1; - - while (! shdread(required_flags, &d,file_handle)) { - if (!strcmp(resource_name,file_handle->name)) return 0; - } - - return 1; + unsigned int d; + d = shdopen(); + if (d == 0xffff) { + return 1; + } + + while (!shdread(required_flags, &d, file_handle)) { + if (!strcmp(resource_name, file_handle->name)) { + return 0; + } + } + + return 1; } /* Read bytes from a SYSPART shared resource. Returns number of bytes read. */ -unsigned int shread(unsigned char *ptr, unsigned int count, struct shared_resource *f) +unsigned int shread( + unsigned char* ptr, unsigned int count, struct shared_resource* f) { - unsigned int read_bytes = 0; + unsigned int read_bytes = 0; - if (!f) return 0; + if (!f) { + return 0; + } - // EOF - if ( f->position >= f->length ) return 0; + // EOF + if (f->position >= f->length) { + return 0; + } - if (count > (f->length - f->position)) count = (f->length - f->position); + if (count > (f->length - f->position)) { + count = (f->length - f->position); + } - while(count > 0) { - // Work out how many bytes we can read from the current sector - unsigned int bytes = 512 - (f->position & 511); - if (bytes > count) bytes = count; + while (count > 0) { + // Work out how many bytes we can read from the current sector + unsigned int bytes = 512 - (f->position & 511); + if (bytes > count) { + bytes = count; + } - // Read the sector in which our bytes are to be found - do_shres_trap(f->first_sector + (f->position >> 9) ); + // Read the sector in which our bytes are to be found + do_shres_trap(f->first_sector + (f->position >> 9)); - lcopy(0xffd6e00L + (f->position & 511),(unsigned long)ptr, bytes); + lcopy(0xffd6e00L + (f->position & 511), (unsigned long)ptr, bytes); - // Advance output pointer and file offset pointer - ptr += bytes; - f->position += bytes; + // Advance output pointer and file offset pointer + ptr += bytes; + f->position += bytes; - // And reduce the number of bytes we need. - count -= bytes; + // And reduce the number of bytes we need. + count -= bytes; - read_bytes += bytes; - } + read_bytes += bytes; + } - return read_bytes; + return read_bytes; } -char shseek(struct shared_resource *f,long offset, unsigned char whence) +char shseek(struct shared_resource* f, long offset, unsigned char whence) { - if (!f) return 1; - switch(whence) { - case SEEK_CUR: - f->position += offset; - break; - case SEEK_END: - f->position = f->length + offset; - break; - case SEEK_SET: - default: - f->position = offset; - } - - if (f->position<0) { f->position=0; return 1;} - if (f->position>f->length) { f->position = f->length; return 1; } - + if (!f) { + return 1; + } + switch (whence) { + case SEEK_CUR: + f->position += offset; + break; + case SEEK_END: + f->position = f->length + offset; + break; + case SEEK_SET: + default: + f->position = offset; + } + + if (f->position < 0) { + f->position = 0; + return 1; + } + if (f->position > f->length) { + f->position = f->length; + return 1; + } } shared_resource_dir shdopen() { - char i; - if (do_shres_trap(0)) return 0xffff; + char i; + if (do_shres_trap(0)) { + return 0xffff; + } - sdcard_busy_wait(); - - // Make sure the magic string is present in the shared resource area - for(i=0;magic_string[i];i++) { - if (lpeek(0xffd6e00L + i) != magic_string[i]) break; - } - if (magic_string[i]) return 0xffff; + sdcard_busy_wait(); - // It's valid, so return sector number of the first entry in the shared resource - // table. - return 1; + // Make sure the magic string is present in the shared resource area + for (i = 0; magic_string[i]; i++) { + if (lpeek(0xffd6e00L + i) != magic_string[i]) { + break; + } + } + if (magic_string[i]) { + return 0xffff; + } + + // It's valid, so return sector number of the first entry in the shared + // resource table. + return 1; } -char shdread(unsigned long required_flags, shared_resource_dir *directory_handle, struct shared_resource *dirent) +char shdread(unsigned long required_flags, + shared_resource_dir* directory_handle, struct shared_resource* dirent) { - // Scan shared resources file for the next matching file, or until we reach - // the end of the shared resources directory. - do { - // The directory handle is really just the sector number in the shared resources area. + // Scan shared resources file for the next matching file, or until we reach + // the end of the shared resources directory. + do { + // The directory handle is really just the sector number in the shared + // resources area. - if (do_shres_trap(*directory_handle)) return 1; - sdcard_busy_wait(); - - // Check for end of directory (length of filename is 0) - if (!lpeek(0xffd6e10L)) return 2; - - // Copy directory entry to dirent - lcopy(0xffd6e00L,(unsigned long)dirent,256); - dirent->position = 0L; - - (*directory_handle) ++; - } - while ((dirent->flags & required_flags) != required_flags); - - return 0; + if (do_shres_trap(*directory_handle)) { + return 1; + } + sdcard_busy_wait(); + + // Check for end of directory (length of filename is 0) + if (!lpeek(0xffd6e10L)) { + return 2; + } + + // Copy directory entry to dirent + lcopy(0xffd6e00L, (unsigned long)dirent, 256); + dirent->position = 0L; + + (*directory_handle)++; + } while ((dirent->flags & required_flags) != required_flags); + + return 0; } From 0ee08bb47c1459fc02a0280261f37dc64b4496e6 Mon Sep 17 00:00:00 2001 From: Paul Gardner-Stephen Date: Sat, 14 Jun 2025 13:57:36 +0930 Subject: [PATCH 12/29] add doxygen documentation #70 --- include/mega65/shres.h | 110 ++++++++++++++++++++++---- src/shres.c | 172 ++++++++++++++++++++++++----------------- 2 files changed, 198 insertions(+), 84 deletions(-) diff --git a/include/mega65/shres.h b/include/mega65/shres.h index a2fee66..1513658 100644 --- a/include/mega65/shres.h +++ b/include/mega65/shres.h @@ -1,38 +1,120 @@ -/* - MEGA65 SYSPART Shared Resources Access API +/** + * @file shres.h + * @brief MEGA65 SYSPART Shared Resources Access API + * + * This API provides access to shared resources stored in the MEGA65 system partition (SYSPART), + * including files such as fonts, icons, or other binary assets. + * + * Resources are accessed via a special trap instruction and a sector-based directory format. + * This API allows enumeration, opening, reading, and seeking within those shared resources. + */ -*/ +#ifndef SHRES_H +#define SHRES_H +/// Triggers the low-level SYSPART shared resource trap. extern void shres_trap(void); + +/// Registers used for communicating with the shared resource trap. extern unsigned char shres_regs[5]; +/// Flag indicating that the resource is a font. #define SHRES_FLAG_FONT 1 -// Flags with meaning only if FLAG_FONT set + +/// Indicates the font is 16x16 pixels (requires SHRES_FLAG_FONT). #define SHRES_FLAG_16x16 2 + +/// Indicates the font supports Unicode (requires SHRES_FLAG_FONT). #define SHRES_FLAG_UNICODE 4 +/// Maximum length of a resource name (not including null terminator). #define MAX_RES_NAME_LEN 240 + +/** + * @struct shared_resource + * @brief Represents a file or other data resource in the SYSPART directory. + * + * This structure includes metadata stored on disk (such as name, flags, and sector info), + * as well as an in-memory field to track read position for streaming access. + */ struct shared_resource { - // Matches sector format: + /// First sector of the resource. unsigned long first_sector; + + /// Length of the resource in sectors. unsigned long length_in_sectors; + + /// Length of the resource in bytes. unsigned long length; + + /// Bitmask of resource flags (e.g., SHRES_FLAG_FONT, SHRES_FLAG_16x16). unsigned long flags; + + /// Length of the resource name (as stored in the directory). unsigned char name_len; + + /// Null-terminated name of the resource (up to MAX_RES_NAME_LEN). char name[MAX_RES_NAME_LEN + 1]; - // Internal state for tracking file once opened: - // (i.e., fields not stored on disk) + /// Current read position in bytes (used internally; not stored on disk). unsigned long position; }; +/// Type alias for a directory handle (really a sector index). #define shared_resource_dir unsigned int -char shopen(char* resource_name, unsigned long required_flags, - struct shared_resource* file_handle); -unsigned int shread( - unsigned char* ptr, unsigned int count, struct shared_resource* f); -char shseek(struct shared_resource*, long offset, unsigned char whence); -shared_resource_dir shdopen(); +/** + * @brief Opens a named shared resource and verifies required flags. + * + * @param resource_name The null-terminated name of the resource to open. + * @param required_flags A bitmask of flags that must be set on the resource. + * @param file_handle Pointer to a shared_resource structure to populate. + * @return 0 on success, 1 if not found or error. + */ +char shopen(char *resource_name, unsigned long required_flags, + struct shared_resource *file_handle); + +/** + * @brief Reads data from an open shared resource file. + * + * @param ptr Pointer to the output buffer. + * @param count Number of bytes to read. + * @param f Pointer to the shared_resource handle. + * @return Number of bytes actually read. + */ +unsigned int shread(unsigned char *ptr, unsigned int count, + struct shared_resource *f); + +/** + * @brief Seeks to a new position in an open shared resource. + * + * @param f Pointer to the shared_resource handle. + * @param offset Byte offset from the origin. + * @param whence One of SEEK_SET, SEEK_CUR, or SEEK_END. + * @return 0 on success, 1 if the seek was out of bounds or invalid. + */ +char shseek(struct shared_resource *f, long offset, unsigned char whence); + +/** + * @brief Opens the shared resource directory for iteration. + * + * @return A directory handle (starting sector index), or 0xFFFF on failure. + */ +shared_resource_dir shdopen(void); + +/** + * @brief Reads the next matching directory entry. + * + * @param required_flags A bitmask of required flags the resource must match. + * @param directory_handle Pointer to the directory handle returned by shdopen(). + * @param dirent Pointer to a shared_resource structure to populate. + * @return + * - 0 on success (entry read and matches), + * - 1 if the trap failed, + * - 2 if end of directory reached (no more entries match). + */ char shdread(unsigned long required_flags, - shared_resource_dir* directory_handle, struct shared_resource* dirent); + shared_resource_dir *directory_handle, + struct shared_resource *dirent); + +#endif // SHRES_H diff --git a/src/shres.c b/src/shres.c index 22cfb42..81cad90 100644 --- a/src/shres.c +++ b/src/shres.c @@ -1,24 +1,43 @@ +/** + * @file shres.c + * @brief Implementation of MEGA65 SYSPART Shared Resources Access API + * + * Provides functions to access shared resources stored in the MEGA65 system partition (SYSPART), + * including file opening, reading, seeking, and directory traversal. Resources are accessed + * via a custom trap interface to the SYSPART filesystem. + */ + #include #include #include "mega65/shres.h" #include "mega65/memory.h" -unsigned char magic_string[] = { 0x4d, 0x45, 0x47, 0x41, '6', '5', // MEGA65 - 0x53, 0x48, 0x41, 0x52, 0x45, 0x44, // SHARED - 0x52, 0x45, 0x53, 0x4f, 0x55, 0x52, 0x43, 0x45, 0x53, // RESOURCES - 0x00 }; +/// Magic string identifying the SYSPART shared resource area. +static const unsigned char magic_string[] = { + 0x4D, 0x45, 0x47, 0x41, '6', '5', // "MEGA65" + 0x53, 0x48, 0x41, 0x52, 0x45, 0x44, // "SHARED" + 0x52, 0x45, 0x53, 0x4F, 0x55, 0x52, 0x43, 0x45, 0x53, // "RESOURCES" + 0x00 +}; +/** + * @brief Waits until the SD card is no longer busy. + */ void sdcard_busy_wait(void) { - while (PEEK(0xD680) & 0x03) { + while (PEEK(0xD680) & 0x03) continue; - } } +/** + * @brief Executes the shared resource trap for a given sector number. + * + * @param arg The sector number to read (as a 32-bit address). + * @return 0 on success, 1 if the SD card is busy or the trap fails. + */ char do_shres_trap(unsigned long arg) { - // Fail if SD card is busy if (PEEK(0xD680) & 0x03) { return 1; } @@ -29,82 +48,86 @@ char do_shres_trap(unsigned long arg) shres_regs[3] = (arg >> 24) & 0xff; shres_trap(); - // Check trap response in P + // Success is indicated by bit 0 = 1 in shres_regs[4] return (shres_regs[4] & 0x01) ^ 0x01; } -/* Open SYSPART Shared Resource area. - Return 0 if success, or non-zero if error. -*/ -char shopen(char* resource_name, unsigned long required_flags, - struct shared_resource* file_handle) +/** + * @brief Opens a shared resource file by name and flags. + * + * @param resource_name The null-terminated name of the resource to open. + * @param required_flags Bitmask of required flags the resource must have. + * @param file_handle Pointer to the shared_resource struct to populate. + * @return 0 on success, 1 if the resource was not found or an error occurred. + */ +char shopen(char *resource_name, unsigned long required_flags, + struct shared_resource *file_handle) { - unsigned int d; - d = shdopen(); - if (d == 0xffff) { + unsigned int d = shdopen(); + if (d == 0xffff) return 1; - } while (!shdread(required_flags, &d, file_handle)) { - if (!strcmp(resource_name, file_handle->name)) { + if (!strcmp(resource_name, file_handle->name)) return 0; - } } return 1; } -/* Read bytes from a SYSPART shared resource. - Returns number of bytes read. +/** + * @brief Reads bytes from an open shared resource. + * + * @param ptr Pointer to the output buffer to fill. + * @param count Number of bytes to read. + * @param f Pointer to an open shared_resource structure. + * @return Number of bytes actually read. */ -unsigned int shread( - unsigned char* ptr, unsigned int count, struct shared_resource* f) +unsigned int shread(unsigned char *ptr, unsigned int count, + struct shared_resource *f) { unsigned int read_bytes = 0; - if (!f) { - return 0; - } - - // EOF - if (f->position >= f->length) { + if (!f || f->position >= f->length) return 0; - } - if (count > (f->length - f->position)) { + if (count > (f->length - f->position)) count = (f->length - f->position); - } while (count > 0) { - // Work out how many bytes we can read from the current sector unsigned int bytes = 512 - (f->position & 511); - if (bytes > count) { + if (bytes > count) bytes = count; - } - // Read the sector in which our bytes are to be found - do_shres_trap(f->first_sector + (f->position >> 9)); + // Load the appropriate sector + if (do_shres_trap(f->first_sector + (f->position >> 9))) + break; + // Copy bytes from the sector buffer to the output buffer lcopy(0xffd6e00L + (f->position & 511), (unsigned long)ptr, bytes); - // Advance output pointer and file offset pointer ptr += bytes; f->position += bytes; - - // And reduce the number of bytes we need. count -= bytes; - read_bytes += bytes; } return read_bytes; } -char shseek(struct shared_resource* f, long offset, unsigned char whence) +/** + * @brief Seeks to a specific byte offset in an open shared resource. + * + * @param f Pointer to an open shared_resource structure. + * @param offset Byte offset to seek. + * @param whence One of SEEK_SET, SEEK_CUR, or SEEK_END. + * @return 0 on success, 1 if seek was out of bounds or f is NULL. + */ +char shseek(struct shared_resource *f, long offset, unsigned char whence) { - if (!f) { + if (!f) return 1; - } + switch (whence) { case SEEK_CUR: f->position += offset; @@ -115,9 +138,10 @@ char shseek(struct shared_resource* f, long offset, unsigned char whence) case SEEK_SET: default: f->position = offset; + break; } - if (f->position < 0) { + if ((long)f->position < 0) { f->position = 0; return 1; } @@ -125,53 +149,61 @@ char shseek(struct shared_resource* f, long offset, unsigned char whence) f->position = f->length; return 1; } + + return 0; } -shared_resource_dir shdopen() +/** + * @brief Opens the shared resource directory for reading entries. + * + * @return A directory handle (starting sector index) on success, or 0xffff on failure. + */ +shared_resource_dir shdopen(void) { char i; - if (do_shres_trap(0)) { + + if (do_shres_trap(0)) return 0xffff; - } sdcard_busy_wait(); - // Make sure the magic string is present in the shared resource area + // Verify magic string in sector 0 for (i = 0; magic_string[i]; i++) { - if (lpeek(0xffd6e00L + i) != magic_string[i]) { - break; - } - } - if (magic_string[i]) { - return 0xffff; + if (lpeek(0xffd6e00L + i) != magic_string[i]) + return 0xffff; } - // It's valid, so return sector number of the first entry in the shared - // resource table. + // Directory starts at sector 1 return 1; } +/** + * @brief Reads the next resource entry from the shared resource directory + * that matches the required flags. + * + * @param required_flags Bitmask of required flags the resource must have. + * @param directory_handle Pointer to the current directory sector (auto-increments). + * @param dirent Pointer to a shared_resource struct to populate. + * @return + * - 0 on success (matching entry read), + * - 1 if trap failed, + * - 2 if end of directory reached (no more entries). + */ char shdread(unsigned long required_flags, - shared_resource_dir* directory_handle, struct shared_resource* dirent) + shared_resource_dir *directory_handle, + struct shared_resource *dirent) { - - // Scan shared resources file for the next matching file, or until we reach - // the end of the shared resources directory. do { - // The directory handle is really just the sector number in the shared - // resources area. - - if (do_shres_trap(*directory_handle)) { + if (do_shres_trap(*directory_handle)) return 1; - } + sdcard_busy_wait(); - // Check for end of directory (length of filename is 0) - if (!lpeek(0xffd6e10L)) { + // Check for end of directory (name_len == 0) + if (!lpeek(0xffd6e10L)) return 2; - } - // Copy directory entry to dirent + // Copy entry from buffer into dirent lcopy(0xffd6e00L, (unsigned long)dirent, 256); dirent->position = 0L; From 7d954dbd427f8fd77b2035126a3e4749cddb5f8c Mon Sep 17 00:00:00 2001 From: Paul Gardner-Stephen Date: Sat, 14 Jun 2025 13:58:19 +0930 Subject: [PATCH 13/29] reapply clang-format #70 --- include/mega65/shres.h | 33 ++++++++++--------- src/shres.c | 73 +++++++++++++++++++++++++----------------- 2 files changed, 61 insertions(+), 45 deletions(-) diff --git a/include/mega65/shres.h b/include/mega65/shres.h index 1513658..4a52e1e 100644 --- a/include/mega65/shres.h +++ b/include/mega65/shres.h @@ -2,11 +2,13 @@ * @file shres.h * @brief MEGA65 SYSPART Shared Resources Access API * - * This API provides access to shared resources stored in the MEGA65 system partition (SYSPART), - * including files such as fonts, icons, or other binary assets. - * - * Resources are accessed via a special trap instruction and a sector-based directory format. - * This API allows enumeration, opening, reading, and seeking within those shared resources. + * This API provides access to shared resources stored in the MEGA65 system + * partition (SYSPART), including files such as fonts, icons, or other binary + * assets. + * + * Resources are accessed via a special trap instruction and a sector-based + * directory format. This API allows enumeration, opening, reading, and seeking + * within those shared resources. */ #ifndef SHRES_H @@ -34,8 +36,9 @@ extern unsigned char shres_regs[5]; * @struct shared_resource * @brief Represents a file or other data resource in the SYSPART directory. * - * This structure includes metadata stored on disk (such as name, flags, and sector info), - * as well as an in-memory field to track read position for streaming access. + * This structure includes metadata stored on disk (such as name, flags, and + * sector info), as well as an in-memory field to track read position for + * streaming access. */ struct shared_resource { /// First sector of the resource. @@ -71,8 +74,8 @@ struct shared_resource { * @param file_handle Pointer to a shared_resource structure to populate. * @return 0 on success, 1 if not found or error. */ -char shopen(char *resource_name, unsigned long required_flags, - struct shared_resource *file_handle); +char shopen(char* resource_name, unsigned long required_flags, + struct shared_resource* file_handle); /** * @brief Reads data from an open shared resource file. @@ -82,8 +85,8 @@ char shopen(char *resource_name, unsigned long required_flags, * @param f Pointer to the shared_resource handle. * @return Number of bytes actually read. */ -unsigned int shread(unsigned char *ptr, unsigned int count, - struct shared_resource *f); +unsigned int shread( + unsigned char* ptr, unsigned int count, struct shared_resource* f); /** * @brief Seeks to a new position in an open shared resource. @@ -93,7 +96,7 @@ unsigned int shread(unsigned char *ptr, unsigned int count, * @param whence One of SEEK_SET, SEEK_CUR, or SEEK_END. * @return 0 on success, 1 if the seek was out of bounds or invalid. */ -char shseek(struct shared_resource *f, long offset, unsigned char whence); +char shseek(struct shared_resource* f, long offset, unsigned char whence); /** * @brief Opens the shared resource directory for iteration. @@ -106,7 +109,8 @@ shared_resource_dir shdopen(void); * @brief Reads the next matching directory entry. * * @param required_flags A bitmask of required flags the resource must match. - * @param directory_handle Pointer to the directory handle returned by shdopen(). + * @param directory_handle Pointer to the directory handle returned by + * shdopen(). * @param dirent Pointer to a shared_resource structure to populate. * @return * - 0 on success (entry read and matches), @@ -114,7 +118,6 @@ shared_resource_dir shdopen(void); * - 2 if end of directory reached (no more entries match). */ char shdread(unsigned long required_flags, - shared_resource_dir *directory_handle, - struct shared_resource *dirent); + shared_resource_dir* directory_handle, struct shared_resource* dirent); #endif // SHRES_H diff --git a/src/shres.c b/src/shres.c index 81cad90..8176545 100644 --- a/src/shres.c +++ b/src/shres.c @@ -2,9 +2,10 @@ * @file shres.c * @brief Implementation of MEGA65 SYSPART Shared Resources Access API * - * Provides functions to access shared resources stored in the MEGA65 system partition (SYSPART), - * including file opening, reading, seeking, and directory traversal. Resources are accessed - * via a custom trap interface to the SYSPART filesystem. + * Provides functions to access shared resources stored in the MEGA65 system + * partition (SYSPART), including file opening, reading, seeking, and directory + * traversal. Resources are accessed via a custom trap interface to the SYSPART + * filesystem. */ #include @@ -14,20 +15,20 @@ #include "mega65/memory.h" /// Magic string identifying the SYSPART shared resource area. -static const unsigned char magic_string[] = { - 0x4D, 0x45, 0x47, 0x41, '6', '5', // "MEGA65" - 0x53, 0x48, 0x41, 0x52, 0x45, 0x44, // "SHARED" - 0x52, 0x45, 0x53, 0x4F, 0x55, 0x52, 0x43, 0x45, 0x53, // "RESOURCES" - 0x00 -}; +static const unsigned char magic_string[] + = { 0x4D, 0x45, 0x47, 0x41, '6', '5', // "MEGA65" + 0x53, 0x48, 0x41, 0x52, 0x45, 0x44, // "SHARED" + 0x52, 0x45, 0x53, 0x4F, 0x55, 0x52, 0x43, 0x45, 0x53, // "RESOURCES" + 0x00 }; /** * @brief Waits until the SD card is no longer busy. */ void sdcard_busy_wait(void) { - while (PEEK(0xD680) & 0x03) + while (PEEK(0xD680) & 0x03) { continue; + } } /** @@ -60,16 +61,18 @@ char do_shres_trap(unsigned long arg) * @param file_handle Pointer to the shared_resource struct to populate. * @return 0 on success, 1 if the resource was not found or an error occurred. */ -char shopen(char *resource_name, unsigned long required_flags, - struct shared_resource *file_handle) +char shopen(char* resource_name, unsigned long required_flags, + struct shared_resource* file_handle) { unsigned int d = shdopen(); - if (d == 0xffff) + if (d == 0xffff) { return 1; + } while (!shdread(required_flags, &d, file_handle)) { - if (!strcmp(resource_name, file_handle->name)) + if (!strcmp(resource_name, file_handle->name)) { return 0; + } } return 1; @@ -83,25 +86,29 @@ char shopen(char *resource_name, unsigned long required_flags, * @param f Pointer to an open shared_resource structure. * @return Number of bytes actually read. */ -unsigned int shread(unsigned char *ptr, unsigned int count, - struct shared_resource *f) +unsigned int shread( + unsigned char* ptr, unsigned int count, struct shared_resource* f) { unsigned int read_bytes = 0; - if (!f || f->position >= f->length) + if (!f || f->position >= f->length) { return 0; + } - if (count > (f->length - f->position)) + if (count > (f->length - f->position)) { count = (f->length - f->position); + } while (count > 0) { unsigned int bytes = 512 - (f->position & 511); - if (bytes > count) + if (bytes > count) { bytes = count; + } // Load the appropriate sector - if (do_shres_trap(f->first_sector + (f->position >> 9))) + if (do_shres_trap(f->first_sector + (f->position >> 9))) { break; + } // Copy bytes from the sector buffer to the output buffer lcopy(0xffd6e00L + (f->position & 511), (unsigned long)ptr, bytes); @@ -123,10 +130,11 @@ unsigned int shread(unsigned char *ptr, unsigned int count, * @param whence One of SEEK_SET, SEEK_CUR, or SEEK_END. * @return 0 on success, 1 if seek was out of bounds or f is NULL. */ -char shseek(struct shared_resource *f, long offset, unsigned char whence) +char shseek(struct shared_resource* f, long offset, unsigned char whence) { - if (!f) + if (!f) { return 1; + } switch (whence) { case SEEK_CUR: @@ -156,21 +164,24 @@ char shseek(struct shared_resource *f, long offset, unsigned char whence) /** * @brief Opens the shared resource directory for reading entries. * - * @return A directory handle (starting sector index) on success, or 0xffff on failure. + * @return A directory handle (starting sector index) on success, or 0xffff on + * failure. */ shared_resource_dir shdopen(void) { char i; - if (do_shres_trap(0)) + if (do_shres_trap(0)) { return 0xffff; + } sdcard_busy_wait(); // Verify magic string in sector 0 for (i = 0; magic_string[i]; i++) { - if (lpeek(0xffd6e00L + i) != magic_string[i]) + if (lpeek(0xffd6e00L + i) != magic_string[i]) { return 0xffff; + } } // Directory starts at sector 1 @@ -182,7 +193,8 @@ shared_resource_dir shdopen(void) * that matches the required flags. * * @param required_flags Bitmask of required flags the resource must have. - * @param directory_handle Pointer to the current directory sector (auto-increments). + * @param directory_handle Pointer to the current directory sector + * (auto-increments). * @param dirent Pointer to a shared_resource struct to populate. * @return * - 0 on success (matching entry read), @@ -190,18 +202,19 @@ shared_resource_dir shdopen(void) * - 2 if end of directory reached (no more entries). */ char shdread(unsigned long required_flags, - shared_resource_dir *directory_handle, - struct shared_resource *dirent) + shared_resource_dir* directory_handle, struct shared_resource* dirent) { do { - if (do_shres_trap(*directory_handle)) + if (do_shres_trap(*directory_handle)) { return 1; + } sdcard_busy_wait(); // Check for end of directory (name_len == 0) - if (!lpeek(0xffd6e10L)) + if (!lpeek(0xffd6e10L)) { return 2; + } // Copy entry from buffer into dirent lcopy(0xffd6e00L, (unsigned long)dirent, 256); From 5f70804b3338df8c489eb4ee8f5c7ac8a1e674ed Mon Sep 17 00:00:00 2001 From: Paul Gardner-Stephen Date: Sat, 14 Jun 2025 14:14:36 +0930 Subject: [PATCH 14/29] initial llvm-mos implementation of shres_asm.s #70 --- src/llvm/shres_asm.s | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) create mode 100644 src/llvm/shres_asm.s diff --git a/src/llvm/shres_asm.s b/src/llvm/shres_asm.s new file mode 100644 index 0000000..f69d529 --- /dev/null +++ b/src/llvm/shres_asm.s @@ -0,0 +1,29 @@ +.global _shres_trap +.global _shres_regs + +.section .text + +; _shres_trap() +; Sends a 32-bit argument in _shres_regs[0..3] to $D645, +; then stores 32-bit return result back into _shres_regs[0..3] +; and processor flags into _shres_regs[4]. + +_shres_trap: + ldq _shres_regs ; Load 32-bit value from _shres_regs + stq $D645 ; Store to the MEGA65 SYSPART trap address + nop ; Delay/stabilize (preserved from original) + + stq _shres_regs ; Store result back into _shres_regs + + php + pla + sta _shres_regs+4 ; Save status register into 5th byte + ldx #0 + txa + rts + +.section .bss + +; Register block: 4 bytes for argument/result, 1 byte for flags +_shres_regs: + .zero 5 From b6d1c7bdfb67950c75bb1b2e86c81bb4cdbd2cc0 Mon Sep 17 00:00:00 2001 From: Paul Gardner-Stephen Date: Sat, 14 Jun 2025 14:24:57 +0930 Subject: [PATCH 15/29] add shres API to llvm cmake #70 --- src/CMakeLists.txt | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 4683bc7..e4c26b9 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -1,6 +1,7 @@ set(assembler llvm/fileio.s llvm/dirent.s + llvm/shres_asm.s llvm/memory_asm.s) set(objects @@ -14,6 +15,7 @@ set(objects mouse.c random.c sdcard.c + shres.c targets.c tests.c time.c) @@ -30,6 +32,7 @@ set(headers ${PROJECT_SOURCE_DIR}/include/mega65/mouse.h ${PROJECT_SOURCE_DIR}/include/mega65/random.h ${PROJECT_SOURCE_DIR}/include/mega65/sdcard.h + ${PROJECT_SOURCE_DIR}/include/mega65/shres.h ${PROJECT_SOURCE_DIR}/include/mega65/targets.h ${PROJECT_SOURCE_DIR}/include/mega65/tests.h ${PROJECT_SOURCE_DIR}/include/mega65/time.h) From 95cd1a9d041c826ba4e59679bdd40581e881ab3c Mon Sep 17 00:00:00 2001 From: Paul Gardner-Stephen Date: Mon, 16 Jun 2025 20:36:16 +0930 Subject: [PATCH 16/29] wait for sector read to complete in shread() #70 --- src/shres.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/shres.c b/src/shres.c index 8176545..4ee6a42 100644 --- a/src/shres.c +++ b/src/shres.c @@ -109,7 +109,9 @@ unsigned int shread( if (do_shres_trap(f->first_sector + (f->position >> 9))) { break; } - + // And wait for the SD card to actually read it. + sdcard_busy_wait(); + // Copy bytes from the sector buffer to the output buffer lcopy(0xffd6e00L + (f->position & 511), (unsigned long)ptr, bytes); From 61ab9eafbd23d949b2ca43cd44b507385fe67942 Mon Sep 17 00:00:00 2001 From: Paul Gardner-Stephen Date: Fri, 29 Aug 2025 17:06:09 +0930 Subject: [PATCH 17/29] add argument to chdirroot() function #73 --- include/mega65/fileio.h | 2 +- src/cc65/fileio.s | 5 +++++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/include/mega65/fileio.h b/include/mega65/fileio.h index 1052f64..e00e8f7 100644 --- a/include/mega65/fileio.h +++ b/include/mega65/fileio.h @@ -82,7 +82,7 @@ chdir(char* filename); __attribute__((leaf)) #endif uint8_t -chdirroot(void); +chdirroot(uint8_t partition); /** * @brief Struct for holding version information of the hypervisor diff --git a/src/cc65/fileio.s b/src/cc65/fileio.s index 26eec38..fb83fe4 100644 --- a/src/cc65/fileio.s +++ b/src/cc65/fileio.s @@ -146,10 +146,15 @@ _close: rts _chdirroot: + ;; HYPPO requires partition number in X. + tax ;; Change to root directory of volume lda #$3C sta $d640 clv + ;; HYPPO trap_dos_cdroot() doesn't set return value: It is deemed to always succeed + ;; if called on a valid disk. + ldx #$00 ldx #$00 rts From d987fb8c196f90d61206c34d1beaa57bfd62660a Mon Sep 17 00:00:00 2001 From: Paul Gardner-Stephen Date: Sat, 30 Aug 2025 11:06:29 +0930 Subject: [PATCH 18/29] ensure SD card buffer selected in shread #70 --- src/shres.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/shres.c b/src/shres.c index 4ee6a42..3a44d75 100644 --- a/src/shres.c +++ b/src/shres.c @@ -111,6 +111,9 @@ unsigned int shread( } // And wait for the SD card to actually read it. sdcard_busy_wait(); + + // Select SD card buffer, not FDC buffer + POKE(0xD689L,PEEK(0xD689L)|0x80); // Copy bytes from the sector buffer to the output buffer lcopy(0xffd6e00L + (f->position & 511), (unsigned long)ptr, bytes); From 8174c8f1a05c8e672661f970b8f5b2d8bd4ea7d2 Mon Sep 17 00:00:00 2001 From: Paul Gardner-Stephen Date: Sat, 30 Aug 2025 11:07:34 +0930 Subject: [PATCH 19/29] remove vestical openfile call in chdir #74 --- src/cc65/fileio.s | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/cc65/fileio.s b/src/cc65/fileio.s index fb83fe4..921aa77 100644 --- a/src/cc65/fileio.s +++ b/src/cc65/fileio.s @@ -182,9 +182,6 @@ chdir_file_exists: lda #$0C sta $d640 clv - lda #$18 - sta $D640 - clv ldx #$00 rts From f230e1a499580e71a8415c72e7526034f2878a74 Mon Sep 17 00:00:00 2001 From: Paul Gardner-Stephen Date: Thu, 25 Sep 2025 18:30:17 +0930 Subject: [PATCH 20/29] fix llvm shres issue #70 --- src/shres.c | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/src/shres.c b/src/shres.c index 3a44d75..59757fb 100644 --- a/src/shres.c +++ b/src/shres.c @@ -14,6 +14,9 @@ #include "mega65/shres.h" #include "mega65/memory.h" +void _shres_trap(void); +extern unsigned char *_shres_regs; + /// Magic string identifying the SYSPART shared resource area. static const unsigned char magic_string[] = { 0x4D, 0x45, 0x47, 0x41, '6', '5', // "MEGA65" @@ -43,14 +46,14 @@ char do_shres_trap(unsigned long arg) return 1; } - shres_regs[0] = (arg >> 0) & 0xff; - shres_regs[1] = (arg >> 8) & 0xff; - shres_regs[2] = (arg >> 16) & 0xff; - shres_regs[3] = (arg >> 24) & 0xff; - shres_trap(); + _shres_regs[0] = (arg >> 0) & 0xff; + _shres_regs[1] = (arg >> 8) & 0xff; + _shres_regs[2] = (arg >> 16) & 0xff; + _shres_regs[3] = (arg >> 24) & 0xff; + _shres_trap(); // Success is indicated by bit 0 = 1 in shres_regs[4] - return (shres_regs[4] & 0x01) ^ 0x01; + return (_shres_regs[4] & 0x01) ^ 0x01; } /** From 33eb3ba6046cc00fc3bf4b8a75de33f37ed91f90 Mon Sep 17 00:00:00 2001 From: Paul Gardner-Stephen Date: Thu, 25 Sep 2025 18:52:02 +0930 Subject: [PATCH 21/29] fix llvm -Oz bug with ldq/stq #70 --- src/llvm/shres_asm.s | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/src/llvm/shres_asm.s b/src/llvm/shres_asm.s index f69d529..5345d7c 100644 --- a/src/llvm/shres_asm.s +++ b/src/llvm/shres_asm.s @@ -9,11 +9,24 @@ ; and processor flags into _shres_regs[4]. _shres_trap: - ldq _shres_regs ; Load 32-bit value from _shres_regs - stq $D645 ; Store to the MEGA65 SYSPART trap address + ldx #3 +ll1: lda _shres_regs,x + sta $D645,x + dex + bpl ll1 + + lda _shres_regs+0 + ldx _shres_regs+1 + ldy _shres_regs+2 + ldz _shres_regs+3 + sta $D645 ; Store to the MEGA65 SYSPART trap address nop ; Delay/stabilize (preserved from original) - stq _shres_regs ; Store result back into _shres_regs + ; Store result back into _shres_regs + sta _shres_regs+0 + stx _shres_regs+1 + sty _shres_regs+2 + stz _shres_regs+3 php pla From 6a445003146c20e9e48770d0a6a38a4ba3f38c04 Mon Sep 17 00:00:00 2001 From: Paul Gardner-Stephen Date: Thu, 25 Sep 2025 21:21:14 +0930 Subject: [PATCH 22/29] fix llvm target bugs #70 --- src/llvm/fileio.s | 4 ++-- src/llvm/shres_asm.s | 20 ++++++++++++-------- src/shres.c | 3 +++ 3 files changed, 17 insertions(+), 10 deletions(-) diff --git a/src/llvm/fileio.s b/src/llvm/fileio.s index f7ceb8f..bc3ad6d 100644 --- a/src/llvm/fileio.s +++ b/src/llvm/fileio.s @@ -144,10 +144,10 @@ chdir: hyppo HYPPO_FINDFILE bcs chdir_ok lda #FILE_ERROR - rts + rts chdir_ok: hyppo HYPPO_CHDIR - hyppo HYPPO_OPENFILE; outputs to A + rts .global gethyppoversion diff --git a/src/llvm/shres_asm.s b/src/llvm/shres_asm.s index 5345d7c..2843015 100644 --- a/src/llvm/shres_asm.s +++ b/src/llvm/shres_asm.s @@ -8,31 +8,35 @@ ; then stores 32-bit return result back into _shres_regs[0..3] ; and processor flags into _shres_regs[4]. -_shres_trap: - ldx #3 -ll1: lda _shres_regs,x - sta $D645,x - dex - bpl ll1 +_shres_trap: + +phy +phz lda _shres_regs+0 ldx _shres_regs+1 ldy _shres_regs+2 ldz _shres_regs+3 + sta $D645 ; Store to the MEGA65 SYSPART trap address nop ; Delay/stabilize (preserved from original) + ; Store result back into _shres_regs sta _shres_regs+0 stx _shres_regs+1 sty _shres_regs+2 stz _shres_regs+3 - + php pla sta _shres_regs+4 ; Save status register into 5th byte ldx #0 - txa + txa + + ply + plz + rts .section .bss diff --git a/src/shres.c b/src/shres.c index 59757fb..5371748 100644 --- a/src/shres.c +++ b/src/shres.c @@ -179,6 +179,9 @@ shared_resource_dir shdopen(void) { char i; + POKE(0xD021,2); + + if (do_shres_trap(0)) { return 0xffff; } From 78931f4826a94f55f981ccb0b471127a2e2456e0 Mon Sep 17 00:00:00 2001 From: Paul Gardner-Stephen Date: Sat, 27 Sep 2025 17:24:07 +0930 Subject: [PATCH 23/29] usleep() bug with values not modulo 64usec #70 --- src/hal.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/hal.c b/src/hal.c index e88e9bd..a041096 100644 --- a/src/hal.c +++ b/src/hal.c @@ -11,7 +11,7 @@ void usleep(uint32_t micros) while (PEEK(0xD012) == b) { continue; } - micros -= 64; + if (micros>=64) micros -= 64; else break; } return; } From 9d8888e0cc5c8e9959752b92f48667d19142a737 Mon Sep 17 00:00:00 2001 From: Paul Gardner-Stephen Date: Sat, 27 Sep 2025 21:06:37 +0930 Subject: [PATCH 24/29] fix Y Z pop order #70 --- src/llvm/shres_asm.s | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/llvm/shres_asm.s b/src/llvm/shres_asm.s index 2843015..1dab3cb 100644 --- a/src/llvm/shres_asm.s +++ b/src/llvm/shres_asm.s @@ -34,8 +34,8 @@ phz ldx #0 txa - ply plz + ply rts From 031c0e0dc0167b5e6df0c7a29bc83ecfacdaa52b Mon Sep 17 00:00:00 2001 From: Paul Gardner-Stephen Date: Sun, 28 Sep 2025 00:29:14 +0930 Subject: [PATCH 25/29] fix llvm behaviour for shres #70 --- src/hal.c | 18 +++++++++++++++--- src/llvm/shres_asm.s | 9 ++++++--- src/shres.c | 5 +---- 3 files changed, 22 insertions(+), 10 deletions(-) diff --git a/src/hal.c b/src/hal.c index a041096..065c2cc 100644 --- a/src/hal.c +++ b/src/hal.c @@ -7,11 +7,23 @@ void usleep(uint32_t micros) // Each VIC-II raster line is ~64 microseconds // this is not totally accurate, but is a reasonable approach while (micros > 64) { - uint8_t b = PEEK(0xD012); +#ifdef LLVM_503_WORKAROUND + asm volatile( + "ldx $D012\n" + "1:\n" + "cpx $D012\n" + "beq 1b\n" + : + : + : "x" // X is clobbered + ); +#else + uint8_t b = PEEK(0xD012); while (PEEK(0xD012) == b) { - continue; + continue; } - if (micros>=64) micros -= 64; else break; +#endif + micros -= 64; } return; } diff --git a/src/llvm/shres_asm.s b/src/llvm/shres_asm.s index 1dab3cb..417ecdf 100644 --- a/src/llvm/shres_asm.s +++ b/src/llvm/shres_asm.s @@ -39,8 +39,11 @@ phz rts -.section .bss - ; Register block: 4 bytes for argument/result, 1 byte for flags + + .section .bss _shres_regs: - .zero 5 + .space 5 + + + .section .text diff --git a/src/shres.c b/src/shres.c index 5371748..ab4449b 100644 --- a/src/shres.c +++ b/src/shres.c @@ -15,7 +15,7 @@ #include "mega65/memory.h" void _shres_trap(void); -extern unsigned char *_shres_regs; +extern unsigned char _shres_regs[5]; /// Magic string identifying the SYSPART shared resource area. static const unsigned char magic_string[] @@ -178,9 +178,6 @@ char shseek(struct shared_resource* f, long offset, unsigned char whence) shared_resource_dir shdopen(void) { char i; - - POKE(0xD021,2); - if (do_shres_trap(0)) { return 0xffff; From 141dd6237a7faa5c2364a1a16a1e5a09af07d2e0 Mon Sep 17 00:00:00 2001 From: Paul Gardner-Stephen Date: Sun, 28 Sep 2025 14:54:42 +0930 Subject: [PATCH 26/29] fix chdirroot for llvm #70 --- src/llvm/fileio.s | 1 + 1 file changed, 1 insertion(+) diff --git a/src/llvm/fileio.s b/src/llvm/fileio.s index bc3ad6d..211afcf 100644 --- a/src/llvm/fileio.s +++ b/src/llvm/fileio.s @@ -133,6 +133,7 @@ close: .global chdirroot .section .text.fileio_chdirroot,"ax",@progbits chdirroot: + ldx #0 hyppo HYPPO_CDROOTDIR rts From 8433fff5ac81c6202f6c7af9797965108f6cff3b Mon Sep 17 00:00:00 2001 From: Paul Gardner-Stephen Date: Sun, 28 Sep 2025 18:40:42 +0930 Subject: [PATCH 27/29] preserve Y value --- src/llvm/fileio.s | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/llvm/fileio.s b/src/llvm/fileio.s index 211afcf..f1cacf3 100644 --- a/src/llvm/fileio.s +++ b/src/llvm/fileio.s @@ -154,7 +154,9 @@ chdir_ok: .global gethyppoversion .section .text.fileio_gethyppoversion,"ax",@progbits gethyppoversion: - hyppo HYPPO_GETVERSION ; outputs to Q = A, X, Y, Z - stq (__rc2) ; store Q to __rc2 pointer - ldz #0 ; Z must be cleared before returning - rts + phy + hyppo HYPPO_GETVERSION ; outputs to Q = A, X, Y, Z + stq (__rc2) ; store Q to __rc2 pointer + ldz #0 ; Z must be cleared before returning + ply + rts From 5c2d089b09962d3474a22ab5e7541599e88d3fdc Mon Sep 17 00:00:00 2001 From: Paul Gardner-Stephen Date: Sun, 28 Sep 2025 18:41:26 +0930 Subject: [PATCH 28/29] debug shres stuff #70 --- src/shres.c | 23 +++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/src/shres.c b/src/shres.c index ab4449b..9b50110 100644 --- a/src/shres.c +++ b/src/shres.c @@ -18,7 +18,7 @@ void _shres_trap(void); extern unsigned char _shres_regs[5]; /// Magic string identifying the SYSPART shared resource area. -static const unsigned char magic_string[] +static const unsigned char magic_string[22] = { 0x4D, 0x45, 0x47, 0x41, '6', '5', // "MEGA65" 0x53, 0x48, 0x41, 0x52, 0x45, 0x44, // "SHARED" 0x52, 0x45, 0x53, 0x4F, 0x55, 0x52, 0x43, 0x45, 0x53, // "RESOURCES" @@ -64,13 +64,15 @@ char do_shres_trap(unsigned long arg) * @param file_handle Pointer to the shared_resource struct to populate. * @return 0 on success, 1 if the resource was not found or an error occurred. */ + char shopen(char* resource_name, unsigned long required_flags, struct shared_resource* file_handle) { - unsigned int d = shdopen(); - if (d == 0xffff) { - return 1; - } + unsigned int d = shdopen(); + + if (d == 0xffff) { + return 1; + } while (!shdread(required_flags, &d, file_handle)) { if (!strcmp(resource_name, file_handle->name)) { @@ -78,7 +80,7 @@ char shopen(char* resource_name, unsigned long required_flags, } } - return 1; + return 2; } /** @@ -159,11 +161,11 @@ char shseek(struct shared_resource* f, long offset, unsigned char whence) if ((long)f->position < 0) { f->position = 0; - return 1; + return 2; } if (f->position > f->length) { f->position = f->length; - return 1; + return 3; } return 0; @@ -180,15 +182,16 @@ shared_resource_dir shdopen(void) char i; if (do_shres_trap(0)) { - return 0xffff; + return 0xffff; } sdcard_busy_wait(); + // Verify magic string in sector 0 for (i = 0; magic_string[i]; i++) { if (lpeek(0xffd6e00L + i) != magic_string[i]) { - return 0xffff; + return 0xffff; } } From 106c10d4c6034ab9c95d4f18ae56c6ce564ffe8e Mon Sep 17 00:00:00 2001 From: Paul Gardner-Stephen Date: Thu, 1 Jan 2026 16:23:53 +1030 Subject: [PATCH 29/29] Reduce memory requirements for shres #76 --- include/mega65/shres.h | 17 ++++++++++++++-- src/shres.c | 45 +++++++++++++++++++++++------------------- 2 files changed, 40 insertions(+), 22 deletions(-) diff --git a/include/mega65/shres.h b/include/mega65/shres.h index 4a52e1e..97186b5 100644 --- a/include/mega65/shres.h +++ b/include/mega65/shres.h @@ -40,7 +40,7 @@ extern unsigned char shres_regs[5]; * sector info), as well as an in-memory field to track read position for * streaming access. */ -struct shared_resource { +struct shared_resource_dirent { /// First sector of the resource. unsigned long first_sector; @@ -58,11 +58,23 @@ struct shared_resource { /// Null-terminated name of the resource (up to MAX_RES_NAME_LEN). char name[MAX_RES_NAME_LEN + 1]; +}; + +struct shared_resource { + /// First sector of the resource. + unsigned long first_sector; + + /// Length of the resource in sectors. + unsigned long length_in_sectors; + + /// Length of the resource in bytes. + unsigned long length; /// Current read position in bytes (used internally; not stored on disk). unsigned long position; }; + /// Type alias for a directory handle (really a sector index). #define shared_resource_dir unsigned int @@ -118,6 +130,7 @@ shared_resource_dir shdopen(void); * - 2 if end of directory reached (no more entries match). */ char shdread(unsigned long required_flags, - shared_resource_dir* directory_handle, struct shared_resource* dirent); + shared_resource_dir* directory_handle, + struct shared_resource_dirent* dirent); #endif // SHRES_H diff --git a/src/shres.c b/src/shres.c index 9b50110..50424e0 100644 --- a/src/shres.c +++ b/src/shres.c @@ -65,6 +65,8 @@ char do_shres_trap(unsigned long arg) * @return 0 on success, 1 if the resource was not found or an error occurred. */ +struct shared_resource_dirent sr_dirent; + char shopen(char* resource_name, unsigned long required_flags, struct shared_resource* file_handle) { @@ -74,9 +76,13 @@ char shopen(char* resource_name, unsigned long required_flags, return 1; } - while (!shdread(required_flags, &d, file_handle)) { - if (!strcmp(resource_name, file_handle->name)) { - return 0; + while (!shdread(required_flags, &d, &sr_dirent)) { + if (!strcmp(resource_name, sr_dirent.name)) { + lcopy((unsigned long)&sr_dirent, + (unsigned long)file_handle, + sizeof(struct shared_resource)); + file_handle->position=0; + return 0; } } @@ -179,24 +185,24 @@ char shseek(struct shared_resource* f, long offset, unsigned char whence) */ shared_resource_dir shdopen(void) { - char i; + unsigned char i; - if (do_shres_trap(0)) { + if (do_shres_trap(0)) { + return 0xffff; + } + + sdcard_busy_wait(); + + + // Verify magic string in sector 0 + for (i = 0; magic_string[i]; i++) { + if (lpeek(0xffd6e00L + i) != magic_string[i]) { return 0xffff; } - - sdcard_busy_wait(); - - - // Verify magic string in sector 0 - for (i = 0; magic_string[i]; i++) { - if (lpeek(0xffd6e00L + i) != magic_string[i]) { - return 0xffff; - } - } - - // Directory starts at sector 1 - return 1; + } + + // Directory starts at sector 1 + return 1; } /** @@ -213,7 +219,7 @@ shared_resource_dir shdopen(void) * - 2 if end of directory reached (no more entries). */ char shdread(unsigned long required_flags, - shared_resource_dir* directory_handle, struct shared_resource* dirent) + shared_resource_dir* directory_handle, struct shared_resource_dirent* dirent) { do { if (do_shres_trap(*directory_handle)) { @@ -229,7 +235,6 @@ char shdread(unsigned long required_flags, // Copy entry from buffer into dirent lcopy(0xffd6e00L, (unsigned long)dirent, 256); - dirent->position = 0L; (*directory_handle)++; } while ((dirent->flags & required_flags) != required_flags);