ProDOS #9
Buffer Management Using BASIC.SYSTEM

Revised by Matt Deatherage (November 1988)
Revised by Pete McDonald (October 1985)

This Technical Note discusses methods for allocating buffers which will not be arbitrarily deallocated in BASIC.SYSTEM.

Note: Yes, there are two "revised" by-lines and no "written" by-line for this Technical Note. This is how I found it online. -- AH

Section A.2.1 of the ProDOS 8 Technical Reference Manual describes in detail how an application may obtain a buffer from BASIC.SYSTEM for its own use. The buffer will be respected by BASIC.SYSTEM, so if you choose to put a program or other executable code in there, it will be safe.

However, BASIC.SYSTEM does not provide a way to selectively deallocate the buffers it has allocated. Although it is quite easy to allocate space by calling GETBUFR ($BEF5) and also quite easy to deallocate by calling FREEBUFR ($BEF8), it is not so easy to use FREEBUFR to deallocate a particular buffer.

In fact, FREEBUFR always deallocates all buffers allocated by GETBUFR. This is fine for transient applications, but a method is needed to protect a static code buffer from being deallocated by FREEBUFR for a static application.

Location RSHIMEM ($BEFB) contains the high byte of the highest available memory location for buffers, normally $96. FREEBUFR uses it to determine the beginning page of the highest (or first) buffer. By lowering the value of RSHIMEM immediately after the first call to GETBUFR, and before any call to FREEBUFR, we can fool FREEBUFR into not reclaiming all the space. So although it is not possible to selectively deallocate buffers, it is still possible to reserve space that FREEBUFR will not reclaim.

Physically, we place the code buffer between BASIC.SYSTEM and its buffers, in the space from $99FF down.

After creating the protected static code buffer, we can call GETBUFR and FREEBUFR to maintain temporary buffers as needed by our protected module. FREEBUFR will not reclaim the protected buffer until after RSHIMEM is restored to its original value.

The following is a skeleton example which allocates a two-page buffer for a static code module, protects it from FREEBUFR, then deprotects it and restores it to its original state.

START    LDA #$02            ;get 2 pages
         JSR GETBUFR 
         LDA RSHIMEM         ;get current RSHIMEM
         SEC                 ;ready for sub
         SBC #$02            ;minus 2 pages
         STA RSHIMEM         ;save new val to fool FREEBUFR
         JSR FREEBUFR        ;CALL FREEBUFR to deallocate.

At this point, the value of RSHIMEM is the page number of the beginning of our protected buffer. The static code may now use GETBUFR and FREEBUFR for transient file buffers without fear of freeing its own space from RSHIMEM to $99FF.

To release the protected space, simply restore RSHIMEM to its original value and perform a JSR FREEBUFR.

END      LDA RSHIMEM         ;get current val
         CLC                 ;ready for ADD
         ADC #2              ;give back 2 pages
         STA RSHIMEM         ;tell FREEBUFR about it

You can reserve any number of pages using this method, as long as the amount you reserve is within available memory limits.

Further Reference

This and all of the other Apple II Technical Notes have been converted to HTML by Aaron Heiss as a public service to the Apple II community, with permission by Apple Computer, Inc. Any and all trademarks, registered and otherwise, are properties of their owners.