So What Techncial Notes
#6

Call Box
Using GS/OS Calls

Written by: William Stephens - February 15,1990

This technical note describes how to use GS/OS Class 1 calls to load a disk file into an allocated block of memory.

Loading and managing your own blocks of data is vital for any sophisticated program and is necessary for things such as sound files for the Sound Manager and A.C.E. The process requires several steps and necessitates the set-up of a direct page for all the parameter blocks and pathname buffer. The scenario goes something like this ... Allocate a direct page, Create the GS/OS Caller, Create the Pathname, OPEN the file, ALLOCATE a block for it, READ the file into the block followed by CLOSE the file. When you are done with the files data you DE-ALLOCATE the block of memory, and then DE-ALLOCATE the direct page and then quit. This is how it's done in Assembly language or for that matter from any language.

The following diagram shows the layout of the needed GS/OS parameter blocks:

Figure x

The first step of this process is to allocate and then setup the direct page work area. Allocate 1 direct page as outlined in tech note 4:

CALL PO,4,704,$F52001A9 : CALL PO,708,$60BE :
CALL 704 A = PEEK{PO + 244} : A = A + 1 : POKE PO + 244, A :
D1 = PO . (A * 256):
FOR I = 0 TO 255 : POKE D1 + 1,0 : NEXT


D1 equals the starting address of this direct page. Let's layout the direct page as follows ... starting at address Dl put the GS/OS Caller Routine which takes up 25 bytes. Next is the GSOpen parameter block which is 58 bytes long followed by the GSRead block (18 bytes) the Expand_Path block (12 bytes) and the GSClose block (4 bytes) fmally let's use the last 128 bytes of the direct page for the pathname buffers. Give a variable to each of these locations to simplify the code.

D2 = D1 + 25 : D3 = D2 + 58 : D4 = D3 + 18 : D5 = D4 + 12 :
D6 = D1 + 128 : D7 = D1 + 190 : D8 = D1 + 188


Now D1 = GS/OS Caller Routine, D2 = GSOpen parameter block, D3 = GSRead parameter block, D4 = Expand_Path block, D5 = GSClose parameter block, D6 = Input buffer, D7 = Output Path and D8 = Output Path Buff.

Its time to setup this page by first writing in the GS/OS Caller routine:

CALL PO,4,D1,$30C2FB18 : CALL PO,4,4 + D1,$E1 00A822 :
CALL PO,4,14 + D1,$02BOFE85 : CALL PO,4,18 + D1,$30E2FE64 :
CALL PO,3,22 + D1,$60FB38


Next put the PCounts and buffer size in.

CALL PO,2,D2,15 : CALL PO,2,D3,5 : CALL PO,2,D4,3 : CALL PO,2,D5,1 : CALL PO,2,D8,66

It's now time to put the pathname in the pathname buffer. For this example let's assume that the pathname is contained in the string variable A$.

L1 = LEN(A$): FOR I = 1 TO L1 :
A = ASC(MID${A$,1,1)) : POKE D6 + 1 + I,A : NEXT :
CALL PO,2,D6,L1


Use Expand_Path to create a full pathname from the partial in A$.

CALL PO,4,2 + D4,06 : CALL PO,4,6 + D4,D8 : CALL PO,4,10 + D1,D4 CALL PO,2,8 + D1,$200E : CALL D1
IF PEEK(254) < > 0 THEN (GS/OS ERROR MESSAGE ROUTINE)


It's now time to make a GSOpen call:

CALL PO,4,4 + D2,D7 : CALL PO,4,10 + D1,D2: CALL PO,2,8 + D1,$2010: CALL D1
IF PEEK(254) < > 0 THEN (GS/OS ERROR MESSAGE ROUTINE)


If this call is successful then all of the data specified in the GSOpen parameter block will be filled in. If this call fails for some reason then you need to handle the errors yourself, if the volume specified in the pathname is not online then a dialog box will appear prompting you to insert the proper volume before proceeding.

Pass the reference numbers to the other parameter blocks from the GSOpen block.:

CALL PE,2,2 + D2,A: CALL PO,2,2 + D3,A: CALL PO,2,2 + D5,A

The GSOpen call will return several pieces of data, one of them in particular is of inttest to you and that is the EOP. EOF (End Of File) is the length of the file you just opened, it's found at the 42nd byte of the GSOpen parameter block. You must now use the EOF to allocate a block of memory for the file to reside in. Use the procedure outlined in tech note 2 to allocate this block of memory, use the EOF for the 2nd (length) parameter in the call.:

CALL PE,4,42 + D2,L : ID = 6144 + PEEK(PO + 180) CALL LC,_O,_L,ID,$OOOO,_O\$0902\_H
IF H = 0 THEN (MEMORY ERROR MESSAGE ROUTINE)
CALL PE,4,H,A


A will hold the address of the beginning of the allocated block and H will hold its handle ... keep both of these for later use.

Now we can read the file into the block, but first we must setup the GSRead parameter block. Put the address (A) and the length (L) into the parameter block.:

CALL P0,4,4 + D3,A: CALL PO,4,B + D3,L

Read the file into the block."

CALL PO,4,10 + D1,D3: CALL PO,2,8 + D1,$2012: CALL D1
IF PEEK(254) < > 0 THEN (GS/OS ERROR MESSAGE ROUTINE)


All that is needed now is to close the file.:

CALL PO,4,10 + D1,D5: CALL PO,2,8 + D1,$2014: CALL D1

This puts the file in the block and everything is ready for use. REMEMBER ... A holds the address and H holds the handle. Do not loose these values because they are vital for locating and deallocating this memory block when your program is ready to shutdown.

Example Code:
The following pages present actual Applesoft program lines which you can copy into your programs. There are 3 memory allocation routines, 5 GS/OS read routine and 3 GS/OS setup/error routines. The variables ID,I,A,L,Ll,H,P,D1,D2,D3,D4,D5,D6,D7 and D8 are used by these routines. H = Memory block handle L = Block size P = Memory block address ID = special user I.D. number D1 = Direct page address.

Allocate a block of memory: (in = L, out = H,P,ID)
De-Allocate all special blocks: (in = ID, out = )
Allocate and clear a Direct Page: (in =, out = D 1)
Load a file into memory GS/OS Class 1: (in =A$,D1,D2,D3,D4,D5,D6,D7,D8, out = H,P,L,ID)
GSExpand_Path: (in = A$,D1,D4,D6,D8 out =)
GSOpen: (in = D 1 ,D2,D5 ,D7, {full patbname} out = )
GSRead: (in = D1,D3,P,L out =)
GSClose: (in = Dl,D5 out = )
Set-Up the GS/OS Dir. Page and Error Messages: (in =, out = Dl,D2,D3,D4,D5,D6,D7,D8)


Use routine 56000 once at the beginning of your program and simply put a full or partial pathname in A$ and GOSUB 50000 to load it into memory and get the Handle, Pointer and Length returned to you. An error handler is included as well using text file GSOSERROR.T.

44999   REM 

                    Allocate a block of memory 

45000   ID = 6144 + PEEK (PO + 180) : CALL LC,_0,_L,ID,$0000,_0\$0902\_H : IF H = 0 THEN
        55030 
45010   CALL PE,4,H,P : RETURN 
45019   REM 

                    De-Allocate all special Blocks 

45020   CALL LC, ID\$1102\ : RETURN 
45029   REM 

                    Allocate and Clear a Direct Page 

45030   CALL PO,4,704,$F52001A9 : CALL PO,2,708,$60BE : CALL 704:A = PEEK (PO + 244) : A
        + 1 : POKE PO + 244,A : D1 = PO - (A • 256) : FOR I = 0 TO 255 : POKE 01 + 1,0 : NEXT 
        : RETURN 
49999   REM 

                    Load a file into memory GS/OS Class 1 

50000   GOSUB 50100 : GOSUB 50200 : CALL PE,4,42 + D2,L : GOSUB 45000 : GOSUB 50300 :
        GOTO 50400 
50099   REM

                    GSExpand_Path 

50100   L1 = LEN (A$) : FOR I = 1 TO L1 : A = ASC ( MID$ (A$,I,1)) : POKE D6 + 1 + I,A : NEXT : 
        CALL PO,2,D6,Ll : CALL PO,4,2 + D4,D6 : CALL PO,4,6 + D4,D8 
50110   CALL PO,4,10 + D1,D4 : CALL PO,2,8 + D1,$200E: CALL D1 : IF PEEK (254) < > 0 THEN
        55000 
50120   RETURN 
50199   REM 

                    GSOpen 

50200   CALL PO,4,4 + D2,D7 : CALL P0,4,10 + D1,D2 : CALL PO,2,8 + D1,$2010 : CALL D1 : IF 
        PEEK (254) < > 0 THEN 55000 
50210   CALL PE,2,2 + D2,A : CALL PO,2,2 + D3,A : CALL PO,2,2 + D5,A : RETURN 
50299   REM 

                    GSRead 

50300   CALL PO,4,4 + D3,P: CALL P0,4,8 + D3,L: CALL P0,4,10 + D1,D3: CALL PO,2,8 + 
        D1,$2012: CALL D1: IF PEEK (254) < > 0 THEN 55000 
50310   RETURN 
50399   REM 

                    GSClose 

50400   CALL PO,4,10 + D1,D5 : CALL PO,2,8 + D1,$2014 : CALL D1 : RETURN 
54999   REM 

                    GSOS Error Handler 

55000   CALL SC,O : HOME FOR I = 0 TO 21 : CALL AY,2,ER,[I],A : IF A = PEEK (254) THEN
        55020 
55010   NEXT 
55020   CALL SC,O : HOME : PRINT 'GS/OS Error ... ' : CALL AY,2,ER$,[X],A$ : GOSUB 45020 : 
        CALL- 1052: CALL QF: END 
55030   POP : CALL SC,O : PRINT 'Memory Allocation Error ... ' : GOSUB 45020 : CALL QF: END 
55999   REM 

                   Setup the GSOS Dir. Page and Error Messages 

56000   GOSUB 45030 : D2 = D1 + 25 : D3 = D2 + 58 : D4 = D3 + 18 : D5 = D4 + 12 : D6 = D1 + 128 : D7 = 
        D1 + 190 : D8 = D1 + 188 
56010   CALL P0,4,D1,$30C2FB18 : CALL PO,4,4 + D1,$E100A822 : CALL P0,4,14 + 
        D1,$02BOFE85 : CALL PO,4,18 + D1,$30E2FE64 : CALL PO,3,22 + 01,$60FB38 : CALL
        PO,2,D2,15 : CALL PO,2,D3,5 : CALL PO,2,D4,3 : CALL PO,2,D5,1 : CALL PO,2,D8,66 
56020   CALL AY,1,ER,[21] : CALL AY,1,ER$,[21] : PRINT CHR$ (4);"OPEN GSOSERROR.T" : 
        PRINT CHR$ (4);"REAO GSOSERROR.T" 
56030   FOR I = 0 TO 21 : INPUT A: CALL AY,3,ER,[I],A: NEXT : FOR I = 0 TO 21 : INPUT A$ : 
        CALL AY,3,ER$,[I],A$ : NEXT : PRINT CHR$ (4);"CLOSE" : A = FRE (0) : RETURN 
Figure x


Further Reference
GS/OS Reference
Apple IIgs Toolbox Reference: Volume(s) 1,2 and 3 Call Box BASIC Manual V2.0
Tech Notes 2 and 4


Call Box - So What Software 10221 Slater Ave. Suite 103 Fountain Valley, CA. 92708