ProDOS-8 / ProDOS8-Testing

QA and Testing for ProDOS-8 Releases
MIT License
29 stars 1 forks source link

ProDOS 2.4.2: Bitsy Bye leaves paths for BASIS.SYSTEM with high bits set #68

Open inexorabletash opened 1 year ago

inexorabletash commented 1 year ago

Description

When launching an interpreter (e.g. BASIC.SYSTEM or BASIS.SYSTEM), in addition to populating the interpreter's $2006 with the path to the file, the Bitsy Bye / BASIS.SYSTEM convention is to set $280 to the containing path of the target, and $380 to the path to the interpreter.

Expected Behavior

I'd expect both of these paths to be ProDOS's usual ASCII (7 bit values, so high bit clear)

Actual Behavior

Steps to Reproduce

  1. Boot ProDOS 2.4.2
  2. Launch a BASIC file
  3. Break into the monitor (or use an emulator's debugger) and inspect $280 / $380

Context

I'm not aware of any code that uses $280 / $380, but if this convention is going to be established then it should be well defined. I've updated A2DeskTop to populate $380 when invoking an interpreter, and I'm leaving it with high bits clear.

NOTE: Edited to correct: Bitsy populates the path at $280 to the full containing path of the target (e.g. "/VOL/DIR") not just the volume.

inexorabletash commented 1 year ago

Similarly, Bitsy doesn't uppercase the paths. This has proven to be a compat issue with a BASIS.SYSTEM tested on the II+ (or using a PLUS.SYSTEM that fakes it) that used PRORWTS2. When run on a IIe (without PLUS.SYSTEM) the paths were mixed case, which confused the code.

(This could be argued to be an app bug.)

inexorabletash commented 1 year ago

More disturbing: I noticed that when Bitsy Bye launches a SYS file, per https://prodos8.com/docs/techref/writing-a-prodos-system-program/ the path to the system file is left at $280 so that the system file can "locate any files it needs for processing". But Bitsy leaves the high bits set in the path at $280.

oliverschmidt commented 1 year ago

When launching an interpreter (e.g. BASIC.SYSTEM or BASIS.SYSTEM), [...] the Bitsy Bye / BASIS.SYSTEM convention is to set $280 to the path of the root volume [...]

[...] when Bitsy Bye launches a SYS file, per https://prodos8.com/docs/techref/writing-a-prodos-system-program/ the path to the system file is left at $280 [...]

Even after reading this multiple times, it still seems to me that those two statements contradict each other. Maybe/likely I'm missing the point...

I'm not aware of any code that uses $280 / $380

Because of the ambiguity above the following might not be relevant, but just to be sure...

The statement The complete or partial pathname of the system program is stored at $280, starting with a length byte. The string is a full pathname if it starts with a slash. It is a partial pathname if it starts with a letter. is potentially leveraged by every cc65 program via access to argv[0] - https://github.com/cc65/cc65/blob/master/libsrc/apple2/mainargs.s#L45-L46

And at least one cc65 program makes actual use of that feature - https://github.com/cc65/ip65/blob/main/apps/wget65.c#L453-L461

inexorabletash commented 1 year ago

Re: seeming contradiction: There's a difference between launching a system file directly (which should get self path at $280) and launching a system file as an interpreter (e.g. BASIC.SYSTEM or BASIS.SYSTEM) for a target file (e.g. BAS or whatever) which should at least get the target path at $2006.

Interpreters (BASIS.SYSTEM and BASIC.SYSTEM) launched with a target get "enhanced" behavior from Bitsy Bye - not only the target path at $2006 but $280 and $380 set. (IMHO those should be swapped but I wasn't in the room when Bitsy was designed.)

inexorabletash commented 1 year ago

Re: cc65 / argv[0] - maybe double check my observation by launching a system file directly from BitsyBye and checking the path? I was using 2.4.2 and a debugger to inspect $280 right when $2000 was executed, but it seems surprising to me that we wouldn't have noticed this before. (Maybe cc65 strips the high bits transparently?)

oliverschmidt commented 1 year ago

[...] launching a system file as an interpreter (e.g. BASIC.SYSTEM or BASIS.SYSTEM) for a target file [...]

I see, at least I believe I do. In that case I hope, that this behavior is limited to "some" well known (or configurable) list of interpreters. Because in general, any SYSTEM file has the right to expect its own path at $280, no matter if a $2006 startup file is given or not.

And btw. I totally agree with you not understanding why the $280 semantics wasn't just left alone and the root volume added as additional, backward-compatible feature at $380.

oliverschmidt commented 1 year ago

maybe double check my observation by launching a system file directly from BitsyBye and checking the path?

I can indeed easily reproduce the issue.

#include <stdio.h>

void main (int argc, char *argv[])
{
    char *c = argv[0];
    while (*c)
        printf("%02X ", *c++);
    printf("\n");
    getchar();
}

From BASIC.SYSTEM: image

From BitsyBye: image

inexorabletash commented 1 year ago

Re: interpreters: I believe Bitsy only handles BAS files with BASIC.SYSTEM and any other file with BASIS.SYSTEM if it's present at the root of the volume. Name intentionally chosen as only one character different to squeeze it in.

(The BASIS.SYSTEM protocol idea is really nifty. It has allowed things like demo disks full of audio/video files that can be launched from Bitsy if the bundled player is named BASIS.SYSTEM. I've added similar support into A2D so you can just double-click those files and the player they're packaged with is invoked on them.)

oliverschmidt commented 1 year ago

Sorry for not being explicit enough. I understand the BASIS.SYSTEM idea pretty well (at least I think I do). I actually offered John to write a configuration utility that allows the user to edit the associations between file types and programs to launch: https://groups.google.com/g/comp.sys.apple2/c/HKF3KhkYBaM/m/6zZr2IZVAAAJ

JohnMBrooks commented 1 year ago

The short answer is that the path at $280 and file at $380 are not 'clean' bit7=0 due to code size limitations (ie, $300 bytes in P8 for the BitsyBye program selector code).

The path at $280 is set via a P8 online call (bit7=0), but then a leading slash ($AF) is both stored onscreen and stored at the start of the path buffer.

The basis filename passed to the launcher SYS file comes from the selected file as it is printed onscreen, so has bit7=1.

ProDOS accepts (expects?) bit7=1 paths and filenames. Here is part of the P8 parser:

0E092 E092 B1 48               5            lda (tpath),y   ; get character
0E094 E094 29 7F               2            and #$7f        ; we're not interested in high order bit.
0E096 E096 E8                  2            inx         ; prepare for next character.
0E097 E097 C8                  2            iny
0E098 E098 C9 2F               2            cmp #$2f        ; is it delimiter "/"?
0E09A E09A F0 40         0E0DC 2            beq endname     ; branch if it is.
0E09C E09C C9 61               2            cmp #$61        ; is it lower case character?
0E09E E09E 90 02         0E0A2 2            bcc notlower    ; branch if not.
0E0A0 E0A0 29 5F               2            and #$5f        ; upshift to upper case
0E0A2 E0A2 9D D700             5    notlower    sta pathbuf,x   ; store charcter.

I doubt it would take much additional code to keep both the $280 path and $380 filename as bit7=0. I will look into it.

inexorabletash commented 1 year ago

Thanks John! I figured as much.

ProDOS's parser handles bit7=1, but my loop stripping off the filename to then set the prefix was looking for #$2F and having a bad time.

All of this can be worked around and 2.4.2 has been in the wild long enough that programs will need to be resilient, but I figured I should report the issues anyway, if only for posterity/documentation.