// IIgs GS/OS file I/O wrappers. // // GS/OS calls dispatch through $E100A8 with X holding the call number // and a 16-bit pointer to a class-1 parameter block pushed on the // stack. The parm block layout is per-call but always begins with a // pCount field giving the number of parameters used. // // These wrappers are STUBS — they construct the parm blocks and call // the dispatcher, but require the caller to have a real ProDOS volume // mounted (or equivalent GS/OS volume) for the calls to succeed. // Without that, the dispatcher returns an error code or hangs. // // To use these in MAME smoke tests you'd need: // - A 2img / po / dsk image containing a ProDOS volume // - MAME launched with the image as floppy or hard-disk // - Tool Locator + GS/OS init via iigsToolboxInit() // None of which the current smoke harness provides — these wrappers // are infrastructure for a future GS/OS-aware test rig. // // Class-1 GS/OS calls (pCount-prefixed): // $2001 Create // $2002 Destroy // $2004 ChangePath // $2010 Open // $2012 Read // $2013 Write // $2014 Close // $2016 SetMark // $2017 GetMark // $2018 SetEOF // $2019 GetEOF // $2029 Quit (special — no return) // See "GS/OS Reference" for the full ~50 calls and parm-block layouts. #ifndef IIGS_GSOS_H #define IIGS_GSOS_H #ifdef __cplusplus extern "C" { #endif // GS/OS string descriptor: 2-byte length + char data (no NUL). // Use with caller-allocated storage: // struct { unsigned short len; char text[14]; } pname = { 6, "MYFILE" }; typedef struct { unsigned short length; char text[1]; // variable-length; total size = length + 2 } GSString; // Class-1 Open parm block. typedef struct { unsigned short pCount; // 2 (or up to 12 for full options) unsigned short refNum; // [out] file reference number void *pathname; // [in] GSString * // Optional fields (if pCount > 2): requestAccess, resourceNumber, // accessRequested, optionList, ... — left out for the basic open. } OpenParm; // Class-1 Read/Write parm block. typedef struct { unsigned short pCount; // 4 unsigned short refNum; // [in] file reference void *dataBuffer; // [in] in-bank pointer to buffer unsigned long requestCount; // [in] bytes requested unsigned long transferCount;// [out] bytes actually transferred } IORecGS; // Class-1 Close / GetEOF / SetEOF / etc. — simple refNum-only blocks. typedef struct { unsigned short pCount; // 1 unsigned short refNum; } RefNumRecGS; typedef struct { unsigned short pCount; // 2 unsigned short refNum; unsigned long eof; } EOFRecGS; // Class-1 SetMark/GetMark parm block — 32-bit position within file. typedef struct { unsigned short pCount; // 2 unsigned short refNum; unsigned long position; // [in for SetMark, out for GetMark] } MarkRecGS; // Class-1 Destroy parm block — single pathname. typedef struct { unsigned short pCount; // 1 void *pathname; // [in] GSString * } DestroyRecGS; // Class-1 ChangePath parm block — old + new pathname (same-dir rename). typedef struct { unsigned short pCount; // 2 void *oldPathname; // [in] GSString * void *newPathname; // [in] GSString * } ChangePathRecGS; // GS/OS ResultBuf — caller-allocated max-length buffer for routines // that return a variable-length string (Get_Prefix, Get_Dir_Entry's // name field). The OS writes a 2-byte length followed by the string // bytes (no NUL). maxLen is the size of bufString.text + 2; if the // answer is longer, GS/OS returns a "buffer too small" error and // leaves bufString.length set to the required length so the caller // can retry. typedef struct { unsigned short maxLen; // [in] sizeof(bufString) - 2 GSString bufString; // [out] length + text } ResultBuf; // Class-1 Get_Prefix parm block ($200A). Reads the value of a // numbered prefix (0 = default/cwd, 8 = working directory, 1..31 = // user prefixes). Returns the prefix's effective pathname in // `prefix->bufString` with length set to the actual returned length. typedef struct { unsigned short pCount; // 2 unsigned short prefixNum; // [in] 0..31 void *prefix; // [in/out] ResultBuf * } PrefixRecGS; // Class-1 Get_File_Info parm block ($2006). pCount controls which // fields the OS fills in (callers usually set pCount=12 for full info // or pCount=4 when they only need storageType to distinguish file // from directory). storageType: 1=seedling, 2=sapling, 3=tree, // 4=Pascal area, 5=extended, 13=directory, 15=volume directory. typedef struct { unsigned short pCount; // 1..12 void *pathname; // [in] GSString * unsigned short access; // [out] unsigned short fileType; // [out] unsigned long auxType; // [out] unsigned short storageType; // [out] unsigned char createDate[8];// [out] unsigned char modDate[8]; // [out] void *optionList; // [out] OptionList * unsigned long eof; // [out] unsigned long blocksUsed; // [out] unsigned long resourceEOF; // [out] unsigned long resourceBlocks;// [out] } FileInfoRecGS; // Class-1 Get_Dir_Entry parm block ($201C). Iterates a directory // opened via gsosOpen() — set base=0/displacement=+1 to advance to // the next entry. Returns $61 endOfDir when no more entries. // `name` receives the entry's filename via the supplied ResultBuf. typedef struct { unsigned short pCount; // 1..18 unsigned short refNum; // [in] dir reference number unsigned short flags; // [in] reserved, set 0 unsigned short base; // [in] 0=current, 1=first, 2=mark unsigned short displacement; // [in] +N entries from base void *name; // [in/out] ResultBuf * unsigned short entryNum; // [out] absolute entry # within dir unsigned short fileType; // [out] unsigned long eof; // [out] unsigned long blockCount; // [out] unsigned char createDate[8];// [out] unsigned char modDate[8]; // [out] unsigned short access; // [out] unsigned long auxType; // [out] unsigned short fileSysID; // [out] void *optionList; // [out] OptionList * unsigned long resourceEOF; // [out] unsigned long resourceBlocks;// [out] } DirEntryRecGS; // Open / Read / Write / Close wrappers. Each returns 0 on success or // a non-zero GS/OS error code (see gsos.h reference for codes). The // parm block lives on the caller's stack; you set the input fields // before the call and read output fields after. // // Implementation lives in runtime/src/iigsGsos.s — needed because the // W65816 backend's inline asm can't take memory operands for the // parm-block address. extern unsigned short gsosOpen (OpenParm *p); extern unsigned short gsosRead (IORecGS *p); extern unsigned short gsosWrite (IORecGS *p); extern unsigned short gsosClose (RefNumRecGS *p); extern unsigned short gsosGetEOF (EOFRecGS *p); extern unsigned short gsosSetEOF (EOFRecGS *p); extern unsigned short gsosSetMark(MarkRecGS *p); extern unsigned short gsosGetMark(MarkRecGS *p); extern unsigned short gsosDestroy (DestroyRecGS *p); extern unsigned short gsosChangePath(ChangePathRecGS *p); extern unsigned short gsosGetPrefix (PrefixRecGS *p); extern unsigned short gsosGetFileInfo(FileInfoRecGS *p); extern unsigned short gsosGetDirEntry(DirEntryRecGS *p); // Returns 1 when a real GS/OS dispatch surface is linked (either // iigsGsos.o for bare-metal or libcGno.o for GNO/ME), 0 when only // the universal-success stub (iigsGsosStub.o) is linked, and 0 when // no GS/OS surface is linked at all. Newly-added GS/OS wrappers // should check this BEFORE issuing a call so the stub can't silently // fabricate success — see Phase 1.2 of docs/GAP_CLOSURE_PLAN.md. extern int __gsosAvailable(void); #ifdef __cplusplus } #endif #endif // IIGS_GSOS_H