Skip to content

MON 50B OpenFile (OPEN) - emulation notes

Behaviour-focused model of the SINTRAN III L-VSX-500 OPEN handler for an emulator author. Grounded in the byte-verified disassembly 050B-OPEN.ASM (OPENF entry 123525B in 006-S3FS.bin) plus the official parameter/error tables. Anything not byte-traced is marked UNVERIFIED.

Registers / parameters

MON 50B is called with a 4-parameter list (SINTRAN passes them via the standard monitor-call parameter block; the ND-100 MAC form loads A/T/X directly):

  param 1 : file number        INT  (in/out; the caller's file-number cell)
  param 2 : access code        INT  (in)   e.g. R, W, RW, RX, WX, D, ...
  param 3 : file name          STR  (in)   pointer to a packed 2-char/word name
  param 4 : default file type  STR  (in)   e.g. "SYMB", "DATA", "BRF"

Return: on success A = file number (>= 0), skip/normal return. On failure A = a file-system error code (see table) and the error return is taken; the program normally follows MON 50 with MON 65 (ErrorMessage) which aborts on a non-zero code.

Control flow (verified against 050B-OPEN.ASM)

OPENF:
    enter monitor frame                      ; 123531B call 003752B (resident)
    CLPAR(file name)                         ; 123536B call 044777B
        on parse error -> return err         ; 123537B -> 123612B
    CLPAR(default type)                      ; 123541B call 044777B
        on parse error -> return err         ; 123542B -> 123612B
    ; --- validate access code ---
    for entry in ACCESS_TABLE[0..8]:         ; 123545B..123554B  (9 entries, SAT 11)
        if access_code == entry: goto ok
    A := 104B ; return err                    ; 123555B "No such access code"
ok: ...                                        ; 123557B call 010500B (resident)
    A := FOPEN(name, access, type)            ; 123565B call 067432B
        on FOPEN error -> return err          ; 123566B -> 123614B
    store file number into param 1            ; 123574B..123606B
    return A = file number                    ; 123611B -> 003776B (resident exit)

CLPAR (044777B) parses a string parameter, matching two-letter mnemonics (the disassembly checks ASCII 'R' 'W' 'S' 'A' 'F' 'I' 'D' 'B' 'L' 'O' 'X'); it is used for the default-type / access spelling. FOPEN (067432B) performs the directory lookup by name and allocates an open-file-table slot; its own error constants seen in code include SAA 122B (too many files).

Q1 - empty / all-zero name

There is no default-file, init-file, or scratch fallback in OPEN. Scratch and direct opens are separate calls (235B ScratchOpen -> OPENS; 220B DirectOpen -> DOPEN). An empty name terminates at the first NUL, the directory search matches nothing, and OPEN returns an error (non-zero A). Best-supported code: 056B "No such file name" (HIGH confidence it is an error; MEDIUM that the code is exactly 056B vs a CLPAR parameter error such as 021B "Illegal character in parameter" / 044B "Too long parameter").

Emulator rule: OPEN(name="") -> error, never success. Do not synthesise a default/scratch file.

Relevant file-system error codes (octal; from ND-60.050.06 Users Guide)

Code Meaning Where
000 Illegal monitor call internal-error class
003 End of File RFILE next read past EOF
021 Illegal character in parameter name/type parse
044 Too long parameter name/type parse
056 No such file name directory search (empty/unknown name)
057 Ambiguous file name directory search
074 No such file version directory search
104 No such access code OPENF access-code table (VERIFIED at 123555B)
105 File already opened FOPEN
107 Attempt to open too many files FOPEN
121 Too many mass-storage files FOPEN
122 Attempt to open too many files FOPEN (SAA 122B seen in code)

Pseudocode

function OPEN(fileno_cell, access_code, name_str, type_str) -> A:
    name = parse_string(name_str)          # CLPAR; may raise 021/044
    type = parse_string(type_str)          # CLPAR
    if access_code not in ACCESS_TABLE:     # 9 valid codes
        return err(0o104)                   # No such access code

    if name is empty:                       # all-zero / zero-length
        return err(0o056)                   # No such file name  (no fallback)

    ent = directory_lookup(name, type, access_code)
    if ent is None:
        return err(0o056)                   # No such file name
    if no_free_open_slot():
        return err(0o122)                   # Attempt to open too many files
    if already_open_conflict(ent, access_code):
        return err(0o105)                   # File already opened
    slot = allocate_open_file_entry(ent, access_code)
    store fileno_cell = slot.file_number
    return slot.file_number                 # success (A >= 0)

C sketch (emulator side)

/* Return value: >=0 file number on success, negative -errcode on failure.
   The caller mirrors it into A and (for the file-number cell) param 1. */
int sintran_open(uint16_t *fileno_cell, int access_code,
                 const uint8_t *name, size_t name_len,
                 const char *deftype)
{
    /* 1. access code must be one of the 9 valid codes (OPENF table @123545B) */
    if (!access_code_valid(access_code))
        return -0104;                 /* octal 104: No such access code */

    /* 2. empty / all-zero name has NO special meaning in MON 50B.
          Names are NUL/apostrophe terminated; an all-zero buffer is empty.   */
    size_t n = 0;
    while (n < name_len && name[n] != 0 && name[n] != '\'' )
        n++;
    if (n == 0)
        return -0056;                 /* octal 056: No such file name        */
                                      /* (NOT a scratch/default open)         */

    /* 3. directory lookup by (name, deftype) */
    dir_entry_t *e = fs_dir_lookup(name, n, deftype);
    if (e == NULL)
        return -0056;                 /* No such file name                   */

    /* 4. allocate an open-file-table slot (FOPEN @067432B) */
    int slot = oft_alloc(e, access_code);
    if (slot == OFT_FULL)   return -0122; /* Attempt to open too many files  */
    if (slot == OFT_INUSE)  return -0105; /* File already opened             */

    *fileno_cell = (uint16_t)oft_file_number(slot);
    return oft_file_number(slot);
}

Not verified / open items

  • Exact error for a zero-length name (056B vs a CLPAR parameter code) - the name-analysis / directory-search that emits 056B lives in resident routines (003752B, and code reached from FOPEN) whose L-binary addresses are offset from the L07 resident symbol table, so they were not byte-traced here.
  • The 9 concrete access-code values in the OPENF table were not decoded (they are compared as data at 123550B-relative offsets); the emulator can use the documented access mnemonics (R, W, RW, RX, WX, WA, D, ...) instead.