202 lines
7.9 KiB
C
202 lines
7.9 KiB
C
// 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
|