ProDOS Bitsy Bye

Documentation & code source.

1ère publication: lundi 07/01/2019.


Documentation


Bitsy Bye du néo ProDOS 2.4.2 est le program selector remplaçant le standard "MLI Quit" d'Apple.
Comme son prédécesseur, il est intégré à ProDOS mais a l'avantage de pouvoir s'exécuter sur les différentes plateformes de la gamme Apple II.
En effet, il est en mode texte 40 colonnes et n'utilise que le jeu d'instructions du 6502.

Au lancement, il affiche le contenu du dernier volume ProDOS utilisé.

Bitsy Bye screen

AFFICHAGE DU CONTENU

Chaque nom de fichier peut être précédé d'un caractère.
S'il y en a un, cela signifie que le type du fichier est géré par le program selector.
Les caractères suivants peuvent être affichés: I (BASIC INTEGER: ProDOS type $FA), B (BIN: ProDOS type $06), A (BASIC APPLESOFT: ProDOS type $FC), T (TXT EXEC: ProDOS type 04), - (SYS: ProDOS type $FF ou SYS16: ProDOS type $B3).
Bitsy Bye prend donc en compte davantage de types de fichiers que son précédesseur.
A noter la particularité du sous-répertoire pour lequel le caractère "/" se trouve collé au nom et décalé par rapport aux autres noms de fichiers.


NAVIGATION SUR LES DIFFERENTS VOLUMES

TAB ou CTRL-I : passe au volume suivant (navigation sur les numéros de slot en décroissant et en numéros de lecteurs croissants).
1..7 : sélectionne le volume correspondant au slot choisi et charge le contenu du volume. A noter qu'en cas de choix successifs du même slot, cela effectue un toggle sur le numéro du lecteur.


NAVIGATION SUR LE VOLUME EN COURS

Flèche DROITE ou Flèche BAS ou CTRL-J : fait descendre le curseur vers le bas si c'est possible. Eventuel scroll de la liste vers le haut si le curseur se trouvait en milieu d'écran.
Flèche GAUCHE ou Flèche HAUT ou CTRL-H ou CTRL-K : fait monter le curseur vers le haut si c'est possible. Eventuel scroll de la liste vers le bas si le curseur se trouvait en milieu de page.

ESC : tente de remonter au répertoire parent. Si l'utilisateur est déjà au niveau root, reste sur place.
A..Z : positionne comme 1er nom en haut de l'écran le 1er fichier dont la 1ère lettre commence par la lettre saisie. La recherche commence à s'effectuer à partir de l'emplacement du curseur et vers le bas. En cas d'échec, la recherche recommence depuis le début.
Exemple ci-dessous. Sur le 1er écran, je tape "F". Le 1er nom de fichier commençant par cette lettre à partir du curseur est "FASTDSK".


Bitsy Bye screen
Bitsy Bye screen

RETURN sur le nom d'un sous-répertoire:  affichage de son contenu et retourne au gestionnaire de touches. A noter que sur la 1ère ligne est affiché le chemin complet, après le slot et le drive. Si le nom dépasse la longueur de l'écran, alors seule la fin du nom du path sera affichée.

Bitsy Bye est moins sensible que son précédesseur aux erreurs rencontrées lors d'un accès drive. Il essayera d'aller jusqu'au bout en récupérant tous les fichiers présents sur le volume/répertoire pour les présenter dans sa liste.


SELECTION D'UN FICHIER

La sélection s'effectue en appuyant sur la touche RETURN lorsque le curseur est au dessus d'un fichier dont le type est géré.
Le program selector effectue alors un SET PREFIX sur le chemin correspondant.

Si sélection d'un fichier SYS, alors chargement en $2000 et lancement.

Si sélection d'un fichier BASIC INTEGER, BASIC APPLESOFT, BIN, SYS16 ou TXT (pour faire EXEC) alors charge BASIS.SYSTEM en $2000.
- Si présent, ajout à partir de $2006 du nom du fichier sélectionné comme élément à exécuter, puis BRUN de BASIS.SYSTEM. Le fichier sélectionné sera alors lancé ensuite automatiquement.
- Si BASIS.SYSTEM est absent alors retente la même chose avec BASIC.SYSTEM.

BASIS.SYSTEM a été présenté par John Brooks comme le moyen de lancer un driver (ou une fonctionnalité précise selon le besoin de l'utilisateur) juste avant d'exécuter le fichier sélectionné.


Source complet et commenté pour ACME

Pour faire suite à un autre dossier sur le MLI Quit du ProDOS 8 2.0.3, ci-dessous le code source (introuvable ailleurs) de la version 2.4.2 de Bitsy Bye.
Dans un anglais approximatif mais qui sera toujours mieux qu'en français pour les quelques personnes que c'est susceptible d'intéresser.
A noter que ce ne fut pas évident à comprendre du fait de l'emploi de subtilités du langage: j'ai du avoir souvent recours au bouquin "Programmation du 6502" par Rodnay Zaks (chez Sybex) pour capter le résultat d'une optimisation (et aussi parce que je commence à me faire vieux!)

Sinon, une précision: si vous avez une question, il faudra trouver la réponse par vous-même car je ne réponds plus aux emails ayant comme sujet l'Apple II...


ACME 6502 source code
ACME
Download Bitsy Bye 2.4.2 Source code from ProDOS 8 2.4.2


Oliver Schmidt, 17 janv 2018.

Hi John,

>I have Bitsy Bye fixes for the Appletalk workstation card and Mac LC Apple II card and was
>planning on releasing them with new features in 2.5 rather than doing a 2.4.2 release.

It's a pity that you haven't open sourced Bitsy Bye by now for at
least two reasons:

1. The fixes you mention above would visible as explicit commits which
I'm pretty sure would be interesting to others (aka me) too.

2. It would allow others (aka me) to (try to) create variants of the
Bitsy Bye screen layout making that probably compatible with the taste
of a larger number of users.

Regards,
Oliver



Oliver Schmidt, 17 janv 2018.

Hi John,

>I intend to open source Bitsy Bye along with several new drivers as part of ProDOS 2.5.

Cool :-)

>The issue is that Bitsy Bye 2.4 is parsing directories in a way that is incompatible with ProDOS 2.5,
>so I want to hold off sharing that version.

I see, although - as mentioned in PM - I personally would prefer to
see the 2.4 version released and the changes you made/make for 2.5
made visible as changes so that the history becomes available too.

That could even become a positive thing for you personally. I imagine
people having written software that's incompatible with 2.5 asking you
what they need to change. Then you could - beside giving a conceptual
answer - point them to your BB change as an example what needs to be
done. Coding more as a social process than a purely result driven
me-myself-and-I thing ;-)

>Once the new 2.5 system is in place, it will be ready for sharing, customizing, and migrating into other apps.

Looking forward to it, although I'd have loved to be able to
contribute to 2.5 instead to post-2.5 ...

Regards,
Oliver


;@com.wudsn.ide.asm.hardware=APPLE2
!cpu 6502
!to "BITSYBYE#061000",plain
!convtab "a2txt.bin"

                    *=      $1000

;--------------------------------
; BITSY BYE 2.4.2 (18-JAN-2018)
; by John Brooks / Peter Ferrie
; (source) by Deckard 20181230
; ACME 6502 assembler
;--------------------------------

; New ProDOS 8 releases : https://prodos8.com
; Qkumba compression & code optimization master : http://pferrie.000webhostapp.com/
; Deckard : http://underground2e.free.fr

; A major new feature in the 2.4 release was replacing the OS ram-resident program launcher with a new version
; called Bitsy Bye.
; Bitsy Bye is an interactive, menu-based system for choosing which program to run next after the previous
; program exits with the quit or bye command.
; -JB

; Our tag-team optimization of Bitsy Bye in 2016 was epic.
; -JB

; Unique goal: 6502 memory exercise
; -Dckd

; Apple II memory info
; $0000..$00FF : zero page
; $0100..$01FF : stack
; $0200..$02FF : character input buffer
; $0300..$03CF : free space
; $0400..$07CF : txt screen (+variables in holes)
;
; $0B00..$0EFF : open buffer
; $1000..$12FA : Bitsy Bye 2.4.2 (code)
; $12FB..$13FF : Bitsy Bye 2.4.2 (datas)
; $1400..$BECF : structure infos (internal files list: up to 2733 files) 2733*16=$AAD0

;--------------------------------

CV                  =       $25                         ; cursor vertical position
BASL                =       $28                         ; low txt screen addr (left)
BASH                =       $29                         ; high txt screen addr (left)
CUR_SLOT_DRV        =       $56                         ; current slot/!drive fmt=0000SSS? (?=!D)
VOLNAME_LENGTH      =       $57                         ; volume name length+1 (including 1st "/")
PTR_1ST_NAME_ON_SCREEN =    $58                         ; +$59 pointer for 1st name of screen ($1400..)
PTR_WORK_NAME       =       $5A                         ; +$5B pointer used to work with names structure
PTR_CURRENT_NAME    =       $5C                         ; +$5D pointer for current name (reverse cursor)
SCREEN_POSITION     =       $5E                         ; position on screen : $00 (top)..$0A (middle)..$13 (bottom)
DISPLAY_MODE        =       $5F                         ; for AND : #%00111111 ($3F) = INVERSE / #%11111111 ($FF) = NORMAL
NAME_LENGTH         =       $60                         ; length of name $00 (no name) or $01..$0F
FIRST_CHARACTER     =       $60                         ; pressed key (research by name)
TBL_ONLINE          =       $6E                         ; table for MLI ONLINE
TBL_OPEN            =       $72                         ; table for MLI OPEN
TBL_READ            =       $78                         ; table for MLI READ

PATHNAME_LENGTH     =       $0280                       ; partial path of current volume or directory
PATHNAME            =       $0281                       ; partial path of current volume or directory

SYS_LAUNCHER_LENGTH =       $0380                       ; full (root) path to the launcher (BASIS.SYSTEM or BASIC.SYSTEM)
SYS_LAUNCHER        =       $0381                       ; full (root) path to the launcher (BASIS.SYSTEM or BASIC.SYSTEM)

TXT_LINE0           =       $0400                       ; TXT screen: line 0
TXT_LINE1           =       $0480                       ; TXT screen: line 1

H1400               =       $1400                       ; internal structure infos
SYSTEM_ADDR         =       $2000                       ; implantation addr of SYS file

; ProDOS

MLI                 =       $BF00                       ; machine language interface https://prodos8.com/docs/techref/calls-to-the-mli/
DEVNUM              =       $BF30                       ; last used device DSSS0000
BITMAP              =       $BF58                       ; memory bit map (ProDOS)

; ROM

CLR80STORE          =       $C000                       ; 80STORE off
INIT                =       $FB2F                       ; screen initialization
BASCALC             =       $FBC1                       ; calc base addr in BASL/BASH
BELL                =       $FBDD                       ; DING! an error occurs...
VTAB                =       $FC22                       ; perform vertical tab
HOME                =       $FC58                       ; clear TXT screen
RDKEY               =       $FD0C                       ; read key
SETKBD              =       $FE89                       ; IN#0
SETVID              =       $FE93                       ; PR#0

; ProDOS MLI cmds

QUIT                =       $65                         ; exit from 1 interpreter, dispatch another
GET_FILE_INFO       =       $C4                         ; return file's attributes
ONLINE              =       $C5                         ; return names of one or all online volumes
SET_PREFIX          =       $C6                         ; change default pathname prefix
OPEN                =       $C8                         ; open a file
READ                =       $CA                         ; read 1 or more bytes from an open file
CLOSE               =       $CC                         ; close open file(s), flushing buffers
GET_EOF             =       $D1                         ; return end of file position of an open file

;--------------------------------

                    CLD                                 ; bin mode (ADC/SBC)
                                                        ; valid routine

                    LDA     $C082                       ; enables rom
                    CLI                                 ; interrupts are allowed
                    STA     $C00C                       ; 40 col
                    STA     CLR80STORE
                    JSR     SETVID
                    JSR     SETKBD
                                                        ; acc=$FD (high COUT1 $FDF0) %11111101
                    STA     $04FB                       ; screen hole (scratchpad ram : slot 3)
                                                        ; VMODE for RDKEY/KEYIN (escape sequence & escape enable bit)
                                                        ; see "Inside the //c" Gary B. Little p.56/148/150

                    JSR     INIT
                    JSR     HOME

; Init ProDOS memory bitmap & copy datas in zero page

                    LDX     #$DF                        ; X=$DF..$FF
                    LDA     #%11001111                  ; $CF => used mem pages: $00/$01/$04..$07
                                                        ; (zero page/stack/txt screen)
H101E               STA     BITMAP-$DF,X                ; $BF58=$CF

                    LDA     H134F-$DF,X                 ; copy $134F..$136F
                    STA     $7A,X                       ; into $7A+[$DF..$FF]= [$59..$79] (zero page addressing mode)

                    LDA     #0                          ; $BF59..$BF78=0 (unused mem pages +open file buffers)
                    TXS                                 ; last loop: S=$FF
                    INX
                    BNE     H101E

; Apple ProDOS 8 Technical Reference Manual : Using the Stack
; System programs should set the stack pointer to $FF at the warm-start entry point.
;
; I set the stack to $FF before launching SYS files from Bitsy Bye (the new Quit dispatcher in P8 2.4)
; -JB 

                    !8      $C2,2                       ; 6502/65c02: SKB #2 (skip next bytes / unofficial opcode)
                                                        ; DOP=double NOP

                                                        ; 65816: REP#%00000010 => Z=0

                                                        ; acc=0/X=0
                    BEQ     H1034                       ; always (6502/65c02) Z=1

                                                        ; //gs only--start                 
                    INX                                 ; X=1
                    STX     $C029                       ; //gs new video register=1
                                                        ; //gs direct access to mega II aux bank
                                                        ; //gs only--stop
                   
H1034               INC     BITMAP+$17                  ; $BF6F=1: $BF mem page is used

;--------------------------------
; Build initial TXT screen with
; authors and instructions
;--------------------------------

                    LDX     #$57                        ; counter X=$57..$01 step-1
H1039               LDA     H1300-1,X                   ; $1300..$1356
                    BMI     H1045                       ; got a printable character

                                                        ; got a special byte
                                                        ; for coord update (requires 2 loop exec)
                                                        ; for each coord update, the bascalc code is executed 2 times.
                                                        ; - 1st is bad (X instead of Y coord + following byte) => ignored
                                                        ; - 2nd is correct (Y coord and X coord) and BASCALC is correct

                                                        ; comments below are for 2nd exec
                                                        ; acc=txt screen line (Y coord)                
                    JSR     BASCALC                     ; set BASL/BASH pointer
                    LDY     H1300,X                     ; get X coord (next byte)
                   
                    !8      $2C                         ; BIT trick: don't write Y coord byte on screen!

H1045               STA     (BASL),Y                    ; display printable character
                    DEY                                 ; X coord -1
                    DEX                                 ; previous data byte
                    BNE     H1039                       ; continue

                                                        ; X coord=41-1=40 (ready to write "-" line)
                                                        ; acc="-"

                                                        ; write dashed lines #1 & #22
H104B               STA     TXT_LINE1,Y                 ; write "-" on line 1
                    STA     (BASL),Y                    ; write "-" on line 22
                    DEY                                 ; until X coord<0 (exit)
                    BPL     H104B                       ; continue

;--------------------------------
; Get content of current S/Drive
;--------------------------------

; ProDOS unit numbers are bytes where the bits are arranged in the pattern DSSS0000,
; where D = 0 for drive one and D = 1 for drive two, SSS is a three-bit integer with values
; from one through seven indicating the device slot number (zero is not a valid slot number),
; and the low nibble is ignored.
;
; It isn't practical.
; A better format is 0000SSS? where ? = !D (NOT drive #)
;  0000SSS0 means !D=0 => D=1 drive 2
;  0000SSS1 means !D=1 => D=0 drive 1
;
; To search the next unit number, you just have to:
;
; LDX current 0000SSS?
; DEX
; TXA
; AND #%00001111 (if current 0000SSS? was 0, X=$FF after DEX and now acc contains S=7, !D=1 => D=0 drive 1)
; STA new current 0000SSS?
; test if volume is OK for this unit number
; if volume OK, get content...
;
; You can navigate over ProDOS volumes using TAB key.
; e.g. current volume = /PRODOS.2.4.2 in slot 6, drive 1 (X=current 0000SSS? = 00001101)
; TAB => after DEX : 00001100 slot 6, !D=0 => D=1 drive 2
; TAB => after DEX : 00001011 slot 5, !D=1 => D=0 drive 1
; TAB => after DEX : 00001010 slot 5, !D=0 => D=1 drive 2
; TAB => after DEX : 00001001 slot 4, !D=1 => D=0 drive 1
; TAB => after DEX : 00001000 slot 4, !D=0 => D=1 drive 2
; TAB => after DEX : 00000111 slot 3, !D=1 => D=0 drive 1
; TAB => after DEX : 00000110 slot 3, !D=0 => D=1 drive 2
; TAB => after DEX : 00000101 slot 2, !D=1 => D=0 drive 1
; TAB => after DEX : 00000100 slot 2, !D=0 => D=1 drive 2
; TAB => after DEX : 00000011 slot 1, !D=1 => D=0 drive 1
; TAB => after DEX : 00000010 slot 1, !D=0 => D=1 drive 2
; TAB => after DEX : 00000001 slot 0, !D=1 => D=0 drive 1 not a valide ProDOS unit #
; TAB => after DEX : 00000000 slot 0, !D=0 => D=1 drive 2 not a valide ProDOS unit #
; TAB => after DEX+TXA+AND : 00001111 slot 7, !D=1 => D=0 drive 1
; TAB => after DEX : 00001110 slot 7, !D=0 => D=1 drive 2

                                                        ; get name of last used volume
                    LDA     DEVNUM                      ; DSSS0000
                    LSR                                 ; 0DSSS000
                    LSR                                 ; 00DSSS00
                    LSR                                 ; 000DSSS0
                    TAX
; init !D
                                                        ; easy way to get !D (NOT drive #)
                    INX                                 ; X=000DSSS1 (!D=1 => D=0 drive 1)

; the original "D" in "DSSS" will not be used anymore after this CMP
; Bitsy Bye always uses 0000SSS? (?=!D)

                    CMP     #%00010000                  ; acc 000DSSS0 < 00010000 : test if D=0 (drive 1)?
                    BCC     H1060                       ; yes, drive 1
                   
                                                        ; X=000DSSS? (1st entry) D is ignored

                                                        ; X=0000SSS?
H105F               DEX                                 ; X-1
                                                        ; = switch from drive 1 (!D=1) to drive 2 (!D=0)
                                                        ; or exec slot-1, drive 1 (!D=1)

                                                        ; if drive 1: X=0000SSS1
                                                        ; if drive 2: X=0000SSS0
H1060               JSR     GET_VOLUME_NAME             ; get volume name (PATHNAME)
                    BEQ     H105F                       ; Z=1 (length=0). try another slot/drive
                   
H1065               LDA     #>H1400
                    STA     TBL_READ+3                  ; read buffer (high)
                    STA     PTR_1ST_NAME_ON_SCREEN+1    ; 1st name addr = $1400 (high)
                    LDY     #<H1400
                    STY     TBL_READ+2                  ; read buffer (low)
                    STY     PTR_1ST_NAME_ON_SCREEN      ; 1st name addr = $1400 (low)

                                                        ; Y=0 : max number of bytes of data to read (high)
                    JSR     GET_CONTENT                 ; get content of volume or sub directory and store it in internal structures ($1400..)
                    CPY     #$4C                        ; end of file (MLI Read return code)
                    BEQ     H107B                       ; ok, all files read
                   
                    JSR     BELL                        ; read error
                   
H107B               LDA     #0
                    TAY
                    STA     (TBL_READ+2),Y              ; clear 1st byte of next internal file location
                    TAX                                 ; X=0

                                                        ; cursor on the top
H1081               STX     SCREEN_POSITION

; Display full path (or less) on screen (line 0)

H1083               LDX     #34                         ; available size on screen=40-6 (sizeof "Ss,Dd:")
                    LDY     VOLNAME_LENGTH              ; length
                    CPY     #34                         ; exceeds the available screen size?
                    BCS     H108D                       ; yes, length>=34. write only the end of the volname

                                                        ; enough room to write the full name
                    LDY     #34                         ; force trailing spaces (if shorter name)
H108D               DEY
                    LDA     #" "                        ; character = trailing space
                    CPY     VOLNAME_LENGTH              ; need to write it?
                    BCS     H1098                       ; yes
                   
                                                        ; write name
                    LDA     (TBL_ONLINE+2),Y            ; get character
                    ORA     #%10000000                  ; normal mode
H1098               STA     TXT_LINE0+5,X               ; write it on screen
                    STA     SYS_LAUNCHER,Y              ; build full SYS pathname
                    DEX                                 ; size-1
H109F               BNE     H108D                       ; not finished

                    LDX     #2
                    STX     CV                          ; y position of the 1st name

; equivalent to
;                   LDA     PTR_1ST_NAME_ON_SCREEN
;                   STA     PTR_WORK_NAME
;                   LDA     PTR_1ST_NAME_ON_SCREEN+1
;                   STA     PTR_WORK_NAME+1
;                   LDX     #0
; optimization result = 3 bytes

H10A5               LDA     PTR_1ST_NAME_ON_SCREEN-1,X  ; init working ptr
                    STA     PTR_WORK_NAME-1,X
                    DEX
                    BNE     H10A5

; optimized routine for:
; - writing a vertical line of "!" on the middle of the screen
; - displaying file's type (if managed, including subdir) and file's name for all files of the page
; - displaying the cursor (video INVERSE) for the current selected name
; - adding BASIS.SYSTEM after the full SYS path
; - getting addr of the current selected name
 
                                                        ; X=0
H10AC               JSR     VTAB
                    INC     CV                          ; for next JSR VTAB
                    LDY     #20                         ; middle of txt screen
                    LDA     #"!"
                    STA     (BASL),Y                    ; write separator (dir content/authors)

                    LDA     $61,X                       ; /BASIS.SYSTEM
H10B9               STA     SYS_LAUNCHER_LENGTH,X       ; $0382,X .. $0391,X (self-modifying code)
                    LDA     #%11111111                  ; display = NORMAL
                    CPX     SCREEN_POSITION             ; cursor position?
                    BNE     H10CC                       ; no
                   
                    LDA     PTR_WORK_NAME               ; save pointer for current name
                    STA     PTR_CURRENT_NAME
                    LDA     PTR_WORK_NAME+1
                    STA     PTR_CURRENT_NAME+1
                   
                    LDA     #%00111111                  ; display = INVERSE
                   
                                                        ; acc=$FF (normal) or $3F (inverse)
H10CC               STA     DISPLAY_MODE
                    LDY     #0                          ; get infos byte
                    LDA     (PTR_WORK_NAME),Y           ; DTTTLLLL
                    BMI     H10EF                       ; sub-directory (D=1)
                   
                    BNE     H10DD                       ; there's a file in this location

                                                        ; acc=0                
                    LDY     #$10                        ; set ptr to "no name here" (empty location)
                    STA     (PTR_WORK_NAME),Y           ; 1st byte=file/unknow type/len=0 = no file
                    TAY                                 ; Y=0
                    BEQ     H10E4                       ; always

; Process a file

H10DD               LSR                                 ; 0DTTTLLL
                    LSR                                 ; 00DTTTLL
                    LSR                                 ; 000DTTTL
                    LSR                                 ; 0000DTTT
                    AND     #%00000111                  ; keep only type
                    TAY                                 ; in Y
                   
H10E4               LDA     LETTER_FILE_TYPE,Y          ; display internal file type on screen
                    LDY     #0
                    STA     (BASL),Y
                   
                    INC     BASL                        ; next pos
                    BNE     H10FD                       ; always
                   
                                                        ; file is a subdirectory
H10EF               LDA     #" "                        ; don't display a file type here
                    STA     (BASL),Y
                    INC     BASL
                    INC     BASL                        ; x position+2
                   
                    LDA     #"/"                        ; but display this character to identify a directory
                    AND     DISPLAY_MODE                ; INVERSE (cursor) or NORMAL (not the cursor)
                    STA     (BASL),Y

; Display file's name (+additional trailing spaces)
                                                        ; Y=0 (always)
H10FD               LDA     (PTR_WORK_NAME),Y           ; DTTTLLLL
                    AND     #%00001111                  ; 0000LLLL
                    STA     NAME_LENGTH                 ; save len of name
H1103               LDA     #" "                        ; trailing space. character used to erase previously written name
                    CPY     NAME_LENGTH
                    INY                                 ; next byte of the name (instr doesn't change carry)
                    BCS     H1110                       ; Y>=len. name is displayed. now complete with trailing space
                   
                    LDA     (PTR_WORK_NAME),Y           ; load character
                    ORA     #%10000000                  ; default = NORMAL
                    AND     DISPLAY_MODE                ; INVERSE if requested for cursor
                   
H1110               STA     (BASL),Y                    ; write character (or NORMAL space)
                    CPY     #17                         ; 17=1 (infos byte) + 1 (extra "/" for subdir) + 15 (name)
                    BNE     H1103                       ; not finished

; Prepare for next name
                                                        ; carry=0
                    LDA     #$0F                        ; next name (ptr+16). if 20 names are now displayed, the work ptr=1st name of the next page
                    ADC     PTR_WORK_NAME               ; low
                    STA     PTR_WORK_NAME
                    BCC     H1120
                   
                    INC     PTR_WORK_NAME+1             ; high+1
                   
H1120               INX                                 ; next name
                    CPX     #20                         ; was it the last?
                    BCC     H10AC                       ; no, display next one

; In Bitsy Bye I use RdKey ($FD0C), but move the cursor offscreen first by pointing BASH above the text page:
;  ASL $29
;  JSR $FD0C
;
; test with:
; 300:06 29 4c 0c fd
;
; I don't bother restoring the BASH afterward as Bitsy Bye does a VTAB (which resets BASH) after each keypress
; and before characters are printed to the screen.
;
; -JB
                                                        ; X=$14 (addr $14XX -> out of TXT screen)
                    STX     BASH                        ; not ASL but same effect
                    JSR     RDKEY
                                                        ; acc=key
                    CMP     #$8D                        ; return (=select)?
                    BNE     H11A8                       ; no
                   
;--------------------------------
; Select a file/directory
;--------------------------------
                   
                    JSR     MLI                         ; The ProDOS PREFIX is set to the directory containing the selected file
                    !8      SET_PREFIX                  ; (PATHNAME_LENGTH + PATHNAME)
                    !wo     TBL_SET_PREFIX
                    BCS     H1191                       ; error
                   
                    TAY                                 ; acc=0, Y=0
                    LDA     (PTR_CURRENT_NAME),Y        ; get DTTTLLLL
                    BEQ     H11A2                       ; typeless file + no length => error
                   
                    STY     TBL_READ+2                  ; read buffer =$2000
                    LDX     #>$2000
H113F               STX     TBL_READ+3
                    CMP     #$60                        ; test internal file type
                    AND     #%00001111                  ; 0000LLLL

                    BCS     H1174                       ; acc>=$60 (SYS+DIR)

;--------------------------------
; process INT or BIN or BAS or
; TXT or GS/OS pgm
;--------------------------------

                                                        ; Y=0, acc=0000LLLL
                    STA     (PTR_CURRENT_NAME),Y        ; store length
                    INC     TBL_OPEN+2                  ; $02XX => $03XX (high) => SYS_LAUNCHER
                    DEY                                 ; Y=$FF : max number of bytes of data to read (high)
                                                        ; load single file
                    JSR     GET_CONTENT                 ; load BASIS.SYSTEM (built-in hook)
                    DEY                                 ; MLI return code -1
                    BMI     H1164                       ; no error (BASIS.SYSTEM found and loaded)
                   
                                                        ; BASIS.SYSTEM not found
                    LDX     H10B9+1                     ; $82..$91
                    LDA     #"C"                        ; now BASIC.SYSTEM
                    STA     SYS_LAUNCHER+1-$82+5,X
                   
                    LDY     #$FF                        ; max number of bytes of data to read (high)
                                                        ; load single file
H115C               JSR     GET_CONTENT                 ; read file BASIC.SYSTEM
                    DEC     TBL_OPEN+2                  ; $03XX => $02XX (high) => PTR_CURRENT_NAME
                    DEY                                 ; MLI return code -1
                    BPL     H11A2                       ; error (unable to load BASIC.SYSTEM). Can't run the selected file.

                                                        ; OK. BASIS.SYSTEM or BASIC.SYSTEM loaded at $2000

; https://prodos8.com/docs/techref/writing-a-prodos-system-program/
; Chapter 5.1.5
;
; There is a way to pass a second pathname to interpreters -- for example, to language interpreters -- that
; like to run startup programs.
; Done by sophisticated program selectors.
;
; It requires that the interpreter start a certain way:
;
; $2000 is a jump instruction. $2003 and $2004 are $EE.
; If the interpreter starts this way, byte $2005 is assumed to indicate the length of a buffer that starts
; at $2006 and holds the pathname (starting with a length byte) of the startup file.
;
; Interpreters that support this mechanism should supply their own default string, which should be a standard
; choice for a startup program or a flag not to run a startup program.
                   
H1164               LDY     #$0F                        ; copy name + length
H1166               LDA     (PTR_CURRENT_NAME),Y
                    STA     SYSTEM_ADDR+6,Y             ; from $2006
                    DEY
                    BPL     H1166
                   
H116E               JSR     HOME
                    JMP     SYSTEM_ADDR                 ; run BASIS.SYSTEM or BASIC.SYSTEM (and after that the selected file)

;--------------------------------
; Execute SYS or go DIR
;--------------------------------
                   
                                                        ; acc=0000LLLL
H1174               TAY
                    ADC     VOLNAME_LENGTH              ; rem: carry=1 (=an additionnal character for "/" after pathname)
                    STA     VOLNAME_LENGTH
                    TAX                                 ; path length + selected name length + 1
H117A               LDA     (PTR_CURRENT_NAME),Y        ; add selected name to path
                    STA     PATHNAME-1,X                ; if Y=0 acc=DTTTLLLL
                    DEX
                    DEY
                    BPL     H117A                       ; Y>=0

                                                        ; Y=$FF
                                                        ; acc=DTTTLLLL
                    ASL                                 ; carry=D
                    LDA     #"/"                        ; add "/" before selected file name
                    STA     PATHNAME,X
                    BCS     H11A5                       ; file is a directory. process it.
                   
                                                        ; SYS file
                                                        ; Y=$FF max number of bytes of data to read (high)
                                                        ; load single file
                    JSR     GET_CONTENT                 ; load it
                    TYA                                 ; acc= mli return code
                    BEQ     H116E                       ; no err: run it
                                                       
                                                        ; unable to load SYS file
H1191               JSR     BELL

;--------------------------------
; ESC
;--------------------------------

; Go to parent sub-directory or volume directory
;
; Example: current = /HD1/TOOLS (len=$0A)
;
; $0280: 0A AF  48  44  31  AF  54  4F  4F  4C  53
;           "/" 'H' 'D' '1' "/" 'T' 'O' 'O' 'L' 'S'
;                                               ^
;                                               !
; ESC pressed
;                           ^
;                           ! stop here
;
; current = /HD1
; $0280: 04 AF  48  44  31


HANDLE_ESC
H1194               LDY     VOLNAME_LENGTH
H1196               LDA     (TBL_OPEN+1),Y              ; acc = volume name character
                    DEY                                 ; length-1
                    BEQ     H11A2                       ; can't esc: already root level
                                                        ; but display files list from 1st name
                   
                                                        ; esc can be processed
                    TAX                                 ; test character
                    BPL     H1196                       ; 'character'
                                                        ; "character" <=> found "/"
                    STY     VOLNAME_LENGTH              ; set new length
                    BMI     H11A5                       ; always. go read parent dir

;--------------------------------
; Error subroutine
;--------------------------------
                   
H11A2               JSR     BELL
H11A5               JMP     H1065

;--------------------------------

H11A8               LDX     SCREEN_POSITION
                                                        ; acc=key
                    CMP     #$95                        ; "right" arrow?
                    BNE     H11E5                       ; no


;--------------------------------
; Go down
;--------------------------------

; In
;   X       : screen location [0..19]

HANDLE_DOWN
H11AE               INX                                 ; screen location+1
                    LDY     #16                         ; is next location empty?
                    LDA     (PTR_CURRENT_NAME),Y
                    BEQ     H11D1                       ; yes. can't go down
                   
                                                        ; can go down
                                                        ; but where is the cursor?
                    CPX     #$0A                        ; cursor was on the middle of the screen?
                    BCC     H120E                       ; no. save screen position (X) and go to display routine (JMP H1081).
                   
                                                        ; middle of the screen
                                                        ; need to scroll down if 20 names on screen
                                                        ; 1 name=16 byte. 20 names on the screen. 20*16=$0140=$0100+$40
                    INC     PTR_1ST_NAME_ON_SCREEN+1    ; change temporarily : high+1 <=> +$100
                    LDY     #$40                        ; +$40
                    LDA     (PTR_1ST_NAME_ON_SCREEN),Y  ; load
                    DEC     PTR_1ST_NAME_ON_SCREEN+1    ; rollback change
                    TAY                                 ; DTTTLLLL
                    BEQ     H120E                       ; 0 means "less than 20 files on screen".
                                                        ; no scroll down. save screen position (X++)
                                                        ; go to the display routine and move cursor down
                   
                                                        ; filenames list : scroll down required
                    LDA     PTR_1ST_NAME_ON_SCREEN      ; pointer (low)
                    LDY     PTR_1ST_NAME_ON_SCREEN+1
                    ADC     #$0F                        ; low+16
                    BCC     H11CD                       ; no action for high
                   
                    INY                                 ; high+1

H11CD               STA     PTR_1ST_NAME_ON_SCREEN      ; set new ptr
                    STY     PTR_1ST_NAME_ON_SCREEN+1    ; scroll up/down with screen refresh
                   
H11D1               JMP     H1083                       ; don't save screen position (X++)
                                                        ; go screen refresh

;--------------------------------
; Change slot
;--------------------------------

; in
;   acc     : $F9..$FF (key "1".."7")
;   carry   : 1
;
; Bitsy Bye uses keys 1-7 as slot keys with subsequent presses toggling the drive number at that slot.
; -JB

HANDLE_CHANGE_SLOT
H11D4               EOR     #%11111000                  ; $01..$07
                    ROL                                 ; $03..$0F (carry in bit 0)                                
                    TAX                                 ; 0000SSS1 (!D=1 => D=0 : drive 1 default)

                                                        ; retrieve current drive code
                    EOR     CUR_SLOT_DRV                ; 0000SSS? (?=!D)
                                                        ; bit 0 : 1 EOR 0 = 1 (!D=0 => D=1 current=drive 2)
                                                        ; bit 0 : 1 EOR 1 = 0 (!D=1 => D=0 current=drive 1)

                    LSR                                 ; bit 0 in carry.

                                                        ; carry=0 => bit 0 = 0 (current drive=drive 1)
                                                        ; carry=1 => bit 0 = 1 (current drive=drive 2)

                                                        ; (selected slot) EOR (current slot):
                                                        ; 1 EOR 1 = 0
                                                        ; 0 EOR 0 = 0
                                                        ; if same slot acc=0

                    BNE     H11E0                       ; not same slot. begin with drive 1 (default)
                   
                                                        ; same slot
                    BCS     H11E0                       ; carry=1 : current=drive 2. toggle: drive 1 required (keep default)
                   
                    DEX                                 ; 0000SSS0 : !D=0 => D=1 (drive 2 required)

H11E0               JSR     GET_VOLUME_NAME             ; get volume
                    BPL     H11A5                       ; always. JMP H1065 (go read content)

;--------------------------------
       
H11E5               CMP     #$9B                        ; esc?
                    BEQ     HANDLE_ESC                  ; yep
                   
                    CMP     #"A"
                    BCS     HANDLE_FIRST_LETTER         ; acc >= "A"
                   
                                                        ; carry=0
                    ADC     #$48
                    CMP     #"y"                        ; test : $B1+$48..$B7+$48
                                                        ; acc >= $F9
                    BCS     HANDLE_CHANGE_SLOT          ; yep: "1".."7"

                                                        ; carry=0
                    SBC     #$CF                        ; <=> -$D0
                                                        ; acc+$48-$D0=0 <=> acc=$D0-$48=$88
                    BEQ     HANDLE_UP                   ; ^H (left arrow)
                   
                    TAY
                    DEY                                 ; acc+$48-$D0-1=0 <=> acc=$89
                    BEQ     HANDLE_TAB                  ; ^I (TAB)
                   
                    DEY                                 ; acc=$8A?
                    BEQ     HANDLE_DOWN                 ; ^J (down arrow)
                   
                    DEY                                 ; acc=$8B? ^K (up arrow)
                    BNE     H11D1                       ; no : JMP H1083

;--------------------------------
; Go up
;--------------------------------

; In
;   X       : screen location [0..19]

HANDLE_UP
                                                        ; check if not already the 1st name of the directory/volume
H1201               LDY     PTR_1ST_NAME_ON_SCREEN+1
                    LDA     PTR_1ST_NAME_ON_SCREEN
                    BNE     H1211                       ; if low <> 0 when can't be $1400, so we can go up
                   
                                                        ; low=$00
                    CPY     #>H1400                     ; high=$14?
                    BNE     H1211                       ; no, can go up
                   
                                                        ; already at the top of the screen
                                                        ; X=0

H120B               DEX                                 ; screen position-1.
                                                        ; if X=$FF, DEX used only to branch to H11D1 (H1083)

H120C               BMI     H11D1                       ; always if top of screen. don't save X in screen position

H120E               JMP     H1081                       ; save X to screen position

                                                        ; the cursor can move up
H1211               CPX     #$0A                        ; cursor current pos>=middle of the screen+1?
                    BCS     H120B                       ; yes. don't need to scroll up the list. DEX=cursor up.
                   
                                                        ; filenames list : scroll up required
                                                        ; carry=0
                    SBC     #$0F                        ; ptr low -16. pointer on previous name
                    BCS     H11CD                       ; ptr high ok
                   
                    DEY                                 ; ptr high-1
                    BCC     H11CD                       ; always
                   
;--------------------------------
; Scan for another volume
;--------------------------------

; slot DESC (7 -> 6 -> 5 -> 4 -> 3 -> 2 -> 1 -> 0 -> 7 -> etc...)
; drive ASC (1 -> 2 -> 1 & slot-1 -> 2 -> etc...)

HANDLE_TAB
H121C               LDX     CUR_SLOT_DRV                ; 0000SSS? (?=!D)
                    JMP     H105F                       ; DEX done before calling GET_VOLUME_NAME:
                                                        ;  if drive 1 (!D=1) then try drive 2 (!D1=0)
                                                        ;  if drive 2 (!D=0) then try slot-1, drive 1 (!D=1)
                                                        ;  if slot-1=$FF than AND #$0F set slot 7, drive 1 (!D=1)

;--------------------------------
; First name beginning with
; letter
; If found, become the 1st
; filename displayed on the
; screen
;--------------------------------

; In
;   acc     : "letter"

; feature: Allows files to be selected by typing the first letter of their filename
;
; Notes:
; - search from the current cursor position.
; - If not found, try again from the beggining of the list.
; - If still not found (no filename starts with that letter), the cursor doesn't move.

HANDLE_FIRST_LETTER
H1221               AND     #%01011111                  ; "letter" to 'letter' for comparison
                    STA     FIRST_CHARACTER

; 1st attempt (X=1) : from current cursor position

                    LDX     #0
                    LDY     PTR_CURRENT_NAME            ; init Y with current ptr low
                    STX     PTR_CURRENT_NAME            ; and set current ptr low=0
                    INX                                 ; X=1
                   
H122C               TYA                                 ; acc=ptr low
                    CLC                                 ; +16. next filename
                    ADC     #$10                        ; carry=1 if ptr high+1 required
                    TAY                                 ; Y=ptr low+16. no effect on carry
                    BCC     H1235                       ; ptr high OK
                   
                    INC     PTR_CURRENT_NAME+1          ; ptr high+1
                                                        ; Y=0
                   
H1235               LDA     (PTR_CURRENT_NAME),Y        ; load DTTTLLLL
                    BEQ     H124A                       ;  end of list
                   
                    INY                                 ; pos=1st letter of the filename
                    LDA     (PTR_CURRENT_NAME),Y        ; load 1st letter
                    DEY                                 ; pos=DTTTLLLL
                    CMP     FIRST_CHARACTER             ; key pressed?
                    BNE     H122C                       ; no, not the same letter
                   
                                                        ; found. start list with that name
                    STY     PTR_1ST_NAME_ON_SCREEN
                    LDA     PTR_CURRENT_NAME+1
                    STA     PTR_1ST_NAME_ON_SCREEN+1
                    JMP     H107B                       ; refresh display
                   
                                                        ; acc=0
H124A               DEX                                 ; another try?
;                                                       ; X=$FF?
                    BMI     H120C                       ; yes. 2 fails. stop now. rebuild PTR_CURRENT_NAME ptr
                                                        ; with SCREEN_POSITION
                   
; 2nd attemp (X=0): retry from the beginning of the list

                    TAY                                 ; Y=0. ptr low=0
                    LDA     #>H1400                     ; set ptr high = $14
                    STA     PTR_CURRENT_NAME+1 
                    BNE     H1235                       ; always
                   
;--------------------------------
; Get volume name
;--------------------------------

; In
;   X       : 000DSSS? (?=!D) 1st entry : "D" is erased by TAX+AND #$0F
;           : 0000SSS? (?=!D) others

; Out
;   $56     : CUR_SLOT_DRV fmt=0000SSS? (?=!D)
;   $57     : VOLNAME_LENGTH = volume name length+1
;   $0281   : "/" remplace PATHNAME's length
;   $0282..$0290 : PATHNAME
;   $0380   : SYS_LAUNCHER_LENGTH = full length : length("/BASIS.SYSTEM")=$0D + 1st "/" = $0E
;               $0E : if name length=0
;               $0F : if name length=1
;               $10 : if name length=2
;               $11 : if name length=3
;               $12 : if name length=4
;               $13 : if name length=5
;               $14 : if name length=6
;               $15 : if name length=7
;               $16 : if name length=8
;               $17 : if name length=9
;               $18 : if name length=10 ($0A)
;               $19 : if name length=11 ($0B)
;               $1A : if name length=12 ($0C)
;               $1B : if name length=13 ($0D)
;               $1C : if name length=14 ($0E)
;               $1D : if name length=15 ($0F)
;   $10BA   : name length $82..$91
;   Y       : name length
;   acc     : name length $82..$91
;               $82 : if name length=0
;               $83 : if name length=1
;               $84 : if name length=2
;               $85 : if name length=3
;               $86 : if name length=4
;               $87 : if name length=5
;               $88 : if name length=6
;               $89 : if name length=7
;               $8A : if name length=8
;               $8B : if name length=9
;               $8C : if name length=10 ($0A)
;               $8D : if name length=11 ($0B)
;               $8E : if name length=12 ($0C)
;               $8F : if name length=13 ($0D)
;               $90 : if name length=14 ($0E)
;               $91 : if name length=15 ($0F)
;   X       : unchanged

GET_VOLUME_NAME
H1254               TXA
                    AND     #%00001111                  ; get slot 0000SSS?
                    STA     CUR_SLOT_DRV                ; save as current
                    LSR                                 ; 00000SSS
                                                        ; !D in carry
                    BEQ     H127C                       ; slot 0: not a valid ProDOS device (LLLL=0)
                   
H125C               PHP                                 ; save !D (carry)
H125D               ORA     #"0"
H125F               STA     TXT_LINE0+1                 ; write slot on TXT screen
H1262               ASL                                 ; 0000SSS0
                    ASL                                 ; 000SSS00
                    ASL                                 ; 00SSS000
H1265               ASL                                 ; 0SSS0000
H1266               PLP                                 ; restore !D (carry)

                    LDY     #"1"                        ; drive "1"
H1269               BCS     H126E                       ; carry=1 => !D=1 => D=0 (drive 1)

                                                        ; carry=0 => !D=0 => D=1 (drive 2)
H126B               ORA     #%10000000                  ; 1SSS0000
                    INY                                 ; drive "2"

                                                        ; Y=drive ("1"/"2")
                                                        ; acc=DSSS0000
H126E               STA     TBL_ONLINE+1                ; unit number for ONLINE
H1270               STY     TXT_LINE0+4                 ; write drive on TXT screen

                    JSR     MLI                         ; identity single volume (unit number)
                    !8      ONLINE                      ; fill PATHNAME (16 bytes)
                    !8      TBL_ONLINE,0                ; table in zero page
                   
                    LDA     PATHNAME                    ; DSSSLLLL
H127C               LDY     #"/"                        ; replace DSSSLLL by "/"
                    STY     PATHNAME
                    AND     #%00001111                  ; 0000LLLL (volume name length) $00..$0F
                    TAY                                 ; Y=length
                    CLC
                    ADC     #$0E                        ; $0E..$1D
                    STA     SYS_LAUNCHER_LENGTH
                    ADC     #$74                        ; $82..$91
                    STA     H10B9+1                     ; low
                    INY                                 ; Y=length+1
                    STY     VOLNAME_LENGTH
                    DEY                                 ; Y=length. if length=0, Z=1
                    RTS

;--------------------------------
; Get a content
;--------------------------------

; In
;   VOLNAME_LENGTH  : path length+1
;   PATHNAME
;   Y               : max number of bytes of data to read (high)
;                       $00 : load the content of a volume/directory
;                       $FF : load a file
;
; Out
;   Y       : MLI code return ("OPEN" if KO otherwise "READ")
;   acc     : MLI code return ("CLOSE")
;   $1400..$???? structures buffer:
;           16 bytes : 1st structure
;           16 bytes : 2st structure
;           ...
;
;           structure infos (BB 2.4.2):
;               $00      : format DTTTLLLL (infos byte)
;                           D    : 0=file, 1=subDirectory
;                           TTT  : internal file type
;                                       0=not managed type, 1=INT, 2=BIN, 3=BAS, 4=TXT, 5=GS/OS app pgm, 6=SYS
;                                       TTT=0 if D=1
;                           LLLL : name length
;               $01..$0F : name
;   PATHNAME_LENGTH : length including "/"
;
;
; Feature: Does not abort on drive errors, but instead lists and allows launching of all readable files
;
; I intend to open source Bitsy Bye along with several new drivers as part of ProDOS 2.5.
; The issue is that Bitsy Bye 2.4 is parsing directories in a way that is incompatible with ProDOS 2.5, so I want to hold off sharing that version.
; Once the new 2.5 system is in place, it will be ready for sharing, customizing, and migrating into other apps.
; -JB

GET_CONTENT
H1294               LDA     VOLNAME_LENGTH              ; name length+1 (including "/")
                    STA     PATHNAME_LENGTH
                   
                    JSR     MLI                         ; open name
                    !8      OPEN
                    !8      TBL_OPEN,0                  ; table in zero page
                   
                    BCS     H12F3                       ; error
                   
                    LDA     TBL_OPEN+5                  ; reference number (OPEN)
                    STA     TBL_READ+1                  ; set ref number (READ)
                                                        ; Y=$00 or $FF
                    STY     TBL_READ+5                  ; max number of bytes of data to read (high)
                    LDA     #$2B                        ; size of volume directory/subdirectory header
                    LDX     #$0D                        ; nbr of file descriptive entries in 1 block
                                                        ; (volume header + 12 files)

                    !8      $2C                         ; BIT trick (hide size below)
H12AC               LDA     #$27                        ; size of file descriptive entry

                    DEX                                 ; nbr-1
                    BNE     H12B5

                                                        ; process last name of the block
                                                        ; note : 1 block = $2B + 12*$27 = $1FF
                                                        ; +extra $00 at the end of the block

                    LDA     #$2C                        ; read $27 + extra $00 + 4 bytes of next block (next/previous block pointers)
                    LDX     #$0D                        ; loop for 13 entries
                                                        ; if no "next" block: actual length=$28+mli return code $4C
                                                        ; but no err => BB tries to read next & fail

H12B5               STA     TBL_READ+4                  ; max number of bytes of data to read (low)
       
                    JSR     MLI                         ; read
                    !8      READ
                    !8      TBL_READ,0                  ; table in zero page
                   
                    INY                                 ; Y=$FF+1? If Y=0 => file loaded
                    BEQ     H12F3                       ; stop reading
                   
                                                        ; processing a directory (not a file)                  
                    LSR     TBL_READ+6                  ; actual number of bytes placed in buffer (low)
                    BEQ     H12F3                       ; EOF : stop reading

; Note : if there's no file then the 1st byte of the corresponding structure is always set to 0.
;        it's mandatory for the display routine and the cursor movement.

                    TAY                                 ; Y=0
                    LDA     (TBL_READ+2),Y              ; read 1st byte of buffer
                    AND     #%10001111                  ; keep vol/dir bit + name length
                    STA     (TBL_READ+2),Y
                    ASL                                 ; remove vol/dir bit 000LLLL0
                    BEQ     H12AC                       ; file is deleted (LLLL=0) or no file here. skip it
                   
                    LDY     #$10
                    LDA     (TBL_READ+2),Y              ; get file type
                   
                    LDY     #7                          ; loop for known file types list+1
                                                   
H12D4               DEY
                    BEQ     H12DC                       ; Y=0 : was last (file type not in the list)
                   
                    CMP     FILE_TYPE_LIST-1,Y          ; file type in list?
                    BNE     H12D4                       ; not this one. Check another one.
                                                        ; Y : 1..6
                   
H12DC               TYA                                 ; acc = 00000TTT type index (TTT=0=not managed)
                    ASL
                    ASL
                    ASL
                    ASL                                 ; acc = 0TTT0000
                    LDY     #0                          ; merge type index and
                    ORA     (TBL_READ+2),Y              ; vol/dir bit (7) + LLLL (bits 3..0)
                    STA     (TBL_READ+2),Y              ; format DTTTLLLL
                                                        ; directory: D=1 TTT=0

                    LDA     TBL_READ+2                  ; buffer addr (low) for next name
                    ADC     #$10                        ; +16 bytes
                    STA     TBL_READ+2
                    BCC     H12AC                       ; same mem page. next name.
                   
                    INC     TBL_READ+3                  ; buffer addr (high) +1
                    BNE     H12AC                       ; always. next name.
                   
                                                        ; close everything
H12F3               TAY                                 ; Y=MLI return code (err if <> 0)
                    JSR     MLI
                    !8      CLOSE
                    !wo     TBL_CLOSE
                   
                    RTS

;--------------------------------
; Table for MLI CLOSE
;--------------------------------

TBL_CLOSE
H12FB               !8      1                           ; parameter count
                    !8      0                           ; close all files

;--------------------------------
; Table for MLI SET_PREFIX
;--------------------------------

TBL_SET_PREFIX
H12FD               !8      1
                    !wo     PATHNAME_LENGTH

;--------------------------------
; TXT screen datas
; read from H1356 to H1300 desc
;--------------------------------

; X: 1..40
; Y: 0..23
                                                        ; end of screen datas
H1300               !tx     "-"                         ; not printed on screen in this loop
                    !8      22,41                       ; coord: X=41(out of screen),Y=22
                   
                    !tx     "BITSY  BYE"
                    !8      5,36                        ; coord: X=36,Y=5
                   
                    !tx     "BY"
                    !8      10,32                       ; coord: X=32,Y=10

; WTF!!! Authors name... in plain text!
; No tricks, no crazy encoding routine, even not a small EOR or inverted names!
; I'm very disappointed!

                    !tx     "J.BROOKS"
                    !8      15,35                       ; coord: X=35,Y=15
                   
                    !tx     "P.FERRIE"
                    !8      18,35                       ; coord: X=35,Y=18

                    !tx     "RETURN:SELECT"
                    !8      23,13                       ; coord: X=13,Y=23

                    !tx     "ESC:BACK"
                    !8      23,24                       ; coord: X=24,Y=23

                    !tx     "TAB,#:NEW VOL"
                    !8      23,40                       ; coord: X=40,Y=23

; $59..$60
H134F               !tx     "S6,D1:"
                    !8      0                           ; coord: Y=0
H1356               !8      6                           ; coord: X=6
                                                        ; beginning of screen datas                
;--------------------------------
; Relocated in zero page $61..$6D
;--------------------------------

; John Brooks at KansasFest 2017
; https://youtu.be/Sm4D1wtWPck?t=957

; BASIS.SYSTEM
;
; - Could 'smart launch' at boot or from Bisty Bye
; - Called by Bitsy Bye for non-SYS file types
; - Could map file/aux type to launch app path
; - If not found, Bitsy Bye will use BASIC.SYSTEM

; Chris Torrence : Assembly Lines #41 : ProDOS 2.4.1 Easter Egg
; https://www.youtube.com/watch?v=-_6P_a5C4Z0

; $61
                    !tx     "/BASIS.SYSTEM"

;--------------------------------
; Relocated in zero page $6E..$71
;--------------------------------
; TBL_ONLINE
; $6E
                    !8      2                           ; parameter count
; $6F
                    !8      $00                         ; unit number DSSS0000
; $70..$71
                    !wo     PATHNAME                    ; 16 bytes buffer : $0281..$0290

;--------------------------------
; Relocated in zero page $72..$77
;--------------------------------
; TBL_OPEN
                    !8      3                           ; parameter count
; $73..$74
                    !wo     PATHNAME_LENGTH             ; addr of pathname $0280 (len) $0281..$02BF (name)
; $75..$76
                    !wo     $0B00                       ; addr of filebuffer $0B00..$0EFF
; $77
                    !8      $00                         ; reference number

;--------------------------------
; Relocated in zero page $78
;--------------------------------  
; TBL_READ
; $78
                    !8      4                           ; parameter count
; $79     : reference number (TBL_READ+1)
; $7A-$7B : addr of data buffer (TBL_READ+2/TBL_READ+3)
; $7C-$7D : requested length (TBL_READ+4/TBL_READ+5)
; $7E-$7F : actuel length // returned value (TBL_READ+6/TBL_READ+7)


;--------------------------------
; ProDOS file type known by BB
;--------------------------------

FILE_TYPE_LIST
H136F               !8      $FA                         ; INT
                    !8      $06                         ; BIN
                    !8      $FC                         ; BAS
                    !8      $04                         ; TXT
                    !8      $B3                         ; GS/OS app pgm (S16)
                    !8      $FF                         ; SYS

;--------------------------------
; Letter for ProDOS file type
;--------------------------------

LETTER_FILE_TYPE                   
H1375               !tx     " "                         ; unsupported file type
                    !tx     "I"                         ; Integer BASIC
                    !tx     "B"                         ; Binary
                    !tx     "A"                         ; AppleSoft BASIC
                    !tx     "T"                         ; Text
                    !tx     "-"                         ; GS/OS app pgm (S16)
                    !tx     "-"                         ; SYS