Subject: Re: Himem with prodos basic? From: Chad Choi Lin Date: Sun, Oct 25, 1998 0350 Message-id: <3633026D.1652@nyetcom.com> Jm wrote: > I made an assembly language program that I need to interface with my > prodos basic program. The problem is what addresses should it go in? > Right now I'm loading it into the first hires graphics page. It seems > to work there but will prodos basic start scribbling all over it if I > make my program too long? I tried doing himem:(whatever hex 3500 is in > decimal) but then I got a "no buffers available" message when I tried > to load files. My apple 2c has 128K of RAM I think. Also, when I use & > to call the program, how would I type paramaters for it? Would it be > "& 3 2" or "&3,2,3" or what? And how does the program get them, are > they pushed onto the stack or something? Aha, another //c hacker! Having bumped my head many times against the problem of combining assembly/machine language routines with BASIC programs on the //c, I can give you some first-hand advice on the subject. Your suspicions about memory conflicts between your assembly code and ProDOS BASIC are correct: if your BASIC program is rather large, it may directly overwrite whatever is stored in Hi-Res Graphics Page 1 or indirectly stomp on the same memory area with variable storage. Fortunately, there are ways of protecting your assembly code from being destroyed. It is of great value to understand how Applesoft BASIC organizes memory for storing program code and variable data. BASIC uses a group of pointers to define a sort of "workspace" in memory, which is then divided into different sections. The following chart describes these pointers in detail. Pointer Addresses Points to... ------- --------- ------------ TXTTAB $67 (103) and Start of BASIC program (usually $68 (104) $801) PRGEND $AF (175) and End of BASIC program + 1 or 2 $B0 (176) VARTAB $69 (105) and Start of simple variable storage $6A (106) space (usually PRGEND + 1) ARYTAB $6B (107) and Start of array variable storage $6C (108) space STREND $6D (109) and End of variable storage space $6E (110) FRETOP $6F (111) and Start of string storage space $70 (112) MEMSIZ $73 (115) and End of string storage space $74 (116) (usually $9600 under ProDOS) Armed with this information, we can use any of the following techniques to create a "safehouse" for our assembly language routine(s): 1.) Move TXTTAB up to a higher address The start-of-program pointer is normally set to $801 (right after page 1 of text video memory) but can be changed to a higher address. Since page 2 of text video memory is not supported by Apple firmware, addresses $800 (2048) through $BFF (3071) will be unused by anything except our own assembly code; all we have to do is obey these guidelines for adjusting TXTTAB: (a) the location immediately before the address pointed to by TXTTAB must *always* contain a zero, and (b) you must not modify TXTTAB from within a BASIC program unless you immediately terminate said program or promptly load another BASIC program. This means that you must preceed your main BASIC program with a special "loader" program that "paves the way," like this.... 10 POKE 103,1 : POKE 104,12 : REM Change TXTTAB 20 POKE 3072,0 : REM Store zero at TXTTAB - 1 30 PRINT CHR$(4);"RUN MY.PROGRAM" : REM Load and execute the main BASIC code The above example reserves the entire page 2 area of text video memory for our use, then loads the BASIC file "MY.PROGRAM" from disk. 2.) Move VARTAB up to a higher address The start-of-variables pointer is normally set to the address immediately after the end of the BASIC program (pointed to by PRGEND). However, VARTAB can be adjusted upwards *as long as it is done before any variables have been defined by the program*. The advantage to this method is that, if we know ahead of time how many bytes our assembly code will require, we can set aside *exactly* as much memory as we need. All we have to do is add the number of required bytes to the current value of PRGEND and assign the sum to VARTAB, like so.... 10 LOMEM: PEEK(175) + PEEK(176)*256 + 42 : REM Assuming that we need 42 bytes 20 REM Rest of program continues from here.... Another nice thing is that, as long as the number of required bytes remains the same, we can go ahead and make the BASIC program larger or smaller -- because each time that we run the program, line 10 will automatically recalculate VARTAB (using the LOMEM: statement) according to the value of PRGEND no matter how it has changed. Of course, this is assuming that you are reloading your assembly code at VARTAB - n (where n = number of bytes needed) every time as well. 3.) Move MEMSIZ to a lower address In a sense, this is the most problematic technique because of the way that ProDOS modifies MEMSIZ on the fly. When opening a disk file, ProDOS will automatically lower MEMSIZ by $400 (1024) bytes to create a temporary disk buffer. Because strings are stored in reverse order (starting at MEMSIZ, then moving down to lower and lower addresses) ProDOS has to perform extra work to prevent strings from being overwritten by the $400-byte disk buffer. When the disk file is closed, ProDOS moves MEMSIZ back up to its original value. Also, ProDOS only allows *multiples of $100 (256)* for values of MEMSIZ. If we take all this into account, we can then safely adjust MEMSIZ by following these guidelines: (a) Close all disk files (by using the universal CLOSE command under ProDOS) (b) Lower the value of MEMSIZ high (hex $74, dec 116) by the number of pages required, *plus* the four pages needed for the temporary ProDOS disk buffer (so if your assembly code uses three pages, you should lower MEMSIZ by seven) (c) If you are changing MEMSIZ by using the HIMEM: command from within a BASIC program, you must do so before defining any strings (otherwise you may overwrite them!) (d) Don't set MEMSIZ too low, or you'll bump into the simple/array variable storage area of memory (this is probably what caused the "NO BUFFERS AVAILABLE" error in your case: ProDOS didn't have enough room to create its temporary disk buffer) 4.) Stick your code in page 3 It's an old Apple II programmer's trick, but sometimes the old ways work best. Since the memory section from addresses $300 (768) through $3CF (975) is not used by the Apple firmware and lies completely out of the way of the Applesoft BASIC memory workspace, it makes an ideal refuge for small assembly/machine language routines. Of course, this makes it prime real estate for all sorts of neat little binary programs and machine language utilities, so you may already be using page 3 for something else. BTW, that 128K in your //c is not one contiguous block of memory. Instead, it is divided into two sections of 64K called the "main" and "auxiliary" memory banks -- this is due to the fact that the 65C02 processor (the CPU in your //c) can only address up to 64K at a time. In fact, the topic of //c memory management deserves an entire discussion of its own, but suffice to say that having 128K does not usually mean that you have twice as much room to play in. Furthermore, the art of passing parameters from a BASIC program to a machine language routine is so involved that I'll have to postpone describing it until later. Hopefully I've given you enough information to get off on a promising start. Until next time, happy hacking! -- Peace, Love, and Apple II Forever! Chad Choi Lin chadlin@nyetcom.com ********************************* New and improved .sig file -- now with munged address AND spambait! To send e-mail, remove the "y" from the domain name of address. ********************************* Hey MLM scam artists -- send your spam to the Federal Trade Commission: pyramid@ftc.gov The IRS wants to know how much money you REALLY make: net-abuse@nocs.insp.irs.gov These guys love sending spam -- let's see how much they like GETTING it: shadowcomm.com 2hootersup.com newpower.com wildsnatch.com 2-girls.com cumshower.com cumsuckingsluts.com pornotheater.com fabulousfacials.com knobgobblers.com cherrypit.com sexxxlinks.com ******************************** Okay, I lied -- I'm not a NETCOM accountholder. You can e-mail me at "dirtlink" (fnord) dot "net" ********************************