1

Topic: Application Package Format

I've created an application package format for SE Basic IV 4.2. I'm considering creating a dot command version that would enable programs that don't depend on the ROM to run on esxDOS as well. Applications are stored as a collection of files and folders within a  folder in a top-level folder called PROGRAMS. Application names can be any length and contain any valid FAT32 filename character (including space). In SE Basic, applications are launched with RUN "appname". The dot command equivalent would be .run appname. The application name is truncated to derive the folder and binary filenames and spaces are converted to underscores. The package format is as follows:

PROGRAMS
|----------- MY_APP_N.AME
             |----------- PRG
                          |----------- MY_APP_N.PRG
                          RSC
                          |----------- RESOURCE.BIN

The RUN command sets the SP to $6000, loads the binary (PRG file) at $6000, changes the path to the resource (RSC) folder and calls $6000. If the binary fails to load it restores the stack and falls back to BASIC. This means the binary can be up to 40K in length. The binary is then responsible for loading its own resources. The method for passing parameters to the app is to define a variable in BASIC.

This approach has a number of advantages over the single executable file method. For example, with multi-lingual software, only the selected language resources need to be loaded. It is also easy to customize the app without the need to recompile it.

2 (edited by aowen 2019-07-01 11:10:13)

Re: Application Package Format

I've created a DOT command version. Will work with any version of esxDOS that has a RET command at $1FFA in the ROM.

Syntax: .RUN program name

Base64 encoded:

fbQgGzc+AskR3iAB/wt+p8j+Osj+DcjtoBDz6zYAyc0IICGzIBH+IAEKAO2wId4gAQsAfv4gIAM+X3ftoH6nKAR5sCDuIbwgAQYA7bA+KiH+IM+pOK7tc84gMQBgId0gBgkjfqcoAhD56yHCIAEFAO2wId4gPioGAc+aOIcy0CAh0SDPodoEIDrQIO1L2CAhAGDPndoEIDrQIM+bOA4+KiHHIM+pIQBg5cP6H+17ziDaBCAvcHJvZ3JhbXMvcHJnLwAucHJnAC4uL3JzYwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==

Decoder

3

Re: Application Package Format

Example SCREEN$ slideshow app.
Compile the source to ZXSHOW.PRG and put it in: /PROGRAMS/ZXSHOW/PRG/
Put the .SCR files you want to display in: /PROGRAMS/ZXSHOW/RSC/
Launch the app with: .RUN ZXSHOW

    divmmc equ 8;
    hook_base equ 128;
    misc_base equ hook_base + 8;
    fsys_base equ misc_base + 16;
    disk_status equ hook_base + 0;
    disk_read equ hook_base + 1;
    disk_write equ hook_base + 2;
    disk_ioctl equ hook_base + 3;
    disk_info equ hook_base + 4;
    m_dosversion equ misc_base + 0;
    m_getsetdrv equ misc_base + 1;
    m_driveinfo equ misc_base + 2;
    m_tapein equ misc_base + 3;
    m_tapeout equ misc_base + 4;
    m_gethandle equ misc_base + 5;
    m_getdate equ misc_base + 6;
    f_mount equ fsys_base + 0;
    f_umount equ fsys_base + 1;
    f_open equ fsys_base + 2;
    f_close equ fsys_base + 3;
    f_sync equ fsys_base + 4;
    f_read equ fsys_base + 5;
    f_write equ fsys_base + 6;
    f_seek equ fsys_base + 7;
    f_fgetpos equ fsys_base + 8;
    f_fstat equ fsys_base + 9;
    f_ftruncate equ fsys_base + 10;
    f_opendir equ fsys_base + 11;
    f_readdir equ fsys_base + 12;
    f_telldir equ fsys_base + 13;
    f_seekdir equ fsys_base + 14;
    f_rewinddir equ fsys_base + 15;
    f_getcwd equ fsys_base + 16;
    f_chdir equ fsys_base + 17;
    f_mkdir equ fsys_base + 18;
    f_rmdir equ fsys_base + 19;
    f_stat equ fsys_base + 20;
    f_unlink equ fsys_base + 21;
    f_truncate equ fsys_base + 22;
    f_attrib equ fsys_base + 23;
    f_rename equ fsys_base + 24;
    f_getfree equ fsys_base + 25;
    fa_read equ %00000001;
    fa_write equ %00000010;
    fa_open_ex equ %00000000;
    fa_open_al equ %00001000;
    fa_create_new equ %00000100;
    fa_create_al equ %00001100;
    fa_use_header equ %01000000;

    org $6000

setup:
    xor a;                                // LD A, 0;
    out ($fe), a;                        // set black border

read_files:
    ld b, 0;                            // folder access mode (read only)
    ld a, '*';                            // use current drive
    ld ix, folder_path;                    // folder path buffer
    rst divmmc;                            // issue a hookcode
    defb f_opendir;                        // open folder
    ld (handle_p), a;                    // store path handle

read_files_2:
    ld ix, folder_entry;                // buffer
    ld a, (handle_p);                    // get path handle
    rst divmmc;                            // issue a hookcode
    defb f_readdir;                        // read a folder entry
    or a;                                // last entry?
    jr z, last_entry;                    // jump if so
    ld hl, folder_entry;                // buffer
    ld a, (hl);                            // attibutes to A
    and %00010000;                        // folder?
    jr nz, read_files_2;                // skip folders

    ld ix, folder_entry + 1;            // ASCIIZ filename
    ld a, '*';                            // use current drive
    ld b, fa_read | fa_open_ex;            // open for reading if file exists
    rst divmmc;                            // issue a hookcode
    defb f_open;                        // open file
    ld (handle_f), a;                    // store file handle

    ld ix, $4000;                        // offset 0 in frame buffer
    ld bc, 6912;                        // byte count
    call load;                            // load the 1st half of file

    ld a, (handle_f);                    // file handle
    rst divmmc;                            // issue a hookcode
    defb f_close;                        // close file

space:
    ld a, $7f;                            // high byte of I/O address
    in a, ($fe);                        // read byte
    rra;                                // set carry if space pressed
    jr c, space;                        // loop if not
    jr read_files_2;                    // do next entry

load:
    ld a, (handle_f);                    // file handle
    rst divmmc;                            // issue a hookcode
    defb f_read;                        // read bytes
    ret;                                // end of subroutine

last_entry:
    ld a, (handle_p);                    // get folder handle
    rst divmmc;                            // issue a hookcode
    defb f_close;                        // close it
    jp read_files;                        // loop

handle_p:
    defb 0;                                // path handle

handle_f:
    defb 0;                                // file handle

folder_path:
    defb "/programs/zxshow/rsc", 0;    // folder path

folder_entry:
    defb 0;                                // folder entry