Skip to main content

Full text of "The_Hitchhiker's_Guide_to_GEOS"

See other formats


Not for resale 



The Hitchhiker's 
Guide to GEOS 

A Potpourri of Technical Programming Notes 

(provided "as is" without support) 
April 1988 



Copyright ©1988,. 1989 Berkeley Softworks. 

This is a copyrighted work and is not in the public domain. However, you may use, copy, and 
distribute this document without fee, provided you do the following: 

• You display this page prominently in all copies of this work. 

• You provide copies of this work free of charges or charge only a distribution fee for the 
physical act of transferring a copy. 

Please distribute copies of this work as widely as possible. 

Note: Berkeley Softworks makes no representations about the suitability of this work for any 
purpose. It is provided "as is" without warranty or support of any kind. 

BERKELEY SOFTWORKS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS 
WORK, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND 
FITNESS. IN NO EVENT SHALL BERKELEY SOFTWORKS BE LIABLE FOR ANY 
SPECIAL, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 
WHATSOEVER RESULTING FROM LOSS OF USE, DATA, OR PROFITS, WHETHER IN 
AN ACTION OF CONTRACT. NEGLIGENCE, OR OTHER TORTIOUS ACTIONS, ARISING 
OUT OF OR IN CONNECnOr^ WITH THE USE OF THIS WORK. 



Introduction (second edit / MGL) 



1/13/88 12:22 PM 



Introduction 



In 1986, Berkeley Softworks pioneerecj GEOS — the Graphic Environment Operating System — 
for the Commodore .64. GEOS bffered the power of an icon/windowing operating system, once 
thought possible'.on the likes of Apple's Macintosh, to one of the world's lowest priced 
microcomputers. The computing community quickly recognized this innovation as significant: the 
Software Publisher's Association (SPA) gave GEOS a Technical Achievement Award and 
Commodore Business Machines endorsed it as the official operating system for the Commodore 
64. Some industry critics even said it brought the Commodore 64 out of obsolescence. Since that 
time, GEOS has been ported to the Commodore 128 and, most recently, to the Apple 11 family of 
computers. Boasting an installed base approaching one-million units, GEOS not only promises to 
be around for some time, but to grow into^the operating system for low-end computers 



Why Develop GEOS Applications 

GEOS provides an environment for programmers and software companies to quickly and 
efficiently develop sophisticated applications. GEOS insulates the programmer from the frustrating 
details and dirty work usually associated with application development. By using the GEOS 
facilities for disk file handling, screen graphics, menus, icons, dialog boxes, printer and input 
device support, the application can concentrate on doing what it does best, applying itself to the 
task at hand, using the GEOS system resources, routines, and user-interface facilities to both speed 
program development and build better programs. 

Consistent User-interface 

A very large portion of GEOS is devoted to supporting the user-interface. THe GEOS interface has 
proven popular with thousands of users, and an application that takes advantage of this will likely 
be well received because the users will already be familiar with the basic program operation. Once 
a user has learned to operate geoWrite, for example, it is a smooth transition to another application 
such as geoCalc. 

Large Installed Base and Portability 

GEOS is currently available for three machines: the Commodore 64, the Commodore 128, and the 
Apple 11. There are hundreds of thousands of owners who use GEOS on these machines and there 
is a correspondingly large demand for follow-on products. With careful programming, an 
application can be developed to run under all available system configurations with only minor 
changes. Berkeley Softworks plans to port GEOS to other 6502-based microconiputers, thereby 
further increasing the user base. As the popularity of GEOS grows, so does the market for your 
product. 

Application Integration 

GEOS offers a flexible cut and paste facility for text and graphic images. These photo scraps and 
text scraps allow applications to share data: a word processor can use graphics from a paint 
program and a graph and charting application can use data from a spreadsheet. The scrap format is 
standard and allows applications from different manufacturers to exchange data, Berkeley 
Softworks is currently developing a second-generation scrap facility for object-oriented graphics 
such as those used in desktop publishing and CAD programs. 



1 



Introduction (second edit / MGL) 



1/13/88 



12:22 PM 



Input and Output Technology 

GEOS supports the concept of a device driver. A device driver is a small program which co-resides 
with the GEOS Kemal and communicates with I/O devices. Device drivers translates data and 
parameters from a generalized format. that GEOS understands into a format relevant to the specific 
device. GEOS has input drivers for mice, joysticks, light pens, and other input devices, printer 
drivers for text and graphic output devices (including laser printers), and disk drivers for storage 
devices such as floppy disk drives, hard disks, and RAM expansion units (RAMdisks). As new 
devices become available, it is merely necessary to write a driver to support it. 

What Exactly is GEOS? 

First and foremost, GEOS is an operating system: a unified means for an application to interact 
with peripherals and system resources. GEOS is also an environment — specifically, a graphics- 
based user-interface environment offering a standard library of routines and visual-based controls, 
such as menus and icons. And finally, GEOS is a programmer's toolbox, providing routines for 
double-precision integer math, random-number generation, and memory manipulation.. 



NOTE: GEOS as a general term can represent full range of concepts — an operating system, a 
user environment, the deskTop, a group of integrated applications — but in this book it 
usually refers specifically to the GEOS KernaU the resident portion of the operating 

system with which the application deals with. 



GEOS As an Operating System 

College textbook writers are forever coming up with splendid new metaphors to describe operating 
systems. But as the coach of a baseball team or the governor of California, an operating system has 
the same basic function: it is the manager of a computer, providing facilities for controlling the 
• system while isolating the application from the underlying hardware. An operating system allows 
the application to function in higher-level abstract terms such as "load a file into memory" rather 
than "let a bit rotate into the serial I/O shift register and send an acknowledge signal." The 
operating system will handle the laborious tasks of reading disk files, moving the mouse pointer, 
and printing to the printer, 

GEOS provides the following basic operating system functions: 

♦ Complete management of system initialization, multiple RAM banks, interrupt 
processing, keyboard/joystick/mouse input, as well as an application environment that 
supports dynamic overlays for programs larger than available memory, desk 
accessories, and the ability to launch other applications. 

• A sophisticated disk file system that supports multiple drives, fast disk I/O, and RAM 
disks. 

• Time-based processes, allowing a limited form of multitasking within an application. 

♦ Printer output support, offering a unified way to deal with a wide variety of printers. 



2 



Introduction (second edit / MGL) 



1/13/88 12:22 PM 



GEOS As a Graphic and User-Interface Environment 

Interactive graphic interfaces have become the norm for niodem day productivity. GEOS provides 
a services for placing lines, rectangles, and images on the screen, as well as handling menus, 
icons, and dialog boxes. Using the GEOS graphic elements make applications look better and 
easier to use. 

GEOS provides the following graphic and user-interface functions: 

• Multi-level dynamic menus which can be placed anywhere on the screen. GEOS 
automatically handles the user's interaction with the menus without permanently 
disrupting the display. 

• Icons — graphic pictures the user can click on to perform some function. 

• Complete dialog box library offering a standard set of dialog boxes (such as the file- 
selector) ready for use. The application may also define its own custom dialog boxes. 

• A library of graphic primitives for drawing points, lines, patterned rectangles, and 
pasting photo scraps from programs like geoPaint. 

• Sprite support. (Sprites are small graphic images which overlay the display screen and 
can be moved easily. The mouse pointer, for example, is a sprite.) 

• A secondary screen buffer for undo operations. 
GEOS As a Programmer's Toolbox 

« GEOS also contains a large library of general support routines for math operations, string 
manipulations, and other functions. This relieves the application programmer of the task of writing 
and debugging common routines ("re-inventing the wheel" as it were). 

GEOS provides the following support routines: 

• Double-precision (two-byte) math: shifting, signed and unsigned multiplication and 
division, random number generation, etc. 

• Copy and compare string operations. 

• Memory functions for initializing, filling, clearing, and moving. 

• Miscellaneous routines for performing cyclic redundancy checks (CRC), initialization, 
error handling, and machine-specific functions. 

Development System Recommendations 

There are many ways to develop GEOS applications. Berkeley Softworks, for example, uses a 
UNIX™ based 6502 cross assembler and proprietary in-circuit emulators to design, test, and 
debug GEOS applications. Most developer's, however, will find this method too costiy or 
impractical and will opt to develop directly on the target machines. Anticipating this, Berkeley 



3 



Introduction (second edit / MGL) 



1/13/88 12:22 PM 



Softworks has developed geoProgrammer, an assembler, linker, debugger package designed 
specifically for building GEOS applications. 

geoProgrammer 

geoProgrammer is a sophisticated set of assembly language development tools designed 
specifically for building GEOS applications. geoProgrammer is a scaled-down version of the 
UNIX™ based development environment Berkeley Softworks actually uses to develop GEOS 
programs. In fact, nearly all the functionality of our microPORT™ system has been preserved in 
the conversion to the GEOS environment. All sample source code, equates, and examples in this 
book are designed for uses with geoProgrammer. 

The geoProgrammer development system consists of three major components: 

geoAssembler, the workhorse of the system, takes 6502 assembly language source code and 
creates linkable object files. 

• Reads source text from geoWrite documents; automatically converts graphic and icon 
images into binary data. 

• Recognizes standard MOS Technology 6502 assembly language mnemonics and 
addressing modes. 

• Allows over 1,000 symbol, label, and equate definitions, each up to 20 characters long. 

• Full 16-bit expression evaluator allows any combination of arithmetic and logical 
operations. 

• Supports local labels;, as targets for branch instructions. 

• Extensive macro facility with nested invocation and multiple arguments. 

• Conditional assembly, memory segmentation, and space allocation directives. 

• Generates relocatable object files with external definitions, encouraging modular 
programming. 

geoLinker takes object files created with geoAssembler and links them together, resolving all 
cross-references and generating a runable GEOS application file. 

• Accepts a link command file created with geoWrite. 

• Creates all GEOS applications types (sequential, desk accessory, and VLIR), allowing a 
customized header block and file icon. geoLinker will also create standard Commodore 
applications which do not require GEOS to run. 

• Resolves external definitions and cross-references; supports complex expression 
evaluation at link-time. 

• Allows over 1,700 unique, extemally referenced symbols. 

• Supports VLIR overlay modules. 



4 



Introduction (second edit / MGL) 



1/13/88 12:22 PM 



geoDebugger allows you to interactively track-down and eliminate bugs and errors in your GEOS 
applications. 

• Resides with your application and maintains two independent displays: a graphics screen 
for your application and a text screen for debugging. 

• Automatically takes advantage of a RAM-expansion unit, allowing you to debug 
applications which use all of available program space. 

• Complete set of memory examination and modification commands, including memory 
dump, fill, move, compare, and find. 

• Symbolic assembly and disassembly. 

• Supports up to eight conditional breakpoints. 

• Single-step, subroutine step, loop, next, and execute commands. 

• RESTORE key stops program execution and enters the debugger at any time. 

• Contains a full-featured macro programming language to automate multiple keystrokes 
and customize the debugger command set. 

Commodore 64 

GEOS was first implemented on the Commodore 64, and currentiy there are more GEOS 
applications for this system than the Apple II or the Commodore 128. The following is 
recommended for developing under this environment: 

• Commodore 64 or 64c computer. 

• Commodore 1351 mouse. 

• At least one 1541 or 1571 disk drive. 

• Commodore 1764 or 1751 RAM-expansion unit. 

• GEOS supported printer. 

• The basic GEOS operating system (GEOS 64), version 1.3 or later which includes 
geoWrite and geoPaint. 

• geoProgrammer for the Conimodore 64. 
Commodore 128 

The Commodore 128 may be the ideal environment for prototyping and developing GEOS 
applications because it can be used to create programs which run under GEOS 64 (in 64 emulation 
mode) and GEOS 128. The 128 sports a larger memory capacity, and geoProgrammer takes 
advantage of this extra space for symbol and macro tables. The following is recommended for 
developing under this environment: 



5 



Introduction (second edit / MGL) 1/13/88 12:22 PM 

• Commodore 128 computer, 

• Commodore 1351 mouse. 

• At least one 1541 or 1571 disk drive. 

• Commodore 1764 or 1751 RAM-expansion unit. 

• GEOS supported printer. 

• The basic GEOS operating system (GEOS 64), version 1.3 or later which includes 
geoWrite and geoPaint. 

• The basic GEOS 128 operating system, version 1.3 or later which includes geoWrite 
128 and geoPaint 128. 

• geoProgrammer for the Commodore 128. 
Apple II 

The Apple II is the latest addition to the GEOS family. The following is recommended for 
developing in this environment: 

• Apple He, lie, or Ilgs computer. 

• Apple Mouse card. 

• At least one floppy disk drive. 

• RAM card or hard disk. 

• GEOS supported printer. 

• The basic GEOS operating system (Apple GEOS), which includes geoWrite and 
geoPaint. 

• geoProgrammer for the Apple 11. 
Other Useful GEOS Applications 

In addition to those applications listed above, you may find the following useful: 

• GEOS Icon Editor for customizing you icons. 

• Photo Manager and Text Manager for cutting and pasting text and graphics to and from 
your geoProgrammer source code modules. 

• Text Grabber for converting any 6502 source code you may have already written to 
geoWrite. 



6 



Graphics Routines (fourth edit / MGL) 



4/24/88 8:13 PM 



Graphic Routines 



As the name GEOS (Graphics Environment Operating System) implies, screen graphics are central 
to both the operating system and its applications. GEOS provides a number of graphic primitives 
("primitive" because they are the basis of more complex objects) for drawing points, lines, 
rectangles, and other objects, as well as displaying bitmap images such as those cut from geoPaint. 
GEOS also provides graphic support routines for undoing regions, inverting areas, scrolling,.and 
direcdy accessing the screen memory. 

Drawing with the built-in GEOS routines increases program portability by making much of the 
internal, machine-dependent screen architecture transparent to the application. When you draw a 
line, for example, you merely supply the two endpoints. GEOS takes care of calculating the proper 
pixel locations and modifying the screen memory. This allows an application to use the same code 
to draw lines on machines with very different graphics hardware and spares the programmer from 
dealing direcdy with screen memory. 

Introduction to GEOS Graphics 

If you look closely at a monitor or television screen, you will notice that the image is made up of 
many small dots. These small dots, called pixels, can be either on or off and are represented in 
memory by I's and 0*s, respectively. A pixel with a value of one is considered set and a pixel of 
value zero is considered clear. This binary, or bitwise, representation of images is refered to as 
bitmapped graphics, and a bitmap is a picture or image created in this way. 




0000000000 
0000000000 
0000000000 
0000000000 



1 



Graphics Routines (fourth edit / MGL) 



4/24/88 8:13 PM 



Color 

Although some hardware configurations support color graphics, GEOS assumes that the screen is 
a monochromatic device; that is, GEOS only deals with one drawing color and one background 
color. Typically, the drawing color is black, like ink and the background color is white, like a piece 
of paper. Depending on the monitor being used and the Preference Manager settings, the actual 
displayed colors may be different. We will refer to the color displayed by a zero-pixel as the 
background color and the color displayed with a one-pixel as the drawing color. Applications that 
support multiple drawing colors, such as the Commodore 64 version of geoPaint, must do so on 
their own, bypassing GEOS (at the expense of portability) to provide multiple colors on the screen. 

The GEOS Virtual Screen 

The GEOS screen is often referred to as virtual screen^ one whose layout and internal storage 
characteristics exist independent of any underlying graphics hardware. For this reason, the GEOS 
screen is fundamentally identical under all versions of the operating system. 

The GEOS screen is a rectangular array of pixels arranged like a sheet of graph paper. Each pixel 
on the screen has a corresponding (x,y) coordinate. The x-axis begins with zero and runs 
horizontally (left to right) across the screen, and the y-axis begins with zero and runs vertically (top 
to bottom) down the screen. The maximum x- and y-positions, because they differ from machine 
to machine, are calculated by subtracting one from the GEOS constants SC FIX WIDTH and 
SC FIX HEIGHT. 



(0. 0) 


^ (SC FIX WIDTH-1.0 






X increasing 




-< 






5* 
o 

3 


GEOS 




0) 
22. 


SCREEN COORDINATES 




3* 
(Q 




(0. SC_PIX_HEIGHT-1 ) (SC_PIX_WIDTH-1 , SC_PIX_HEIGHT-1 ) 



Important: GEOS does no clipping or range-checking on coordinates passed to it. If you pass 
it invalid data or coordinates, Ae results are unpredictable and will often crash the 
application. 



2 



Graphics Routines (fourth edit / MGL) 4/24/8 8 8:13 PM 



GEOS 128 40/80-Column Support 

Because applications that run under GEOS 128 may want to take advantage of both the 40- and 80- 
column screen modes, the following conventions have been adopted for the screen width and 
height constants: 

• The following constants can be used to access the dimensions of the 40- or 80-column 
screen specifically: 



SC 40 WIDTH 


Pixel width of 40-column screen. 


SC 40 HEIGHT 


Pixel height of 40-column screen. 


SC 80 WIDTH 


Pixel width of 80-column screen. 


SC 80 HEIGHT 


Pixel height of 80-column screen. 



• If the application is designed to run under GEOS 128 only and not run under GEOS 64 
(the C64 constant is set to $00 and the CI 28 constant is set to $01 ), then the standard 
SC^PIXJWIDTH and SCJPIXJHEIGHT constants take on the following values: 



SC FIX WIDTH 


Pixel width of 80-column screen. 


iiC'HX'HElOHT 


Pixel height of 80-column screen. 



• If the application is designed to run under GEOS 64 and GEOS 128 (both the C64 
constant and the C128 constant set to $01), then the standard SC_PIX_WIDTH and 
SC_PIX_HEIGHT constants take on the following values: 



WiDtH 


Pixel width of 40-column screen. 


SC FIX HElGHt 


Pixel height of 40-column screen. 



This is because the application (typically) will be written with the 40'Column screen in 
mind. At runtime, the application can check to see which version of GEOS it is running 
under and add doubling bits to the appropriate coordinate values so that the 40'Column 
coordinates will be normalized automatically when GEOS 128 is in 80'Column mode. 



An application can use the following subroutine to determine whether it is running under GEOS 
128 or GEOS 64: 

.if (0) 

Checkl28: 

Check for GEOS 128. 

Pass : 

nothing 
Returns : 

St minus flag set if running under GEOS 128, 
Example usage: 

/ignore if under GEOS 64 

;else, patch x-coordinates with doubling bits 

'3 



jsr Checkl28 

bpl 10$ 

jsr DoDoubling 

10$: 



3 



Graphics Routines (fourth edit / MGL) 



4/24/88 



8:13 PM 



.endif 



Checkl28: 
Ida 
cmp 
bpl 



10$: 



Ida 
rts 



#$12 

version 

10$ 

cl28Flag 



cl28Flag not guaranteed to be valid in version 1.2 and lower 
first see if version <= 1.2 

if so; branch and say C64 . Note this is a signed comparison, 
(it WILL NOT work if GEOS goes beyond version $7f !) 
else set minus based on high bit cl28Flag 



When running under GEOS 128, the graphMode variable may be checked to determine whether 
GEOS is in 40- or 80-column mode: 



bit graphMode / check 40/80 mode bits 

bpl C64Mode ; branch if in 4 0-column mode 

; else, handle as 80-column... 



For more information, refer to "GEOS 128 X-poisition and Bitmap Doubling" in this chapter. Also 
see NormalizeX in the Routine Reference Section. 



Inclusive Dimensions 

All dimensions and GEOS coordinates are inclusive: a line contains the endpoints which define it, 
and a rectangle includes the lines that make up its sides. For example, a rectangle defined by an 
upper-left comer of (10,10) and a lower-right comer of (20,20) would include the lines around its 
perimeter defined by the points (10,10), (10,20), (20,10), and (20,20). 

Linear Bitmap 

For the purpose of bitmap compaction and patterns, the GEOS screen is treated as a linear bitmap, 
a contiguous block of bytes with each bit controlling an individual pixel. The bytes are lined up 
end-to-end for each screen line! The high-order bit (bit 7) of each byte controls the leftmost pixel 
and the low-order bit (bit 0) controls the rightmost pixel. 



X-axis 



1 1 1 J 1 1 1 1 1 1 ij 1 1 1 r 



1 

X 

(5* 



byte byte 1 



GEOS Virtual Screen 



Keep in mind that this is a conceptual organization of the screen; the actual in-memory storage of 
the screen and bitmap data may be very different 

Dividing the Screen Into Cards 

Many GEOS routines subdivide the GEOS virtual screen into 8x8-pixel blocks called cards. A card 
is a two-dimensional unit of measurement eight pixels on each side. The first card begins in the 



4 



Graphics Routines (fourth edit / MGL) 



4/24/88 8:13 PM 



upper-left comer of the screen (0, 0) and extends to (7, 7). The next card is just to the right of the 
first and extends from (8, 0) to (15, 7). 

Cards are always aligned to eight pixel boundaries called card boundaries (pixel positions 0, 8, 16, 
24, etc.). Aligning an object to a card boundary is called card alignment^ and tiie position of an 
object expressed in cards is called its card position. Pixel position (32, 72), for example, would 
correspond to card position (4, 9) because 32/8 =.4 and 72/8 = 9). The card width of an object is 
its width in cards, and the card height is its height in cards. An entire row of cards is called a 
cardrow. 



The card is a convenient unit of measurement because its dimensions, 8x8, which is a power of 2, 
lend themselves to simple binary arithmetic. For example, converting a pixel position to a card 
position is merely a matter shifting right three times. 

Example: 



MseToCardPos : 

converts current mouse positions to card position 



Pass : 
Uses : 
Returns : 

Destroys : 



nothing 

MouseXPos, MouseYPos 

rOL mouse card x-position (byte) 
rOH mouse card y-position (byte) 



a,x,y 

(mgl) 

llr It 1^ ************************** * 

MseToCardPos: 



php 




• save current interrupt disable status 


sei 




• disable interrupts so mouseXPos doesn't change 


MoveW 


MouseXPos, rO 


' copy mouse x-position to zp work reg (ro) 


pip 




• reset interrupt status asap. 


Idx 


#rO 


• divide x-position (rO) by 8 


Idy 


#3 


• (shift right 3 times) 


jsr 


DShiftRight 


• this gives us the card x-position in rOL 


Ida 


MouseYPos , 


• get mouse y-position 


Isr 


a t 


' and shift right 3 times 


Isr 


a < 


• which is a divide by 8 


Isr 


a t 


• and gives us the card y-position in a 


sta 


rOH 


• set down card y-position 


rts 




• exit 



Cards are also convenient because they map directly to the internal storage format of the 
Commodore 40-column graphics screen. (Converting to other formats, such as the Commodore 
128 80-column screen or the Apple n double hi-res screen, requires additional translation. This 
translation is handled automaticdly by the GEOS graphics routines.) 



Display Buffering 



Normally the application has control of the screen. But when an item such as a dialog box or a 
menu is displayed, GEOS overwrites the screen. When the dialog box is removed or the menu is 
retracted, GEOS needs to restore the portion of the screen it destroyed. For this purpose, GEOS 



5 



Graphics Routines (fourth edit / MGL) 



4/24/88 8:13 PM 



maintains a background screen buffer. Most of the time, the background buffer contains an exact 
copy of the foreground screen (rfie screen that is displayed) because GEOS normally sends 
graphics data to both screen buffers. When a temporary object is displayed, however, it is only 
drawn to the foreground screen. Removing the object, or recovering the original area of the screen, 
is then simply a matter of copying pixels from the background buffer to the foreground screen. The 
GEOS dialog box and menu routines- handle this sort of recovery automatically. 

dispBufferOn 

Usually the application will want to draw to both buffers so that GEOS can properly recover the 
foreground screen after menus and dialog boxes. If graphics are only drawn to one buffer and a 
menu is brought down or a dialog box is displayed, the subsequent recover may restore the wrong 
data. 

However, sometimes an application may want to limit drawing to only the foreground or 
background screen buffer. GEOS graphics and text routines use the global variable 
dispBufTerOn to determine whether to draw to the foreground screen, the background buffer, or 
both simultaneously. Bits 6 and 7 of dispBufferOn determine the writing and reading mode: 









bit 7: 


i 


1 — use foreground screen. 

— do not use foreground screen. 


bit 6: 




1 — use background buffer. 

— do not use background buffer. 


bits 5-0: 




reserved for future use — should always be 0. 



There are some constants which allow you to gain access to these bits: 

ST^WR^FORE use foreground. 
ST_WR_B ACK use background. 

and they can be used in following manner: 

;Use both foreground screen and background buffer (normal) . 
LoadB dispBufferOn, # (ST__WR_FORE I ST_WR_BACK) 

;Use foreground screen only. 

LoadB dispBufferOn, #ST__WR_FORE 

;Use background buffer only. 

LoadB dispBufferOn, #ST_WR_BACK 

Note: If bits 6 and 7 of dispBufferOn are both zero, GEOS considers this an undefined 
state and will not produce useful results. In most cases, the internal address calculations 
will force your graphic objects to appear in the center of the drawing area where they 
can do little harm. If the center line on the screen becomes garbled, dispBufferOn 

probably contains a bad value. 

Using dispBufferOn 

Typically applications leave dispBufferOn set to draw to both screens, whereas most desk 
accessories will only draw to the foreground screen. In some situations, an application may want 
to limit drawing to the foreground screen so that it may recover from the background buffer at a 
later time. Internally this is what GEOS does when it opens a menu or dialog box: the object is 



6 



Graphics Routines (fourth edit / MGL) 



4/24/88 8:13 PM 



only drawn to the foreground screen, and when it needs to be erased, the original data is recovered 
from the background buffer. dispBufTerOn can also be used to pre-draw complex objects in the 
background buffer (ST_WR_BACK) and make them instantly appear on the foreground screen 
by doing a recover. " 

An application must take special precautions.when using dispBufferOn to draw selectively to 
one buffer or the other. For example, when GEOS automatically recovers from a menu or a dialog 
box, it recovers the data from the background buffer. If the background buffer has not been 
updated (the application has been drawing with the ST_WR_BACK bit cleared, for example), 
then the menu or dialog may recover the wrong data. 

Since dialog boxes are only displayed when the the application calls DoDlgBox and menus are 
only opened while GEOS is in MainLoop, the application has some control over GEOS's 
automatic recovering. The application can postpone displaying dialog boxes and returning to 
MainLoop until the foreground screen and background buffer contain the same data. If an 
application must return to MainLoop while the buffers contain different data (to let processes run, 
for example), it can always disable menus by clearing the.MENUON_BIT bit of mouseOn. The 
menus may be reenabled again by restoring the MENUON_BIT bit of mouseON: 

Example: 



StopMenus : 

MoveB 

rmbf 

rts 



mouseOn, oldMouseOn 
MENUON BIT,mouseOn 



save current enable status for later 

disable menus temporarily 

exit. 



RestartMenus : 
Ida 
and 
ora 
sta 
rts 



OldMouseOn : 



OldMouseOn 

#(%1 «MENUON_BIT) 

mouseOn 

mouseOn 



.byte $00 



get old menu enable status 
ignore all but menu bit 
restore old menu bit 
in current mouseOn byte 
exit 

temp save area for mouseOn variable 



Using the Background Buffer as Extra Memory 

Some applications are so starved for memory that they opt to use the background buffer for 
program code or data. To do this, they must always keep the ST_WR BACK bit of 
dispBufferOn clear so that the background buffer is not corrupted with graphic 3ata. 

If you disable the background buffer, GEOS cannot automatically recover after menus and dialog 
boxes. The application must provide its own routine for restoring the foreground screen. There is a 
GEOS vector called RecoverVector, which normally points to the RecoverRectangle 
routine. Whenever GEOS needs to recover from a menu, dialog box, or desk accessory, it sets up 
parameters as if it were going to call RecoverRectangle and jsr's indirectly through the address 
in RecoverVector. If the application is using the background buffer, it must place the address of 
its own screen recover routine in RecoverVector. When GEOS needs to recover a portion of the 
screen, it will jsr to the application's recover routine with the following register values describing 
the rectangular area to recover: 

r3 XI — x-coordinate of upper-left (word). 

r2L Yl — y-coordinate of upper-left (byte). 

r4 X2 — x-coordinate of lower-right (word). 

r2H Y2 — y-coordinate of lower-right (byte). 



7 



Graphics Routines (fourth edit / MGL) 



4/24/88 8:13 PM 



where (X1,Y1) is the upper-left comer and (X2,Y2) is the lower-right comer of the rectangular 
area to recover. The rectangle's coordinates are inclusive. The application must then use these 
values to restore the portion of the screen that lies within the rectangle's boundaries and retum with 
an rts. This recovery can be as simple as filling with a halftoned pattern or as involved as 
redrawing graphic and text objects that fall within the rectangular recover area. 

Most of the larger Berkeley Softworks GEOS applications use a technique called 
saveFG/recoverFG (short for "save foreground" and "recover background") to save and recover 
the foreground screen when displaying menus and dialog boxes. Basically, saveFG will save a 
rectangular subregion of the foreground screen to a special buffer just before GEOS displays a 
menu or a dialog box. When GEOS tries to recover from the background buffer, recoverFG 
restores the data from the special buffer. Although the size of the buffer varies from application to 
application, it will seldom be larger than 5.5K (just large enough to hold the largest standard 
dialog box). 

Transferring data to and from the buffer is fairly straightforward. With the Commdore 40-column 
screen, it is mostly a matter of calculating the proper address offsets and copying bytes. With the 
GEOS 128 80-column screen, the process is compUcated a bit because the bytes must be read from 
the VDC chip's RAM. With Apple GEOS, the process is simplicity itself because there are two 
routines for saving and restoring automatically: saveFG and recoverFG. 

The real trick is knowing how to intercept the normal GEOS menu and dialog box drawing and 
recovering mechanisms. Dialog boxes are the easiest because they are always called by the 
application. The program only needs to save the foreground screen area prior to calling 
DoDIgBox. The size of the dialog box can be caculated from its table (be sure to account for any 
shadow) and the foreground data can be copied into the saveFG buffer. When the dialog box is 
finished, GEOS will jsr through RecoverVector. The application installs its own recoverFG 
routine into RecoverVector and restores the foreground area from the saveFG buffer. The 
GEOS dialog box recovery does have one quirk that concerns shadowed dialog boxes. GEOS 
shadowed dialog boxes consists of two overlapping rectangular areas: the actual diaJog box and the 
slightly offset shadow rectangle. GEOS first calls through RecoverVector once for the region 
bounded by the shadow box, then again for the region bounded by the dialog box. When saving 
the foreground area, the entire dialog box region (the area bounded by the union of all eight comer 
points) should be saved and a special flag should be set so that the area is only recovered once. 
Under Apple GEOS, the recovery of dialog box shadows can be suppressed by setting 
recoverOnce to a non-zero value. When recoverOnce is non-zero, GEOS only vectors through 
RecoverVector once with the bounding rectangle of the dialog box. The application's recover 
routine will need to compensate for the shadow box. For more information on dialog boxes, refer 
to Chapter @DLG@ . 

Saving the foreground area before a menu is displayed is a bit tougher because GEOS displays 
menus at MainLoop, the application has little notice that a submenu is opening up. Fortunately, 
there is a workaround: GEOS supports a special type of sub-menu called a dynamic sub-menu. 
Just before a dynamic sub-menu opens, GEOS calls a subroutine whose address is stored in the 
menu data structure. This opporunity can be used to save the foreground screen area before GEOS 
draws the menu by calculating the bounding rectangle from the menu structure. When GEOS 
recovers a menu, it calls through RecoverVector as it does with dialog boxes. With multiple 
sub-menus, the menus are always recovered in the reverse order they were drawn. For more 
information on menus, refer to Chapter @ICNMENU@ 



8 



Graphics Routines tfourth edit / MGL) 



4/24/88 8:13 PM 



Manual Imprinting and Recovering 

Within an application, data can be moved between the foreground screen and background buffer 
with GEOS routines that copy data to and from the two areas. Copying data from the foreground 
screen to the background buffer is called imprinting, and copying data from the background buffer 
to the foreground screen is called recovering. There are GEOS routines for imprinting and 
recovering points, lines, and rectangular regions. 

Some Possible dispBufferOn Complications 

When drawing with both buffers enabled (with both foreground and background bits set in 
dispBufferOn), GEOS requires that the foreground screen and the background buffer contain 
exacdy the same data. If they are different, the resuhs of graphic operations may be unpredictable. 
If you need to draw to the foreground screen and the background buffer when they contain 
different data, you must perform the graphic operation once by writing only to the foreground 
screen, and then a second time, writing only to the background buffer — you cannot write to both 
of screen areas simultaneously if they contain different data. 

Machine Dependencies 

The GEOS graphics routines hide much of the underlying hardware from the application. This 
allows the same code to run under a variety of different environments with very few changes. 
However, it is sometimes necessary to optimize graphic routines for a specific machine. This can 
be as simple as taking advantage of color display capabilities or as complex as direct screen 
memory manipulation. Either way, an application should only resort to such tactics when the 
desired effect cannot be achieved through the standard graphics routines. Be aware that 
circumventing the GEOS Kemal will very likely increase your development time and that there is 
no guarantee that the techniques will be compatible with future versions of GEOS. 

Commodore 64 

The Commore 64 version of GEOS uses the standard high-resolution bitmap mode (not multi-color 
bitmap mode), which is 320 pixels wide by 200 pixels high. Memory is mapped to the screen in 
eight-byte stacks called cards: byte controls pixels (0,0) through (7,0), with bit 7 on the left and 
bit on the right, and byte 1 controls the same pixels on the Une below, which is pixels (0,1) 
through (7,1). This stacking continues through byte 7, which controls pixels (0,7) through (7,7) 
and completes the 8x8-pixel card. Byte 8 begins the next card, controlling pixels (8,0) through 
(15,0). The screen memory begins at SCREEN BASE and occupies 8,000 bytes, extending to 
SCREEN_BASE+7999. The background buf^r begijis at BACK SCR BASE and extends 
to BACK^SCR_BASE+7999. 

GEOS does not directly support the foreground and background color options of the standard 
high-resolution bitmap mode. The color matrix, located from COLOR_MATRIX to 
COLOR MATRIX+999, is set to a constant foreground and background color as determined 
by the Preference Manager. If an application wants to support color Gike geoPaint), it must manage 
the color matrix itself. Each byte in the color matrix sets the foreground and background colors of a 
card (8x8 pixel block): color byte sets the colors for card (bitmap bytes 0-7) and color byte 1 
sets the colors for card 1 (bitmap bytes 8-15). Before the application exits, it must restore the 
original color matrix. This best done by sa;ving the first byte and then filling the color matrix before 
calling EnterDeskTop, as the following code fragments illustrate: 



Example: 



Graphics Routines (fourth edit / MGL) 



4/24/88 8:13 PM 



;0n entry, save off the first byte of the color matrix 
MoveB COLOR_MATRIX, saveColor 



;0n exit, fill the color matrix with the saved value 

LoadW rO,#1000 /color matrix is 1000 bytes 

LoadW r 1 , #COLOR_MATRIX 

MoveB saveColor, r2L ;fill with original color 
jsr FillRam 

Commodore 128 

In 40-column mode, GEOS 128 screen memory is identical to the Commodore 64. In 80-column 
mode, GEOS 128 uses the high-resolution 640x200 mode supported by the 8563 VDC (Video 
Display Controller) chip.. The foreground screen memory is not stored in the normal Commodore 
memory but on the VDC chip instead. The VDC RAM is accessed indirecdy through the VDC 
control registers. The screen occupies 16,000 bytes, and each byte is accessed one at time by its 
address within the VDC display RAM(the first screen byte is at 0, the last at 15999). Bits are 
mapped sequentially from memory to the screen pixels: bits 7 through of byte (in that order) 
control the first seven pixels, (0,0) through (7,0). The following byte controls the next seven 
pixels, (8,0) through (15,0). And so on for the remainder of the screen. The following two 
subroutines will access bytes in the VDC screen RAM when GEOS 128 is in 80-column mode: 

Example: 



*********************************** **«***«***«****«4r**********«**«***-****««^ 



StaSOFore 
LdaSOFore 



Pass : 



r5 
A 



— stores byte to 128 80-column foreground screen 

— loads byte from 128 80-column foreground screen 



= address in foreground memory 
= data value (for StaSOFore) 



Returns: 
A 

Destroyed: 
x 



» data value (for Lda80Fore) 



Note: Call TempHideMouse to disable software sprites before accessing 
foreground screen directly. 

(mgl) 

Constants for VDC internal registers 



VDC_HI_UPDATE 
VDC_LO_UPDATE 
VDC DATA 



18 
19 
31 



/update hi-byte of VDC pointer 
/update lo-byte of VDC pointer 
;data byte at current VDC pointer 



StaSOFore: 

; Send data byte to the VDC chip 

jsr NewVDCAddress 

Idx #VDC_DATA 

stx VDC 

30$: bit VDC 

bpl 30$ 

sta VDC+1 

rts 



Update VDC address with fg screen pointer (r5) 
request VDC data register 

test VDC status 

loop till VDC ready for data byte 

store data byte 

exit 



10 



Graphics Routines (fourth edit / MGL) 



4/24/88 8:13 PM 



LdaSOFore: 

; Get data byte from the VDC chip 

jsr NewVDCAddress ; Update VDC address with fg screen pointer (r5) 

Idx #VDC__DATA ; request VDC data register 
stx VDC 

30$: bit VDC ; t^st VDC status 

bpl 30$ ; loop till data byte ready 

Ida VDC+1 ; get data byte 

rts / exit 

NewVDCAddress : 



; Transfer value in r5 to VDC internal hi/lo address register. 



; Destroys: 


X 






Idx 


#VDC_HI__UPDATE 


ask VDC for high byte 




stx 


VDC 




10$: 


bit 


VDC 


• check VDC status 




bpl 


10$ 


• and loop till VDC ready 




Idx 


r5H 


• store hi-byte of address 




stx 


VDC+1 


• to VDC chip 




Idx 


#VDC_LO_UPDATE 


• ask VDC for low-byte 




stx 


VDC 




20$: 


bit 


VDC 


• check VDC status 




bpl 


20$ 


• and loop till VDC ready 




Idx 


r5L 


• store lo-byte of address 




stx 


VDC+1 


• to VDC chip 




rts 




• exit 



For more information on controlling the 8563 VDC chip, refer to the Commodore 128 
Programmer's Reference Guide. 

Before writing directly to the 80-column foreground screen, be sure to call TempHideMouse to 
temporarily disable the virtual sprites (for more information, refer to TempHideMouse in 
Chapter XX). 

c 

Because the 80-column screen requires a 16,000-byte background buffer, GEOS 128 (when in 80- 
column mode) uses the 8,000-byte 40-column screen foreground buffer (SCREEN BASE to 
SCREEN_BASE+7999) for store the first 100 scanlines of background buffer data and the 
8,000-byte foreground screen buffer (BACK_^SCR_BASE to BACK_SCR_BASE+7999) 
to store the last 100 scanlines of background^buffeF data. Because these data areas are not 
contiguous, an application that directly accesses the background screen must compensate for this 
break. 



Apple II 

Apple GEOS uses the double hi-res screen, which is 560 pixels wide by 192 pixels high. The 
seven lower bits (0-6) of each graphic byte are displayed in bit to bit 6 order on the screen, and 
bit 7 is ignored (not displayed). That is. Pixel (0,0) is controlled by bit of byte 0, pixel (1,0) is 
controlled by bit 1 of byte 0, and pixel (7,0) is controlled by bit of byte 1. The graphic screen is 
located in memory at SCREEN^BASE ($2000) to SCREEN_BASE+$lfff ($3fff) in both the 
main and auxiliary memory banks? The bytes in main memory are mapped to odd byte positions on 
the screen (bytes 1,3,5...), and the bytes in auxiliary memory are mapped to even byte positions 
on the screen (byte 0,2,4...). This means that adjacent bytes on the screen are in separate banks of 
memory. For example, byte is located at $2000 in the auxiliary bank and byte 1 is located at 
$20(X) in the main memory bank. (For more information on accessing the Apple foreground screen 
across memory banks, refer to GetScanLine in the Routine Reference Section.) 



11 



Graphics Routines (fourth edit / MGL) 



4/24/88 8:13 PM 



Apple GEOS uses over 7K of tables to efficiently map pixel positions to screen memory bytes, 
thereby avoiding time-consuming shift and convert algorithms. If an application writes directly to 
screen memory, keep in mind that it will need to handle this pixel conversion manually. Also, 
before writing directly to the Apple screen, be sure to call TempHideMouse to temporarily 
disable the virtual sprites (for more information, refer to TempHideMouse in Routine Reference 
Section). 

Porting Considerations and Techniques 

Outside of the normal considerations for porting a GEOS application from one machine to another, 
there are a few additional elements which pertain specifically to graphics. 

Apple GEOS and GEOS 128 Virtual Sprites 

Apple GEOS and GEOS 128 (in 80-column mode) render sprites entirely in software by modifying 
the actual bitmap screen. (GEOS 64 and GEOS 128 in 40-column mode, use the hardware sprite 
capabilities of the VIC chip.) In order to properly treat these virtual sprites as if they were apart 
from the bitmap screen, they must be erased before any graphic operation, whether drawing, 
testing, imprinting, or recovering, is done. To do this, Apple GEOS and GEOS 128 provide the 
TempHideMouse routine to temporarily remove all sprites. The sprites are not redrawn until the 
application returns to MainLoop. Normal GEOS graphics and text routines will automatically call 
TempHideMouse; only applications that are directly accessing the foreground screen area need 
call TempHideMouse. For more information, refer to TempHideMouse in the Routine 
Reference Section "Software Sprites" in Chapter @ SPRITE®. 

GEOS 128 X-position and Bitmap Doubling 

Because the GEOS 128 80-column bitmap screen has a horizontal resolution exacdy twice that of 
GEOS 64 (640 vs. 320), GEOS 128 supports the ability to automatically double the x- 
coordinate(s) of graphic and text objects, and the width of bitmap objects, by setting spetial bits in 
the x-position and width calling parameter(s). This allows the visual elements of a GEOS 64 
application to run in 80-column mode under GEOS 128 with a minimum of effort. The special bits 
can also be added at run-time to dynamically configure a program to run correctly under both 
GEOS 64 and GEOS 128. X-position and bitmap doubling is supported by nearly every GEOS 
128 routine that writes to the screen (including text, dialog lx)x, and icon routines). 

The following constants may be bitwise or*ed into GEOS 128 x-coordinates and bitmap widths to 
take advantage of the automatic 80-column doubling features: 



12 



Graphics Routines (fourth edit / MGL) 



4/24/88 8:13 PM 



DOUBLE^W 


For doubling word-length values. Normal x- 
coordinates, such as those passed to Rectangle and 
DrawPoint. 


DOUBLETS 


For doubling byte-length values. A byte-lei||Mt value is 
either a card x-position or a card width, botn of which 
apply almost exclusively to bitmap routines, such as 

R iftTiJi nT In nnH Ritmanr^lin 
u 11 Jii<i p u p diivi JLyiiiiiapv^ii |j. 


ADDl^W 


Used in conjunction with DOUBLE_W; adds one to 
a doubled word-length value. This allows addressing 
odd-coordinates, as when drawing a one-pixel frame 
around a filled rectangle. 




Used in conjunctioij-with DPUBLEJB; ad^s-one u>a 
^oublpd:Dyte lengtn valupr^ / 



These doubling bits have no effect when GEOS 128 is in 40-column mode but come to life when 
GEOS 128 is in 80-column mode. For example, the following code fragment will frame a filled V^>5i^>^, 
rectangle. It will appear similarly in both 40- and 80-column modes. 

Example: 



XI 


= 35 


;left 


edge 






X2 


« 301 


/ right 


edge 






Yl 


= 40 


/top edge 






Y2 


= 100 


/bottom edge 






; Draw 


a filled 


rectangle using the 


current 


pattern 






jsr 


i_Rectangle. 




/inline call 






.byte 


Yl . . 




;yi 






.byte 


Y2 




;y2 






.word 


(X1|D0UBLE_W|ADD1_W) 




/xl with doubled 


width 




.word 


(X2|D0UBLE__W) 




/x2 with doubled 


width 




jsr 


i^FrameRect angle 




/inline call 






.byte 


Yl 




;yi 






.byte 


Y2 




;y2 






.word 


(X1|D0UBLE__W) 




/xl with doubled 


width 




.word 


(X2I DOUBLE WIADDl W) 




/x2 with doubled 


width 




.byte 


$ff 




/solid line pattern 




rts 






/ exit 





+ space on left for frame 



+ offset for frame 



NOTE: GEOS 128 filters all word-length x-coordinates (but not widths or byte-length x- 
coordinates) through the routine NormalizeX to process the doubling. For more 
detailed information on how this routine works, refer to its documentation in this 
chapter. NormalizeX will also double signed x-coordinates. If the x-coordinate is a 
signed number (like you might pass to SmallPutChar), then the double bits must be 

exclusive-or'ed into the x-coordinate parameters rather than simply ofed. 



The graphic elements of existing GEOS 64 applications can be ported to run under GEOS 128 with 
a minimum of effort by taking advantage of the GEOS 128 doubling bits. However, once the 
doubling bits have been installed, the application will' no longer run under GEOS 64. The simplest 
approach to this problem is to have two entirely different applications. One designed to run under 
GEOS 64 and the other designed to run under GEOS 128. The doubling bits may be controlled at 
assembly-time with conditional assembly, as the following example illustrates. 

Example: 



13 



Graphics Routines (fourth edit / MGL) 



4/24/88 8:13 PM 



DblDemol : 

;Will assemble differently depending on the status of the C64 and C128 assembly 
/constants. If assembling for GEOS 64, doubling constants will be set to zero so 
;that they will not affect the x-poisitions. If assembling for GEOS 64, doubling 
/constants will be set according to geosConstants file so that graphic operations 
;will double automatically in 128 mode. 



.if (C128 C64) 
.if !C128 



DOUBLE_B 
ADDl e 



DOUBLE__W 
ADDl W 



;C64/C128 flags must be mutually exclusive! 

;if not assembling for GEOS 128, force doubling 
/constants to harmless values so GEOS 64 graphics 
/routines don't get confused. 



= $00 



-= $0000 
= $0000 




.endif 



BM__XPOS 
BM YPOS 



= (32/8) 
« 20 



/byte x-position of bitmap (40-col) 
/y-position of bitmap 



Bitmap: 



BM_WIDTH 
BM HEGHT 



PicW 
PicH 



/byte bitmap width (40-col) 
/bitmap height 



FPATTERN 
DoBmap: 



%11111111 /pattern for surrounding frame 



/Place the bitmap on the screen, loading the registers with 



/inline 


data 


(note double-width settings) . 






jsr 


i__BitmapUp 


/inline call 




.word 


Bitmap 


/bitmap address 




.byte 


(BM_XPOS|DOUBLE_B) 


/xpos 




.byte 


BM^YPOS 


/ypos 




.byte 


(BM_WIDTH 1 DOUBLETS) 


/width 




.byte 


BM_HEIGHT 


/ height 


90$: 


rts 


/exit 




• else 


/ (both 


C128 & C64 constants were both true or both false) 




.echo 


"DblDemo routin^'^Ursigned to assemble for both GEOS 


.endif 




r\ 






Designing an application so that it runs well under both GEOS 64 and GEOS 128 is a more 
difficult task. It usually involves using self-modifying code: part of the initialization code for each 
module can check the version of GEOS it is running under (use the Checkl28 subroutine 
illustrated in "GEOS 128 40/80-Column Support" in this chapter) and add the proper doubling-bits 
to all relevant x-coordinates. 



14 



Graphics Routines (fourth edit / MGL) 



4/24/88. 8:13 PM 



Apple Bitmap Doubling and Aux-memory Bitmaps 

Apple GEOS supports the ability to automatically double the width of bitmap objects by setting 
special bits in the x-width calling parameter(s). TTiis allows GEOS 64 bitmaps to be converted to 
Apple GEOS with a minimum of effort. By doubling the width, a similar appearance can be 
maintained. Apple GEOS bitmap routines can also specify whether the bitmap data is in main 
memory or auxiliary memory by setting special bits in the x-position parameters. Bitmap doubling 
and aux-memory specification applies to the following routines and any other higher-level routines 
which depend on these for placing bitmaps on screen (such as Dolcons): 

• BitmapUp 

• NewBitUp 

• BitmapCIip 
•NewBitCIip 

• BitOhterClip 

• NewBitOtherClip 

Because Apple GEOS allows widths specified by byte values (as in BitmapUp) and widths 
specified by word values (as in NewBitUp), there are different bits and constants to use for 
doubling the width, depending on the number of bytes (one or two) in the parameter. To double 
the widdi of a bitmap, bitwise-or one of the following constants into the width parameter: 



d6uble w 


For doubling word-length values. 


DOUBLE b 


For doubling byte-length values. 



\ 



To force Apple GEOS to grab the bitmap data from auxiliary memory, bitwise-or the bitmap x- 
position with one of the following values, depending on whether the x-position is a byte-length or 
word-length parameter: 



INAUX B 


for byte-length x-position parameters. 


iNai)X"'w 


for word-length x-position parameters. 



For more information on the bits to set for bitmap doubling and auxiliary memory specificatiion, 
refer to the documentation of the specific routines in Routine Reference Section. 

Example: 

;Put a bitmap up, using an address in auxiliary memory and doubling its width 



LoadW r , tMyAuxBitmap 

LoadW r3, # (MY^XPOS I INAUX__W) 

LoadB rlH,#MY_YPOS 

LoadB r2,#(MY_CWIDTH*8) I DOUBLE I W 

LoadB rlL, #MY__HEIGHT 

jsr NewBitUp 



;aux address of bitmap 
; x-position + in-aux flag 
;y-coordinate 

/width = card width * 8 + doubling bit 
/height 

;put bitmap on screen 



15 



Graphics Routines (fourth edit / MGL) 



4/24/88 8:13 PM 



Points and Lines 



Points 

The simplest graphic operation involves setting, clearing, or testing the state of an individual pixel, 
or point, on the screen. GEOS provides two routines for working with points: 



• DrawPoint 


Set or clear a single point. 


• TestPoint 


Test a single point: is it set or clear? 



Horizontal and Vertical Lines 

Due to the rectangular nature of bitmapped graphics, horizontal and vertical lines are inherently fast 
and easy to create and manipulate. GEOS provides five routines for working with horizontal and 
vertical lines: 



• HorizontalLine 


Draw a horizontal line with a repeating bit pattern. 


• VerticalLine 


Draw a vertical line with a repeating bit pattern. 


• InvertLine 


Invert the pixels in a horizontal line. 


♦ ImprintLine 


Imprint a horizontal line to the background buffer. 


• RecoverLine 


Recover a horizontal line from the background buffer. 



Line Patterns. 

Both HorizontalLine and VerticalLine use a byte-sized bit pattern when creating the line. Each 
bit in the pattem byte represents a pixel in the line: wherever a one appears in the pattern byte, the 
corresponding pixel will be set, and wherever a zero appears , the corresponding pixel will be 
cleared. This allows lines which vary from solid (all Ts) to dashed (a mixture of Ts and O's) to 
clear (all O's). Note: this concept of a line-pattem is different from die 8x8 GEOS fill patterns used 
for rectangles. 

Bits in the pattem byte are used left-to-right for horizontal lines and top-to-bottom in vertical lines, 
where bit 7 is at the left and the top, respectively. A bit pattem of %1111(X)(X) would create a 
horizontal line like: 

mmKErnjmmMjjn 

and a vertical line like: 



16 



Graphics Routines (fourth edit / MGL) 



4/24/88 8:13 PM 



I 

I 

The pattern byte is always drawn as if aligned to an eight-pixel boundary. If the endpoints of a line 
do not coincide with eight-pixel boundaries, then bits are masked off the appropriate ends. The 
effect of this is that a pattern is always aligned to specific pixels, regardless of the endpoints and 
that adjacent lines drawn in the same pattern will line up. That is, positions 0, 8, 16, 24, etc. will 
always depend on pattern bit 7, and positions 1,9, 17, 25, etc. will always depend on pattern bit 6. 

NOTE: Because of the internal memory layout of screen memory, horizontal lines will often 
draw up to eight times faster than vertical lines. 



Diagonal Lines 

For the same reason that bitmap displays are well-suited for displaying horizontal and vertical 
lines, they are ill-suited for displaying diagonal Hnes. A smooth, even-density line cannot be drawn 
diagonally between two points (except at 45-degree angles) — the points on the line must be 
approximated in a stairstep fashion: 




GEOS provides one routine for drawing and recovering a line between two arbitrary points: 

pT)rawLine Draw or recover a line between any two points. 

DrawLine does not utilize a pattern byte; it will either set or clear all pixels between the two 
endpoints. 



NOTE: DrawLine is the most general-purpose drawing routine. It can be used to draw single 
points (both endpoints the same), horizontal and vertical lines, or lines at arbitrary 
angles. However, it is burdened by this flexibility^ making it appreciably slower than 
the other plotting routines. 



Patterns and Rectangles 




17 



Graphics Routines (fourth edit / MGL) 



4/24/88 8:13 PM 



GEOS uses two types of patterns: line patterns and fill patterns. A line pattern is a one-byte 
repeating pixel pattern used by routines lUce HorizontalLine and VerticalLine, and a fill pattern 
is an 8x8 pixel block represented by eight bytes in memory and used by routines like Rectangle. 
Line patterns are discussed in "Points and Lines" earlier in this chapter. Fill patterns are discussed 
here. 

A 50% fill pattern might be defined by the following: 

.byte %10101010 
.byte %01010101 
.byte %10101010 
.byte %01010101 
.byte %10101010 
.byte %01010101 
.byte %10101010 
.byte %01010101 

The pattern has alternating set and clear pixels. Drawing a filled rectangle in this pattern would 
produce a medium-dark block. 

All versions of the GEOS Kemal contains the following predefined patterns: 



18 



Graphics Routines (fourth edit / MGL) 



4/24/88 



8:13 PM 



Apple GEOS contains an additional, user-defined pattern which is left for the application to 
modify. 

Fills occur in the current pattern. The current pattern can be changed with the following routine: 

hSetPattern Set the current pattern. 

To use one of the system patterns, the application would first call SetPattern with the appropriate 
pattern number. SetPattern calculates tihe proper pattern address, the adckess of the eight-byte 



19 



Graphics Routines (fourth edit / MGL) 



4/24/88 8:13 PM 



block, and places it in the GEOS variable curPattern (formeriy currentPattern). Any 
subsequent call to a routine which uses a system pattern will index off of the address in 
curPattern to access the 8x8 block. Some applications, finding the need to define their own 
patterns, modify either the address in curPattern to point to their own eight-byte pattern or use 
the address in curPattern (after a valid call to SetPattern) to modify the GEOS system patterns 
directly. This technique will work on both GEOS 64 and GEOS 128, but will not on Apple GEOS 
because the patterns are stored in a fairly inaccessible portion of memory. Apple GEOS provides 
two routines for accessing and redefing patterns: 



• GetPattern 


Download a GEOS pattern to an eight-byte buffer. 


• SetUserPattern 


Upload an eight-byte buffer to a GEOS pattern. 



NOTE: GEOS does not restore the system patterns when an application exits. If an application 
modifies the patterns, it should restore them when it exits unless it is desirable for the 
next application to inherit the redefined patterns (as with the GEOS Pattern Editor). 



Rectangles 

Rectangles in GEOS are defined by their upper-left and lower-right comers. The upper-left is 
usually referred to as (X1,Y1) and the lower-right as (X2,Y2), where XI, X2, Yl, and Y2 are 
valid X and y screen positions. From these two coordinates, the rectangle routines can determine 
the coordinates of the other two comers: 



(XI, YD 


{X2,Y1) 


(XI, Y2) 


(X2,Y2) 



GEOS provides five routines for dealing with rectangular regions: 



• Rectangle 


Draw a solid rectangle using the current fill pattern. 


♦ FrameRectangle 


Draw an unfilled rectangle (bounding frame). 


• InvertRectangle 


Invert the pixels in a rectangular area. 


• ImprintRectangle 


Imprint a rectangular area to the background buffer. 


• RecoverRectangle 


Recover a rectangular area from the background buffer. 



Bit-mapped Images 

All graphic picture objects, such as icons and Photo Scrap images cut from geoPaint, are stored 
internally in GEOS Compacted Bitmap Format to save space. When you paste an image or icon 
into a geoProgrammer source file, it is in compacted bitmap format, and when you read a geoPaint 
image, it too is in compacted bitmap format If a compacted image were to be copied direcdy to the 
screen, it would very likely be unrecognizable. GEOS bitmap routines first decompact the image 
and then transfer it to the screen area. 



20 



Graphics Routines (fourth edit / MGL) 



4/24/88 8:13 PM 



Standard Bitmap Routines 

All versions of GEOS support the following bitmap routines: 



• BitmapUp 


Place a full compacted bitmap on the screen. 


• BitmapClip 


Place a rectangular subset of a compacted bitmap on the screen. 


• BitOtlierCIip 


Special version of BitMapClip which uses an application- 
defined routine to collect the compacted bitmap data a byte at a 
time, allowing the image to come from disk or other I/O device. 



GEOS bitmaps are compacted from the GEOS virtual screen format rather than the internal machine 
format. Because the standard bitmap routines deal with byte-sized chunks (eight-pixels at a time), 
the following apply: 

♦ Horizontally, the bitmap occupies pixels up to the nearest eight-pixel (byte) boundary. 
That is: a bitmap of five pixels is extended to eight and a bitmap of 30 pixels is extended to 
32 pixels. Bitmaps which are not evenly divisable by eight (in the horizontal direction) are 
usually padded with zero bits. 

• Bitmaps can only be placed at eight-pixel intervals on the x-axis (0, 8, 16...). This 
limitation does not apply to the y-axis. 

Apple GEOS, however, provides two extended bitmap routines for overcoming these limitations. 
These routines might eventually be incorporated into GEOS 64 and GEOS 128. 

Apple GEOS Extended Bitmap Routines 

The Apple GEOS extended bitmap routines allow bitmaps of any pixel width and do not force the 
bitmap to be drawn on eight-pixel x-axis boundaries. These bitmaps are still compacted in byte- 
sized chunks, but by specifying a pixel width, any extra bits at the end of the last byte are ignored 
(masked out) when the bitmap is displayed. Apple GEOS offers three new bitmap routines: 



• NewBitUp 


Pixel width and positioning version of BitmapUp. 


• NewBitCIip 


Pixel width and positioning version of BitmapClip. 


• NewBitOtherClip 


Pixel width and positioning version of BitOtherClip. 



GEOS Compacted Bitmap Format 

The GEOS compacted bitmap format relies on the observation that pixel patterns in bitmap images 
are frequently repetitive. If you were to examine a rectangular area of the screen (in GEOS linear 
bitmap format) it would often be the case that adjacent bytes would be identical. The compacted 
bitmap format encodes this redundancy into groups of bytes called packets. Each packet can 
decompress to a large number of bytes in the actual bitmap. 



21 



Graphics Routines (fourth edit / MGL) 



4/24/88 8:13 PM 



Packet Format 

Each packet in a GEOS compacted bitmap follows a specific foraiat. The first byte of each packet 
is called the count byte and is part of the packet header. Depending on its value, it has the 
following significance: 



COUNT 


(HEX) 


SIGNIFICANCE 





($00) 


reserved for future use. 


1-127 


($00-$7f) 


repeat: repeat the following byte count times. The total length of 
this packet is two bytes and decompresses to count bytes in the 
actual bitmap. 


128 


($80) 


reserved for future use. 


129-219 


($81-$db) 


unique: use the next count-128 bytes literally. The total length 
of this packet is (count-128)+l or count-127 bytes and 
decompresses to count-128 bytes. 


220 


($dc) 


reserved for future use. 


221-255 


($dd-$ff) 


bigcount: the next byte is a bigcount value in the range 2 
through 255. The following count-220 bytes comprise data in 
repeat and unique format that should be repeated bigcount 
times. The total length of this packet depends on the decompacted 
size of tht.repeat and unique packets. A bigcount cannot 
containt another bigcount. 



Decompaction Walkthrough 

Given the following compacted data: 

.byte 25, 0, 133, 240, 220, 10, 0, 7, 224, 4, 3, 10, 5, 3 

The decompaction routine would interpret it like this: 

repeat: the decompaction routine encounters the count value 25. Since it is in the range 
1-127, the following byte (0), is repeated 25 times: 

0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 

133, 240, 220, 10, 0, 7"! 

unique: the next packet begins with a count of 133,which is in the range 129-219, The 
next 133-128 = 4 bytes are used once each: 

240, 220, 10, 0, 7 

1224, 4, 3, 10, 5, 3 | 

bigcount: the final packet begins with a count of 24 which is in the range 221-255. 
This signals a two byte header and the following byte, the bigcount, is 4. These two 
bytes are interpreted to mean repeat the next 224-220 = 4 bytes four times. The next four 
bytes, however, are expected to be in the unique and repeat compacted formats. In this 
case, its 3,10 (repeat: 10 three times) and 5,3 (repeat: 3 five times), which in turn are 
repeated four times: 



22 



Graphics Routines (fourth edit / MGL) 



4/24/88 8:13 PM 



10, 10, 10 ,3, 3, 3, 3, 3, 10, 10, 10 ,3, 3, 3, 3, 3, 10, 10, 10 ,3, 3, 3, 3, 3, 10, 
10, 10 ,3, 3, 3, 3, 3 



Compacting Strategy 

The easiest way to compact a bitmap image is to let geoPaint do it for you by cutting the image out 
as a photo scrap and pasting it directly into your geoProgrammer source code. Sometimes this 
method is impractical and you will want to compress images directly from within an application. 
The following subroutine can be used to compact bitmap data: 

.if (0) 

*»««**«***★**«**««********★***★***«★********«**«***«* 

BitCompact 

«*««*■««*★*★★*«****»*********«★★*★**★«*★***★★★***** 

DESCRIPTION: 

Converts linear bitmap data into compacted bitmap format, suitable 
for passing to routines such as BitmapDp. 

When compacting bitmaps directly from screen memory, the data must 
must first be converted from the internal screen format to linear 
bitmap format. The left edge of the source bitmap must start on a 

card boundary and the right edge must extend to the end of another,....-^ . ^ 

card boundary. (Under Apple GEOS, strictly speaking, the wrg^^t "Cdge^ need 
not fully extend to a card boundary because the new bitmap routines 
(NewBitUp, NewBitClip, etc.) can mask bits at the right edge.) 

This bitmap data must then be converted to a linear format, where 
the first byte represents the first eight pixels of the upper-left 
corner of the bitmap, the next byte represents the next eight pixels 
and so on to the right edge of the bitmap. The byte following the 
last byte in a single line of a bitmap is the first byte of the next 
line. (The actual dimensions of the bitmap will be reconstructed from 
the WIDTH and HEIGHT parameters passed to the bitmap display routine. 

To convert from internal screen format to linear bitmap format: 

C64: Set dispBufferOn appropriately (to reflect which 
screen buffer to grap data from) and... 



( 



7 



Cnvrt40: 






Idx 


yPos 


; get y coord of top of bitmap 


jsr 


GetScanLine 


; use it to calc screen ptrs 


Ida 


xPos 


; get x pixel coord (lo byte) 


and 


#%11111000 


; strip off 3 bits for card x-position 


clc 




; Add card offset to 


adc 


r5L 


; base pointer (lo byte first) 


sta 


r5L 




Ida 


xPos+1 


; (hi byte also) 


adc 


r5H 




sta 


r5H 




;At 


this point, (r5) 


points to the first byte in 


;the 


bitmap (upper-left corner) . 



Now step through each byte in this scanline by adding 
8 to the pointer in r5 (compensating for the card architecture) 
to get to the next byte, and repeat this process for each line 
in the bitmap (incrementing yPos appropriately for each scanline) , 



C128: (40-column, same as C64; 80-column, read on...) 

Conveniently, the 80-column data is already in linear bitmap 



23 



Graphics Routines (fourth edit / MGL) 



4/24/88 8:13 PM 



format. The data, will probably be coming from the 
background buffer because the foreground screen is 
entirely contained on the VDC chip's internal RAM and 
is difficult to access... 



CnvrtSO: 

bit graphicsMode 

bpl Cnvrt4 

PushB dispBufferOn 

LoadB dispBufferOn, #ST_WR 

Idx yPos 

jsr GetScanLine 

Movew xPos,rO 

Idx #rO 

Idy #3 

jsr DShiftRight 

AddW r0,r6 

;At this point (r6) points 
/bitmap. 



; make sure in 80-col mode 
; handle 40 like C64 
; save current dispBuffer 
BACK /force use of back buffer 
get y coordinate 
use it to calc screen ptrs 
copy x-position to zp work reg 
divide rO by 8 
(shift right 3 times) 
this gives us the card offset 
add card (byte) offset to scanline addr 
to the first byte of the 



Now step each byte in this scanline by adding 
1 to the pointer in r6 to get to the next byte, 
and repeat this process for each line in the 
bitmap (incrementing yPos appropriately) . 



Apple: Use the Apple GEOS Kernal routines ReadScanLine 

and ReadBackLine to convert the internal Apple 
screen format into linear bitmap format. Nice and simple. 

CALLED BY: 



PASSED: 

rO Pointer to destination buffer to store compacted data 

(this buffer must be at least 1 and 1/64 of size of the 
uncompacted data because it is possible, but unlikely, that 
the compacted data will actually be larger than the ucompacted 
data) . 

rl Pointer to linear bitmap data to compact. 

r2 # of bytes to compact. 



RETURNS : 

rO Points to byte following last byte in compacted data. 



DESTROYED: 

a, X, y, rl-r6 



PSEUDO CODE / STRATEGY: 

Starts with the first source byte and counts the number of identical bytes 
following it to determine whether to generate a UNIQUE or REPEAT packet. If 
there are three or less identical bytes in a row, a UNIQUE packet is generated, 
four or more generates a REPEAT packet. The packet is placed in the destination 
buffer and this process is then repeated until all bytes in the source buffer 
have been compressed. 

KNOWN BUGS / SIDE EFFECTS / IDEAS: 

Only uses the UNIQUE and REPEAT compaction types. The BIGCOUNT compaction type is 
such that it is difficult to determine the compaction payoff point. BIGCOUNT could 
be used to compress adjacent scanlines that are identical because this type of check 
would be trivial. The basic scanline could be compressed with UNIQUE and REPEAT, then 
duplicated by placing it inside a BIGCOUNT. 

This routine is not limited to compressing bitmap data. In fact, it works quite 



24 



Graphics Routines (fourth edit / MGL) 



4/24/88 8:13 PM 



well on any data where strings of identical bytes are common (e.g., fonts). It does 
not, for example, compress text very efficiently. A Huffman-based algorithm yields 
better results. 



ir********* 



t * * * 'k te ic * * it -i 



(mgl) 



.endif 



MAX__R£?£AT 
MAXJJNIQUE 
UNIQ THRESH 



127 

91 

3 



maximum repeat COUNT value 
maximum unique COUNT value 

byte count threshold, beyond which a REPEAT type 
should be used instead of UNIQUE. 



BitCompact : 
10$: 



jsr 
cmp 
ble 

sta 

Idy 

sta 

Ida 

iny 

sta 

AddVW 

bra 

20$: 



jsr 

Idy 
ora 
sta 

Ida 

iny 

sta 

cpy 

bne 

inc 

AddBW 

dec 



30$: 



100$: 



AddBW 

SubBW 

Ida 

ora 

bne 

rts 



CountRepeat 

#UNIQ_THRESH 

20$ 



r5L 
#0 

(rO) . 
(rl) , 



(rO),y 

#2,r0 

100$ 



GetUnique 
#0 

#$80 
(rO) ,y 

(rl) ,y 

(rO),y 

r5L 

30$ 

r5L 

r5L, rO 

rSL 



r5L,rl 

r5L,r2 

r2L 

r2H 

10$ 



rl = current addr in source buffer 

rO = current addr in destination buffer 

r2 = # bytes left in source 

count the # of identical bytes here 

Enough repeats to justify REPEAT type? 

No, go use UNIQUE 

yes, use REPEAT (A = # to repeat) 

store repeat # for later 

init. index into buffers 

store repeat # to destination 

get repeat value 

point to next byte in dest buffer 
store to destination buffer 
move up dest . pointer 
exit. 

use UNIQUE 

Calc # of unique bytes to use 
(A = number of unique) 
init. index into buffers. 

convert unique count to packet count value 
store to dest. buffer 

get first unique value 

increment pointer pointer 

store to destination buffer 

done yet? (r5L « repeat #) 

loop till done copying 

convert to # to add to dest pointer 

move up destination pointer 

correct bac)c to # done 

fall through to -exit 

move up source pointer 

subtract off # left in source buffer 

check for zero bytes left 

more to do? 

if so, loop 

else, exit. 



CountRepeat : 



Idy 
Idx 



#0 
#0 



rl « current pointer into source buffer 
rO = current pointer into destination buffer 
r2 « number of bytes left in source 
initialize relative buffer index 
initalize current repeat count 



25 



Graphics Routines (fourtli edit / MGL) 



4/24/88 8:13 PM 





Ida 


(rl),y 


get first byte 




sta 


r6L 


keep in r6L. This is the byte we're trying 








to match. 


10$: 










Ida 


r2H 


more than 255 bytes left in source? 




bne 


20$ 


if so, ignore # check 




cpx 


r2L 


else, are we at the last byte? 




beq 


90$ 


if so, exit 


20$: 










cpx 


#MAX__REPEAT 


check repeat count with max # of repeats 




beq 


90$ 


if at maximum, branch to exit. 




Ida 


(rl),y 


does it actually match? 




cmp 


r6L 


check against 1st byte 




bne 


90$ 


if no match, exit. 




inx 




else, we found a match, increment repeat count 




iny 




move to next byte in source 


;NOTE 


— following branch changed to 


save a byte, y is never incremented to $00. 




bra 


10$ 


and loop to check it 




bne 


10$ , 


branch always... iny above will always clear z 


90$: 










txa 




return repeat count in A 




rts 




exit 


GetUnique: 








PushW 


rl 


Save orig pointer 




LoadB 


r5L,#0 


start none unique 


10$: 










inc 


r5L 


• do one more unique 




Idx 


r5L 


• get # unique so far 




Ida 


r2H 


• lots left? 




bne 


20$ 


• if so, skip end check 




cpx 


r2L 


• all of them? 




beq 


90$ 


• if yes, then that many 


20$: 










cpx 


#MAX_UNIQUE 


? max # unique 




beq 


90$ 


? if full, do them 




AddVW 


#l,rl 


; move up a byte 




jsr 


CountRepeat 


; how many of the following bytes are repeats? 




cmp 


#UNIQ THRESH 


? Enough to warrant a REPEAT packet? 




ble 


10$ 


; No, go stuff them in this UNIQUE packet 








; Yes, close this UNIQUE packet. 


90$: 










PopW 


rl 


; retrieve start pointer 




Ida 


r5L 


; get # to do unique 




rts 







Direct Screen Access and Block Copying 



Direct Screen Access 

One purpose of an operating system such as GEOS is to insulate the application from the 
peculiarities of the machine it is running on, allowing the programmer to worry more abot how the 
application will function than how it will interact with the hardware. However, because of the 
complexity of GEOS graphics routines, it is sometimes necessary, for performance reasons, to 
bypass the operating system and manipulate the screen memory directly. Although this practice is 
not recommended — it increases portability problems, defeating much of the purpose of a GEOS 



26 



Graphics Routines (fourth edit / MGL) 



4/24/88 8:13 PM 



— it is a reality. And with that in mind, Berkeley Softworks built routines into GEOS to facilitate 
direct screen access. The following routine exists in all versions of the Kemal: 

I • GetScanLine Calculate the address of the first byte of a particular screen line. 

And these two additional routines exist in Apple GEOS: 



• GetScreenLine 


Copy a horizontal line (in internal format) from the screen to an 
application's buffer. 


• PutScreenLine 


Copy a horizontal line (in internal format) from an application's 
buffer to the screen. 



GetScreenLine and PutScreenLine are intended to let the application directly access the Apple 
double hi-res screen without worrying about bank switching on alternate bytes. The screen is 
treated as a contiguous block, as if the alternating bytes in the two memory banks were actually 
adjacent in memory. These routines are not well-suited for scrolling large regions (they are too 
slow), but are sufficient for drawing with small brushes. For scrolling, use the block copy 
routines. 

Linear Bitmap Conversion (Apple GEOS) 

Because the Apple's pixel memory mapping scheme is so convoluted, Apple GEOS provides 
routines to convert a line of data (in Apple's internal format) to linear bitmap data, where pixels 
occupy contiguous bits in contiguous bytes: 



• ReadScanline 


Translates a screen line from the foregorund screen from Apple 
internal format to linear bitmap format. 


• ReacBackLine 


Translates a screen line from the background buffer from Apple 
internal format to linear bitmap format. 



Although it would seem that routines which translate in the other direction — from linear bitmap 
format to Apple format — are necessary, BitmapUp can be used for this purpose. Merely 
prepend a 70 to the front of the linear bitmap and call BitmapUp as if the line were a bitmap 70 
bytes wide and one pixel high. 

Block Copy and Scrolling (Apple GEOS) 

Apple GEOS also extends the direct screen access facilities by offering three block copy routines 
which are useful for scrolling and moving rectangular areas of the screen: 

• CopyLine Copies a horizontal line from one area of the foreground screen to 

another. 

"^opyScreenBlock Copies a rectangular area from one part of the screen to another. 

♦ CopyFuIIScreen Copies a rectangle of the full width of the screen (but of variable 

height) to another position vertically. 

Although these routines deal directly with the screen, the screen architecture is actually transparent 
to the application. Therefore, future versions of GEOS may implement these functions. 



27 



Graphics Routines (fourth edit / MGL) 



4/24/88 8:13 PM 



Special Graphics Related Routines 

GEOS provides a few graphics-related routines which don't fit nicely into any other category: 



• GraphicsString 


Execute a string of graphics commands. 


• DivideBySeven 


Quickly divide a screen coordinate by seven for direct screen 
access (Apple GEOS only). 


• NormalizeX 


Adjust an x-coordinate (under GEOS 128 only) to compensate for 
the higher-resolution 80-column mode. 


• SetNewMode 


Change GEOS 128 graphics mode (40/80-column). 



28 



Icons, Menus, and Other Mouse Presses 



Icons, Menus, and Other Mouse Presses 



When the user clicks the mouse button, GEOS determines whether the mouse pointer was 
positioned over an icon, a menu item, or some other region of the screen. GEOS has a unique 
method of handling a mouse press for each of these cases. If the user pressed on an icon, GEOS 
calls the appropriate icon event routine. If the user pressed on a menu, GEOS opens up a sub- 
menu or calls the appropriate menu event routine, whichever is applicable. And if the user pressed 
somewhere else, GEOS calls through otherPressVector, letting the application handle (or 
ignore) these "other" mouse presses. 

Icons 

When you open a disk by clicking on its picture, delete a file by dragging it to the trash can, or 
click on the CANCEL button in a dialog box, you are dealing with iconSy small pictorial 
representations of program functions. A GEOS icon is a bitmapped image, whether the picture of a 
disk or a button-shaped rectangle, that allows the user to interact with the application. When the 
application enables icons, GEOS draws them to the screen and then keeps track of their positions. 
When the user clicks on an icon, an icon event is generated, and the application is given control 
with information concerning which icon was selected 

Icon Table Structure 

The information for all active screen icons is stored in a data structure called the icon table. GEOS 
only deals with one icon table at a time. The icon table consists of an icon table header and a 
number of icon entries. The whole table is stored sequentially in memory with the header first, 
followed by the individual icon entries. 

Icon Table Header 

The icon table header is a four byte structure which tells GEOS how many icons to expect in the 
structure and where to position the mouse when the icons are enabled. It is in the following format: 

Icon Table Header: 



Index 


Constant 


Size 


Descriptibn 


+0 


OFF_LNUM 


byte 


Total number of icons in this table. 


+1 


OFFJ.MX 


wad 


Initial mouse x-posidon. If $0000, mouse positiion will not 
be altered 


+3 


OFF_I_MY 


byte 


Initial mouse y-position. 



This first byte reflects the number of icon entries in the icon table (and, hence, the number of icons 
that can be displayed). The table can specify up to MAX_ICONS icons. 

The next word (bytes 1 and 2) is an absolute screen x-coordinate and the following byte (byte 3) is 
an absolute screen y-coordinate. The mouse will be positioned to this coordinate when the icons 
are first displayed. If you do not want the mouse positioned, set the x-coordinate word to $0000, 
which will signal Dolcons to leave the mouse positions alone. 



1 



IconSp Menus, and Other Mouse Presses 



Icon Entries 

Following the icon table header are the icon entries, one for each specified in the OFF_I_NUM 
byte in the icon table header. Each icon entry is a seven-byte structure in the following format: 

Icon Entries: 



Index 


Constant 


Size 


Description 


+0 


OFFJ.PIC 


wod 


Pointer to compacted bitmap picture data for this icon. If set 
to $0000, icon is disabled. 


+2 


OFF I X 


byte 


Card x-position for icon bitmap. 


+3 


OFF I Y 


byte 


Y-position of icon bitmap. 


+4 


OFF I WIDTH 


byte 


Card width of icon bitmap. 


+5 


OFF I HEIGHT 


byte 


Pixel height of icon biunap. 


+6 


OFFJ EVENT 


wad 


Pointer to icon event routine to call if this icon is selected. 



The first word (OFF I PIC) is a pointer to the compacted bitmap data for the icon. The icon can 
be of any size (up tolhe full size of the screen). If this word is set to NULL ($0(X)0), the icon is 
disabled. 

The third byte (OFF I X) is the x byte-position of the icon. The x byte-position is the x-position 
in bytes — icons are"pTaced on the screen by BitmapUp and so must appear on an eight-pixel 
boundary. The byte-position can be calculated by dividing the pixel-position by eight 
(x_byte_position = x.pixeLposition/8). 

The fourth byte (OFF_I Y) is the pixel position of the top of the icon. The icon will be placed at 
(x_byte_position*8 , y_pixeLposition). 

The next two bytes (OFF J^WIDTH and OFF J_.HEIGHT) are the width in bytes and height 
in pixels, respectively. These values correspond to the geoProgrammer internal variables PicW 
and PicH when they are assigned immediately after a pasted icon image. 

The final word (OFF_I_EVENT) is the address of the icon event handler associated with this 
icon. 

Sample Icon Table 

The following data block defines three icons which are placed near the middle of the screen. The 
mouse is positioned over the first icon: 

/SAMPLE ICON TABLE 

********************************************** 

;Icon positions and bitmap data 

I__SPACE - 1 /space between our icons (in cards) 

Paint Icon: 



PAINTW - PicW 



Icons, Menus, and Other Mouse Presses 



PAINTH » PicH 
PAINTX = 16/8 
PAINTY « 80 

Writelcon : 



WRITEW = PicW 
WRITER = PicH 

WRITEX " PAINTX + PAINTW + I_SPACE 
WRITEY = PAINTY 

Publishlcon : 



PUBLISHW 
PUBLISHH 
PUBLISHX 
PUBLISHY 



PicW 
PicH 

WRITEX + WRITEW + I__SPACE 
WRITEY 



;The actual icon data structure to pass to Dolcons follows 
IconTable: 



I_header : 

.byte 
.word 
.byte 



NUMOFICONS 

(PAINTX*8) + (PAINTW*8/2) 
PAINTY + PAINTH/2 



number of icon entries 
position mouse over paint icon 



I_entries: 
PaintlStruct : 

.word Paintlcon 

.byte 

.byte 

.word 



PAINTX, PAINTY 
PAINTW, PAINTH 
PaintEvent 



; pointer to bitmap 
;icon position 
;icon width, height 
/event handler 



WritelStruct : 

.word Writelcon 
.byte 
.byte 



WRITEX, WRITEY 
WRITEW, WRITER 



.word WriteEvent 



/pointer to bitmap 
/icon position 
/icon width, height 
/event handler 



PublishlStruct : 

.word Publishlcon 
.byte PUBLISHX, PUBLISHY 
.byte PUBLISHW, PUBLISHH 
.word PublishEvent 



NUMOFICONS 



(*-I_entries) /lESIZE 



/pointer to bitmap 
/icon position 
/icon width, height 
/event handler 

/number of icons in table 



/Dummy icon event routines which do nothing but return 
V PaintEvent: 
^'"^ WriteEvent : 



3 



Icons, Menus, and Other Mouse Presses 



PublishEvent : 
rts 



Installing Icons 

When an application is first loaded, GEOS will not have an active icon structure. GEOS must be 
given the address of tiie applications icon table before MainLoop can display and track the user's 
interaction with them. GEOS provides one routine for installing icons 

I • Dolcons Display and activate an icon table. | 

Dolcons draws the enabled icons and instructs MainLoop to begin watching for a single- or 
double-click on one. The icon table stays activated and enabled until the ICONS_ON_BIT of 
mouseOn is cleared or another icon table is installed by calling Dolcons with the address of a 
different icon structure. In either case, the old icons are not erased from the screen by GEOS. 

Dolcons will draw to the foreground screen and background buffer depending on the value of 
dispBufferOn. Icons are usually permanent structures in a display and so often warrant being 
drawn to both screens. If icons are only drawn to the foreground screen, they will not be recovered 
after a menu or dialog box. 

Example: 

; IconsUp Draw and intialize our icons 

•*★**★★**★****★★***★*******★**★*★*****★★**★*★***★★★*★*★*★*★*★ 

IconsUp: 

LoadB dispBufferOn, #(ST_WR_FORE I ST_WR_BACK) ;draw to both buffei;s 
LoadW rO, #IconTable ;point to icon table 

jsr Dolcons /install icons 

rts ;exit 



Important: Due to a limitation in the icon-scanning code, the application must always install an 
icon table with at least one icon. If the application is not using icons, create a 
dummy icon table with one icon (see below). 



Nolcons Install a dummy icon table. For use in applications that 

aren't using icons. Call early in the initialization of the 
application, before returning to MainLoop. 

Nolcons: 

LoadW rO,#DummyIconTable /point to dummy icon table 
jmp Dolcons /install. Let Dolcons rts 

DummylconTabie : 

.byte 1 ;one icon 

.word $0000 /dummy mouse x (don't reposition) 

•byte $00 /dummy mouse y 

.word $0000 /bitmap pointer to $0000 (disabled) 

.byte $00 /dummy x-pos 



4 



Icons, Menus, and Other Mouse Presses 



.byte $00 /dummy y-pos 

.byte 1,1 /dummy width and height 

.word $0000 /dummy event handler 

MainLoop and Icon Event Handlers 

When the user clicks the mouse button on an active icon, GEOS MainLoop will recognize this as 
an icon event and call the icon event handler associated with the particular icon. The icon event 
handler is given control with the number of the icon in rOL (the icon number is based on the 
icon^s position in the table: the first icon is icon 0). Before the event handler is called, though, 
MainLoop might flash or invert the icon depending on which of the following values is in 
iconSelFlag: 



Constants for iconSelFlag: 



ST NOTHING 


The icon event handler is immediately called; the icon image is untouched. 


ST.FLASH 


The icon ijs inverted for selectionFlash vblanks and then reverted to its 
nonnal state before the event handler is called. 


ST_INVERT 


The icon is inverted (foreground screen image only) before the event handler is 
called. The event handler will usually want to revert the image before returning 
to MainLoop by calculating the bounding rectangle of the icon, loading 
dispBufferOn with ST^WILJFORE, and calling InvertRectangle. 



Detecting Single- and Double-clicks on Icons 

When the user first clicks on an icon, GEOS loads the global variable dblCIickCount with the 
GEOS constant CLICK^GOUNT, GEOS then calls the icon event handler with rOH set to 
FALSE, indicating a single-click. dblClickCount is decremented at interrupt level every vblank. 
If the icon event handler returns to MainLoop and the the user again clicks on the icon before 
dblClickCount reaches zero, GEOS calls the icon event handler a second time with rOH set to 
TRUE to indicate a double-click. 

Checking for a double-click or a single-click (but not both) on a particular icon is trivial: merely 
check rOH. If rOH is TRUE when you're looking for a single-click or its FALSE when you're 
looking for a double-click, then return to MainLoop immediately. Otherwise, process the click 
appropriately. This way, tS the user single-clicks on an icon which requires double-clicking or 
double-clicks on an icon which requires single-clicking, the event will be ignored 

However, checking for both a double- or a single-click on the same icon (and performing different 
actions) is a bit more complicated because of the way double-clicks are processed: during the brief 
interval between the first and second clicks of a double-click, the icon event handler will be called 
with rOH set to FALSE, which will appear as a single-click; when the second press happens 
before dblClickCount hits zero, the icon event handler is called a second time with rOH set to 
TRUE, which will appear as a double-click. There is no simple way (using the GEOS double- 
click facility) to distinguish a single-click which is part of a double-click from a single-click which 
stands alone 

There are two reliable ways to handle single- and double-click actions on icons: the additive 
function method and the polled mouse method. The additive function method relies on a simple 
single-click event which toggles some state in the application and a double-click event (usually 
more complicated) which happens in addition to the single-click event. The GEOS dcskTop uses 
tiie additive function method for selecting (inverting) file icons on a single-click and selecting and 
opening them on a double-click. The icon event handler first checks the state of rOH. If it is 



5 



Icons, Menus, and Other Mouse Presses 



FALSE (single-click) then the icon (and an associated selection flag) is inverted. If it is TRUE 
(double-click) then the file is opened. If the user single-clicks, the icon is merely inverted. If the 
user double-clicks, the icon is inverted (on the first click) and then processed as opened (on the 
second click). 

Example: 

Icon double-click handler 
additive function method 

**«★*★********★******★*★★**★★★★*★**★*★*«★***★**★★*★★* 

IconEventl: 

Ida rOH ; check double-click flag 

bne 10$ /branch if second click of a double-click 

;else, this is a single-click or the 
; first: push of a double-click, 
; ;so just invert the selection 

;and exit. 



10$: 



90$: 



jsr Invertlcon 
bra 90$ 

jsr Open Icon 



rts 



/double-click detected, go process it 
;fall through to exit 

/return to MainLoop 



The polled-mouse method can be used when the single-click and double-click functions are 
mutually exclusive. When a single-click is detected the icon event handler, rather than returning to 
MainLoop and letting GEOS manage the double-click, handles it manually by loading 
dblCIickCount with a delay and watching mouseData for a release followed by a second click. 

Example: * 

*********************************************** ****:«r«««************** 

Icon double-click handler . 
polled mouse method 

** it** *ic ********** it It-it itir* it *it*it*****ik*irit***icitii*ic* 

IconEvent2 : 

;User pressed mouse once, start double-click counter going 
LoadB dblClickCount,#CLICK_COUNT /start delay 

/Loop until double-click counter times-out or button is released 
10$: 

Ida dblClickCount /check double-click timer 

beq 30$ /If timed-out, no double-click 

Ida mouseData /Else, check for release 

bpl 10$ /loop until released 



/mouse was released, loop until double-click counter times-out or 

/button is pressed a second time. 

20$: 

Ida dblClickCount /check double-click timer 
beq 30$ /If timed-out, no double-click 

Ida mouseData ./Else, check for second press 

bmi 20$ /loop iinril pressed 

/.Double-click detected (no single-click) 

.'30$i- jsr DoDoubleClick /do double-click stuff 

• bra 90$ /exit 



/Single-click detected (no double-click) 



Icons, Menus, and Other Mouse Presses 



jsr DoSingleClick ;do single-click stuff 

;and fall through to exit 

/Exit 

90$: rts /return to MainLoop - 



Note: These techniques for handling single- and double-clicks are described here as they 
pertain to icons; they are not directly applicable to applications that detect mouse clicks 
through otherPressVector. When control vectors through otherPressVector, the 
value in rOH is meaningless. For more information on otherPressVector, refer to 

"Other Mouse Presses" in this chapter. 



Other Things to Know About Icons 

Icon Releases and otherPressVector 

When the user clicks on an active icon, MainLoop will call the proper icon event routine rather 
than vectoring through otherPressVector. However, the routine pointed to by 
OtherPressVector will get called when the mouse is released. Applications that aren*t using 
OtherPressVector can disable this vectoring by storing a. $0000 into otherPressVector 
($0000 is actually its default value). Applications that depend on otherPressVector, however, 
can check mouseData and ignore all releases. 

Example: 

/OtherPressVector routine that ignores releases (high bit of mouseData is set on releases) 

MyOtherPress: /control comes here from otherPressVector 

Ida mouseData /check state of the mouse button 

bmi 90$ /ignore it if it's a release 

jsr PressDown /otherwise process the press' 

90$: 

rts /return to MainLoop 

For more information on otherPressVector, refer to "Other Mouse Presses" in this chapter. 
Icon Precedence 

GEOS draws icons sequentially. Therefore, if icons overlap, the ones which are drawn later will 
be drawn on top. When the user clicks somewhere on the screen, GEOS scans the icon table in this 
same order, looking for an icon whose rectangular boundaries enclose the coordinates of the 
mouse pointer. If more than one icon occupies the coordinate position, the icon that is defined first 
in the icon table (and therefore drawn on bottom) will be given the icon event. If an active menu 
and an icon overlap, the menu will always be given precedence. 

Disabling Icons 

An application can disable an icon in the current icon structure by clearing the OFF_PIC ICON 
word of tiie icon (setting it to $(X)00). If an icon is disabled prior to a call to Dolcons, the icon 
will not be drawn. If an icon is disabled after the call to Dolcons, the icon will remain on die 
screen but will be ignored during the icon scan. The application can reenable the icon by restoring 
the OFF_PIC^ICON word to its original value. (Actually, any non-zero value will do because 
reenabling an Icon does not redraw it, it only restores the coordinates to MainLoop's active 
search list.) 



7 



Icons, Menus, and Other Mouse Presses 



GEOS 128 Icon Doubling 

as with bitmaps, special flags in the icon data structure can be set to automatically double the x- 
position and/or icon width when GEOS 128 is running in 80-column mode. To have an an icon's 
x-position automatically doubled in 80-column mode, bitwise-or the OFF_I X parameter with 
DOUBLE^B. To double an icon*s width in 80-colunin mode, bitwise-or the^OFFJ^WIDTH 
parameter with DOUBLE_B. These bits will be ignormed when GEOS 128 is running in 40- 
column mode. Do not, however, use these doubling bits when running under GEOS 64. GEOS 64 
will try to treat the doubling bit as part of the coordinate or width value rather than a special-case 
flag. For more information, refer to "GEOS 128 X-position and Bitmap Doubling" in Chapter 
@GR@. 

Example: 

/SAMPLE GEOS 128 ICON TABLE THAT USES AUTOMATIC DOUBLING FEATURE 
.if !C128 

.echo Error: cannot assemble GEOS 128 specific code without C128 flag set 

.else 

Paintlcon: 



PAINTW = PicW 
PAINTH •= PicH 
PAINTX » 16/8 
PAINTY « 80 

;The actual icon data structure to pass to Dolcons follows 
IconTable: 



I_header : 

.byte NUMOFICONS 

.word ((PAINTX*8) + (PAINTW*8/2) ) I DOUBLE^W) 

.byte PAINTY + PAINTH/2 



number of icon entries 
position mouse over paint icon 



I__entries: 
PaintlStruct : 

.word Paintlcon 

.byte (PAINTX I DOUBLE_B) 

.byte PAINTY 

.byte (PAINTW | DOUBLE_B) 

.byte PAINTH 

.word PaintEvent 



/pointer to bitmap 

;x card position (dbl in 80-column mode) 
;y-position 

;icon width (dbl in 80-column mode) 
;icon height 
/event handler 



NUMOFICONS 



(*-I_entries)/IESIZE 



/number of icons in table 



/Dummy icon event routines which do nothing but return 
PaintEvent: 
rts 



.endif 



8 



Icons, Menus, and Other Mouse Presses 



Apple GEOS Double-width and Aux-memory Icons 

As with Apple GEOS bitmaps, special flags can be set in the icon data structure to double an icon's 
width and/or lcx)k for the icon image data in auxiliary memory. To double an icon's width, bitwise- 
or the OFF_I_^WIDTH parameter with DOUBLE B. To mark the OFF I PIC word as an 
address in auxiliary memory, bitwise-or the OFF_r_X parameter with INaTIX_B. For more 
information, refer to "Apple Bitmap Doubling and Aux^emory Bitmaps" in Chapter @GR@. 

Menus 

Menus, one of the most common and powerful user-interface facilities provided by GEOS, allow 
the application to offer lists of items and options to the user. The familiar menus of the GEOS 
deskTop, for example, provide options for selecting desk accessories, manipulating files, copying 
disks, and opening applications. Virtually every GEOS-based program will take advantage of these 
capabilities, providing a consistent interface across applications. 

GEOS menus come in two flavors: horizontal and vertical. The main menu, the menu which is 
always displayed, is usually of the horizontal type and is typically placed at the top of the screen. 
Each selection in the main menu usually has a corresponding vertical sub-menu that opens up when 
an item in the main menu is chosen. These sub-menus can contain items that trigger the application 
to perform some action. They can also lead to further levels of sub-menus. For example, a 
horizontal main menu item can open up to a vertical menu, which can have items which then open 
up other horizontal sub-menus, which can then lead to other vertical menus, and so on. 

Division of Labor with Menus 



GEOS divides the labor of handling menus between itself and the application. The GEOS Kemal 
handles all of the user's interaction with the menus. This includes drawing the menu items, 
opening up necessary sub-menus, and restoring the Screen area from the background buffer when 
the menus are retracted. MainLoop manages the menus, keeping track of which items the user 
selects. If the user moves off of the menu area without making a selection, GEOS automatically 
retracts the menus without alerting the application. 

If the user selects a menu item which generates a menu event, the application's menu event handler 
is called with the menus left open. Leaving the menus open allows the application to choose when 
and how to retract them: all the way back to the main menu, up one or more levels (for multiple 
sub-menus), or up no levels (keeping the current menu open). This lets the application choose the 
menu level which is given control upon return, thereby allowing multiple selections from a sub- 
menu without forcing the user to repeatedly traverse the full menu tree for each option. 

Menu Data Structure 

The main menu, all its sub-menus, their individual selectable items, and various attributes 
associated with each menu and each item are all stored in a hierarchical data structure called the 
menu tree. Conceptually, a menu tree with multiple sub-menus might have the following layout: 



9 



icons, Menus, and Other Mouse Presses 



sub-menu 




Level 



gill Level 1 




Level 2 
Level 3 



Sample Menu Tree 



The main menu (or level 0) is the first element in the tree; it is the menu that is always displayed 
while menus are enabled. Each item in a main menu will usually point to a secondary menu or 
submenu. Items in these submenus can point to events (alerts to Ae application that an item was 
selected) or they can point to additional submenus. Menus are linked together by address pointers. 

Sub-menus are sometimes referred to as child menus, and the menu which spawned the sub-menu 
as its parent. Sub-menus can be nested to a depth determined by the GEOS constant 
MAX_M NESTEVG, which reflects the internal variable space allocated to menus. The depth or 
level of tEe current menu can be determined by the GEOS variable menuNumber, which can 
range from to (MAX^M^NESTING- 1). 

In memory, all menus, whether the main menu or its children, are stored in the same basic menu 
structure format Each menu is comprised of a single menu header block followed by a number of 
menu item blocks (one for each selectable item in the menu): 



10 



Icons, Menus, and Other Mouse Presses 



menu 




Menu/Sub-menu structure 



Menu/Sub-menu Header 

The menu header is a seven-byte structure that specifies the size and location of the menu (How big 
is the rectangle that suirounds the menu and where should the menu be drawn?), any attributes that 
affect the entire menu (Is it a vertical or horizontal menu?), and the number of selectable items in 
the menu. The header is in the following format: 

Menu/Sub-menu Table Header: 



Index 


Constant 


Size 


Description 


+0 


OFF M Y TOP 


byte 


Top edge of menu rectangle (yl pixel position). 


+1 


OFF M Y BOT 


byte 


Bottom edge of menu rectangle (yl pixel position). 


+2 


OFF M X LEFT 


wad 


Left edge of menu rectangle (xl pixel position). 


+4 


OFF_M_X_RIGHT 


wcxd 


Right edge of menu rectangle (x2 pixel position). 


+6 


OFF^NUM^M.ITEMS 


byte 


Menu type bitwise-or*ed with number of items in this 
menu/sub-menu. 



The first six bytes specify the screen location and size of the menu with the positions of the 
bounding rectangle in pixel positions. The x-positions are word (two-byte) vdues and the y- 
positions are byte values These values are absolute screen pixel positions. The size of die bounding 
rectangle depends on the number of menu items and the size of text strings within the toenu. The 
height of the rectangle can be calculated with the constant M^HEIGHT: a horizontal menu is 
always a height of M HEIGHT, and a vertical menu is a height of the number of menu items 
multiplied by M HEIGHT. For example, the height of a vertical menu with seven items would 
be 7*M_HEIGITT. The width of a menu is more difficult to calculate because it depends on the 



1 1 



Icons, Menus, and Other Mouse Presses 



length of the individual text strings. It is best to use a large number for this dimension and adjust it 
to a smaller size if necessary. 



Important: GEOS 64 and GEOS 128 before version 2.0 do not correctly handle menus that 
extend beyond an x-position of 255. This problem does not exist in Apple GEOS. 

All menus and sub-menus are positioned independently. This means that the main menu need not 
be at the top of the screen (it can be inside a window, for example), and sub-menus need not be 
adjacent to their parent menus (although that is where you will usually want them). You can 
experiment with the flexibility of menu positioning to customize your applications. 

The seventh byte is the attribute byte. It is the number of selectable items in the menu bitwise-or'ed 
with any menu type flags. A menu can have as many as MAX_M_ITEMS selectable menu 
items. 



Menu/Sub-menu Types (use in attribute byte): 



Constant 


Description 


HORIZONTAL 


Arrange menu items in this menu/sub-menu horizontally. 


VERTICAL 


Arrange menu items in this menu/sub-menu vertically. 


CONSTRAINED 


Constrain the mouse to the menu/sub-menu. If the menu is a sub-menu, the 
mouse can still be moved off to the parent menu (off the top of a vertical sub- 
menu or off the left of a horizontal menu). 


UN.CONSTRAINED 


Do not constrain the mouse to the menu/sub-menu. If the user moves off of 
the menu, GEOS will retract it 


Bitwise Breakdown of the Attribute Byte: 


7 6 5 4 


3 2 1 


b7 b6 1 


b5-bO 1 



b7 orientation: 1= vertical; = horizontal, 

b6 constrained: 1 = yes; = no. 

b5-bO number of items in menu/sub-menu (up to MAX_M_ITEMS). 



Some of the menu types are obviously mutually exclusive: you can't, for example, make a menu 
both vertical and horizontal, nor simultaneously constrained and unconstrained. 

A vertical, unconstrained menu with seven selectable items would have an attribute byte of: 

.byte (7 | VERTICAL | UN_CONSTRAINED) 

A horizontal, constrained menu with 1 1 selectable items would have an attribute byte of: 

.byte (11 I HORIZONTAL I CONSTRAINED) 

Most sub-menus are unconstrained: if the user moves the pointer off the sub-menu, all opened 
menus are retracted as if GotoFirstMenu had been called. A constrained menu, on the other 
hand, restricts the pointer from moving off the menu area from aU but one side. A constrained 
menu will only allow the pointer to move off the side leading back to where it expects the parent 
menu to be: off the top for a vertical sub-menu and off the left for a horizontal sub-menu. If the 



12 



Icons, Menus, and Other Mouse Presses 



user moves off of a constrained menu (in the only available direction), the current sub-menu is 
retracted and the parent menu becomes active as if DoPreviousMenu had been called. 

NOTE: The constrain option is only applicable to sub-menus — if the CONSTRAINED flag 
is set in the main menu (level 0), the option will have no effect. 



Menu Item Structure 

For each selectable item in a menu (the number items is specified in the header) there is a five-byte 
item structure. These item structures follow the menu header in memory. The first item represents 
the first menu selection (top- or leftmost), the second, the second, and so on. Each item structure 
specifies the text that will appear in the menu, what happens when the item is selected (Will it 
generate an event or a sub-menu?), and the appropriate event routine or sub-menu. Each menu item 
is in the following format: 

Menu Item: 



Index 


Constant 


Size 


Description 


+0 


OFF_TEXTJTEM 




Pointer to null-terminated text string for this menu 
item. 


+2 


OFF TYPE ITEM 


byte 


Selection type (sub-menu, event, dynamic sub-menu). 


+3 


OFF_POINTERJTEM 


woid 


Pointer to sub-menu data structure, event routine, or 
dynamic sub-menu routine, depending on selection type. 



The first word of the item is a pointer to the text that will be placed in the menu. The text is 
expected to be null-terminated (the last byte should be $00 or NULL). If the menu rectangle 
specified in the header is not wide enough to contain the entire text string, the text will be clipped at 
the right edge when the menu is drawn. 

The byte following the text pointer (die third byte) is an item type indicator. Each selectable item 
can either be an an action, a sub-menu, or a dynamic sub-menu selection. An action "type item 
generates a menu event from MainLoop. A sub-menu type item automatically opens up a sub- 
menu structure. And a dynamic sub-menu type selection opens up a sub-menu, but before it does, 
it calls an application's routine. Dynamic sub-menus are useful for modifying a menu structure on 
the fly. For example, a point size sub-menu, such as those used in geoWritc, can be changed 
dynamically when a new font is selected. When the user chooses the font item, the dynamic sub- 
menu routine checks the list of available point sizes and builds out the point size sub-menu based 
on its findings. The following table summarizes the three menu item types: 

Types of Menu Items (for use in item type byte): 



Constant Description 



SUB.MENU 


This menu item leads to a sub-menu. The OFF_POINTER_ITEM is a 
pointer to the sub-menu data structure (points thelfirst byte of a menu/sub- 
menu header). 


DYN.SUB.MENU 


This menu item is a dynamic sub-menu. The OFF_POINTER_ITEM is a 
pointer to a dynamic sub-menu routine that is called before the menu is 
actually drawn. The dynamic sub-menu routine can do any necessary pre- 
processing and return with rO containing a pointer to a sub-menu data 
structure or $0000 to ignore the selection. 


MENU.ACnON 


This menu item generates an event. The OFF^POINTERJTEM is a 
pointer to the event routine that will to call. 



1 3 



icons, Menus, and Other Mouse Presses 



Bitwise Bre^ mn of the Item Type Byte: 

7 6 4 3 2 1 

I b7 I b6 I d: I b4-b0 1 

b7 sub-menu flag. 

b6 dynamic sub-menu flag. 

b4-b0 reserved for future use. 



Example Menu 

The following code fragment defines an unconstrained horizontal menu of three items, suitable for 
use as the main menu. Each item in the menu points to a sub-menu that is not shown 
(GeosMenu, FileMenu, and EditMenu). 

Example: 



/SAMPLE MENU TABLE 



MENU CONSTANTS *** 
/bounding rectangle 

MAINXl = /left 

MAINYl = /top edge 

MAINX2 = 72 /right 

MAINY2 = MAINYl + M HEIGHT /bottom edge 



/•• 

/*** MENU DEFINITION *** 
• ************************ 



HEADER 
MainMenu : 

.byte MAINYl 

.byte MAINY2 

.word MAINXl 

.word MAINX2 



/top 
/bottom 
/ left 
/right 



.byte ( HORIZONTAL I UN_CONSTRAINED I M_ITEMS) 



/*** ITEMS 
Mainltems: 
/Geos 



.word 
.byte 
.word 



GeosText 
SUB_MENU 
GeosMenu 



/pointer to null-terminated text 

/generates sub-menu 

/pointer to sub-menu structure 



/File 



.word 
.byte 
.word 



FileText 
SUB_MENU 
FileMenu 



/pointer to null-terminated text 

/generates sub-menu 

/pointer to sub-menu structure 



/Edit 



• word 
.byte 
.word 



EditText 
SDB_MENU 
EditMenu 



/pointer to null-terminated text 

/generates sub-menu 

/pointer to sub-menu structure 



M ITEMS 



(* - Mainltems) /MISI2E /number of items in the menu 



/text string for Geos selection 



14 



Icons, Menus, and Other Mouse Presses 



GeosText : 



.byte 


Geos t 


NULL 


;text string 


for File 


selection 


FileText : 






• byte 


"File", 


NULL 


;text string 


for Edit 


selection 


Edit Text : 






.byte 


"Edit", 


NULL 



; null-terminated item string 



; null-terminated item string 



/null-terminated item string 



Installing Menus 



When an application is first loaded, GEOS will not have an active menu structure. GEOS must be 
given the address of the application's menu structure before MainLoop can display and track the 
user's interaction with it GEOS provides one routine for installing menus: 



!• DoMenu 



Display and activate a menu structure. 



] 



DoMenu draws the main menu on the foreground screen and instructs MainLoop to begin taking 
care of all menu processing. The menu stays activated and enabled until the MENU_ON_BIT or 
the MOUSE_ON BIT of mouseOn is cleared or another menu is installed by calling iJbMenu 
with the address o7a different menu structure. In either case, the old menu is not erased from the 
foreground screen by GEOS. The application must recover the area from the background buffer 
itself. 



MainLoop and Menu Events 

When the user clicks the mouse button on a menu item, GEOS MainLoop will invert the selection 
and examine' the item data block, processing the selection according to its type. 

SUB^MENU 

If the menu item is of the SUB^MENU type, then menuNumber is incremented, the 
appropriate sub-menu is drawn, anS MainLoop begins tracking the user's interaction with the 
sub-menu, making it the current menu. If the user moves off of a sub-menu back onto its parent 
menu, MainLoop will retract the sub-menu, decrement menuNumber, and make the parent 
menu the current menu. If the user moves off of the menus entirely (assuming this is possible — 
the menu might be constrained), then MainLoop retracts all sub-menus back up to the the main 
menu and sets menuNumber to zero. 

DYNAMIC SUB MENU 

If the menu item is of the DYNAMIC_SUB^MENU type, MainLoop calls the routine whose 
address is in tiie item structure. This routine Ts called before the sub-menu is drawn and before 
menuNumber is incremented. The accumulator will contain the item number selected (item 
numbers start with zero). When the routine returns with the address of the appropriate sub-menu in 
rO, MainLoop continues processing as if it was handling a SUB_MENU type menu. If the 
dynamic sub-menu routine returns $0000 in rO, then the sub-menu i^not opened and the current 
menu remains active. 



15 



Icons, Menus, and Other Mouse Presses 



MENU^CTION 

If the menu item is of the MENU ACTION type, GEOS flashes the menu inverted for 
selectionFIash vblanks. selectionPlash is a GEOS variable which is initialized with the 
constant SELECTION_DELAY, but may be adjusted by the application. MainLoop will then 
call the menu event routine whose address is in the item structure, passing the number of the 
selected item in the accumulator (item numbers start with zero). One of the first things a menu 
event routine must do, among its own duties, is specify which menu level MainLoop should 
return to when it gets control. This is done by calling one of the GEOS routines designed for this 
purpose: 



• ReDoMenu 


Reactivate the menu at the current level. 


• DoPreviousMenu 


Retract the current sub-menu and reactivate the menu at the 
previous level. 


• GotoFirstMenu 


Retract all sub-menus and reactivate the menu at the main menu 
level. 



These routines retract menus as necessary (recovering from the background buffer) and sets special 
flags which tell MainLoop what has happened; MainLoop is not given control at this time — 
that is the job of the menu event handler's rts. If an application's menu event handler does not call 
one of these routines before it returns to MainLoop, the menu will remain open but inactive. 



NOTE: A menu remains on the foreground screen until DoPreviousMenu or 
GotoFirstMenu is called to retract it. If graphics need to be drawn in the area 
obscured by a menu, but menus cannot be retracted, then limit drawing to th; 

background buffer by setting the proper bits in dispBufferOn. j 



Specialized Menu Recover Routines 

• 

GEOS provides two very low-level menu routines which recover areas obscured by menus from 
the background buffer. Usually these routines are only called internally by the higher-level menu 
routines such as DoPreviousMenu. They are of little use in most applications and are included in 
the jump table mainly for historical reasons. There are two routines: 

• RecoverMenu Recovers the current menu from the background buffer toThe 

foreground screen. 

• RecoverAllMenus Recovers all extant menus and sub-menus from the background 

buffer to the foreground screen. 

Advanced Menu Ideas 

Menu routines can be as clever as desired One common technique involves dynamically modifying 
the text strings associated with menu items. This can be used, for example, to add asterisks next to 
currendy active options as they are selected 



16 



Icons, Menus, and Other Mouse Presses 



Menus and Mouse-Fault Interaction 



How GEOS uses Mouse Faults 

In general, the following is true: 

• When a menu is down, the system interrupt-level mouse-processing routine is checking 
for two types of mouse faults: the mouse moving outside of the rectangle defined by 
mouseTop, mouseBottom, mouseLeft, and mouseRight and the mouse moving off 
of the menu. It sets bits in mouseFauIt accordingly. 

• If the menu is unconstrained, mouseTop, mouseBottom, mouseLeft, and 
mouseRight are set to full-screen dimensions, thereby ruling out this type of mouse fault, 

• If the menu is constrained, mouseTop, mouseBottom, mouseLeft, and 
mouseRight are set to the dimensions of the current menu's rectangle. This will keep the 
mouse from moving off of the menu area (and will also generate a mouse fault when an 
edge is encountered). 

• The system mouse fault routine (called through mouseFauItVec) checks the 
mouseFauIt variable. If the mouse faulted by moving off of the menu (only possible if 
the menu is unconstrained), DoPreviousMenu is called. If the user moved off of the 
sub-menu without moving onto another menu, mouse menu faults will continue to retract 
menus until only the main menu is displayed. If the mouse faulted by attempting to move 
beyond the mouseTop on a vertical sub-menu or mouseLeft on a horizontal sub-menu 
(only possible on a constrained menu) then DoPreviousMenu is called. 



Application's Use of Mouse Faults 

When the user is interacting with menus, the system uses the mouse fault variables (mouseTop, 
mouseBottom, mouseLeft, and mouseRight) and expects its own fault service routine to be 
called through mouseFauItVec. If an application needs use mouse faults for its own purposes, 
should first disable menus by clearing the MENUON^BIT of mouseOn Before reenabling 
menus, it should set the fault variables to the full screen dimensions and call StartMouseMode to 
restore the system's fault service routine: 



* ************ ***i«r********#****************4r************ 

; Routine to restore the mouse service routines to an 
; operational state after an application's use of 
/mouse faults through mouseFauItVec. Should be called 
/before menus are reenabled. 

Re set Mouse: 



Following lines changed to save bytes 

LoadW mouseLeft, #0 

LoadB mouseTop, #0 

Ida #0 

St a mouseLeft 

sta mouseLeft+1 

sta mouseTop 
.if (C128) 

LoadW rO,# (SC_40_WIDTH-1 

Idx #rO 

jsr NormalizeX 

MoveW rO, mouseRight 
• else ; (APPLE I I C64) 



reset mouse left to left screen edge 
and mouse top to top screen fedge 



I DOUBLE__W I ADD1_W) /put in zp reg to normalize 
/point to register 
/double if in 80-column 
/mouse right to right screen edge 



1 7 



Icons, Menus, and Other Mouse Presses 



LoadW mouseRight, #SC_PIX_WIDTH-1 



/mouse right to right screen edge 



.endif 



LoadB mouseBottom, #SC__PIX_HEIGHT-1 
clc 

jsr StartMouseMode 
rts 



mouse bottom to bottom screen edge 
don't reposition mouse... 



exit 



Sample Menu 



Other Mouse Presses 

When the user clicks the mouse somewhere on the screen where there is no active menu or icon, 
GEOS consideres this an "other" press and checks otherPressVector for an application- 
provided subroutine. If otherPressVector is $0000, then the press is ignored, if 
OtherPressVector contains anything but $0000, GEOS treats the value as an absolute address 
and simulates an indirect jsr to that address. otherPressVector defaults to $0000 at application 
startup. 

OtherPressVector gets called on all presses that are not on an active icon or menu and on all 
releases, whether on a menu, icon, or anywhere else. In most cases, the application will want to 
ignore the releases. This is done simply by checking mouseData for the current state of the 
mouse button, as in:- 



Because otherPressVector gets called on each press (and release), any double-click detection 
must be performed manually by the other-press routine. Handling double-clicks through 



Ida 
bpl 
rts 



mouseData 
10$ 



; check state of the mouse button 

/branch to handle presses 

;but return immediately to ignore releases 



10$: 



1 8 



Icons, Menus, and Other Mouse Presses 



otherPress Vector is similar to the polled mouse method used with icons, the major difference 
being a check for releases on entry. 

Example: 

/Ignore releases on entry 

Ida mouseData /check state of the mouse button 

bpl 5$ /branch to handle presses 

rts /but return immediately to ignore releases 

5$: 

/User pressed mouse once, start double-click counter going 
LoadB dblClickCount, #CLICK__COUNT /start delay 

/Loop until double-click counter times-out or button is released 
10$: 

Ida dblClickCount /check double-click timer 

beq 30$ /If timed-out, no double-click 

Ida mouseData /Else, check for release 

bpl 10$ /loop until released 

/mouse was released, loop until double-click counter times-out or 

/button is pressed a second time. 

20$: 

Ida dblClickCount /check double-click timer 

beq 30$ /If timed-out, no double-click 

Ida mouseData /Else, check for second press 

bmi 20$ /loop until pressed 

^•.Double-click detected (no single-click) 

-J0.$: jsr DoDoubleClick /do double-click stuff 

^' bra 90$ /exit 

' /Single-click detected (no double-click) 

— -r- jsr DoSingleClick /do single-click stuff 

• / and ^f all through to exit 

/Exit 

90$: rts /return to MainLoop 



1 9 



Process Library 



Process Library 



A process is a is an event that is triggered on a regular basis by a timer. This allows GEOS to 
generate an event at specific time intervals, such as 20 times per second, once every minute, or five 
times each hour. Processes allow a limited form of multitasking, where many short routines can 
appear to run concurrently with MainLoop. Thus an application could update an alarm clock and 
scroll the work area while calculating a cell in a spreadsheet. Applications can also use processes to 
monitor the mouse. geoPaint, for example, uses a process to monitor the mouse's position when 
using the line tool; when the mouse moves, the process prints the new line length in the status 
window. geoPublish operates in a similar manner, using a process to update the values in the 
coordinate boxes as the user moves the across the preview page. 



Note: Processes do not provide true multitasking. There is no interrupt-driven context 
switching, nor any concurrence (where two routines run simultaneously). Processes 
are best thought of as events triggered off of MainLoop just like any other event. 
When one process is running, the next process in line won't get executed until the first 

finishes and returns to MainLoop. 



Process Nomenclature 

There are a number of terms associated with processes. Each process has a countdown timer. 
When the countdown timer reaches zero or times-out, the process becomes runable. If a process is 
frozen, its timer is not being decremented. The timer will continue when the process is unfrozen. If 
a process is blocked, a process event will not be generated until the process becomes unblocked. 



Process Data Structure 



The application must initialize the GEOS process handler with a process data structure. Thfe 
process data structure contains the necessary information for all the desired processes. The table 
can specify up to MAX^PROCESSES (formeriy MAXIMUM_PROCESSES) processes. 
Each process in the table is in the following format: 



Index Constant Size Description 



+0 


OEF.PJVENT 


word 


Pointer to event routine that is called when this 
process times-out. 


+2 


OFF^P.TIMER 


word 


Timer initialization value: number of vblanks to 
wait between one event trigger and the next. 



The first word is the address of the process event handler. The process event handler is much like 
any other event handler: it is called by MainLoop when process becomes runable (as opposed to, 
say, when the user clicks on an icon or selects a menu item) and is expected to return with an rts. 

The second word is the number of vblanks to wait between one event trigger and the next. If the 
the OFF_P_TIMER word of a process is set to 20, for example^ then the process event handler 
will be called every 20 vblanks (about 3 times per second on NTSC machines and 2.5 times per 
second on PAL machines). 



1 



Process Library 



c 



Sample Process Table 

The following data block defines three processes, each with a different process event handler. The 
first process will execute once every 10 vblanks, the second will execute once every second, and 
the third will execute once every five minutes. Notice the use of the FRAME_RATE constant to 
calculate the correct vblank delay for PAL and NTSC machines and the automatic assignment of 
process constants with (* - PrTabIe)/PSIZE. 

Sample process data structure 

oc 

PrTable: 
A* MOUSE CHECK PROCESS*** 

Check mouse position and change pointer form as 
necessary. 

MOUSECHECK « (*-P^Table) /PSIZE /process number 

.word CheckMouse /process event routine 

.word 10 ; check every 10 vblanks 

;*** REAL-TIME CLOCK PROCESS *** 

; Increment a r^^l-time clock counter every second 

RTCLOCK = (*-P5,Table) /PSIZE /process number 

.word Tick /process event routine 

.word FRAME_RATE /one second worth of vblanks 

*** SCREEN-SAVER PROCESS *** 

Save the screen by turning off colors after five 
minutes. 

SCRNSAVER = (*-Pr^able) /PSIZE /process number 

.word ScreenSave /process event routine 

.word 5*60*FRAME_RATE /frames in 5 minutes 

/delay « 5 min* 60 sec/min * frames/sec) 

NUM_PROC = (*-ProcTable) /PSIZB*4r /number of processes in this table A/0 T tj 

/for passing to InitProcesses 

.if (NUM__PROC > MAX_PROCESSES) /check for too many processes 

echo Warning: too many processes 

.endif 



Process Management 



Installing Processes 

The application must install its processes by telling GEOS the location of the process data structure 
and the number of processes in the structure. GEOS provides one routine for installing processes: 

pTnitProcesses Initialize and install processes. 

InitProcesses copies the process data structure into an internal area of meir; - v, hidden from the 
application. GEOS maintains the processes within this internal area, keepi: rack of the event 
routine addresses, the timer initialization values (used to reload the timers afie: : time-out), the 
current value of the timer, and the state of each process (i.e., frozen, blocke d, runable). The 
application's copy of the process data structure is no longer needed because GEOS remembers this 
information until a subsequent call to InitProcesses. 



2 



Process Library 



Example: 

Initialize process table *** 

LoadW rO,#ProcTable /point at process data structure 

Ida #NUM_PROC /pass actual number of processes 

jsr InitProcesses /call GEOS to install processes 

/processes in table are now blocked and frozen 



Starting and Restarting Processes 

When a process table is installed, the processes do not begin executing immediately because all 
processes are initialized as frozen. GEOS provides a routine to simultaneously unblock and 
unfreeze a single process while reinitializing its countdown timer: 

plRestartProcess Initialize a process's timer value then unblock and unfreeze it. | 

RestartProcess should always be used to start a process for the first time, otherwise the timer 
will begin in an unknown state. 

Example: 



start all processes *** 

Idx #NUM_PR0C-1 /process numbers range from to NUM_PR0C-1 

10$: 

jsr RestartProcess /reset timer, unblock, and unfreeze process 

dex /next process 

bpl 10$ /loop until done 

RestartProcess can also be used rewind a process to the beginning of its cycle. One application 
for this is a screen-saver utility which blanks the screen after, say, five minutes of inactivity to 
prevent phosphor bum-in. A five-minute process is established which, when it triggers an event, 
blanks the screen. Any routine which detects activity from the user (a mouse movement, button 
press, keypress, etc.) before the screen is blanked can call RestartProcess to reset the screen- 
saver countdown timer to its initial five minute value. 



Freezing and Blocking Processes 

When a process is frozen, its timer is no longer decremented every vblank. It will therefore never 
time-out and generate a process event When a process is unfrozen, its timer again begins counting 
from the point where it was frozen. GEOS provides the following routines for freezing and 
unfreezing a process's timer: 



• FreezeProcess 


Freeze a process's countdown timer at its current value. 


• UnfreezeProcess 


Resume (unfreeze) a process's countdown timer. 



Example: 



Freeze all processes *** 
php 
sei 

Idx #NUM_PR0C-1 

10$: 

jsr FreezeProcess 
dex 

bpl 10$ 
pip 



disable interrupts to synchronize freezing 

process numbers range from to NUM_PR0C-1 

/freeze process 
/next process 
•loop until done 
/restore interrupt status 



3 



Process Library 



A process may also be blocked. Blocking a process temporarily prevents the event service routine 
from being executed. It does not stop the timer from decrementing, but when the timer reaches zero 
and the process bcomes runable, the event is not generated. When a process is subsequently 
unblocked, its events will again be generated. GEOS provides the following routines for blocking 
and unblocking processes: 

• BlockProcess Block a process's events. 

• UnblockProcess Allow a process's events to go through. 

Example: 

Block mouse-checking process *** 

Idx #MOUSECHECK /process number of mouse check 

jsr BlockProcess ;block it 

Unblock Real-time clock process *** 

Idx #RTCLOCK ; process number of real-time clock 

jsr UnblockProcess /unblock it 

When a timer reaches zer (times-out), its process becomes runable. An internal GEOS flag (called 
the runable flag) is set, indicating to MainLoop that an event is pending. The timer is then 
restarted with its initialize "'on value. MainLoop will ignore the runable flag as long as the process 
is blocked. When the prox iss is later unblocked, MainLoop will see the runable flag, recognize it 
as a pending event, and ca:l the appropriate service routine. However, multiple pending events are 
ignored: if a blocked processes timer reaches zero more than once, only one event will be generated 
when it is unblocked. 

Freezing vs. Blocking 

The differences between freezing and blocking are in many cases unimportant to the application. 
However, a good understanding of their subtleties will prevent problems that may arise if the 
wrong method is used. 

Normally, a process's timer is decremented every vblank. If a process is frozen, however, the 
GEOS vblank interrupt routine will ignore the associated timer. The timer value will not change 
and, hence, will never reach zero. The process will never become runable. If you think of a 
process as a wind-up alarm clock, freezing is equivalent to disconnecting the drive spring — even 
the second hand stops moving. 

Freezing a process only guarantees that the process will not subsequently become runable. The 
process may in fact already be marked as runable and GEOS is only awaiting the next pass through 
MainLoop to generate an event. (A process that is marked as runable but not yet run is said to be 
apending event.) 

If a process is blocked (but not also frozen), GEOS Interrupt Level will continue to decrement the 
associated timer. If the timer reaches zero, GEOS will reset the timer and make the process 
runable. But MainLoop will ignore the process and not generate an event because the process is 
blocked. If the process is later unblocked, the event will be generated during the next pass through 
MainLoop. Using the alarm clock analogy, freezing is equivalent to disconnecting the alarm bell 
— the clock continues to run but the alarm does not sound unless the bell is reconnected. 

The only way to absolutely disable a process — both stopping its clock and preventing any 
pending events to get through — is to freeze and block it. 

Example: 



4 



Process Library 



**************************************************************************************** 

StopProcess — freeze a process timer and block any pending events 

UnstopProcess — unfreeze and unblock the process 

Pass: X = process number 

Returns: x unchanged 

Destroys: a 



StopProcess: 

jsr FreezeProcess ;not that it really matters, but we'll freeze first 

jmp BlockProcess ;then block (let BlockProcess rts) 

UnstopProcess : 

jsr UnblockProcess ;unblock first 

jmp UnfreezeProcess ;then unfreeze (let Unf reezeProcess rts) 



Forcing a Process Event 

Sometimes it is desirable to force a process to run on the next pass through MainLoop, 
independent of its timer value. GEOS provides one routine for this: 

plEnableProcess Makes a process runable immediately. H 

EnableProcess merely sets the runable flag in the hidden process table. When MainLoop 
encounters a process with this flag set, it will attempt to generate an event, just as if the timer had 
decremented to zero. This means that EnableProcess has no priveleged status and cannot 
override a blocked state. However, because it doesn't depend on (or affect) the current timer value, 
the process can become runable even with a frozen timer. 



The Nitty-gritty of Processes 



Processes involve a complex (but hopefully transparent to the application) interaction between 
multiple levels of GEOS. In advanced uses, it may be necessary to understand this interaction. The 
following discussing clarifies some of the fine points of processes. 

Interrupt Level and MainLoop Level 

Processes involve two distinct levels of GEOS: interrupt level and MainLoop level. Every vblank 
an IRQ (Interrupt ReQuest) signal is generated by the computer hardware. Part of the GEOS 
interrupt service routine manages process timers: if a process exists and it is not frozen, its timer is 
decremented. When the timer reaches zero, the interrupt level routine sets the associated runable 
flag and restarts the timer with its initialization value. The process event routine is not called at this 
time. 

If for some reason interrupts are disabled (usually by setting the interrupt disable flag with an sei 
instruction) and a vblank occurs, the interrupt will be ignored and the process timers, therefore, 
will not be decremented during that vblank. This is usually not a problem because interrupts are 
normally enabled. However, be aware that some operating system functions (such as disk I/O) 
disable interrupts. 



5 



Process Library 



During a normal pass through MainLoop, GEOS will examine the active processes. If a 
process's runable flag is set and it is not blocked, MainLoop clears the runable flag and and calls 
the process. If a process is blocked, MainLoop ignores it. 

Because of the way MainLoop and the interrupt level interact, there is a certain level of 
imprecision with processes: 

1: If a process has a very low timer initialization value (e.g., less than five) such that it is 
possible it will time-out more than once during the time it takes for a single pass through 
MainLoop, MainLoop may miss some of these time-outs.Each time the timer reaches 
zero it sets the runable flag, but since there is only one runable flag per process, 
MainLoop has no way of knowing if it should generate more than one event. 

2: It is impossible to guarantee any precise relationship (e.g., a timer difference less than 
five) between two or more timers. Although all processes that time-out during the same 
interrupt will become runable at that time, the interrupt may occur while MainLoop is 
the midst of handling processes: processes that have already been passed-by may bee 
runable but not get executed until the next time through MainLoop, which could 
fraction of a second later. 



For more Information refer to Chapter @ML&INTS@. 



Process Synchronization 

It is sometimes desirable to maintain a synchronized relationship between the timer values of two 
or more processes. This is nontrivial because even if the calls to restart, freeze, or unfreeze these 
timers are done immediately after each other, there is always a slight chance that the vblank 

C interrupt will occur after the status of some of the timers has changed but before all have been 
changed. For example: if an application is trying to freeze three timers simultaneously and the 
interrupt happens after the first timer has been frozen but before the other two, the remaining two 
timers will still be decremented. To circumvent this problem, bracket the calls by disabling 
interrupts before freezing, blocking, or restarting, and reenabling afterward. This is best done as in 
the following example: 

RESTART CLOCK PRCXTESSES AT THE SAME TIME *** 

f 

RstartP: 

php ;save interrupt disable flag 

sei /disable interrupts (stopping timers) 

Idx tRTCLOCK /restart clock 

jsr RestartProcess 

Idx #SCRNSAVER /restart screen-saver 

jsr RestartProcess 

pip /restore interrupt disable status 

Disabling Processes While Menus Are Down 

Because MainLoop is still running when menus are down, process events continue to occur. It is 
often desirable to disable a process while the user has a sub-menu opened. The easiest way to 
handle this situation is to check menuNumber at the beginning of the process event routine. If 
menuNumber is non-zero, then a menu is down and the event routine can exit early: 



PrEventRoutine : 

Ida menuNumber /check menu level 

bne 90$ ;and exit immediately if a menu is down 

jsr DoPrEvent . /else, process the event normally 

90$: 

rts /return to MainLoop 



6 



Process Library 



Sleeping 



Sleeping is a method of stopping execution of a routine for a specified amount of time. That is: a 
routine can stop itself and "go to sleep," requesting MainLoop to wake it up at a later time. GEOS 
provides one routine for sleeping: 



Sleep does not actually suspend execution of the processor. When the application does a jsr 
Sleep, GEOS sets up a hidden timer, much like a process timer, that is decremented during the 
vblank interrupt. It removes the return address from the stack (which corresponds to the jsr 
Sleep) and saves it for later use, then perfoms an rts. Since the return address on the stack no 
longer corresponds to the jsr Sleep, control is returned to a jsr one level lower. In many cases, 
this will return control directly to MainLoop. 

When the timer decrements to zero, a wake-up flag is set, and, on the next pass through 
MainLoop, the sleeping routine will be called with a jsr to the instruction that immediately 
follows the jsr sleep. When the routine finishes with an rts (or another jsr Sleep), MainLoop 
will resume processing. 

Important: Any temporary values pushed onto the stack must be pulled off prior to calling 



Sleep. Also, when a routine is awoken, the values in the processor registers and 
the GEOS pseudoregisters will most certainly contain different values from when it 
went to sleep. This is because MainLoop has been running full-speed, calling 
events and doing its own internal processing, thereby changing these values. If a 
routine needs to pass data from before it sleeps to after it awakes, it must do so in 
its own variable space. 



Sleep can be used to set up temporary, run-once. processes by placing calls to Sleep inside 
subroutines. For example, an educational program may want to flash items on the screen and make 
a noise when the student selects a correct answer. The routines that handle these "bells and 
whistles" can be established using Sleep without needlessly complicating the function that deals 
with correct answers. The following code fragment illustrates this idea: 



1^ Sleep 



Pause execution for a given time interval. 



*1^«****«*4r*********************************** ****************** 



Routine to handle a correct answer. Does some graphics, makes 
some noise, and adjusts the student's score. 



*************************************************************** 



BELL^DELAY 
FLASH DELAY 



60 
23 



; length of bell 

; delay between flashes 



Correct : 



IncW 
jsr 
jsr 
rts 



Bell 
Flash 



score 



/score +« 1 

/start the bell going 

/start the answer flashing 



7 



Process Library 



Subroutine: 



If sound is enabled (user-determined), start the 
bell sound and then go to sleep; Sleep 
returns control to the routine that called us 



When we wake 
to MainLoop 



up, we stop the be'll sound and return 



Bell: 



90$: 



If sound is disabled, then the rts returns 
directly to the routine that called us. 


Ida 


soundFlag 


/check sound flag 


beq 


90$ 


;exit if user turned sound off 


jsr 


BellOn 


;else, turn the bell on 


LoadW 


rO,BELL_DELAY 


;and delay before turning off 


jsr 


Sleep 


;by going to sleep (think rts) 


jsr 


BellOff 


;turn bell off when we awake 


rts 




;exit 



Subroutine: Invert the answer. Go to sleep. 

answer when we wake up. 



Re-invert the 



Flash: 



jsr 

LoadW 

jsr 

jsr 

rts 



InvAnswer 
rO,FLASH_DELAY 
Sleep 
InvAnswer 



; Graphically invert the answer 
;and delay before reverting 
/by going to sleep (think rts) 
/when we awake, revert the image 
/ exit 



8 



Math Routines 



Math Routines 



One of the major limitations of eight-bit microprocessors such as the 6502 is their math capabilites: 
they can only operate directly on eight-bit quantites (0-255), and multiplication and division require 
extensive computational energy. For the sake of the application programmer, GEOS has some of 
the more popular arithmetic routines built into the Kemal. These include double-precison (two- 
byte) shifting, as well as multiplication and divison. 

Parameter Passing to Math Routines 

The math routines use a flexible parameter passing convention: rather than putting values into 
specific GEOS pseudoregisters, the application can place the values in any zero-page location 
(almost) and then tell GEOS where to find die values by passing the address of the of the 
parameter. Because the parameters are located on zero-page, their addresses are one-byte quantites 
that can be passed in the x and y index registers. For example, a GEOS math routine might require 
two word values. The application could place these values in pseudoregisters aO and al, then call 
a GEOS math routine, like Ddiv (double-precision divide) with the address of aO and al in the x 
and y registers. 

Example: 

Idx #aO ;load up address of first parameter 

Idy #al ;and address of other parameter 

jsr Ddiv /divide the word in aO by the word in al 

Important: It is easy to get confused and leave off the immediate-mode sign (#) when trying to 
load the address of a zero-page variable, thereby loading the value contained in the 
variable instead. 



Double-precision Shifting 

The 6502 provides instructions for shifting eight-bit quantites left and right but no instructions for 
directing these operations on 16-bit (double-precision) numbers. GEOS provides two routines for 
double-precision shifting: 



• DShiftLeft 


Arithmetically left-shifts a 16-bit word value. 


• Di^hiftRight 


Arithmetically right-shifts a 16-bit word value. 



Double-Precision Arithmetic 

Many of the possible double-precision arithmetic operations (such as word+word addition) are 
provided with GEOS macros. The standard set of GEOS macros, which include the likes of 
AddW and SubW, are listed in Appendix XX. Many double-precision operations, however, such 
as multiplication and division, are complicated enough to warrant an actual subroutine. GEOS 
provides many of these routines, some of which have signed and unsigned incarnations. 



Math Routines 



Signed vs. Unsigned Arithmetic 

6502 arithmetic operations rely on the two's complement numbering system — an artifact of binary 
math — to provide both signed and unsigned operations with the same instructions (ado and sbc). 
For example, an ado #$6c can be seen as either adding 188 to the accumulator (unsigned math: all 
eight bits represent the positive number, any carry out of bit 7 indicates an overflow) or as adding a 
-68 to the accumulator (signed math: the high-bit, bit 7, holds the sign and any carry out of bit 6 
indicates an overflow). The 6502 has' little trouble adding and subtracting these two*s-complement 
signed numbers. Operations such as multiplication and division, however, need to special-case the 
sign of the numbers. 

Incrementing and Decrementing 

GEOS has only one routine in the category of incrementing and decrementing: 

I • Ddec Decrements a word, setting a flag if the value reaches zero. | 

However, because incrementing and decrementing words are such common operations, Berkeley 
Softworks has created a set of macros specifically designed for incrementing and decrementing 
word values: 

IncW 

Increment Word — IncW addr 

Args: addr — address of word to increment 

Action: IncW increments a word. If the result is zero, 

then the zero flag in the status register is set. 

• macro IncW addr 

inc addr /increment low-byte 

,bne done /branch if no carry into hi-byte 

inc addr+1 /propagate carry into hi-byte 

done: /z-flag is set if both hi & low were $00 

• endm 

*★*★★**★★***★***★*★*★★*****★***★*****★*****★★*★**★******★*★*★**★★ 

DecW 

Decrement Word — DecW zpaddr 

Args: zpaddr — zero-page address of word to decrement 

Action: DecW Decrements a word. If the result is zero, 

then the zero flag in the status register is set. 
a and x registers are destroyed. 

***************************************************************** 

•macro DecW zpaddr 

Idx #zpaddr /load x with address of word for call 

jsr Ddec /call GEOS routine 

/z-flag is set if both hi & low were $00 

• endm 

k******************* ************* ************************ ******** 

Decrement Word #2 — DecW2 addr 
(fast version) 

Args: addr — address of word to decrement 



2 



Math Routines 



Action: DecW2 decrements a word with inline code. No 

flags are set on reaching $0000. Destroys a. 



.macro DecW2 addr 

Ida addr 

bne noOvrflw 

dec addr+1 

noOvrflw: 

dec addr 

.endm 



;get low byte 

;if low_byte != $00, then skip high byte dec 
/decrement hi-byte 

/decrement low-byte 



Most applications will use IncW and DecW to take advantage of the flags which are set when the 
values reach zero. However, DecW2 can be useful when a word needs to be decremented quickly 
and the zero flag is not needed. 

Unsigned Arithmetic 

GEOS provides the following routines for arithmetic with unsigned numbers: 



• BBMult 


Byte-by-byte multiply: multiplies two unsigned byte operands to 
produce an unsigned word result. 


• BMult 


Word-by-byte multiply: multiplies an unsigned word and an 
unsigned byte to produce an unsigned word result. 


• DMuIt 


Word-by- word (double-precision) multiply: multiplies two 
unsigned words to produce an unsigned word result. 


•Ddiv 


Word-by-word (double-precision) division: divides one unsigned 
word by another to produce an unsigned word result. 



Example: 



ConvToUnits 

This routine converts a pixel measurement to inches or, optionally, 
centimeters, at the rate of 80 pixels per inch or 31.5 pixels per 
centimeter . 

pass : 

rO - number to convert (in pixels) 

return : 

rO - inches / centimeters 

rlL - tenths of an inch / millimeters 
affects: 

nothing 
destroys : 

a, X, y, rO-rl, r8-r9 

if AMERICAN 



. INCHES « TRUE 
.else ; ! AMERICAN 

INCHES = FALSE 

.endif 



; decide whether inches or centimeters is 
; appropriate 



ConvUnits : 



Math Routines 



.if 



INCHES 



; First, convert rO to length in 1/20 of 
/standard units 

*** START INCHES SPECIFIC CODE *** 
For ENGLISH, need to multiply by 
20 1 



Idx #rO 

Idy #2 

jsr DShiftRight 

.else /CENTIMETERS 



80 dots/inch 4 

which amounts to a divide by four 
( /4 = two right shifts) 

rO = r0»2 (rO « rO/4) 

;*** START OF CENTIMETER SPECIFIC CODE *** 

For centimeters, need to do multiply by 
20 40 



31.5 dots/cm 
Following lines changed to save bytes 



63 



LoadW 

Idx 

Idy 

jsr 

LoadB 

Idx 

Idy 

jsr 

LoadW 

Idx 

Idy 

jsr 



.endif 



rl,#40 

#rO 

#rl 

DMult 

rl,#40 

#rO 

#rl 

BMult 

rl,#63 

#rO 

#rl 

Ddiv 



First multiply by 40 
(word value) 
(byte value) 

rO « rO*40 (byte by word multiply) 
then divide by 63 



rO = rO/63 



START OF COMMON CODE 



IncW 

LoadW 

Idx 

idy 

jsr 

MoveB 

Isr 

rts 



rO 

rl,#20 

#rO 

#rl 

Ddiv 

r8L,rlL 

rlL 



rO » result in l/20ths 

add in one more l/20th, for rounding 

now divide by 20 (to move decimal over one) 

dividend 

divisor 

rO = rO/20 (rO = result in proper unit) 
rlL « l/20ths 

and convert to 1/lOths (rounded) 
exit 



Signed Arithmetic 

GEOS provides the following routines for arithmetic with signed numbers: 



• Dabs 


Computes the absolute value of a two's-complement signed word. 


• Dnegate 


Negates a signed word by doing a two's complement sign-switch. 


• bSdiv 


Signed word-by-word (double-precision) division: divides one 
two*s complement word by another to produce an signed word 
result. 



There is no signed double-precision multiply routine in the GEOS Kemal. The following 
subroutine can be used to multiply two signed words together. 



4 



Math Routines 



DSir.ult double-precision signed multiply. 

pass: X - zpage address of multiplicand 

y - zpage address of multiplier 

returns: signed result in address pointed to by x 

word pointed to by y is absolute-value of the 

multiplier passed- 
X, y unchanged 



/Strategy: 

Establish the sign of the result: if the signs of the 
; multiplicand and the multiplier are different, then the result 

; is negative; otherwise, the result is positive. Make both the 

; multiplicand and the multiplier positive, do unsigned 

/ multiplication on those, then adjust the sign of the result 

; to reflect the signs of the original numbers. 

/destroys: a, r6 - r8 (mgl) 

DSmult: 



Ida 


zpage+l, X 


;get sign of multiplicand (hi-byte) 


eor 


zpage+l,y 


;and compare with sign of multiplier 


php 




;save the result for when we come back 


jsr 


Dabs 


/multiplicand = abs (multiplicand) 


stx 


r6L 


;save multiplicand index 


tya 




;put multiplier index into x 


tax 




;for call to Dabs 


jsr 


Dabs 


/multiplier = abs (multiplier) 


Idx 


r6L 


/restore multiplier index 


jsr 


Dmult 


/do multiplication as if unsigned 


pip 




/get back sign of result 


bpl 


90$ 


/ignore sign-change if result positive 


jsr 


Dnegate 


/otherwise, make the result negative 


rts 


« 





Dividing by Zero 

Division by zero is an undefined mathematical operation. The two GEOS division routines (Ddiv 
and DSdiv) do not check for a zero divisor and will end up returning incorrect results. It is easy to 
divide-by-zero error checking to these two routines: 

Example: 

/NewDdiv — Ddiv with divide-by- zero error checking 

/NewDSdiv — DSdiv with divide-by-zero error checking 



Pass : 


X 


zp address of dividend 




y 


zp address of divisor 


Returns 


x,y 


unchanged 




2p,x 


result 




r8 


remainder 




a 


$00 — no error 






%ff — divide by zero error 




st 


set to reflect error code in accumulator 



Destroys 



r9 



Math Routines 



DIVIDE BY ZERO = $ff 



t***************** f - ^ ************************************* 



NewDdiv : 

Ida 
ora 
bne 
Ida 
rts 



10$: 



Ida 
rts 



zpage,y 
2page,y 
10$ 

#DIVIDE BY ZERO 



Ddiv 
#$00 



;get low byte of divisor 

;and high byte of divisor 

;.if either is non-zero, go divide 

/return error 

; exit 

! 

/divide 

;and return no error 



NewDSdiv: 
Ida 
ora 
bne 
Ida 
rts 



10$: 



zpage,y 
zpage,y 
10$ 

#DIVIDE BY ZERO 



Apple 
stx 



.if 
.endif 

jsr DSdiv 
.if Apple 
Idx 

.endif 

Ida #$00 

rts 



Xsave 



Xsave 



get low byte of divisor 

and high byte of divisor 

if either is non-zero, go divide 

return error 

exit 

save x-register because Apple destroys 



divide 

restore x-register because that ageos destroyed 



and return no error 



.if Apple 

•ramsect 

Xsave .block 1 

.psect 

.endif 



temp x register save variable for ageos 



6 



r/^/ " Fonts, and Keyboard Input 



Text, Fonts, and Keyboard Input 

At one point or another, almost every application will need to place text directly on the screen or get 
keyboard input from the user. 

GEOS text output facilities support disk-loaded fonts, multiple point sizes, and additive style 
attributes. The application can use GEOS text routines to print individual characters, one at a time, 
or entire strings, including strings with embedded style changes and special cursor positioning 
codes. GEOS will automatically restrict character printing to margins allowing text to be confined 
within screen or window edges. GEOS even contains a routine for formatting and printing decimal 
integers. 

GEOS keyboard input facilities the translation of keyboard input to text output by mapping most 
keypress so that they correspond to the printable characters within the GEOS ASCII character set. 
GEOS will buffer keypresses and use them to trigger MainLoop events, giving the application 
full control of keypresses as they arrive. And if desired, GEOS can also automate the process of 
character input, prompting the user for a complete line of text. 

Text Basics 



Fonts and Point Sizes 

Fonts come in various shapes and sizes and usually bear monikers like BSW 9, Hwnbolt 12, and 
Boalt 10. A font is a complete set of characters of a particular size and typeface. In typesetting, the 
height of a character is measured in points (approximately 1/72 inch), so Humbolt 12 would be a 
12 point (1/6 inch) Humbolt font. A text point in GEOS is similar to a typesetter's point: when 
printed to the screen, each GEOS point corresponds to one screen pixel. GEOS printer drivers map 
screen pixels to 1/80 inch dots on the paper to work best with 80 dot-per-inch printers.A GEOS 
1/80 inch point is, therefore, very close to a typsetter's 1/72 inch point. 

GEOS has one resident font, BSW 9 (Berkeley Softworks 9 point). The application can load as 
many additional fonts as memory will allow. Fonts require approximately one to three kilobytes of 
memory. 

Proportional Fonts 

Computer text fonts are typically monospaced fonts. The characters of a monospaced font are all 
the same width, compromising the appearance of the thinnest and widest characters. GEOS fonts 
arc proportional fonts, fonts whose characters are of variable widths. Proportional fonts tend to 
look better than monospaced fonts because thinner characters occupy less space than wider 
characters; a lower-case "i," for example, is often less than l/5th the width of an upper-case "W." 

Character Width and Height 

Although some characters are taller than others, all characters in a given font are treated as if they 
are the same height. This height is the font's point size. A 10 point font has a height of ten pixels. 
If a character's image is smaller than 10 pbcels, it is because its definition includes white pixels at 
the top or bottom. The height of the current font is stored in the GEOS variable curHeight. 
Although fonts taller than 28 points are rare (some megafonts are as tall as 48 points), a font could 
tiieoretically be as tall as 255 points. 



1 



Text, Fonts, and Keyboard Input 



Because GEOS uses proportional fonts, the width of each character is determined by its pixel 
definition — the tiiinner characters occupy fewer pixels horizontally than the wider characters. 
Most character definitions include a few columns of white pixels on the right side so that the next 
character will print an appropriate distance to the right If this space didn't exist, adjacent characters 
would appear crowded. The width of any single character cannot exceed 57 pixels after adding any 
style attributes, which means that the plaintext version of the character can be no wider than 54 
pixels. 

The Baseline 

Each font has a baseline, an imaginary line that intersects the bottom half of its character images. 
The baseline is used to align the characters vertically and can be thought of as the line upon which 
characters rest. The baseline is specified by a relative pixel offset from the top of the characters (the 
baseline offset). Any portion of a character that falls below the baseline is called a descender. For 
example, an 18 point font might have a baseline offset of 15, which means that the 15th pixel row 
of the character would rest on the baseline. Any pixels in the 16th, 17th, or 18th row of the 
character's definition form part of a descender. The baseline offset for the current font is stored in 
the GEOS variable baselineOffset. The application may increment or decrement the value in this 
variable to print subscript or superscript characters 

The following diagram illustrates the relationship between the baseline and the font height: 




The y-position passed to GEOS printing routines usually refers to the position of the baseline, not 
the top of the character. Most of the character will appear above that position, with any descender 
appearing below. If it is necessary to print text relative to the top of the characters, a simple 
transformation can be used: 

charYPos = graphics YPos + baselineOffset 

Where graphicsYFos is the true pixel position of the top of the characters, charYPos is the 
transformed position to pass to text routines, and baselineOffset is the value in the global 
variable of that name. 

Styles 

The basic character style of a font is called plaintext. Applying additional 5fy/e attributes to the 
plaintext modifies the appearance of the characters. There are five available style attirbutes: reverse, 
italic, bold, outline, and underline. These styles may be mixed and matched in any combination, 
resulting in hybrids such as bold italic underline . The current style attributes are stored in the 
variable currentMode. Whenever GEOS outputs a character, it first alters the image (in an 
internal buffer) based on the flags in this variable: 



2 



Math Routines 



Action : 



DecW2 decrements a word with inline code. No 
flags are set on reaching $0000. Destroys a. 



.macro DecW2 addr 

Ida addr 

bne noOvrflw 

dec addr+1 

noOvrflw: 

dec addr 

.endm 



;get low byte 

;if low^byte != $00, then skip high byte dec 
/decrement hi-byte 

/decrement low-byte 



Most applications will use IncW and DecW to take advantage of the flags which are set when the 
values reach zero. However, Dec\V2 can be useful when a word needs to be decremented quickly 
and the zero flag is not needed. 

Unsigned Arithmetic 

GEOS provides the following routines for arithmetic with unsigned numbers: 



• BBMult 


Byte-by-byte multiply: multiplies two unsigned byte operands to 
produce an unsigned word result. 


• BMult 


Word-by- byte multiply: multiplies an unsigned word and an 
unsigned byte to produce an unsigned word result. 


• DMuIt 


Word-by-word (double-precision) multiply: multiplies two 
unsigned words to produce an unsigned word result. 


•Ddiv 


Word-by-word (double-precision) division: divides one unsigned 
word by another to produce an unsigned word result. 



Example: 



ConvToUnits 

This routine converts a pixel measurement to inches or, optionally, 
centimeters, at the rate of 80 pixels per inch or 31.5 pixels per 
centimeter . 

pass : 

rO - number to convert (in pixels) 

return : 

rO - inches / centimeters 

rlL - tenths of an inch / millimeters 
affects : 

nothing 
destroys : 

a, X, y, rO-rl, r8-r9 

********************************************************* 

if AMERICAN 



; decide whether inches or centimeters is 
; appropriate 



. INCHES = TRUE 
.else ; ! AMERICAN 

INCHES = FALSE 

.endif 



ConvUnits: 



Math Routines 



.if 



INCHES 



; First, convert rO to length in 1/20 of 
/standard units 

*** START INCHES SPECIFIC CODE *** 
For ENGLISH, need to multiply by 
20 1 



Idx #rO 

Idy #2 

jsr DShiftRight 

.else /CENTIMETERS 



80 dots/inch 4 

which amounts to a divide by four 
( /4 = two right shifts) 

rO = r0»2 (rO = rO/4) 

;*** START OF CENTIMETER SPECIFIC CODE *** 

For centimeters, need to do multiply by 
20 40 



31.5 dots/cm 
Following lines changed to save bytes 



63 



LoadW 

Idx 

Idy 

jsr 

LoadB 

Idx 

Idy 

jsr 

LoadW 

Idx 

Idy 

jsr 



rl,#40 

#r0 

#rl 

DMult 

rl,#40 

#r0 

#rl 

BMult 

rl,#63 

#r0 

#rl 

Ddiv 



.endif 



IncW 

LoadW 

Idx 

idy 

jsr 

MoveB 

Isr 

rts 



rO 

rl,#20 

#r0 

#rl 

Ddiv 

r8L,rlL 

rlL 



First multiply by 40 
(word value) 
(byte value) 

rO = rO*40 (byte by word multiply) 
then divide by 63 



rO = rO/63 



;*** START OF COMMON CODE *** 

rO = result in l/20ths 
add in one more l/20th, for rounding 
now divide by 20 (to move decimal over one) 
dividend 
divisor 

rO = rO/20 (rO = result in proper unit) 
rlL - l/20ths 

and convert to 1/lOths (rounded) 
exit 



Signed Arithmetic 

GEOS provides the following routines for arithmetic with signed numbers: 



• Dabs 


Computes the absolute value of a two's-complement signed word. 


• Dnegate 


Negates a signed word by doing a two's complement sign-switch. 


• DSdiv 


Signed word-by-word (double-precision) division: divides one 
two*s complement word by another to produce an signed word 
result. 



There is no signed double-precision multiply routine in the GEOS Kemal. The following 
subroutine can be used to multiply two signed words together. 



4 



Math Routines 



DSmult double-precision signed multiply. 

pass: X - zpage address of multiplicand 

y - zpage address of multiplier 

returns: signed result in address pointed to by x 

word pointed to by y is absolute-value of the 

multiplier passed- 
X, y unchanged 



/Strategy: 

Establish the sign of the result: if the signs of the 
multiplicand and the multiplier are different, then the result 
; is negative; otherwise, the result is positive. Make both the 

; multiplicand and the multiplier positive, do unsigned 

/ multiplication on those, then adjust the sign of the result 

/ to reflect the signs of the original numbers. 

/destroys: a, r6 - r8 (mgl) 

DSmult: 



Ida 


2page+l, X 


;get sign of multiplicand (hi-byte) 


eor 


zpage+1, y 


;and compare with sign of multiplier 


php 




;save the result for when we come back 


jsr 


Dabs 


/multiplicand = abs (multiplicand) 


stx 


r6L 


;save multiplicand index 


tya 




/put multiplier index into x 


tax 




/for call to Dabs 


jsr 


Dabs 


/multiplier = abs (multiplier) 


Idx 


r6L 


/restore multiplier index 


jsr 


Dmult 


/do multiplication as if unsigned 


pip 




/get back sign of result 


bpl 


90$ 


/ignore sign-change if result positive 


jsr 


Dnegate 


/otherwise, make the result negative 


rts 


4 





Dividing by Zero 

Division by zero is an undefined mathematical operation. The two GEOS division routines (Ddiv 
and DSdiv) do not check for a zero divisor and will end up returning incorrect results. It is easy to 
divide-by-zero error checking to these two routines: 

Example: 



-k ic * ie * it * -k -k it it it it it it it it it ic it It it It it it it -k it 1i it it* It icic -kit it -kit it it it It it it it it it it it* 

NewDdiv — Ddiv with divide-by-zero error checking 

— DSdiv with divide-by-zero error checking 



NewDSdiv 
Pass : 



Returns 



Destroys 



X zp address of dividend 

y zp address of divisor 

x,y unchanged 

zp,x result 

r8 remainder 

a $00 — no error 

%ff — divide by zero error 

St set to reflect error code in accumulator 

r9 



Math Routines 



DIVIDE BY ZERO = $ff 



NewDdiv : 



10$: 



Ida 
ora 
bne 
Ida 
rts 

jsr 
Ida 
rts 



2page,y 
2page,y 
10$ 

#DIVIDE BY ZERO 



Ddiv 
#$00 



/get low byte of divisor 

;and high byte of divisor 

;.if either is non-zero, go divide 

/return error 

; exit 

/ 

/divide 

/and return no error 



NewDSdiv: 
Ida 
ora 
bne 
Ida 
rts 



10$: 



zpage,y 
zpage, y 
10$ 

#DIVIDE BY ZERO 



Apple 
stx 



.if 
.endif 

jsr DSdiv 
.if Apple 
Idx 

.endif 

Ida #$00 

rts 



Xsave 



Xsave 



get low byte of divisor 

and high byte of divisor 

if either is non-zero, go divide 

return error 

exit 

save x-register because Apple destroys 



divide 

restore x-register because that ageos destroyed 



and return no error 



•if Apple 

.ramsect 

Xsave .block 1 

.psect 

.endif 



temp x register save variable for ageos 



6 



rf/"^ Fonts, and Keyboard Input 

Text, Fonts, and Keyboard Input 

At one point or another, almost every application will need to place text directly on the screen or get 
keyboard input from the user. 

GEOS text output facilities support disk-loaded fonts, multiple point sizes, and additive style 
attributes. The application can use GEOS text routines to print individual characters, one at a time, 
or entire strings, including strings with embedded style changes and special cursor positioning 
codes. GEOS will automatically restrict character printing to margins allowing text to be confined 
within screen or window edges. GEOS even contains a routine for formatting and printing decimal 
integers. 

GEOS keyboard input facilities the translation of keyboard input to text output by mapping most 
keypress so that they correspond to the printable characters within the GEOS ASCII character set. 
GEOS will buffer keypresses and use them to trigger MainLoop events, giving the application 
full control of keypresses as they arrive. And if desired, GEOS can also automate the process of 
character input, prompting the user for a complete line of text. 

Text Basics 



Fonts and Point Sizes 

Fonts come in various shapes and sizes and usually bear monikers like BSW 9, Humbolt 12^ and 
Boalt 10. A font is a complete set of characters of a particular size and typeface. In typesetting, the 
height of a character is measured in points (approximately 1/72 inch), so Humbolt 12 would be a 
12 point (1/6 inch) Humbolt font. A text point in GEOS is similar to a typesetter's point: when 
printed to die screen, each GEOS point corresponds to one screen pixel. GEOS printer drivers map 
screen pixels to 1/80 inch dots on the paper to work best with 80 dot-per-inch printers.A GEOS 
1/80 inch point is, therefore, very close to a typsetter's 1/72 inch point. 

GEOS has one resident font, BSW 9 (Berkeley Softworks 9 point). The application can load as 
many additional fonts as memory will allow. Fonts require approximately one to three kilobytes of 
memory. 

Proportional Fonts 

Computer text fonts are typically monospaced fonts. The characters of a monospaced font are all 
the same width, compromising the appearance of the thinnest and widest characters. GEOS fonts 
are proportional fonts, fonts whose characters are of variable widths. Proportional fonts tend to 
look better than monospaced fonts because thinner characters occupy less space than wider 
characters; a lower-case "i," for example, is often less than l/5th the width of an upper-case "W." 

Character Width and Height 

Although some characters are taller than others, all characters in a given font are treated as if they 
are the same height. This height is the font's point size. A 10 point font has a height of ten pixels. 
If a character's image is smaller than 10 pbcels, it is because its definition includes white pixels at 
the top or bottom. The height of the current font is stored in the GEOS variable curHeight. 
Although fonts taller than 28 points are rare (some megafonts are as tall as 48 points), a font could 
theoretically be as tall as 255 points. 



1 



Text, Fonts, and Keyboard Input 



Because GEOS uses proportional fonts, the width of each character is determined by its pixel 
definition — the thinner characters occupy fewer pixels horizontally than the wider characters. 
Most character definitions include a few columns of white pixels on the right side so that the next 
character will print an appropriate distance to the right If this space didn*t exist, adjacent characters 
would appear crowded. The width of any single character cannot exceed 57 pixels after adding any 
style attributes, which means that the plaintext version of the character can be no wider than 54 
pixels. 

The Baseline 

Each font has a baseline, an imaginary line that intersects the bottom half of its character images. 
The baseline is used to align the characters vertically and can be thought of as the line upon which 
characters rest. The baseline is specified by a relative pixel offset from the top of the characters (the 
baseline offset). Any portion of a character that falls below the baseline is called a descender. For 
example, an 18 point font might have a baseline offset of 15, which means that the 15th pixel row 
of the character would rest on the baseline. Any pixels in the 16th, 17th, or 18th row of the 
character's definition form part of a descender. The baseline offset for the current font is stored in 
the GEOS variable baseh'neOffset. The application may increment or decrement the value in this 
variable to print subscript or superscript characters 

The following diagram illustrates the relationship between the baseline and the font height: 




The y-position passed to GEOS printing routines usually refers to the position of the baseline, not 
the top of the character. Most of the character will appear above that position, with any descender 
appearing below. If it is necessary to print text relative to the top of the characters, a simple 
transformation can be used: 

charYPos = graphicsYPos + baselineOffset 

Where graphicsYPos is the true pixel position of the top of the characters, charYPos is the 
transformed position to pass to text routines, and baselineOffset is the value in die global 
variable of that name. 

Styles 

The basic character style of a font is called plaintext. Applying additional 5fy/e attributes to the 
plaintext modifies the appearance of the characters. There are five available style attirbutes: reverse, 
italic, bold, outline, and underline. These styles may be mixed and matched in any combination, 
resulting in hybrids such as bold italic underline . The current style attributes are stored in the 
variable currentMode. Whenever GEOS outputs a character, it first alters the image (in an 
internal buffer) based on the flags in this variable: 



2 



7 6 5 4 3 2 1 
I b7 I b6 I b5 I b4 I b3 I b2 I bl 



Fonts, and Keyboard Input 







b7 


underline: 1 = on; = off. 


b6 


boldface: 1 = on; = off. 


b5 


reverse: 1 = on; = off. 


b4 


italic: 1 = on; = off. 


b3 


outline: 1 = on; = Off. 


b2t 


superscript: 1 = on; = off. 


bit 


subscript: 1 = on; = off. 


bO 


unused. 



tSuperscript and subscript characters are not supported by the standard text routines. However, geoWrite 
uses these bits in its ruler escapes. An application can print superscript and subscript by characters by 
changing the value in baselineOffset before printing: subtracting a constant will superscript the 
following characters and adding a constant will subscript the following characters. Additionally, some Apple 
GEOS printer drivers support these two bits when SetMode is used to format ASCII output. 

Normally it is not necessary to modify the bits of currentMode directly. Special style codes can 
be embedded directly in text strings. 

Style attributes temporarily modify the plaintext definition of the character and, in some cases, 
change the size and ultimate shape of the character: 



Underline 


Inverts the pixels of the line beloy^ the baseline. The size of the character 
does not change. 


Boldface 


The character image is shifted onto itself by one pixel. The width of the 
character increases by one. 


Outline 


Transforms the character into an oudine style. This transformation occurs 
after boldfacing and underUning. //e^^/^A 4 \h^c>4^ ^^u^e^^ 


Italic 


Pairs of lines above the baseline are shifted right and pairs of lines below 
the baseline are shifted left. Thus the baseline is not changed, the two 
lines above it are shifted to the right one pixel, the next two are shifted 
four pixels from their original position, and so forth. The effect of this is 
to take the character rectangle and lean it into a parallelogranL The width is 
not actually changed. The same number of italicized characters will fit on a 
line as non-italicized characters, and because the shifting is consistent 
from character to character, adjacent italic characters will appear next to 
each other correctly. However, if a non-italic character immediately 
follows an italic character, the non-italic character will overwrite right side 
of the shifted italic character. This can be avoided by inserting an italicized 
space character. 


Reverse 


Reverses the pixel image of the character. This is the last transformation to 
take place. Thz Sx2f J}o6^ /v^^ OVW/vtc. 



Note: Although, at this time, style attributes affect the printed size of a character in a 
predictable fashion, the application should not perform these calculations itself but use 
the GEOS GetRealSize routine to ensure compatibility with future versions of the 
operating system. For more information, refer to "Calculating Character WidthCin diis 

chapter. \^ 



r 



lo 



3 



Text, Fonts, and Keyboard Input 



How GEOS Prints Characters 



When a character is printed, a rectangular area the width of the character and the height of the 
current font is stamped onto the background, leaving cleared pixels surrounding the character. 
When writing to a clear background, tihe cleared pixels around the character will mesh with the 
cleared background, leaving no trace. But when writing to a patterned background, the background 
will be overwritten: 




Is stampea^\ 
background. J 



There is no simple way to print to a non-cleared background without getting clear pixels 
surrounding the characters. Solutions usually involve accessing screen memory direcdy. 



Text and dispBufferOn 

Like graphics routines, most text routines use the special bits in dispBufferOn to direct printing 
to the foreground screen or the background buffer as necessary. For more information on using 
dispBufferOn, refer to "Display Buffering" in Chapter @GR@. 

GEOS 128 Character X-position Doubling 

GEOS 128 text routines pass character x-coordinates through NormalizeX, allowing automatic 
x-position doubling. (The character width is never doubled, only the x-position). Character x- 
position doubling is very much like graphic x-positions doubling and is explained in "GEOS 128 
X-position and Bitmap Doubling" in Chapter @GR@. There is one notable difference: because 
smallPutChar will accept negative x-positions (allowing characters to be clipped at the left screen 
screen edge), die DOUBLE_W and ADD1_W constants should be bitwise exclusive-or'ed into 
the x-positions as opposed to merely bitwise"br*ed This will maintain the correct sign information 
with negative numbers. 



Character Codes 

Each character in GEOS is referenced by a single-byte code called a character code. GEOS 
character codes are based upon the ASCII character set, offering 128 possible characters 
(numbered 0-127). GEOS reserves the first 32 codes (0-31) as escape codes. Escape codes are 
non-printing characters that provide special functions, such as boldface enabling and text-cursor 
positioning. Character codes 32 through 126 represent the 95 basic ASCII characters, consisting of 
upper- and lower-case letters, numbers, and punctuation symbols. The 127th character is a special 
deletion character, a blank space as wide as the widest character, used internally for deleting and 
backspacing. 

Most GEOS fonts do not offer characters for codes above 127 except in one special instance: the 
standard system character set (BSW 9) includes a 128th character that is a visual representation of 
the shortcut key (a Commodore symbol on Commodore computers and a filled Apple logo on 



4 



Fonts, and Keyboard Input 



Apple computers). There is no inherent limitation in the text routines that would prevent an 
application from printing characters corresponding to codes 129 through 159, assuming the current 
font has image definitions for these character codes. The printing routines cannot handle character 
codes beyond 159, however. The text routines do no range-checking on character codes; do not try 
to print a character that does not exist in the current font. 

A complete list of GEOS character codes appears in Appendix @TBL@, 

Printing Single Characters 

GEOS will print text at the string level or at the character level. The high-level string routines, 
where many characters are printed at once, will often provide all the text facilities an application 
evers need outside the environment of a dialog box. However, in return for generality, string-level 
routines sacrifice some of the flexibility offered by character level routines.Character level routines, 
where text is printed a character at a time, require the application to do some of the work: deciding 
which character to print next and where to place it. Because of this overhead, t is tempting to 
dispense with text at the character level, relying entirely on the string level routines instead. But the 
character level routines are the basic text output building blocks and the string level routines depend 
upon them gready. For this reason, it helps to understand character output even when dealing 
entirely with string-level output 

GEOS provides two character-level routines that are available in all configurations of GEOS: 



• PutChar Process a single character code. Processes escape codes and only 

prints the character if it lies entirely within the left and right 
margins (leftMargin, rightMargin). ^ 

• SmallPutChar Draw a single character. Does not check margins for proper 

placement. Does not handle escape codes. Prints partial characters, 
clipping at margin edges. 

And one routine that only exists in Apple GEOS: 

• EraseCharacter Erase a character from the screen, accounting for the current font 

and style attributes. 

PutChar is the basic character handling routine. It will attempt to print any character within the 
range 32 through 256 ($20 through $ff) as well as process any escape codes (character codes less 
than 32), such as style escapes. It will also check to miake sure that the character image will fit 
entirely within the left and right margins. SmallPutChar, on the other hand, carries none of the 
overhead necessary for processing escape codes and checking margins; it is smaller (hence, the 
name) and faster but requires that Ae application send it appropriate data. Do not send escape codes 
to SmallPutChar. 

Typically an application will call PutChar in a loop, using SmallPutChar to print a portion of a 
character that crosses a marpn boundary. SmallPutChar can also be used by an appUcation that 
does its own range-checking, thereby avoiding any redundancy. Be sure to only send 
SmallPutChar character codes for printable characters. 

PutChar and Margin Faults 

Ptior to printing a character, PutChar checks two system variables, leftMargin and 
rightMargin. When an application is first run, these two margin variables default to the screen 



5 



Text, Fonts, and Keyboard Input 



edges (0 and SC_PIX_WIDTH-1, respectively). If any part of the current character will fall 
outside one of these two margins, the character is not printed. Instead, GEOS jsr's through 
stringFaultVec with the following parameters: 

rll Character x-position. If the character exceeded the right margin, then this is the 
position GECSs tried to place the offending character. If the character fell outside of 
the left margin, then' the width of the offending character was added to the x- 
position, making this the position for the next character. 

r 1 H Character y-position. 

Note: When Apple GEOS vectors through StringFaultVec, the current values of rll and 
rlH are stored on the alternate zero-page. Do a sta ALTZP_ON before accessing 
them and a sta ALTZP_OFF after accessing them. When the string fault routine 
returns, PutChar will automatically copy these working registers over to the main 
zero-page. 



StringFaultVec defaults to $0000. Because GEOS uses the conditional jsr mechanism, 
CallRoutine, a $0000 will cause character faults to be ignored. 

There are many ways to handle a margin faults (including ignoring them entirely), . Faults on the 
left margin are usually ignored or not even bothered with because printing will usually begin 
predictably at the left margin, thereby precluding that type of fault. But faults on the right margin, 
(which are less predictable) will often get special handling, such as using SmallPutChar to 
output the fractional portion of the character that lies to the left of rightMargin. 

There is one unfortunate problem with faults through PutChar: the fault routine has no direct way 
of knowing which character should be printed and so will lose some of its generality by needing 
access to chta that should be local to the routine that calls PutChar. One simple way around this 
problem is to use a global variable — call it something like lastChar — to hold the character code 
of the character being printed, or perhaps, make it a pointer into memory (PutString does just that 
with rO). This way the fault routine will faiow which character caused the fault. 

Example: 

/macro: PutChar char (char « character code) 

; Macro to replace jsr PutChar in your code so that lastChar 

; holds the value of the last character printed 

.***************************************************************** 

.macro PutChar character 

sta lastChar ; character is already in A-reg 

jsr PutChar 

.endm 

Calculating the Size of a Character 

Text foraiatting techniques such as right justification require the application to know the size of a 
character before it is printed. GEOS offers two routines for calculating the size of a character: 



6 



Fonts, and Keyboard Input 



• GetCharWidth 


Calculates the pixel width of a character as it exists in the font (in 
its plaintext form). Ignores any current style attributes. 


• GetRealSize 


Calculates the pixel height, width, and baseline offset for a 
character, accounting for any style attributes. 



These routines can be used in succession to calculate the printed size of any character combination, 
whether groups of random characters, individual words, or complete sentences. 

Partial Character Clipping 

Confining text output to a window on the. screen is called clipping. Characters that will appear 
outside the window*s margins are not printed; they are "clipped," so to speak. Sometimes, 
however, it is desirable to print the portion of the offending character that lies within the margin 
and only clip the portion that lies outside the window area. This sort of clipping is called partial 
character clipping. 

Top and Bottom Character Clipping 

Both PutChar and SmallPutChar handle top and bottom partial character clipping. Any portion 
of a character that lies outside of the vertical range specified by windowTop and 
windowBottom will not be printed. windowTop and windowBottom default to the full 
screen dimensions (0 and SC_PIX_HEIGHT-1, respectively). They may be changed by the 
application before printing text" " 

Left and Right Character Clipping with SmallPutChar 

Whenever a character crosses the left or right margin boundary, PutChar vectors through 
StringFaultVec without printing the character. SmallPutChar, unlike PutChar, will not 
generate string faults. If a character crosses a margin boundary, SmallPutChar will print the 
portidn of the character that lies within the margin. 

SmallPutChar will also accept small negative values as the character x-position, allowing 
characters to be clipped at the left screen edge by placing leftMargin at 0. 

Note: Clipping at the left margin, including negative x-position clipping, is not supported by 
early versions of GEOS 64 (earlier than version 1.4) — the entire character is clipped 
instead. Left margin clipping is supported on all other version of GEOS: GEOS 64 
vl.4 and above, GEOS 128 (in botii 64 and 128 mode), and Apple GEOS. Early 
versios of Apple GEOS (versions earlier than 2.0.3) did not properly clip at the left- 
margin. 



Manual Character Clipping 

Once of the criticisms of GEOS is the iconsistent and sometimes capricious character clipping 
capabilities — not all versions of GEOS fully support partial character clipping and the versions 
that do have inherent ideosyncracies. A carefully desilwd program can usually work around these 
limitations. Some applications, however, will need a reliable method to perform partial character 
clipping. The following ClipChar subroutine will properly clip and print a character Aat partially 
exceeds one of the left or right margins. Be aware that ClipChar does quite a bit of caculation and 
should only be used in special cases where controlled character clipping is needed. 

Example: 



7 



Text, Fonts, and Keyboard Input 



.if (0) 

ClipChar — print a character, clipping to window margins. 

Description: 

Draw a character, clipping it EXACTLY to leftMargin, rightMargin, 
windowTop and windowBottom 

Operates by temporarily modifying the font definition (making the 
character thinner, so as to fit in the margin) . 



Pass : 

a - character to print 
rll - X position 
rlH - y position 

Return : 

rll - X position for next char 
rlH - y position for next char 



Destroyed: 

a, X, y, r2-rlOL 

.endif 
ClipChar: 
sta 



\e It tt It ic -k * * * it -k H 



tit*it*1t'kittt1tiftftt'ttitit1tiHt 



Idx 
jsr 
dey 
tya 
add 
sta 
Ida 
adc 
sta 



rlL 
currentMode 
GetRealSize 



rllL 

r2L 

#0 

rllH 
r2H 



store character 
get width of character 

use width - 1 to calc last position 

r2 = last pixel that char covers 



3$: 



5$: 



10$: 



CmpW 


r2, leftMargin , 


•cfteck for char entirely off window 


bit 


3$ 


•if so then exit 


CmpW 


rightMargin, rll , 




bge 


5$ 




AddWVW 


r2,l,rll ;rll « one pixel beyond where char would 


rts 


; exit 


Ida 


rlL 


•push old width table values 


sub 


#32 


?get card # 


sta 


r3L 




asl 


a 




tay 






Idx 


#0 




Ida 


(curlndexTable) , y 


•store this char's index values 


sta 


savedWidths,x < 




iny 






inx 






cpx 


#4 




bne 


10$ 


'loop to copy values 


CmpW 


leftMargin, rll , 




bit 


30$ 




Ida 


r3L 




asl 


a 1 




tay 






Ida 


leftMargin , 


check for clipping on left 



8 



Fonts, and Keyboard Input 



30$: 



50$: 



60$: 



sub 


rllL 


clc 




adc 


(curlndexTable) , y 


sta 


(curlndexTable) , y 


inv 




Ida 


#0 


adc 


(curlndexTable) ,y 


sta 


(curlndexTable) ,y 


MoveW 


leftMargin, rll 


CmpW 


r2, rightMargin 


bit 


50$ 


Ida 


r2L 


sub 


rightMargin 


sta 


r3H 


Ida 


r3L 


asl 


a 


tav 




iny 




iny 




Ida 


(curlndexTable) , y 


sub 


r3H 


sta 


(curlndexTable) ,y . 


iny 




Ida 


(curlndexTable) ,y 


sbc 


#0 


sta 


(curlndexTable) , y 


Ida 


rlL 


pha 




jsr 


SmallPutChar 


pla 




sub 


#32 


asl 


a 


tay 




Idx 


#0 


Ida 


savedWidths, X 


sta 


(curlndexTable) ,y 


iny 




inx 




cpx 


#4 


bne 


60$ 


rts 





check for clipping on right 
save amount to subtract 



draw the character ! ! 
save it for later 



recover old widths 



, ramsect 
savedWidths : 

.block 4 
•psect 



/values from index tabel stored here 



Printing Decimal Integers (PutDecimal) 

One of the unfortunate side-effects of binary math is the conversion necessary to print numbers in 
decimal. Fortunately, GEOS offers a routine to remove this drudgery from the application: 

rnputPecimal Format and print a 1 6-bit, positive integer H 

PutDecimal is like a combination of character and string level routines. The application passes it 
a single 16-bit, positive integer, some formatting codes (e.g., right justify, left justify, suppress 



9 



Text, Fonts, and Keyboard Input 



leading zeros), and a printing position. PutDecimal converts the binary number into a series of 
one to five numeric characters and calls PutChar to output each one. 

String Level Routines 

Many applications will never need complex text output and can rely on GEOS's string-level 
routines for simple text output and input. GEOS provides two string-level text routines, one for 
printing strings to the screen and one for getting strings through the keyboard 



• PutString 


Print a string to the screen. 


• GetString 


Get a string from the keyboard using a cursor prompt and echoing 
characters to the screen as they are typed. 



GEOS Strings 

A GEOS string is a null-terminated group of character codes. (Null-terminated means the end of 
the string is marked by a NULL character ($00).) These strings can contain alphanumeric 
characters as well as special escape codes for changing the style attributes or changing the printing 
position. 

There is no basic limit to the possible length of a string; GEOS processes the string one character at 
a time until it encounters the NULL, which it interprets as the end of the string. If the string is not 
terminated, GEOS will have way of knowing where the end of the string is and will continue 
printing until it encounters a $00 in memory. 

A simple string of ASCII characters might look like this: 

Stringl : 

.byte "This is a simple string NULL 

The above string, including the NULL, is 25 characters long (and therefore 25 bytes long also). 
Escape codes may be emb^ded within the string to effect changes while printing. An individual 
word, for example, may be underlined by embedding an ULINEON escape code before the word 
and an ULINEOFF after it as in: 

String2 : 

.byte "This word is " 

.byte OLINEON, "underlined", ULINEOFF,".", NULL 

The embedded escape codes change the style attribute bits in currentMode mid-string, resulting 
in something like: 

This word is underlined . 

PutString 

PutString offers a simple way to handle text output. It is really does nothing more than call 
PutChar in a loop, so issues that apply to PutChar, such as top and bottom character clipping, 
also apply to PutString. PutString directly supports a feature that PutChar doesn't, though: 
muWbyte escape codes, such as GOTOXY,which require rO to contain a pointer to the auxUiary 



1 



Fonts, and Keyboard Input 



bytes in a multibyte sequence (PutString maintains rO automatically, allowing the extra 
parameters to be embedded directly in the string). Printing a string to the screen with PutString 
involves specifying a position to begin printing and passing a pointer to a null-tenninated string: 

Example: 



Example use of PutString. Places a test string onto the 
screen. Assumes that leftMargin, rightMargin, windowTop and 
windowBottom contain their default, startup values (full 
screen dimensions) . 



Print : 



String: 



STR_X 


= 40 


;x-position of first character 


STR_Y 


= 100 


;y-position of character baseline 


LoadB 


dispBuffOn,#(ST_WR_ 


JORE 1 ST_WR_BACK) ;both buffers 


LoadW 


rll,#STR__X 


/string x-postion 


LoadB 


rlH,#STR__Y 


/string y-position 


LoadW 


rO,#String 


/address of text string 


jsr 


PutString 


/print the string 


rts 




/exit 


.byte 


"This is a test.", 


NULL /null-terminated string 



String Faults (Left or Right Margin Exceeded) 

Because PutString calls PutChar, if any part of the current character will fall outside of 
leftMargin or rightMargin, the character is not printed. Instead, GEOS jsr's through 
stringFaultVec with the following parameters: 

rll Character x-position. If the character exceeded the right margin, then this is the 
position GEOS tried to place the offending character. If the character fell outside of 
the left margin, then the width of the offending character was added to the x- 
position, making this the position for the next character. 

r 1 H Character y-position. 

rO Pointer to the offending character in the string. Only valid with PutString, unused 
by Putchar. 

Note: When Apple GEOS vectors through StringFaultVec, the current values of rll, and 
rlH, and rO are stored on the alternate zero-page. Do a sta ALTZP_ON before 
accessing them and a sta ALTZP^OFF after accessing them. When the string fault 
routine returns, PutString will automatically copy these working registers over to the 
main zero-page> 

GEOS 64 and GEOS 128 do nothing special to handle these string faults. If the application has not 
installed its own string fault routine, stringFaultVec it should contain a default value of $0000, 
which will cause the string fault to be ignored. If this is the case, the following will happen: 

• If part of the character was outside of the left margin, the width of the offending 
character was added to the x-position in rll before the fault. PutString moves on to 
the next character in the string and attempts to print it at this new position. 



1 1 



Text, Fonts, and Keyboard input 



• If part of the character was inside the left margin but outside the right margin, 
PutString leaves the x-position unchanged and moves on to the next character in the 
string. 

The strategy behind this system is to only print the portion of the string that lies entirely within the 
left and right margins. Unfortunately, this strategy is flawed. Whenever the right margin is 
encountered, PutString should stop completely. But it doesn't. It continues searching through 
the string, looking for a character that will fit. This can be a problem when a thin character follows 
a wide character. For example, trying to print the word "working" with only a few pixels of space 
before the right margin, PrintString would try to print the "w," but since it doesn't fit, would 
move on and try its luck with the following "o." But the "o" won't fit either, so it moves on until it 
encounters the "i," which just happens to fit in the available space. PutString proudly prints the 
"i," thinking it has done a good thing, entirely unaware that the proper sequence of characters has 
been lost. 

The Apple GEOS version of PutString offers a partial solution to this problem. If 
stringFaultVec contains $0000, it installs a temporary string fault routine (PutStringFault). 
PutStringFault immediately terminates string printing on any fault (left or right margin) by 
moving rO forward to point to the null. To disable the Apple PutStringFault so that Apple 
GEOS PutString is identical to GEOS 64 and GEOS 128 PutString, point StringFaultVec to 
an rts prior to calling PutString. PutStringFault can be implemented on GEOS 64 and GEOS 
128 by placing the following routine into StringFaultVec prior to calling PutString: 



PutStrFault (for GEOS 64/128 only) 



String fault routine for duplicating the Apple GEOS PutString 
fault handling on GEOS 64 and GEOS 128. Immediately terminates 
string printing when any fault (left or right margin) is 
generated by setting rO to point at the end of the string. 

******************* € 



PutStrFault : 



;Go through the string looking for the null 

Idy #1 ;load index to look at next character 

bne ^'-^"'0$ 4 M' ; always branch — don't inc on 1st pass 



20$: 

IncW rO /check next character 

10$: Ida (rO),y ;get character 

bne 20$ ;loop until we find null 



/Return to PutString pointing at a null 
rts 



The above technique, however, has two flaws: if a character lies outside the left margin, printing is 
aborted, and, with either type of fault, the application has no way of knowing wjiich character in 
the string caused the fault. The following routine, SmartPutString, will solve both these 
problems. If a character lies outside the left margin, it is skipped, and if it lies outside the right 
margin, SmartPutString returns with rO pointing to the character in the string that caused it to 
terminate. If rO points to a NULL, then SmartPutString was able to print the whole string and 
terminated noraially. 

.if 

. ****** ************* ************* *********************** ********** 

; SmartPutString 



1 2 



Fonts, and Keyboard Input 



New front-end to PutString that handles right-edge string 
; faults by exiting immediately rather than moving through 

/ the string until it finds a character that fits. It operates 

by replacing the current string fault service routine with 
its own routine that tricks PutString into thinking it 
; encountered a null on a right -margin fault. 

/ Pass: same as PutString. The string must not be located 

in zero-page ($00-$f f) . 

; Returns: same as PutString, except that if the string 

; faulted, then rl5 points to the offending character 

rather than the null at the end of the string. If 
rl5 = $0000, then the string printed without a fault 

; Destroys: same as PutString. 

; Note: No inline support. 

.endif 

SmartPutString : 

/Insert our own string fault routine into stringFaultVec, 
; saving the old one so that we can restore it when we leave. 
PushW StringFaultVec ;save old 

LoadW StringFaultVec, #FaultFix ; install new 

; Clear the flag that alerts us to a right-edge fault. If the high 
;byte of rl5 is zero then PutString returns immediately because 
;our string never encountered the right edge. 

LoadW rl5,#0 ; clear rl5 to $0000 

;Call PutString with our string fault routine in place 
jsr PutString 

90$: 

; Restore the old string fault routine 
PopW StringFaultVec 

; Return 

rts 
;FaultFix 

;Our own string fault routine that sets up the string 'pointer 
;so that PutString is tricked into thinking it encountered a 
;NULL when the right margin is exceeded. 

FaultFix: 

; Check to see if we exceeded the right margin or if we just 
; haven't reached the left margin yet. If the right margin was 
;not exceeded, return early — the text routine handles this, 
•case appropriately. If the first character in the string will not 
;fit within either margin, we treat it as if the right margin was 
; exceeded. Don't need to normalize the coordinates under GEOS 128 
/because the character output routine has already taken care of 
;this for us. 

.if (APPLE) /Apple GEOS hides registers 



13 



Text, Fonts, and Keyboard Input 



sta ALTZP_ON ;on aux. zpage. 

.endif 

CmpW rightMargin, rll /check x with right edge 

ble 90$ ;exit if right not exceeded; 

;the character was outside the 

/left edge. 

/Save the pointer to the offending character in rl5 (which is left 
/untouched by the normal PutString) 

Ida rOL 

Idx rOH 

.if (APPLE) /need to change rl5 on main zp if apple 

sta ALTZP__OFF 

.endif 

stx rl5H 

sta rl5L 

.if (APPLE) /return Apple to 

sta ALTZP__ON /aux. zpage. 

.endif 

/Change the string pointer so that PutString thinks the next 
/character is a null. 

LoadW rO, # (FakeNull-1) /one less to compensate for 

/increment that PutString will 

/do before it checks. 

90$: 

/Return to let PutString do its stuff 
.if (APPLE) 
sta ALTZP__OFF 
.endif 

rts /return to to StringFault caller 

FakeNull: .byte NULL /null for FaultFix 

. Embedding Style Changes Within a String 

A string may contain embedded escape codes for changing the style attributes mid-string. For 
example, if while printing a string GEOS encounters a BOLDON (24) escape code, then 
PutString will temporarily escape from normal processing to set the boldface bit in 
currentMode. Any characters thereafter will be printed in boldface. 

Style changes are typically cumulative. If a OUTLINEON code is sent, for example, then the 
outline style attribute will be added to current set of attirbutes. If boldface was already set, then 
subsequent characters will be both outiined and boldfaced. The PLAINTEXT escape code 
returns text to its normal, unaltered state. 

When PutString is first called, it begins printing in the styles specified by the value in 
currentMode and when it returns, currentMode retains the most recent value, reflecting any 
style-change escapes. The next call to PutString (or any other GEOS printing routine) will 
continue printing in that style. To guarantee printing in a particular style without inheriting any 
style attributes from previous strings, the first character in the string should be a PLAINTEXT 
escape code. Any specific style escape codes can then follow. 

Position Escapes (Moving the Printing Position Mid-string) 

GEOS provides escape codes for changing the current printing position. Like other escape codes, 
tiiese can be embedded within the string. Some of them are simple, such as LF and UPLINE, 
which move the current printing position down one line or up one line, respectively, based on the 



14 



Fonts, and Keyboard Input 



height of the current font. Others, such as GOTOX, GOTOY, and GOTOXY, require byte or 
woni pixel coordinates to be embedded within the string immediately after the escape code. 

Example: 

string: 

.byte HOME ; start in the upper-left corner 

.byte LF /move down one line. so we have room 

.byte "This ",LF,"is LF, "stepping ",LF- 

. byte "Down" , LF"ward" , CR 

.byte LF, "HELLO" 

.byte GOTOXY 

.word 4 ;x-position 

.byte 15 ;y-position of baseline 

.byte "Look! I moved." 

.byte NULL 

Escaping to a Graphics String 

GEOS provides a special escape code (ESC_GRAPHICS) that takes the remainder of a string 
and treats it as input to the GraphicsString routine. This allows graphics command to be 
embedded within a text string, which is useful for creating complex displays, especially those that 
require graphics to be drawn over text. The current pen positions for the graphics arc unitialized so 
the first graphics string command should be a MOVEPENTO. 

Example: 

TextGraphics : 

.byte GOTOXY 
.word 20 
.byte 20 
.byte "BOX: 
.byte ESC__GRAPHICS 
.byte MOVEPENTO 
.word 10 
.byte 10 

.byte RECTANGLETO 
.word 50 
.byte 30 
.byte NULL 

Note: When GraphicsString encounters the NULL marking the end of a string, control is 
returned to the application as if PutString had terminated normally. The NULL does 
not resume PutString processing. 

If it is necessary to print additional text after graphics, the ESC^PUTSTRING 
command may be used to escape from GraphicsString. A subsequent NULL will 
still mark the end of the string. Be aware that each context-switch between these two 
routines allocates additional 6502 stack space that is not released until the NULL 
terminator is encountered 



GetString 



; string with both text and graphics 



GetString provides a convenient way for an application to get text input from the user without 
using a dialog box. GetString takes care of intercepting keypresses and echoing the characters to 
the screen. The beauty of GetString is that it builds the string concurrently with the rest of 



Text, Fonts, and Keyboard Input 



Unfortunately, there is no direct way to terminate GetString before the user presses [Return]. 
The trick of choice in this situation is to simulate a press of the return key by loading keyData 
with a CR and vectoring through key Vector as in: 



; simulate a CR to end GetString 

LoadB keyData, #CR ;load up a CR (Return) key 

Ida keyVector .;and vector through keyVector 

Idx keyVector+1 ;so SystemStringService will 

jsr CallRoutine ;think it was pressed now 



This same technique can be used to terminate a DB GETSTRING when an icon is pressed to 
leave a dialog box. 

Note: The Apple GEOS version of GetString always keeps the partial string null-terminated 
while it is building it in the buffer. An application can peek at the status of the string by 
looking in this buffer. GEOS 64 and GEOS 128 (through vl.3) do not null-terminate 

the string until [Return] is pressed (or simulated). 



Fonts 



In GEOS a font is a complete set of characters of a particular size and typeface. On disk, fonts are 
organized by style, where a single font file holds all the available point sizes for a given style. Each 
point size occupies its own VLIR record in the font file. The record number corresponds to the 
point size. For example, a font file called MyFont might use three VLIR records, one for each 
available font size: the MyFont 10 would occupy record 10, MyFont 12 would occupy record 12, 
and MyFont 24 would occupy record 24. 

It is the job of the application to decide which fonts to keep in memory at any one time, reading in 
the appropriate records from the VLIR font file. Once a font is in memory (usually as the result of a 
call to ReadRecord), the application must inform GEOS to begin using the new font with the 
following routine: 

• LoadCharSet Instruct GEOS to begin using a new font. (Font is already ir 
memory.) 



Because Apple GEOS allows font data to be stored in auxiliary memory, an additional routine is 
provided for doing the equivalent of LoadCharSet when the font is in auxiliary memory 
(LoadCharSet is still used when the font is in main memory): 

• LoadAuxCharSet Instruct GEOS to begin using a new font. (Font is already in 

auxiliary memory.) 

Although the word "Load" in LoadCharSet and LoadAuxCharSet is misleading in that it 
implies they automatically load the character set from disk into memory, the application must read 
the font data into memory prior to calling these routines. LoadCharSet and LoadAuxCharSet 
expect an address pointer to the beginning of the font in memory. It will then build out a variable 
table for the text routines, providing information such as the baseline offset and font point height. 
The application may keep as many fonts resident as free memory will allow, switching tiiem at will 
with calls to LoadCharSet and LoadAuxCharSet . Some sophisticated GEOS applications use 
a font-cacheing system where fonts are kept in memory based on their frequency of use. 

GEOS provides an additional routine for returning to the always-resident BSW 9 system font: 



1 8 



Fonts, and Keyboard Input 



I • UseSystemFont Instruct GEOS to begin using the default BSW 9 font. 
UseSystemFont passes the address of the the system BSW 9 font to LoadCharSet. 



The Structure of a Font File 

Fonts are stored in VLIR files of GEOS type FONT, A single font file contains all the available 
point sizes for a particular style (up to a maximum of 16). Each point size occupies one complete 
VLIR record. The record number corresponds to the point size (i.e., record 9 would contain the 
data for the nine point character set). If a VLIR record in a font file is empty, then the 
corresponding point size is not available (the record will exist, but will marked as empty in the 
index table). The data in each of these records is what GEOS considers a character set, and its 
structure is described later in "Character Set Data Structure." Unless the application is creating or 
modifying fonts, this data structure is unimportant,^ 

The font files on a given disk can be (ound^sing the FindFTypes routine. Once the font files 
are known, the application can us^ G5fflBfInft>>^o access the header block for each font file. The 
font file header block contains infotingtiojii^itineht to the particular font file, such as the font style 
ID, the available point sizes, and the amount of memory required for each point size. These values 
can be accessed in the header block by using the following offsets: 



Offset 



Field size Description 



O GHFONTID 


1 word 


Font style ID. 


O^GHPTSIZES 


16 words 


Character set ID's for those available in this 
file. Arranged from smallest to largest point 
size. Table is padded with zeros. 




16 words 


Size (in bytes) of each character set from 
smallest to largest point size. (These numbers 
have a one-to-one coorespondence with the 
O^GHPTSIZES table. Table is padded with 
zeros. 



Every font style has a unique 10-bit ID number. This number is stored in the word-length field 
O^GHFONTID. The next field, O^GHPTSIZES, has room for 16 character set ID numbers.A 
character set ID number is a 16-bit combination of the style ID and a point size identifier. The style 
ID is stored in the upper 10 bits and the point size is stored in the lower 6 bits: 



Character Set ID Wordt 



15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 

I 10-bit Style ID (b6-bl5) I point size (bO-b5) 

b6-bl5 Style ID. 
bO-b5 Point Size. 

This combination of style ID number and point size gives each character set (font) a unique word- 
length identifier. This allows any style/point-size combination to be referenced with a two-byte 
number. For example, the Durrant style has a style ID of 15, so the Durrant 10 font would have a 
character ID of 

(15 « 6) I 10 or $03ca 



1 9 



Text, Fonts, and Keyboard Input 



Berkeley Softworks' applications use the NEWCARDSET escape followed by the character set 
ID word to flag font changes within a text document 

Note: A complete list of font ID's for registered fonts appears in Chapter XX. Developers 
wishing to register their own fonts should contact Berkeley Softworks in writing for 
available ID numbers: 

Berkeley Softworks 
Attn: Font Registration 
2150 Shattuck Avenue 

Berkeley, CA 94704 

Each request must include a disk with the font files along with the desired registration 
names. 



Character Set Data Structure 

A character set is stored — both in memory and in its VLIR record — as a contiguous data 
structure consisting of an eight-byte header, followed by an index table and the actu^ character 
image data. The image data for the characters are stored in a bitstream format, pixel row by pixel 
row. Imagine laying every printable character side by side, in character code order, starting with 
character number 32 (the space character). If the top row of pixels from every character were then 
stored together as a contiguous stream of bits, this would be the proper bitstream format. In 
GEOS, for every pixel of height in a character set, there is a corresponding bitstream row. Starting 
with the top row, each bitstream row is padded with zeros to make it end on a byte boundary. The 
next row (if there is one) is appended at the next byte. The number of bytes in each bitstream row 
is called the set width.J^ 

Because each character in a GEOS font can be of a different pixel width, GEOS needs some way 
of induing into the bitstream data to find the beginning of each character. For each character there 
is gjS»&Pindex werfTfliat indicates where the character begins in the bitstream. For example, if the 
first pixel for the "A" character begins at pixel 148 in the bitstream, then the index value for 
character code 65 (uppercase "A") would be 148. 



20 



Fonts, and Keyboard Input 



Character Set Data Structure 



Offset Field size Description IN 





uyic 


OaoCilllC UiioCl |(/lACio irUili LUp UL dlaiadCly. 


+1 


word 


Bytes in one bitstream row (set width). 


+3 


byte 


Font height, ("/vc^/^ 66/1. o/^ rizr%rneAm fio^%) 


+4 


word 


Pointer to beginning of index table (relative to beginning of 
data structure). Usually $0008 because the index table 
follows immediately after theiieader. ^^Ah WQrt/O . 


+6 


1 word 


Pointer to beginning of character bitstream data (relative to 
beginning of data structure). Bitstream data typically follows 
the index table. 


^ • 


; woras 


inciex taoie. one wora entry lor eacn prmtaoie cnaracter (tne 
first word corresponds to character code 32). Each index 
word is pixel position of the character in each bitstream row. 
Total number of words = number of printable characters in 
the set. 


+? 


? bytes 


Bitstream rows: one row of bitstream data for each pixel of 
height in the character set. Each bitstream row ij padded 
with ztxoi^'^x to the next byte. Total bytes?^ number of 
printable characters in the set times the set width. 



Saving and Restoring the Font Variables 

In both GEOS 64 and GEOS 128/^1 the information GEOS needs for using a font is stored in the 
variable table beginning at fontTable and stretching for FONTLEN bytes. Whenever GEOS 
needs to switch fonts internally (while drawing the BSW 9 text fii^crtnenus, for example), these 
bytes are saved off to saveFontTab, which is also FONTLEN bytes long. If a Commodore 
GEOS application needs to temporarily change fonts, it can simply duplicate tins technique, saving 
and restoring between fontTable and saveFontTab as needed. 

Under Apple GEOS, however, not all the font information is accessible to applications. Apple 
GEOS, therefore, includes two routines for saving and restoring all the necessary font table 
information between its own variables and saveFontTab: 



♦ SaveFontData 


Save internal font data to saveFontTab. 


• RestoreFontData 


Restore internal font data from saveFontTab. 



An application should never return to MainLoop with valid data in the saveFontTab 
area^ecause MainLoop may use the saveFontTab area for its own purposes, thereby 
destroying any font information that may be saved there. Of course, the information in 
saveFontTab can always be copied to another buffer before giving MainLoop control. 

When GEOS runs a desk accessory, it saves off all the current font variables to a special area of 
memory. However, the temporal saveFontTab area is no(j;aved. If a desk accessory uses 
menus, the menu routines will use the area at saveFontTab, thereby overwriting any saved data. 
Since the saveFontTab area is not saved in die context switch between the application and the 
desk accessory, it will come back with incorrect data. It is, therefore, the desk accessory's job to 
save and restore the data at saveFontTab if necessary. 



21 



Text, Fonts, and Keyboard Input 



Keyboard Input 

Many keyboard input needs can be accomodated through normal processing with GetString and 
through dialog boxes with DBGETSTRING, but many specialized functions require servicing 
keypresses directly. The application might want to implement shortcut keys — special key 
combinations that allow quick access t& menu items or other functions — or an application, such as 
a word processor, might need to do dynamic text formatting as characters are typed. 

Key-scan Conversion 

The internal code that the computer hardware returns for each keypress usually reflects the position 
of the key on the keyboard, not the actual character on the keycap. GEOS pre-processes all 
keypresses, ignoring some and translating others. For most keys, the keyp ress is translated into 
the GEOS ASCII character code equivalent: [a] translates to 97, [SHIFT] + [a] translates to 65, 
and [RETURN] translates to CR. These keys can go directly to GEOS text routines wihtout any 
further work. However, there are some key combinations that get translated outside of the printable 
character range (codes between and 32), and the application will need to filter these out. 



Note: Apple GEOS input drivers and aux-drivers both have the opportunity to preprocess or 
translate keypresses before they undergo the standard GEOS translation. For more 
information, refer to KeyFilter and AuxDKeyFilter in the Routine Reference 
Section. 



If the shortcut key (designated by the Commodore logo on CBM computers and the filled Apple 
logo on Apple computers) is pressed in combination with another key, the high-bit (bit 7) of the 
keypress byte will be set. This means, for example, that [SHORTCUT] + [a] is equivalent to 

.byte (SHORTCUT I 'aM 



How GEOS Handles Keypresses 

At interrupt level, GEOS scans the keyboard looking for a key presses and releases. If a new key 
has been pressed or an old key has been held down long enough to begin auto-repeating, GEOS 
places the corresponding character code for the key at the end of the keyboard queue. The 
keyboard queue is a circular FIFO (first-in, first-out) buffer that holds keypresses. A queue is used 
because many typists can, at times, type keys faster than the application can process them. If there 
was no key buffer, keypresses would be lost. As long as there are characters in in the keyboard 
queue, the KEYPRESS^BIT of pressFlag is set. 

On each pass through MainLoop, GEOS checks the KEYPRESS^BIT of pressFIag. If the 
bit is set, GEOS removes the oldest keypress from the queue, places it in the global variable 
keyData, and attempts to vector through keyVector. keyVector usually contains a $0000, 
which causes GEOS to ignore the vector and, hence, ignore the keypress. As long as keyVector 
is $0000, keypresses will continue to accumulate in die queue at interrupt level and be ignored, one 
at a time, at MainLoop level. 

By placing the address of a key-handling routine in keyVector^ the application can be called off 
of MainLoop to process keypresses as they become available. When the application's key handler 
gets called, it merely picks up the key code from keyData, does any necessary processing, and 
returns to MainLoop with an rts when done. 



22 



Fonts, and Keyboard Input 



With this technique, though, the application can only process one keypress on each pass through 
MainLoop, even though the keyboard queue may have more than one character in it. This is 
typically not a problem because the overhead most applications need to handle a character is 
minimal. But take geoWrite, for example. If only one character could be processed at a time, it 
might need to print, word- wrap, and scroll for each character. Even a medium speed typist could 
get far ahead of the screen updating. If there was a way to get at all the keypresses in the queue at 
once, then all the calculating and screen manipulations could be done for more than one character 
on each pass through MainLoop. GEOS offers a routine to do just this: 



I • GetNextChar Retrieve the next character from the keyboard queue!* 



J 



GetNextChar gets the keycode of the next available character from the keyboard queue and 
returns it in the accumulator. If there are no more characters available, GetNextChar returns a 
NULL. To retrieve all the queued keypresses, an application can call GetNextChar in a loop, 
transferring all queued characters to its own buffer. This buffer must be at least KEY_QUEUE 
bytes long so that it won't be overflowed. 



Example: 



KeyHandler 

Sample key handler. Stuff address of this routine into 
keyVector. Unloads the keyboard queue into an internal 
buffer but does nothing with the characters. 



KeyHandler : 
Idx 
Ida 
sta 



#0 

keyData 
newKeys, X 



10$: 



php 
sei 

inx 
jsr 
sta 
cmp 
bne 

pip 



GetNextChar 
newKeys, X 
#NULL 
10$ 



; start at beginning of internal buffer 
;get first keypress 
; store it in my buffer 

;lock out interrupts for a moement 
;so we don't get any new keypresses 

/point to next position in buffer 
;get another character 
;put it in our buffer 
;was that the last 
;loop back to get more 

; restore interrupt disable status 



/All new keys are now in our buffer. Our buffer is conveniently 
/null-terminated because the last character we set down was a 
/NULL. Neat, huh? 

jsr DoNewKeys /go process the keys we picked up 



99$: 

rts 

.ramsect 

newKeys: .block KEY_QUEUE+1 

.psect 



/return to MainLoop 
?max queue size + NULL 



DoNewKeys 

A do-nothing routine that just pretends to empty our own 



23 



Text, Fonts, and Keyboard Input 



; keyboard buffer. 

DoNewKeys : 

Idx #$00 ; start at beginning of buffer 

10$: 

Ida newKeys,x ;get a key 

beq 20$ -/exit loop if it's the null 

nop ;do nothing with this keypress 

inx /point to next position 

bne 10$ /always branch (X should never go to 0) 

20$: 

•We've encountered the NULL and therefore gone through the entire 
/string. Clear the buffer by storing the null in the first 
/position of the string, 
sta newKeys+0 

99$: 

rts /exit 



Ignoring Keys While Menus are Down 

Becuase MainLoop is still running full-speed when menus are down, keyVector will still ber 
vectored through on a regular basis. The application may want to postpone any text output or 
keypress interpretation when menus are down. Checking for this case is simple: 

Ida menuNumber [ /check current menu level 

bne 99$ I- ^ /leave if any menus are down 

Implementing Shortcuts 

Shortcut keys are a common user-interface facility found in GEOS applications. Briefly, a shortcut 
key is a key combination that allows the quick selection of a menu item or function in the 
application. Typically shortcuts are distinguished from other keypresses by pressing the shortcut 
key (the Commodore logo or the filled Apple logo) while typing another key. Key combinations 
that include the shortcut key will have the high-bit set, which maJkes them easy to recognize. Even 
if an application is not using shortcuts, it will most likely want to at least filter out all shortcut keys. 

To process shortcut keys, the normal key handler (the one the application installs into keyVector) 
should first check the high-bit of the keypress and branch to the shortcut key handler if the bit is 
set: 



KeyHandle: 








Ida 


menuNumber 


/check current menu level 




bne 


99$ 


^ . /ignore keys while menus 




Ida 


keyData 


rrTget the keypress 




bmi 


10$ 


/was it a shortcut? 




jsr 


NormalKey 


/no, process normally 




bra 


99$ 


/exit 


10$: 










jsr 


ShortKey 


/yes, process as a shortcut 


99$: 


rts 




/exit 



The shortcut key handler will need to decide what to do based on the key that was pressed Usually 
the shortcut bit (bit 7) will be removed, the character will then be converted to uppercase, and the 
resulting character code will be used to search through a table of valid shortcut keys. If the 
particular shortcut key is not supported, the handler just returns, ignoring the keypress. If the key 
is implemented, the handler needs to call an appropriate subroutine to process the shortcut key: 



24 



Fonts, and Keyboard Input 



/Shortcut key handler. Call with keycode in A-register 
ShortKey : 

;Do some minor conversion on the keycode 
and #-SHORTCUT 
cmp # • a ' 

bit 10$ 
cmp #'z'+l 
bge 10$ 
sec 

she #('a'-»A') 



/lop off shortcut bit 
/check if lowercase 
/branch if less than "a" 
/or greater than "2" — ^ 



/it's lowercase: convert to upper 
/by subtracting the ASCII difference—^ 
/between a lowercase 'a' and an 
/uppercase 'A' 



10$: 

/Now that we have a shortcut key, we go searching through 

/a table of valid shortcut keys, looking for a match. Use Y-reg 

/to index so we can use X-reg later for CallRoutine. 



20$: 



Idy 

cmp 
beq 
dey 
bpl 



bmi 



#NUM__SHORTCUTS 

shortcuts, y 
30$ 

20$ 



99$ 



/start at top of table 

/check for a keycode match 
/branch if found 
/else, try next 
/loop until done. NOTE: must 
/not have more than 127 shortcuts 
/or this branch will fail! 
/no match, ignore this key 



30$: 

/We've found a match. Get the corresponding routine address from 

/the Jump table and call the routine 

Idx h__shortCutTbl, y /get high address of routine 

Ida l__shortCutTbl, y /and low address 

jsr CallRoutine /call the routine 



99$: 



rts 



/ exit 



/Table of shortcut keys and their corresponding routines 



/Valid shortcut keys 






shortcuts: 








.byte 


•0' 


/I 


undo 


.byte 


1 fj* t 


/2 


text 


.byte 


.p. 


/3 


print 


.byte 


«Q« 


/4 


quit 


.byte 


ijjt 


;5 


new document 


.byte 


•G' 


/6 


goto page 


.byte 


•B* 


/7 


boldface toggle 


.byte 


•0' 


/8 


outline toggle 


.byte 


'I' 


/9 


italic toggle 


.byte 


•U' 


/lO 


underline toggle 


.byte 


•D' 


/II 


delete 


.byte 


•c 


/12 


copy 


.byte 


•S' 


/13 


scroll 


.byte 




/14 


load document 


NUM_SHORTCUTS 


ss= { -k _ 


shortcuts 


- 1) /numbe 


.if (NUM__SHORTCUTS 


> 127) 




.echo 


WARNING: 


too many 


shortcuts 



.endif 



25 



Text, Fonts, and Keyboard Input 



; Table of low bytes of shortcut routine 
1 shortCutTbl: 



.byte 


[DoUndo , 


' 1 


. byte 


[DoText , 


' 2 


. byte 


luorrmt , 


• 3 


• byte 


lUOUUxt , 


A 

H 


. byte 


(DoNew , 


' 5 


• byte 


lL/0(jOt , 1 


» c 
o 


.byte 


[DoBoldface , 


7 


.byte 


[DoOutline , 


8 


.byte 


[Doltalic 


9 


.byte 


(DoUnderline , 


•10 


.byte 


IDoDelete , 


•11 


.byte 


(DoCopy , 


•12 


.byte 


[DoScroll t 


•13 


.byte 


[DoLoad t 


•14 



; Table of high bytes of shortcut routine 
h ShortCutTbl: 



.byte 


] DoUndo 


;1 


.byte 


] DoText 


;2 


.byte 


IDoPrint 


;3 


.byte 


IDoQuit 


;4 


.byte 


] DoNew 


;5 


.byte 


]DoGoto 


;6 


.byte 


3 DoBoldface 


;7 


.byte 


] DoOutline. 


;8 


.byte 


] Doltalic 


;9 


.byte 


] DoUnderline 


;io 


.byte 


] DoDelete 


;11 


.byte 


] DoCopy 


;12 


.byte 


] DoScroll 


;13 


.byte 


] DoLoad 


;14 



The Text Entry Prompt 

Whenever an application will be accepting text input, it is a good idea to offer a prompt, or cursor, 
to mark the point at which text will appear. GEOS offers three routines for automatically 
configuring sprite #1 to act as a text entry prompt: 



• InitTextPrompt 


Initialize sprite #1 for use as a text prompt. 


• PromptOn 


Turn on the prompt (show the text cursor on the screen). 


• PromptOff 


Turn off the prompt (remove the text cursor from the screen). 



The prompt automatically flashes on the screen without disrupting the display and can be resized 
to reflect die point size of a particular font 



26 



Fonts, and Keyboard Input 



Important: Interrupts should always be disabled and alphaFlag should be cleared when 
PromptOff is called. The following subroutine illustrates the proper use of 
PromptOff: 

KillPrompt : 

php /save i status 

sei > /disable interrupts 

jsr PromptOff /prompt « off 

LoadB alphaFlag, #0 — ^lear alpha flag ^ 

pip /restore i status 

rts /exit 



Sample Keyboard Entry Routine 

As an example, we will use some of the concepts covered in this chapter in real-world code. The 
following routine will patch into key Vector and output text as keys are pressed: 



/*** CONSTANTS *** 
TXT_LEFT ==10 

TXT_RIGHT == (SC_PIX_WIDTH - TXT_LEFT) 

TXT_TOP ==20 

TXT__BOT == (SC PIX HEIGHT - TXT TOP) 



/text (x,y) starting position 
TXT_X ==20 
TXT_Y ==50 

/size of the text buffer 
TXTBUFSIZE == $200 



/text left margin 

/text right margin 

/text top margin 

/text bottom margin 



/1/2K is far more than enough for ^ 
/now. To accept multiple lines, 
/the buffer will need to grow 



/Characters to accept before buffer overflow fault 
MAX CHARS 30 



if 

Start Text : 

Initializes the text input process by loading the proper 
vectors, setting flags, etc. Wedges Keyin into keyVector to 
intercept keypresses and output them to a single line. 

Pass: nothing 

Returns: text input routine in keyVector 

Destroys: ? 

endif 



StartText: 

/Send our text output to both screens 

LoadB textDispBufOn,#(ST_WR_FORE | ST WR BACK) 



27 



Text, Fonts, and Keyboard Input 



/Install our character handler 

LoadW keyVector, #KeyIn /keypresses vector thru here 

LoadW stringFaultVec,#TextFault /and string faults here 

/Install the system font and clear all text attributes 
jsr UseSystemFont- 
Ida #PLAINTEXT 
jsr PutChar 

/Set the left and right margins 

LoadW leftMargin, #TXT_LEFT 
LoadW rightMargin,#TXT_RIGHT 

/Set the top and bottom margins 
LoadW windowTop, #TXT_TOP 
LoadW windowBottom,TXT_BOT 

/Set the text starting position 
LoadW stringX, #TXT_X 
LoadB stringy, #TXT__Y 

/Initialize the prompt 

Ida currentHeight 
jsr InitTextPrompt 
jsr PromptOn 

/Point at the start of the line buffer 

LoadW txtBuf ,#bigTextBuffer /where to start 

LoadB txtBuf Index, #0 /index from start 

/Max number of characters to accept 
LoadB txtlnMax, #MAX_CHARS 

/And where control goes if we go over... 
LoadW bufFaultVec,#Buf Overflow 

/Turn text on • 
LoadB textOn, #TRUE 

/Exit 

rts 

.ramsect 

/Buffer that will hold all the text we enter. We let the key input 
/routine build it up a line at a time by passing 

bigTextBuf fer: .block TXTBDFSIZE 

textDispBufOn: .block 1 /holds dispBufferOn value for text 

txtlnMax: .block 1 /number of characters that will 

/generate buffer overflow fault 
textOn: .block 1 /text is ON flag. (TRUE « ON) 

.if ((* & $ff) $ff) /if indirect jump vector straddles a page 

.block 1 /boundary, fix it to compensate for a bug 

.endif /in the 6502 architecture ^ 
bufFaultVec .block 2 

.psect 

★★*************************************************************** 

KeyIn: 

When a key is pressed, control comes here off of MainLoop 



28 



Fonts, and Keyboard Input 



Keyin: 



10$: 
99$: 



Ida menuNuiTiber 

bne 99$ 

Ida keyData 

brr.i 10$ 

jsr Norrr.alKey 

bra 99$ 

jsr ShortKey 

rts 



; check current menu level 
/ignore keys while menus down 
;get the keypress 
;w'as it a shortcut? 
/no, process normally 
/exit 

/yes, process as a shortcut 
/exit 



/ShortKey: 

/Control comes here when shortcut keys are pressed 



ShortKey: 
rts 



/no shortcut key handler now. just ignore keypress. 



.**★*★«********«*★****«★**«♦«**** *«******************************* 

/NormalKey : 

/Control comes here when non-shortcut keys are pressed 



SPACE 



32 



/first printable character code 



NormalKey: 

/Return immediately if text is off 
Ida textOn 



bne 
rts 



5$ 



/branch if text on 



5$: 



jsr 



KillPrompt 



/turn the prompt off 



/Save the current value of dispBufferOn and load up the correct 
/value for text output. 

PushB dispBufferOn 

MoveB textDispBuf On, dispBufferOn 



/Load the current cursor position into the PutChar position 
/registers, just in case we need to use them later. 



MoveW stringX,rll 

Ida stringY 
clc 

adc baselineOf f set 

sta rlH 



/X printing position 
/convert y cursor position to 
/baseline position 

/y printing position 



/Process the character 

Ida keyData 
cmp #SPACE 
bge 4 0$ 



/get the keypress again 

/cmp with first printable char 

/branch if printable 



/Check the control character against a table of special action 
/keys. Use Y-reg to index so we can use X-reg later for 



29 



Text, Fonts, and Keyboard Input 



;CallRoutine . 
Idy 

20$: 

cmp 
beq 
dey • 
bpl 



bmi 



#NUM_CTRL ; start at top of table 

i 

ctrlKeys,y /check for a keycode match 

30$ ;branch if key matches table entry 

;else, try next ' 
20$ ;loop until done. NOTE: must not 

./have more than 127 special keys 

/or this branch will fail! 
88$ /no match was found, ignore this key 



30$: 

/We've found a match on a 
/routine address from the 
Idx . h__CtrlTbl,y 
Ida l_CtrlTbl,y 
jsr CallRoutine 
bra 88$ 

4 0$: 

/It's a normal alphanumeric 
/screen and save it in the t 
pha 



control character. Get the corresponding 
jump table and call the routine 

/get high address of routine 
/and low address 
/call the routine 
/go clean up and exit 



Idy 
sta 
iny 
Ida 
sta 
sty 
pla 



Dsr 

MoveW 

Ida 

cmp 

bit 

Ida 

Idx 

jsr 

88$: 

/Clean up 
Ida 
beq 
jsr 



txtBuf Index 
(txtBuf ) ,y 

#NULL 
(txtBuf) ,y 
txtBuf Index 



99$: 



PopB 
rts 



PutChar 
rll, stringX 
txtBuf Index 
txtlnMax 
88$ 

bufFaultVec 

bufFaultVec+1 

CallRoutine 



textOn 
99$ 

Prompt On 



dispBuf ferOn 



character. Output it to the 
ext buffer 

save the character code 
pointer into current text buffer 
place the character into the buffer 
point to next position in buffer 
and null-terminate the string 

set down the new index value 
get the character code back. (Note: 
we could have pulled it off of 
keyData, but future versions may 
pre-process or translate the char 
code in the A-reg before passing) 
print it on the screen 
update the prompt X-position 
was that the last character we 
can accept? 
OK if under max. 
otherwise, call buffer overflow 
routine 



/only re-enable the prompt if text 
/is still on (might have changed!) 
/turn the prompt back on 



/restore dispBufferOn 
/ Exit 



Table of control keys and their corresponding routines 



/Valid control keys 

ctrlKeys : 

.byte CR 
.byte BACKSPACE 
.byte KEY_DELETE 
.-byte KEY INSERT 



1 Carriage return 

2 backspace 

3 ditto 

4 ditto 



30 



Fonts, and Keyboard Input 



.byte KEY__RIGKT ;5 ditto 

NUM_CTRL == (* - ctrlKeys - 1) ; number of control keys 

.if (NUM__CTRL > 127) 

.echo WARNING: too many control keys 

.encif 

; Table of low bytes of control key routine addresses 



l_CtrlTbl: 

.byte [DoReturn ;1 

.byte ' ' (DoBackSpace ;2 

.byte [DoBackSpace ;3 

.byte (DoBackSpace ;4 

.byte [DoBackSpace ;5 



; Table of high bytes of control key routine addresses 
h__CtrlTbl: 

.byte ] DoReturn 

.byte ] DoBackSpace 

.byte ] DoBackSpace 

.byte ) DoBackSpace 

.byte ) DoBackSpace 

; Exit 

rts 

. ramsect 
tempDisp: .block 1 

sysKeySave: .block 2 

.psect 

.**«««**«★***★***★★★★★*★**★★★★★★******★★****«********************* 

;KillPrompt: 

/Proper way to use PromptOff. Disable interrupts and 

/clears alphaFlag. • 

t 



KillPrompt : 

php /save i status 

sei /disable interrupts 

jsr PromptOff /prompt « off 

LoadB alphaFlag, #0 /clear alpha flag 

pip /restore i status 

rts /exit 



/DoReturn: 

/Process a carriage return 
J 

.★***«*****★★****★★★*★**★*★*********★*★*****★*******★***★★ 

DoReturn : 

/No real carriage return handler, yet. Just shut text off 
LoadB textOn, #FALSE / 

rts / . . . 

.*******★*********★*★★★****★*****«*******★***********★*★*★★*** 

/DoBackSpace: 
» 

/Process a- backspace 



/temporary hold for dispBufferOn 
/holds address of system key routine 



31 



Text, Fonts, and Keyboard input 



DoDoBackspace: 



Idy 


txtBuf Index 


;get ptr into current text buffer 


beq 


99$ 


;if no characters in buffer, exit 


dey 




/back up a character 


sty 


txtBuf Index 


7 and make the new index permanent 


Ida 


(txtBuf ) ,y 


;get the character we want to delete 


jsr 


EraseCharacter 


/and remove it from the screen 


Idy 


txtBuf Index 


/get the index to the character we 


Ida 


#NULL 


/we just deleted and make it the 


sta 


(txtBuf ),y 


/ null-terminator 


MoveW 


rll, stringX 


/update the cursor's x-position 


rts 




/exit 



'k**'kit*ie**'k-kitit'k1r-teicie-te1e*ieieif*ie1eieieie*ic1iitirieielrieicie*** 

EraseCharacter: 



Physically remove a character from 

.if (C64 II C128) /This routine 
EraseCharacter : 



10$: 



.endif 



MoveW 


rll,r4 


Idx 


currentMode 


jsr 


GetRealSize 


sta 


r3L 


Ida 


rlH 


sec 




sbc 


r3L 


sta 


r2L 


txa 




clc 




adc 


r2L 


sta 


r2H 


sty 


r3L 


sec 




sbc 


rllL 


sta 


r3L 


Idy 


rllH 


bcs 


10$ 


dey 




sty 


r3H 


jsr 


Rectangle 


rts 





the screen 

is in the Apple GEOS jump table 

/current X is rectangle's right edge 

/get the mode we're in 

/go calc the size of the character 

/set down baseline offset 

/calc top of character by subtracting 

/baseline offset from y-position 

/and making top edge of rectangle 
/add char height to top edge 
/to calc bottom edge 

/and make bottom of rectangle 

/set down width so we can subtract it 

/from the current x-position to 

/find the character's starting 

/position 

/subtract one from hi if borrow 



/make left edge of rectangle 
/erase in current pattern 
/exit 



Buf Over flow: 

What to do if the buffer hits its maximum. 



BufOverflow: 

/No real overflow handler, yet. Just shut text off 
LoadB textOn,#FALSE / 
rts 



/Text Fault: 



32 



Fonts, and Keyboard Input 



; string faults come here. 

************************************************** 

TextFault : 

/No real text fault handler, yet. Just shut text off 
LoadB textOn, #FALSE 

rts ; 



33 



MainLoop and Interrupt Level: a Technical Breakdown 

MainLoop and Interrupt Level: a 
Technical Breakdown 

The GEOS Kemal operates on two distinct levels: MainLoop Level and Interrupt Level. MainLoop 
Level is characterized by the GEOS MainLoop — a never-ending loop at the heart of GEOS that 
routes events to the application. Whenever the application does not have control, MainLoop 
usually does. 

But there is also Interrupt Level. Periodically (usually every l/60th of a second) the computer 
hardware temporarily interrupts the microprocessor. The processor may be in the middle of 
MainLoop, deep within a GEOS routine, or somewhere in the applcation. Either way, the 6502 
immediately suspends whatever it is doing and passes control to the GEOS Interrupt Level. 
Interrupt Level scans the keyboard circuitry, moves the mouse pointer, flashes the text prompt, 
decrements timers, and performs other low-level tasks. Interrupt Level operates independently of 
MainLoop and ensures that certain things get done on a regular basis. When the Interrupt Level 
processing is complete, control returns to the point where the original interrupt occurred. 

Whatever GEOS does at Interrupt Level is mostly transparent to the application. Only when an 
application strays from the beaten path will it need to worry about the specifics of Interrupt Level 
processing. 

This is a technical discussion of MainLoop and Interrupt Level. For a more general 
discussion, refer to Chapter @GEOSAPPS@. 

MainLoop Level 

When GEOS starts an application, it first initializes the operating system and then jsr's to the 
application's start address. The application is expected to perform its basic startup procedures, 
such as initializing its menus, icons, and processes, and the return immediately with an rts. This 
rts will place GEOS at the beginning of MainLoop. MainLoop is primarily a small, endless 
loop of function calls: 

MainLoop Service Routines 

MainLoop itself is rather short. The meat of its function is hidden in the various service routines 
that it calls. Because these service routines interact direcdy with the application, it is useful to 
understand the specific conditions that affect their operation. The pseudo-code diagrams at the end 
of this chapter illustrate the operation of the more important service routines. 

Patching Into MainLoop 

Although most applications can function entirely off of events, some may find the need to install 
their own service routine direcdy off of MainLoop. GEOS has a single vector for tiiis purpose: 
appIicationMain, which usually contains $0000 and is therefore unused. By placing a routine 
address into this vector, GEOS will call through tiiis vector every pass through MainLoop. To 
remove tills call, tfie application can again store $0000 into the vector. 



1 



MainLoop and Interrupt Level: a Technical Breakdown 



The Basics of Interrupt Level 

Interrupt Level is primarily responsible for maintaining the interactive and time-based apsects of 
GEOS. Interrupt Level updates the mouse state and the mouse cursor position, watches for double- 
clicks, decrements process and sleep timers, gets keyboard input, flashes the prompt, and 
generates a new random number every vblank, among other (more obscure) tasks. 

The Vertical Blank Interrupt 

The Interrupt Level interrupt is tied directly to the video circuitry. In order to keep the screen 
phosphors glowing, the image must be redrawn, or refreshed, many times per second. Each 
complete coverage of the picture tube is called 2i frame, and the rate at which frames are drawn is 
cailtdthtframe rate or refresh rate. 

At the end of each frame, the electron beam is switched off and returned to the upper left comer of 
the picture tube to begin drawing again. This period when the beam is off is called the vertical 
blank, or vblank. Every vblank, the IRQ (Interrupt ReQuest) line on the 6502 is pulled low. If the 
interrupt disable bit in the status register is clear (asit usually should be), an interrupt is generated. 
This interrupt is often called the vblank interrupt. ^EOS uses the vblank interrupt as the basis for 
its Interrupt Level processing. 

The vblank interrupt, along with the scanning of the video frame, occurs in a precisely timed 
sequence: 60 times per second on NTSC monitors (the United States standard) and 50 times per 
second on PAL monitors (the European standard).The GEOS FRAME^RATE constant reflects 
the number of frames per second (either 50 or 60) depending on the state of the PAL and NTSC 
constants. 

How to Disable Interrupts 

Because the vblank interupt is an IRQ (Interrupt ReQuest), the 6502 has the option of ingoring the 
request. To disable IRQ interrupts, an application need only set the interrupt disable bit in the 
6502*s status register using the sei (SEt Interrupt disable bit) instruction. Because GEOS depends 
on Interrupt Level executing on a timely basis, an application should disable interrupts only when 
absolutely needs to and then only for short periods of time. If an interupt occurs while the 
interrupt-disable bit is set, the interrupt will not be serviced. If too many interrupts are missed, 
much of the real-time features of GEdS — the mouse pointer, processes, double click detection, 
etc. — will become sluggish. 

In conventional 6502 programming, it is standard practice to surround blocks of interupt-sensitive 
code with an sei-cli sequence: an initial sei to disable interrupts and an ending cli to reenable 
interrupts. This, however, is not a totally safe practice because the cli always reenables interrupts 
regardless of their original state. If interrupts were originally disabled, the cli may inadvertently 
reenable them. As applications get large, it becomes easier to embed these interrupt disable/enable 
sequences deep within subroutines. If one subroutine disables interrupts then calls another 
subroutine that then performs a cli (returning with interrupts enabled when they shouldn't be), the 
results may be a disasterous bug. 

It is good to practice a littie defensive coding and get into the habit of saving the interupt status 
when disabling them around blocks of code. The following sequence works well: 

php ;save current interrupt disable status 

sei /disable interupts 

; (interrupt-sensitive code goes here) 



2 



MainLoop and Interrupt Level: a Technical Breakdown 



pip 



/restore old interrupt status 



This php-sei-pip method will save, set, and then restore the interrupt disable bit. This way 
interrupts won't be inadvertently reenabled when they're expected to be disabled. 

Apple GEOS Interrupts 

Unlike the Commodore computers, the Apple He does not generate its own vblank IRQ interrupts. 
This function is usually provided by external hardware plugged into slot 7: the Apple mouse card 
or the Berkeley Softworks IRQ Management Card. If neither of these devices is present and there 
is no other interrupt source, Apple GEOS will generate software interrupts. 

Apple Software Interrupts 

GEOS may occasionally be run on systems with no interrupt source. This is an unfortunate 
situation because GEOS depends heavily on interrupt processing. GEOS will recognize this 
configuration and generate software interrupts during MainLoop by calling IrqMiddle. With 
applications that don't have time-consuming event routines hanging off of MainLoop, Interrupt 
L^vel processing will occur often enough to make the system usable. If system degradation is too 
great, an application can simulate its own software interrupts as necessary. For more information, 
refer to IrqMiddle in the Routine Reference Section. 

Example: 



DoSoftlnts 

Description: Simulate vblank interrupts under Apple GEOS when no interrupt source is 
present. 

Pass: nothing 

Destroys: a,x,y 



DoSoftlnts: 
bit 
bne 
php 
sei 
Jsr 
pip 

10$: 



intSource 
10$ 



IrqMiddle 



; check interrupt source 
;exit if hardware interrupt source 
;else, generate soft interrupt 
/disable interrupts (just in case) 
/software interrupt now! 
/restore old interrupt status 



The Apple GEOS Interrupt Management Card 

The Berkeley Softworks JRQfManagement card requires reenabling after every interrupt in order to 
generate next interrupt. Part of the Apple Interrupt Level processing reenables the IRQ G enei aio i^ 
card to interrupt on the next vblank. Normally this will keep interrupts triggering on a regular 
basis. 



^miSrd^r 



However, if the«Q44anagemem^ard generates an interupt while the 6502 interrupt disable bit is 
set, the interrupt service routine will not run, and the IRQ Management card will never be 
reenabled for the next interrupt 



Co, 

ho 



MainLoop and Interrupt Level: a Technical Breakdown 



Apple GEOS attempts to keep interrupts running by reenabling the IRQ Management card during 
MainLoop and whenever a call through the jump table switches banks. Normally applications 
will do this often enough in their normal operation to reenable the IRQ Management card ron a 
regular basis. It is conceivable, however, that in some very odd cases neither of these 
circumstances will occur often enough (very odd cases, indeed — if an application is both disabling 
interrupts and not going back to MainLoop, there is probably something fundamentally wrong 
with the structure of the program). An application can reenable the IRQ Management cardwhen 
necessary with the following sequence: 

bit intSource 

bvc 5$ 

St a IRQ__GEN 

5$: 



; check the interrupt source 
/ignore if not BSW card IRQ Manager 
/otherwise, trigger IRQ Manager 



J 



Important Things to Know About Interrupt Level 

The vblank interrupt service routine is one of the most complex aspects of GEOS. Fortunately, 
most applications will need to know little more about the Interupt Level process than its basic 
functionioning. However, there are some unavoidable conflicts between Interupt Level and 
normal, mainstream processing, and these are important to know. 

Two-byte Variables 

During non-interrupt level processing, it is important to disable interrupts before referencing a 
word value that might get changed at Interrupt Level or changing a word value that might get 
referenced at Interupt Level. A two-byte quantity requires two memory accesses, and there is a 
small chance that an interrupt may occur after the first byte has been accessed but before the second 
byte has been accessed. This can result in a situation where a word value has the high-byte of one 
number and the low- byte of another. Take for example the variable mouseXPos, which is 
modified at Interrupt Level. The seemingly innocent code fragment below illustrates the problem: 

MoveW mouseXPos, oldX /update our old mouse x-position with current mouse x 

Which exands to the following at assembly time: 

Ida mouseXPos /update our old mouse x-position with current mouse 

sta oldX 

Ida mouseXPos+1 

sta oldX+1 

If an interrupt occurs between the Ida mouseXPos and the subsequent Ida mouseXPos+1, 
the result word result stored in oldX may be entirely wrong. The solution is to temporarily disable 
interrupts around the access: 

php ; disable interrupts around access 

sei ; 

MoveW mouseXPos, oldX /update our old mouse x-position with current mouse x 

pip ; restore old interrupt status 

Be aware, though, that the php-sei-pip sequence has its own set of ideosyncracies: the pip 
restores the entire status register, not just the interrupt disable bit, thereby overwriting any new 
condition codes. Therefore, disabling as in 

php ; disable interrupts around compare 

sei ; 



4 



MainLoop and Interrupt Level: a Technical Breakdown 



CmpW mouseXPos, oldX /compare current X with Old X 

pip '/restore interrupts 

would defeat the whole purpose of the CmpW. In such cases, the condition codes can, of course, 
be tested before the pip. A better solution, however, would disable interrupts, shadow the word 
value to a temporary variable, restore the interrupt disable status, then do all checking against this 
temporary value, which won't get changed by Interrupt Level. 

Example: 



/Check if mouse is within the left and right text margin 
IsMselnMargins: 



10$: 

20$: 
99$: 



php 
sei 

MoveW mouseXPos,rO 
pip 



CmpW 
bge 
Ida 
beq 

CmpW 
ble 
Ida 
beq 

Ida 

rts 



rO, leftMargin 
10$ 

#FALSE 
99$ 

rO, rightMargin 

20$: 

#FALSE 

99$ 

#TRUE 



disable interrupts around mouseXPos access 
and copy current pos to a working location 

restore interrupts 



/check left margin 
/branch if inside left 
/else, flag fault 
/branch always to exit 

/check right margin 
/branch if inside right 
/else, flag fault 
/branch always to exit 

/no fault (inside text margins) 

/exit 



Word variables to be careful with include mouseXPos, mouseLeft, mouseRight, 
intTop Vector, and intBot Vector, all of which are either read or written to by Interrupt level. 



The Decimal Mode Flag 

GEOS adopts the convention that the normal operating state of the computer has decimal mode 
disabled. Any routine that enables decimal mode must also disable it Versions of GEOS 64 prior 
to V 1.2 do not disable decimal mode during interrupt level processing. If operating under one of 
these versions, it is necessary to disable intemipts prior to using the decimal mode flag. 



Patching Into Interrupt Level 

Very few applications will need access to the system at Interrupt Level. Most tasks that would 
traditionally require the use of a time-based interrupt can be handled deftly enough with GEOS 
processes. If an application can drive itself entirely off of MainLoop events, it should. The world 
of Interrupt Level is a delicate one; it is very easy to disrupt the entire system by doing the wrong 
thing during Interrupt Level. With that said, though, GEOS provides two vectors that allow an 
application that knows what it's doing to tap directly into Interrupt Level: intTopVector and 
intBotVector. 

As illustrated in the Interrupt Level pseudo-code at the end of this chapter, control passes through 
these two vectors at different points in the intermipt process. intTopVector allows the 
application to patch in before most of the Interrupt Level processing has occurred and 
intBotVector allows the application to patch in after most of the Interrupt Level processing has 
occurred. 



5 



MainLoop and Interrupt Level: a Technical Breakdown 



Important: The application should always disable interrupts before loading a new address into 
either intTopVector or intBot Vector. The program will very likely crash if this 
precaution is not taken. 



( 



System Use of intTopVector and intBotVector 

GEOS 64 and GEOS 128 use intTopVector to point to InterruptMain, a vital function of the 
Commodore GEOS Interrupt Level, whereas Apple GEOS does not use either of these vectors. 
The application can use either intTopVector or intBotVector under Apple GEOS without any 
worry. However, under Commodore GEOS, an application that uses intTopVector should call 
the address that was originally in intTopVector when it is done.This will ensure that the 
Commodore GEOS InterruptMain will be executed properly. 

Example: 

; Install our interrupt routine into intTopVector 
Installint : 

php /disable interrupts 

sei 

MoveW intTopVector, oldTopVector ;save address of current routine 
LoadW intTopVector, #MyIntRout /install our interrupt routine 

pip /restore interrupts 

rts 

/Remove our interrupt routine from intTopVector, replacing it with old. 
Removeint 

php /disable interrupts 

sei 

MoveW oldTopVect or, intTopVector /restore old routine 
pip /restore interrupts 

rts 



/My interrupt service routine 
MylntRout : 

Ida OldTopVect or 

Idx oldTopVector+1 
jmp CallRoutine 



/nothing to do yet... 
/exit by vectoring through 
/old interrupt routine 
/let it rts. . . 



Guidlines for Interrupt Level Routines 

There are a few general guidelines for any routine that patches into Interrupt Level: 

• Keep the routines short Interrupt level is not the place for time-consuming code. 

• Stay away from GEOS. Some routines will work correctly at interrupt level and other 
won't. Even worse, the ones that won't work might only show this trait after your 
product has been released and in the hands of users for months. (It is O.K., though, to 
use CallRoutine, as many of the examples in this chapter illustrate.) 

• Never clear the interrupt disable bit 

Following these guidelines will keep your Interrupt Level routines as innocuous as possible. 



6 



MalnLoop and Interrupt Level: a Technical Breakdown 



Interrupt Level Pseudo-Code 

The following pseudo-code diagrams illustrate the general Interrupt Level constructs in each of the 
three systems (GEOS 64, GEOS 128, Apple GEOS). This information can be crucial when trying 
to track down a subtle interaction between the various levels of GEOS. 

GEOS 64 and GEOS 128 Interrupt Level 

CBMInterruptLevel: 
{ 

/ • Context Save: 

Save out any information about the system configuration that we might destroy V 
Save6502Regs(); r save the status of the A. X, Y. and S registers V 

SaveGEOSRegsQ; /* save r0-r15 and a few internal variables*/ 

SaveCBMState(); /* save state of Commodore memory banks V 

SetlOInO; /* set RAM 1 and I/O registers in. Much of Kernal 

is now inaccessibieV 

DblClicksO; T decrement dblClickCount if non-zero V 

if (GEOS128) 

{ DoMouse(); r GEOS 128 updates mouse here V 

DoSetMouseO; /*and also calls SetMouse in mouse driver. SetMouse 

doesn't exists in GEOS 64 input drivers.*/ 

} 

DoKeyboardO; r scan the keyboard and add a char to the queue if key pressed V 

DoAlarmSndO; r update timer for alarm sound duration */ 

/ * Application can patch into the following two vectors. The application's routine should 
always end by indirectly calling the routine whose address was originally installed in 
the vector. Use CallRoutine in the Kernal (it's bank is in) in case the pointer is $0000. 
* / 

Calllndirect(intTopVector) /* call indirectly through intTopVector. On the C64/128, this 

points to InterruptMain. */ 
Calllndirect(intBotVector) /* call indirectly through intBotVector. This is usually 

$0000, which Calllndirect ignores. */ 

/* Context Res^re: S>^i//?/D 
AP5/t>^<:©avB otrt-atTyinformation about the system configuration that we^ might doot fof^/ 



RestoreCBMStateO 
RestoreGEOSRegsO 
Restore6502Regs() 



r put memory banks back as they were */ 

r restore r0-r15, etc.*/ 

r restore A, X, Y, and S registers */ 

ReturnFromlRQO; T pick up where we left off */ 

) 



7 



MainLoop and Interrupt Level: a Technical Breakdown 



GEOS 64 and GEOS 128 interruptMain 



InteruptMain: 

Called through intTopVector under GEOS 64/128. This is *VERY* different from 
InterruptMain under Apple GEOS! 



InterruptMain: 
{ 

if (GEOS64) 
{ DoMouseQ; 
} 

UpdateProcessesO; 

UpdateSleepsO; 

UpdatePromptO; 

GetNewRandomO; 

ReturnO; 



/ * GEOS 64 updates mouse here */ 

/ * Update the process timers */ 

/ • Update the sleep timers */ 

/ • Flash/Update the text prompt V 

/ * jsr GetRandom in Kernal V 



8 



MalnLoop and Interrupt Level: a Technical Breakdown 



Apple GEOS Interrupt Level 

ApplelnterruptLevel: 
{ 

/ * Context Save: 

Save out any information about the system configuration that we might destroy V 
Save6502Regs(); /* save the status of the A, X, Y, and S registers V 

SaveAppleStateO; r save state of Apple memory banks V 

/* Set memory configuration to normal/default state V 

RamReadOffO; 

RamWriteOffO; 

Page20ff(); 

AltZPOffO; 

IrqMiddleO; I* main IRQ processing V 

/ * Context Restore: 

Save out any information about the system configuration that we might destroy V 

Restore AppleStateO; /* put memory banks back as they were V 

Restore6502Regs(); /* restore A. X, Y. and S registers V 

ReturnFromlRQO; /* pick up where we left off V 



9 



MainLoop and Interrupt Level: a Technical Breakdown 

Apple GEOS IrqMiddle 



IrqMiddle (APPLE VERSION). 

This is *VERY* different from InterruptMain under CBM GEOS! 
This is where software generated interrupts are sent. 

* / 

IntorruptMa io: 
{ 

SaveGEOSRegsO; /* save r0-r15 and a few internal variables*/ 

/ * Application can patch into the following vector to get control before most of the 

Interrupt Level processing has occurred. */ 
Calllndirect(intTopVector) /* call indirectly through intTopVector. On the Apple this 

defaults to $0000, which Calllndirect ignores V 

/ * Apple GEOS draws the mouse cursor (soft sprite #0) at interrupt level so that it can 
minimize flicker by avoiding the raster beam. However, because diffent interrupt 
sources (mouse vs. BSW IRQ Generator) pull the IRQ line low at different times in the 
Vblank sequence, the sprite is either drawn earlier or later depending on its position 
on the screen. */ 

if (intSource != BSWIRQ) /* if the BSW IRQ card generated the interrupt... V 
{ i f (mouseYPos < 40) ^ if mouse is at the top of the screen... V 
{ doMouseLater = TRUE /* then avoid the beam by drawing it later V 

} 

else 

{ AppleSoftMouseServiceO; /* else, draw it now.V 
} 

} 

DblClicksO; /* decrement dblClickCount if non-zero V 

DoMouseO; / * update mouse now V 

/ • Turn on aux. memory and give the clock driver control V 

RamReadOnO; /* switch auxiliary memory in V 
RamWrtOnO; 

ReadClocklntO; ^ call to aux. memory jump table for clock driver V 

RamReadOff(); r put main memory back in^ V 

RamWrtOffO; 

DoKeyboardO; /* scan the keyboard and add a char to the queue if key pressed V 
UpdateProcessesO; / * Update the process timers V 

UpdateSleepsO; / * Update the sleep timers V 

UpdatePromptO; / * Flash/Update the text prompt V 

GetNewRandomO; / * jsr GetRandom in Kernal V 

/ * Call the auxiliary device driver interrupt code*/ 
AuxDIntO; 

/ * Application can patch into the following vector to get control after most of the 
Interrupt Level processing has occurred. */ 



1 



MainLoop and Interrupt Level: a Technical Breakdown 



Calllndirect(intBotVector) /* call indirectly through intBotVector. This is usually 

$0000, which Calllndirect ignores. V 

/* if the BSW IRQ card generated the interrupt and we haven't done the mouse yet... V 

if ({intSource BSWIRQ) && (doMouseLater == TRUE)) 

{ AppleSoftMouseServiceO; r then draw the mouse now V 

) 

RestoreGEOSRegsQ; /* restore r0-r15, etc. V 

ReturnO; 

} 



1 1 



MainLoop and interrupt Level: a Technical Breakdown 

UpdateProcesses 



UpdateProcesses: 
{ 

if (numProcesses > 0) / * Only' do this if there are processes in the table V 
{ 

for (EachProcess) /* go through each process in the table V 

{ 

if (Process != FROZEN) /* only if unfrozen... V 
{ DecrementTimer(); I* count down one tick V 

if (Timer ==0) T if timer timed-out 

{ Process = RUNABLE; /* make it runable V 

ResetTimerO; /* and reset the counter */ 

} 

} 

} 

} 

ReturnO; 

} 

UpdateSleeps 

UpdateSleeps: 
{ 

if (numSleeping > 0) / * Only do this if there routines are sleeping */ 

{ 

for (EachSleeping) /* go through each sleeping routine */ 
{ . 

if (SleepTimer /* if counter not zero, then still asleep! */ 

{ Decrement ; ; /* so count down one tick V 

} 

} 

} 

} 



1 2 



MainLoop and Interrupt Level: a Technical Breakdown 



UpdatePrompt 

UpdatePrompt: 
{ 

if (alphaFlag(BIT7) ==1) / * prompt enabled if hi-bit of alphaFlag set */ 

{ 

Decrement AlphaFlagTimerO; /* d®c timer in lower 6 bits of alphaFlag V 
if ((alphaFlag&$3f) == 0) /* if time to change prompt state V 

{ 

r Toggle the state of the prompt V 

if (PromptState ON) /* bit 6 of alphaFlag = 1 V 

{ PromptOffO; 

} 

else 

{ PromptOnO; 
} 

} 

ReturnO; 

} 

DoMouse 



DoMouse: 
{ 

UpdateMouseO; / * call input device driver for new positioning V 

if (mouseOn(MOUSEON_BIT) == 1) r\\ mouse is on... V 
{ 

FaultCheckO; r check for faults V 

r Commodore machines draw the mouse here, Apples don't V 
if(GEOS64||GEOS128) /* if CBM machine... V 

{ 

DrawSprite(mousePicture) r copy mouse picture into sprite data tableV 

PosSprite{mouseXpox.mouseYpos) /* position the sprite V 

if (GEOS64) / * if GEOS 64... V 

{ EnablSprite(MOUSE) r always enable the sprite each time "I 

} 

} 

ReturnO; 



1 3 



MainLoop and Interrupt Level: a Technical Breakdown 



AppleSoftMouseService 

/* Routine to move/draw the mouse (sprite #0) during interrupt level on the Apple. 
GEOS 128 soft-sprite handler does a similar update during MainLoop.*/ 

AppleSoftMouseService: 
{ 

r Only draw the mouse if sprite #0 is enabled and mouse is not temporarily off V 

if ( (mobenble(BIT_0) == 1) && (offFlag(BIT_7) == 0) 

{ 

/* OK to update the mouse, only erase if not yet erased V 
if ( offFlag(BIT_6) == 0) ) /* if mouse not yet erased... V 
{ 

/* Has the mouse moved since last time? Only erase if no movement V 
if ( ( lastYPos I = (mouseYPos) ) || 

( lastXPos 1= (mouseXPos) ) ) 

{ 

EraseSoftMouse(lastXPos,lastYPos); /* erase if mouse moved V 

} 

} 

offFlag a FALSE; T flag: mouse is on and drawn V 

/* make current position the old position for erasure next time around */ 
lastYPos = mouseYPos; 
( ^ lastXPos = mouseXPos; 

DrawSoftMouse(mouseXPos,mouseYpos); /* draw at new position V 

) 

ReturnO; 

} 



1 4 



MainLoop and Interrupt Level: a Technical Breakdown 



FaultCheck 



FaultCheck: 
{ 

/* Check mouse against left constraint and left screen edge*/ 
if {(mouseXPos < mouseLeft) || (nnouseXPos < 0)) 

{ mouseXPos = mouseLeft; /* force mouse to constraint*/ 

faultData(OFFLEFT_BIT) = 1; /* show left fault */ 

} 

/* Check mouse against right constraint and right screen edge*/ 
if ((mouseXPos > mouseRight) || (mouseXPos > SC_PIX_WIDTH-1)) 
{ mouseXPos = mouseRight; /* stop mouse at edge */ 

faultData(OFFRIGHT_BIT) = 1 ; /* show right fault */ 

} 

r Check mouse against top constraint and top screen edge*/ 
if ((mouseYPos < mouseTop) || (mouseYPos < 0)) 
{ mouseYPos = mouseTop; /* stop mouse at edge */ 

faultData(OFFTOP_BIT) = 1; /* show top fault */ 

} 

/* Check mouse against bottom constraint and bottom screen edge*/ 
if ((mouseYPos > mouseBottom) || (mouseYPos > SC_PIX_HEIGHT-1)) 
( mouseYPos = mouseBottom; /* stop mouse at edge */ 

faultData(OFFBOTTOM_BIT) = 1; /* show bottom fault */ 

} 

« 

if (mouseOn(MENUON_BIT) ==1) /* if menus on. see if mouse is off current menu */ 
{ 

i f ( (mouseYPos < menuTop) || 

(mouseYPos > menuBottom) || 

(mouseXPos < menuLeft) || 

(mouseXPos > menuRight) 
) /* if mouse outside any menu edge... */ 

{ faultData(OFFMENU_BIT) = 1; /* show menu fault */ 
} 

} 

ReturnO; 

1 



MainLoop and Interrupt Level: a Technical Breakdown 



MainLoop Level Pseudo-Code 

The following pseudo-code diagrams illustrate the general MainLoop Level constructs in each of 
the three systems (GEOS 64, GEOS 128, Apple GEOS). This pseudo-code is useful for 
determining exacdy how icons, menus, and other event-generating mechanisms interact with your 
application. 

MainLoop 



MainLoop: 
{ 



while (TRUE) 
{ 

if (APPLE) 

{ if (offFlag(BIT7) == 1) 
{ offFlag = $40; 

} 

} 



r This loop is never ending */ 



/• Apple specific */ 

/* If mouse cursor was turned off... */ 

/* Turn it back on now that weVe in MainLoop V 



KeyboardServiceO; 

ProcessServiceO; 

SleepServiceO; 

if (APPLE) 



{ 



r service keyboard and related MainLoop functions V 
/* service processes V 

/• service sleeping routines */ 

/* Apple differs here, too*/ 

r let aux driver's MainLoop routine do what it needs to V 
r Get clock driver to set the time and date variables V 



AuxDMainO; 
ReadClockO; 

AppleTimeServiceO; /* service the apple time V 

if (intSource == Software) /* if generating software interrupts... V 
{ 



} 

} 

else 
{ 



InterruptMainO; 



} 



CBMTimeServiceO; 



/* simulate interrupts V 



/• service the Commodore time V 



Calllndirect(applicationMain); / * Call any application code that NEEDS to be handled 

Every MainLoop V 

} /• endwhile V 



1 6 



MainLoop and Interrupt Level: a Technical Breakdown 



KeyboardService 

KeyboardService: 
{ 

If (C128 II APPLE) r GEOS 128 and Apple GEOS handle sprites here V 
{ SoftSprHandlerO; 

} 

r RUN THROUGH THE BITS IN PRESSFU\G AND DISPATCH AS NECESSARY. 
THESE DISPATCHES GO THROUGH VECTORS THAT TYPICALLY DEFAULT TO 
GEOS ROUTINES FOR HANDLING THE VARIOUS USER-INPUTS V 

/* input device changed vector (currently unused by GEOS) V 
if (pressFlag(INPUT_BIT) ==1) r if input device changed V 
{ 

pressFlag(INPUT.BIT) = 0) /* clear flag V 

Calllndirect(inputVector) r and go through vector «$0000»V 

} 

r state of mouse changed vector (mouse moved; state of button changed) 

mouseVector usually points to an internal GEOS routine SystemMouseService()*/ 
if (pressFlag(MOUSE_BIT) ==1) /* if mouse state changed... */ 
{ 

pressFlag(MOUSE_BIT) = 0) /* clear flag V 

Calllndirect(mouseVector) /* and go through vector «SystemMouseService»*/ 



/* keyboard character ready 

keyVector defaults to $0000. V 
if (pressFlag(KEYPRESS_BIT) 1) /* if key in queue... V 
{ 

keyData = GetCharFromQueue(); /* get keypress */ 

if (QUEUE_EMPTY) /* if no more keys in the queue... V 

{ 

pressFlag(KEYPRESS_BIT) = 0); /* clear flag V 

} 

Calllndirect(keyVector) r go through vector «$0000»V 



r any mouse faults since last time? 

mouseFaultVec usually points to an internal GEOS routine SystemFaultServiceQV 
if (faultData 1= 0) /* if any faults... V 

{ 

Calllndirect(mouseFaultVec); /* go through vector «SystemFaultService»V 
faultData = 0; /* and clear faults afterward V 

} 

ReturnO; 



MainLoop and Interrupt Level: a Technical Breakdown 

ProcessService 



ProcessService: 
{ 

if (numProcesses > 0) / * If no processes, ignore V 
{ 

for (EachProcess) /* go through each process in the table. 

(start with last in table & work backward) V 

{ 

if ((Process == (RUNABLE & -BLOCKED)) /* only if runable & not blocked V 
{ Process -RUNNABLE; r clear runable flag V 

ProcessEventO; /• and generate a process event by calling the 

routine in the table. */ 

} 

} 

} 

ReturnO; 



SleepService 



SleepService: 
{ 

if (numSleeping > 0) 
{ 

for (EachSleeping) 



if (SleepTimer = 0) 
{ 

RemoveSleepO; 
WakeUpO; 

} 

} 

} 

ReturnO; 

} 



/ * If no slee;. -^-^cs V 

r go through eacn .. .^i^s in the table. 

(start with last in table & work backward) */ 

/* if counter zero, then time to awake! */ 

/* remove this sleeper from the internal list V 
r and go wake it up*/ 



1 8 



MainLoop and Interrupt Level: a Technical Breakdown 



SytemMouseService 



SleepService: 
{ 

if ( mouseData(BIT_7) == DOWN ) /* if mouse button down (bit == 0)... V 
{ 

if ( mouseOn(MOUSEON_BIT) ==1 ) T if mouse checking is on... V 
{ 

if ( mouseOn(MENUON_BIT) ==1) /* if menus scanning is on... V 
{ 

/* Check if the mouse is within the currently active menu (level 0/mairi) V 
i f ( (mouseYPos > menuTop) && 

(mouseYPos < menuBottom) && 

(mouseXPos > menuLeft) && 

(mouseXPos < menuRight) ) 



MenuServiceO; /* mouse was pressed on menu, go handle it V 

ReturnO; /* Return without checking icons V 



} 

/* Not on a menu, see if press was on an icon V 

if ( mouseOn(ICONSON_BIT) ==1) /* if icon scanning is on... V 

{ 

r search through the icon table looking for a match */ 

for (Eachlcon) 

{ 

if (icon(OFFJ_PIC) != $0000) / * if icon not disabled... V 
{ 

if (MouseOnlconO TRUE) /* if mouse on top of this icon... V 
{ 

r flash or invert icon as necessary V 
if (iconSelFlag(ST_FLASH_BIT)) /* flash icon? V 
{ InvertlconO; /* invert once V 

Sleep(selectionFlash); /* sleep awhile V 

InvertlconO; /* invert back again V 

) 

else if (iconSleFlag(STJNVERT_BIT)) r invert icon? V 
{ InvertlconO; /* just invert */ 

) 

/* check for double click V 

if (DBL^CLICK) /* if this is the second click of a dbl click...*/ 
{ rOH = TRUE; /* set double click flag V 

} 

else / • else, set single click flag *. 

{ rOH = FALSE; 

} 

r call the icon event routine*/ 

rOL s icon; /* tell event routine which icon V 

Calllndirect(icon(OFFJ_EVENT)); /* generate an event */ 



1 9 



MainLoop and Interrupt Level: a Technical Breakdown 

Re .. n{); /* break out of the for loop (check no more icons!) V 

} 

} 

} 

} 

} 

} 

/* If we got here, the following is true: 

1 ) mouse button was released (as opposed to pressed) 
- or - 

2 ) mouse was pressed, but not on an icon nor on a menu 

V 

Calllndirect(otherPressVec); T it's an "other" press., "other" as in something the 

system doesn't really care about */ 



20 



MainLoop and Interrupt Level: a Technical Breakdown 



SytemFaultService 

SystemFaultService: 
{ 

f only deal with faults if the mouse is on, menu scanning is enabled, and we've got a 

submenu down... */ 
if ( (mouseOn(MOUSEON_BIT) == 1) && (mouseOn(MENUON_BIT) ==!)&& 

(menuNumber > 0) } 

{ 

if (menuType == CONSTRAINED) 
{ 

/* for constrained menus... */ 

/* If mouse faulted off the top of a vertical menu or off the left of a horizontal 
menu, then we go to the previous menu. Otherwise, the fault is ignored because 
the menu is constrained */ 

if ( (menuType == VERTICAL && faultData(OFFTOP_BIT) == TRUE) || 

(menuType == HORIZONTAL && faultData(OFFLEFT_BIT) == TRUE) ) 

{ 

DoPreviousMenuQ; 

} 

} 

else r menuType == UNCONSTRAINED V 
{ 

DoPreviousMenuO; / * always try to go to the previous menu. If mouse didn't 

move onto the previous menu, then next pass through 
mainloop will see this as a fiault and try to remove 
that menu, and so on until we're back to the main menu 

* / 

} 

ReturnO; 

} 



21 



Alphabetical Listing of 

Routines 



AllocateBlock 



lAllocateBlock (Apple, C64, cm) 



mid-level disk 



Function: 
Parameters: 



Uses: 



Returns: 



Alters: 



Destroys: 



Allocate a disk block, marking it as in use, 
CommcxiQrg: 

r6L track number of block (byte). 
r6H sector number of block (byte). 

Apple: 

r6 block number (word). 
curDrive 



Commodore: 
curDirHead 
dir2Headt 
dirSHeadt 

Apple: 

curVBlknot 

VBMchangedt 

numVBMBlkst 



this buffer must contain the current directory header. 
(BAM for 1571 and 1581 drives only) 
(BAM for 1581 drive only) 



used by VBM cacheing routines, 
used by VBM cacheing routines, 
used by VBM cacheing routines. 



^used internally by GEOS disk routines; applications generally don't use. 



r6 

Apple: 
c 



error ($00 = no error); Commodore only: returns BAD_BAM if block 

already allocated. 

unchanged. 



carry flag is set if block is already in use. 



Commodorg: 
curDirHead 
dir2Headt 
dirSHeadt 

Apple: 

curVBIknot 
VBMchanged^ 



BAM updated to reflect newly allocated block. 
(BAM for 1571 and 1581 drives only) 
(BAM for 1581 drive only) 



used by VBM cacheing routines. 

set to TRUE by VBM cacheing routines to indicate cached 
VBM block has changed and needs to be flushed 



^used internally by GEOS disk routines; applications generally don't use. 
a, y, r7, r8H. 



Description: AllocateBlock allocates a single block on this disk by setting the appropriate 
flag in the allocation map (the BAM on Commodore computers and the VBM on 
Apple computers). 



AllocateBlock 



Commodore: If the sector is already allocated then a BAD_BAM error is returned. 

AllocateBlock does not automatically write out tEe BAM. See PutDirHead 
for more information on writing out the BAM. 

The Commodore 1541 device drivers do not have a jump table entry for 
AllocateBlock. All other device drivers, however, do. The following 
subroutine will properly allocate a block on any device, including the 1 54 1 . 



NewAllocateBlock — allocate specific block in BAM 
with any CBM GEOS device driver. 

Pass: r6L,r6H track, sector to allocate 

Uses: BAM in curDirHead 

Returns: x error status ($00 = success, BAD_BAM 
block already in use, etc.) 

Destroys: a,y, r7,r8H 

****************************************************** 

.if (C64 I I C128) 
NewAllocateBlock : 



Idy curDrive 

Ida driveType-8,y 

and #$0f 

cmp #DRV_1571 

bcc 1541$ 

jmp AllocateBlock 



1541$: 



jsr 
beq 

Ida 
eor 
and 

sta 
Idx 
dec 
Idx 
rts 



FindBAMBit 
110$ 

rSH 
#$ff 

curDirHead, x 

curDirHead, X 
r7H 

curDirHead, x 
#$00 



get current drive 

get drive type 

keep only drive format 

see if 1571 or above 

branch if 1541 

else, use driver routine 



get BAM bit info 
if zero, then it's not free 
otherwise, it's free... 
get bit mask for BAM 
convert to clearing mask 
and with BAM byte to clear 

bit and show as allocated 
and store back, 
get base of track's entry 
dec # free blocks this track 
show no error 
exit 



Apple: 



110$: 

Idx 
rts 
.endif 



*BAD BAM 



show error 
exit 



already in use 



Apple GEOS did not include AllocateBlock in its jump table until version 2.1. 
The following patch places the entry into the jump table, thereby allowing 
applications to call AllocateBlock under version 2.0 (which was the first 
version of Apple GEOS). 



.if (APPLE) 

LowSwitch = $fcl6 

o_AllocateBlock « $45cl 

JMPABS = $4c 

VER_2 = $20 



; direct entries into Kernal; do not use 

; except for authorized patches 

; JMP absolute opcode 

; version 2.0 



PatchAllocateBlock : 



2 



AllocateBlock 



Ida 


version ; 


get Kernal version number 


cmp 


#VER_2_0 ; 


check against version 2.0 


bne 


99$ ; 


if not v2.0, then no patch necessary 


Ida 


#JMPABS , 


store jmp LowSwitch into main 


sta 


AllocateBlock , 


jump table 


Ida 


#(LowSwitch , 




sta 


AllocateBlock+1 , 




Ida 


#]LowSwitch , 




sta 


AllocateBlock +2 




sta 


RAMWRT_ON 


; switch in aux bank 


Ida 


#JMPABS 


? store jmp o__AllocateBlock into aux 


sta 


AllocateBlock 


; jump table 


Ida 


# [o_AllocateBlock 




sta 


AllocateBlock+1 




Ida 


# ] o_AllocateBlock 




sta 


AllocateBlock+2 




sta 


RAMWRT_OFF 


; switch back to main bank 


99$: rts 




; exit 


.endif ; (APPLE) 





Example: 



MoveW 


DiskBlock, r6 


i 


block to allocate 


.if (C64 1 1 


C128) 






jsr 


NewAllocateBlock 




(see above) 


cpx 


#BAD_BAM 




BAD_BAM means block in use 


beq 


200$ 




branch if block already in use 


txa 






check for other error 


beq 


150$ 




branch if no error 


jmp 


MyDiskError 




call error handler with error in 


.else / (APPLE) 






jsr 


AllocateBlock 




Allocate the block 


php 




! 


save status of allocation 


txa 




r 


get error status 


beq 


100$ 


f 


branch if no error 


pip 




! 


error: fix stack 


jmp 


MyDiskError 


f 


call error handler with error in 


100$: 








pip 






restore status of allocation 


bcs 


200$ 


! 


branch if block already in use 



.endif 



150$: ; block was free and is now allocated 
; code to handle new block goes here 

200$: ; block is not free... 

/ code to handle block already . allocted goes here 

MyDiskError: / error occurred... 
; code to handle disk errors goes here 

.ramsect 

DiskBlock .block 2 ; disk block to allocate 

.psect 



See also: SetNextFree, BlkAlIoc, FreeBlock. 



3 



AppendRecord 



AppendRecord (Apple, C64, cns) 



VLIR disk 



Function: Adds an empty record after the current record in the index table, moving all 
subsequent records down one slot to make roonx 



Parameters: none. 
Uses: 



Returns: 
Alters: 



Destroys: 
Description: 



curDrive 
nieWrittent 

curRecord 
fileHeader 

Commodore: 

curType 

curDirHead 

dirlHeadt 

dirSHeadt 

Apple: 

curVBlknot 

VBMchangedt 

numVBMBlkst 



if FALSE, assumes record just opened (or updated) and 

reads B AWVBM into memory. 

current record pointer 

VLIR index table stored in this buffer. 



GEOS 64 v1 ,3 and later: for detecting REU shadowing, 
current dirtciovy header/BAM. 
(BAM for 1571 and 1581 drives only) 
(BAM for 1581 drive only) 



used by VBM cacheing routines, 
used by VBM cacheing routines, 
used by VBM cacheing routines. 



^used internally by GEOS disk routines; applications generally don't use. 
X error ($00 = no error). 



curRecord 

usedRecords 

fileWrittent 

fileHeader 

Commodore: 
curDirHead 



new record becomes the current record, 
incremented by one. 

set to TRUE to indicate die file has been altered since last 
updated. 

new record added to index table. 



directory header read in if file Written is FALSE on call. 
^used internally by GEOS disk routines; applications generally don't use. 
a, y, rOL, rlL, r4. 

AppendRecord inserts an empty VLIR record following the current record in 
the index table of an open VLIR file, moving all subsequent records down in the 
record list. The new record becomes the current record. A VLIR file can have a 
up to MAX_VLIR RECS records (127 on the Commodore and 254 on the 
Apple). If adding a record exceeds this value, then an OUT^OF^RECORDS 
error is returned. 

A record added with AppendRecord occupies no disk space until data is written 
to it. The new record is marked as empty in the VLIR index table. (When a VLIR 
file is first created by SaveFile, all records are marked as unused). Some 
applications call AppendRecord repeatedly after creating a new file until an 



4 



AppendRecord 



Note: 



Apple: 



CBM: 



OUT_OF_RECORDS error is retumed This marks all the records as used and 
prepares tfiem to accept data with calls to WriteRecord. 

AppendRecord does not write the VLIR index table out to the disk. Call 
CioseRecordFile or UpdateRecordFiIe to save the index table when all 
modifications are complete. 

An empty record is marked with $ffff in the VLIR index table (stored in the buffer 
at fileHeader). An unused record is marked with $0000. Use PointRecord to 
check the status of a particular record (unused, empty, or filled). 

An empty record is marked with $ffOO in the VLIR index table (stored in the 
buffer at fileHeader). An unused record is marked with $0000. Use 
PointRecord to check the status of a particular record (unused, empty, or 
fiUed). 



Example: 



SaveRecord: 
LoadW 
jsr 
txa 
bne 
Ida 
jsr 
txa 
bne 
jsr 
LoadW 
LoadW 
jsr 
txa 
bne 
jsr 



rO, IFilename 
OpenRecordFile 

99$ 

appendPoint 
PointRecord 

99$ 

AppendRecord 
r7, #BufStart 
r2, #BUFLENGTH 
WriteRecord 

99$ 

CioseRecordFile 



99$: 



rts 



pointer to filename 
open VLIR file 
check open status 
exit on error 
get record to append to 
go to that record 
check point status 
exit on error 

ajppend a record at this point 
point at data buffer 
bytes in buffer (bufEnd-buf Start) 
write buffer to record 
get write status 
exit on error 
close VLIR file 

; return with any error in x 



.ramsect 

appendPoint : 

Filename: 

BufStart 

BUFLENGTH 

.psect 



.block 1 

.block NAME_LENGTH+1 

.block 1024 

o (* - bufStart)+l 



record to append to 

holds null-terminated filename 

data buffer 

length of buffer 



See also: 



InsertRecord, DeleteRecord, PointRecord. 



5 



AuxDExit 



AuxDExit (Apple) 



aux driver! 



Function: 



De-install and remove the current aux driver. 



Parameters: none. 

Returns: a bit 7 set if reinitialization required. 
Destroys: assume x, y, r0-rl5. 

Description: The GEOS deskTop calls AuxDExit prior to loading a new aux driver. This 
allows the current aux driver to deinstall itself properly, removing any hooks it 
may have placed into the operating system. A RAMdisk aux driver, for example, 
would need to remove itself from the device table before it can be replaced. The 
GEOS deskTop and the Configure utility, for example, will call AuxDExit prior 
to replacing the current auxiliary driver. 

If bit 7 of a is set on return, then this indicates that the device table has changed 
and a reset is in order. The deskTop, for example, will reinitialize itself if bit 7 is 
set. This is equivalent to choosing RESET from the options menu. 



Example: 



SAMPLE AuxDExit ROUTINE *** 

o AuxDExit — Deinstall RamFactor Auxiliary driver 



Synopsis : 



Called by: 
Pass : 

Returns: X 
A 



Before loading another aux driver, control vectors 
through the AuxDExit entry in the aux driver's jump 
table. This is the AuxDExit routine for the Ram Factor 
RAM disk driver. We leave the drive in the drive list 
but restore the original ProDOS vector. 

Aux driver jump table AuxDExit entry. 

Nothing 

error status (NOT_IMPLEMENTED is returned if unable to 
uninstall 

= for no RESET needed 
= $80 if reset needed 



AUXRESET 

AUXNORESET 

RamExit : 
Ida 
sta 
Idx 
jsr 
beq 
Idy 
Idx 



10$: 



jsr 



$80 



= $00 



#$ff 

DD_Command 
curDrive 
IsPatched 
110$ 

#AUXNORESET 
numD rive's 



IsPatched 



flag to force RESET function if we change 

the drive tables 

and for not resetting... 



Get current drive 

Check current drive against this driver 
Can't uninstall current drive, do error 
assume no reset necessary 
We're OK. go through each drive in the 
drive table and if it's a RAM factor, 
then restore the old vector 

see if this drive is patched 



6 



AuxDExit 



bne 
Idy 
Ida 
sta 
Ida 
sta 

dex 
bpl 

tya 
Idx 
rts 

Idx 
Ida 
rts 



IsPatched: 

Ida 
cmp 
bne 
Ida 
cmp 
rts 



20$: 



100$: 



110$: 



20$ 

#AUXRESET 
auxDevTabLo, x 
devTabLo, x 
auxDevTabHi, X 
devTabHi,x 



10$ 



#N0 ERROR 



#NOT_IMPLEMENTED 
#AUXNORESET 



devTabHi,x 

# ] PatchRamFactor 

20$ 

devTabLo, x 

# [PatchRamFactor 



if not, then skip it 

found a patched entry, enable RESET 

and put back the real entry point 



try next drive 

and loop until no more 

put RESET flag in accumulator 

and return no error 

exit 

return error 

no need to RESET 



Pass: device number in X 
Returns: result of compare in ST 
Check address of this aux patch 
against vector in device table for 
equality. 



exit 



7 



AuxDInt 



AuxDInt (Apple) 



aux 



driver 



Function: 



Aux driver Interrupt Level routine. 



Parameters: 



none. 



Returns: 



nothing. 



Destroys: assume a, x, y, r0-rl5. 

Description: Apple GEOS calls AuxDInt during Interrupt Level. This allows an aux driver to 



have routines that execute at Interrupt Level. With a hardware interrupt source, 
Interrupt Level will execute approximately every vertical blank (60 times per 
second). 

An aux driver that has no need for Interrupt Level processing should simply 
perform an rts. 



See also: 



AuxDMain. 



8 



AuxDKeyFilter 



AuxDKeyFilter (Apple) 



aux driver 



Function: 

Parameters: 
Returns: 



Description: 



Note: 



Aux-driver keypress filter; pre-processes keyboard input so aux driver may 
interpret special keystrokes. 



a 
a 



KEY — key as scanned from keyboard circuitry, 
translated character or NULL if filtering out 



Destroys: x, y 



An application does not call AuxDKeyFilter directly. The Apple GEOS 
keyboard scanning routine calls AuxDKeyFilter at Interrupt Level immediately 
after calling KeyFilter. This allows the aux driver to translate, remap, or filter- 
out certain keypresses. 

A typical AuxDKeyFilter routine compares the KEY parameter against a list of 
specific keypresses. If there is no match, then AuxDKeyFilter returns without 
altering the KEY code. If there is a match, AuxDKeyFilter can perform some 
action in response and return a different KEY value or a KEY value of NULL. 
(A KEY value of NULL effectively filters out the keypress because GEOS 
ignores the "null-key" value, never placing the key in the keyboard input queue.) 

UKEY is NULL when AuxDKeyFilter is called, then a key was pressed but it 
has already been processed by some other prior filter (most likeley KeyFilter) 
and should be ignored. 

The KEY parameter comes from the Apple hardware register KEYBD_DAT A. 
GEOS then sets high-bit is set to reflect the state of the Option or ll key 
(keyboards that have one, don't have the other). If bit 7 is set, then that key is 
pressed To detect the state of the C5 key, check the OPEN_APPLE hardware 
location. ~ 



Example: 



;Check for open-apple key 
bit OPEN_APPLE 
bmi OpenPressed 



; check open apple key status 
/branch if pressed 



*** SAMPLE AuxDKeyFilter ROUTINE *** 

o_AuxDKeyFilter — key filter routine for screen dump aux driver 

Synopsis: At each keypress, GEOS vectors through the aux driver's 

AuxDKeyFilter jump table entry which points here. 

Called by: AuxDKeyFilter entry in Aux driver's jump table. 

Pass: key in A 

Returns: key value unchanged or NULL if it's the key we're looking 

for 

MAGIC^KEY = ($80 I '!') /close-apple + shift + 1 



o_AuxDKeyFilter : 



9 



AuxDKeyFllter 



99$: 



cmp 
bne 
jsr 
Ida 

rts 



#MAGIC_KEy 
99$ 

DoDump 
#NULL 



check keypress against our 
if no match, then ignore 
else, do screen dump 
and return a null key 

exit 



DoDump: 

; code to handle screen dump goes here 



See also: 



KeyFilter. 



10 



AuxDMain 



AuxDMain (Apple) 



aux driver! 



Function : Aux driver MainLoop Level processing. 

Parameters: none. 

Returns: nothing. 

Destroys: assume a, x, y, r0-rl5. 

Description: Apple GEOS calls AuxDMain on every pass through MainLoop. This allows 
an aux driver to have MainLoop Level functions. 

An aux driver that has no need for MainLoop Level processing should simply 
rts. 



See also: 



AuxDInt. 



11 



BBMult 



BBMult (Apple, C64, C128) 



math 



Function: 
Parameters: 



Returns: 



Unsigned byte-by-byte multiply: multiplies two unsigned byte operands to 
produce an unsigned word result 

X OPERANDI — zero-page address of single-byte multiplicand in the 
low-byte of a word variable (byte pointer to a word variable). 

y 0PERAND2 — zero-page address of the byte multiplier (byte pointer to 
a byte variable). 

Note: result^ OPERANDI (byte) * 0PERAND2(byte). 

X, y, and byte pointed to by OPERANDI unchanged, 
word pointed to by OPERANDI contains the word result. 



Destroys: a, r7L, r8 



Description: 



Note: 



BBMult is an unsigned byte-by-byte multiplication routine that multiplies two 
bytes to produce a 16-bit word result (low/high order). The byte in OPERANDI 
is multiplied by the byte in OPERANDI and the result is stored as a word back in 
OPERANDI. Note ihoxOPERANDl starts out as a byte parameter but becomes a 
word result with the high-byte at OPERAND 

Because r7 and r8 are destroyed in the multiplication process, they cannot be 
used to hold either operand. 

No overflow can occur when multiplying two bytes becuase the result always fits 
inaword($ff*$ff = $fe01). 



Example: 



Multiply rlL by rlH and store the word result in r2 

MoveB rlL, r2L ; r2L <- rlL copy of OPERANDI 

• Idx #r2L / point to copy of OPERANDI (r2L) 

Idx #rlH ; point to 0PERAND2 (rlH) 

jsr BBMult ; r2 <- r2L * r2H do multiplication 



SeeAlso: 



BMult, DMult, Ddiv, DSdiv. 



12 



Bell (Apple) 



utili 



Function: 

Parameters: 

Returns: 

Destroys: 

Description: 

Note: 



Makes a brief beeping sound through the Apple's internal speaker, 
none, 
nothing. 

x,y 

Bell sounds a 1000 Hz signal through the Apple's internal speaker. The sound 
lasts approximately 1/1 0th of a second. 

Bell does not return until after the full duration of the sound. Interrupts are 
disabled during this period. The interrupt-disable status is restored when Bell 
returns. 

C64 & C128: The following routine provides a bell sound under Commodore GEOS. It is 
provided for portability. 

.if (064 I I C128) ; only for Commodore versions; use Kernal 

; routine on Applf. 

Bell — Make a bell sound on C64/128 

Author: Dan Kaufman (w Chris Hawley) 

(mgl) 

Pass: Nothing 
Return: Nothing 
Destroyed: a 

Synopsis: This routine allows you to have the c64 beep when the user 
makes a mistake or does something he shouldn't. 



sidBase 
voicelRegs 



« $D400 
sidBase 



f reqLol 


as 


voicelRegs 


freqHil 




voicelRegs+1 


PWLol 


rs 


voicelRegs+2 


PWHil 




voicelRegs+3 


controlRegl 




voicelRegs+4 


att_decl 




voicelRegs+5 


sus__rell 


ss 


voicelRegs+6 


FCLo 




voicelRegs+7+7+$7 


FCHi 




voicelRegs +7 +7 +$8 


res_filt 




voicelRegs+7+7+$9 


mode_vol 




voicelRegs+7+7+$A 


pulse 




%01000001 


SOUND ON 




$30 



Bell: 



PushB CPU_DATA 

LoadB CPU_DATA,#IO IN 



/switch to I/O space 



13 



Bell 



LoadB 


controlRegl, #0 


sta 


att__decl 


LoadB 


mode__vol, #$18 


LoadB 


sus_rell, #SOUND_ON 


LoadW 


PWLol,#$800 


LoadB 


FCLo,#0 


sta 


FCHi 


sta 


res__f ilt 


LoadB 


att_decl,#6 


LoadB 


sus__rell, #0 


LoadB 


freqLol,#$DF 


LoadB 


freqHil,#$25 


LoadB 


controlRegl, #puise 


PopB 


CPU__DATA 


rts 





/twiddle sound chip 



; return to memory space 



.endif ; (C64 I 1 C128) 



Example: 



r*** Beep three times *** 

r Runs off of MainLoop by using Sleep 



BELL_INTERVAL 


= (FRAME_ 


_RATE/10) 


approx 


1/10 second 


BeepThrice : 










jsr 


Bell 




• sound 


the bell 


LoadW 


rO, #BELL_ 


_INTERVAL 


' pause 


a bit 


jsr 


Sleep 








jsr 


Bell 




• sound 


the bell again 


LoadW 


rO,#BELL_ 


_INTERVAL 


• pause 


a bit 


jsr 


Sleep 








jmp 


Bell 




• sound 


the bell again 



14 



BitmapClip 



BitmapClip (Apple, C64, cns) 



graphics 



Function: Place a rectangular subset of a compacted bitmap on the screen. 



Parameters: 



Uses: 

Returns: 

Destroys: 

Description: 



rO DATA — pointer to the compacted bitmap data (word). 
rlL XPOS — X card position: pixeLposition /8 (byte). 
rlH Y — y-coordinate (byte). 

r2L W^WIDTH — clipping window width in cards: pixeLwidth/8 (byte). 

r2H W^HEIGHT — height in pixels of clipping window (byte). 

rllL DXl — delta-xl: offset of left edge of clipping window in cards from 

left edge of full bitmap (byte), 
r IIH DX2 — delta-x2: offset of right edge of clipping window in cards from 

right edge of full bitmap (byte). 
rl2 DYl — delta-yl: offset of top edge of clipping window in pixels from 

top edge of full bitmap (word). 

where the upper-left corner of the clipped bitmap (the window) is placed at 
(XP0S*8, Y). The lower-right corner is at ([XPOS*8]+[WJVIDTH*8], 
Y-^W^H EIGHT). 

dispBufferOn: 

bit 7 — write to foreground screen if set. 
bit 6 — write to background screen if set 

nothing. 

a, X, y, r0-rl2 

BitmapClip uncompacts a rectangular area of a full bitmap, clipping (ignoring) 
any data that exists ouside of the desired area. The rectangular subset is called the 
clipping window. 



15 



BitmapClip 



The following diagram illustrates the eight BitmapClip parameters: 

full compacted bitmap 



DYf 
(in pixels) 

W_HEIGH1 
(in pixels) 



Note: 



C128: 



Apple: 



clipping window, 





eight-pixel 
boundaries 



DX1 
(in cards) 



WJA/IDTH 
(in cards) 



DX2 
(in cards) 



No checks are made to determine if the data, dimensions, or positions are valid. 
Be careful to pass accurate values. Do not pass a value of $00 for either the 
WJWIDTH or WJiEIGHT parameters, and pay special attention to the fact that 
XPOS, WJWIDTH, DXl, and DX2 are specified in cards (groups of eight pixels 
horizontally), not in individual pixels. 

It may be helpful to think of DYl as the number of scanlines in the bitmap to skip 
initiallly, to think of W_H EIGHT as the number of scanlines to display, to think 
of DXl as the number of cards to skip at the beginning of each scanline, to think 
of W_WIDTH as the number of cards to display, and to think of DX2 as the 
number of bytes to skip at the end of each scanline. 

Under GEOS 128, OR'ing DOUBLE^B into the XPOS and W^WIDTH 
parameters automatically doubles the x-position and the width of the bitmap 
(respecitvely) when running in 80-column mode. 

BitmapClip in the first release of GEOS 128 does not call TempHideMouse 
to disable the sprites and does not properly double the width when drawing to the 
80-column screen. On Kemals where the release byte is greater than $01, these 
problems have been fixed 

DOUBLE__B may be OR'ed into the WJVIDTH parameter to double the bitmap 
width and INAUX_B may be OR'ed into the XPOS parameter to specify 
auxiliary memory. " 



16 



BitmapClip 



Example: 



************************************** 



Displaylmage 



Pass : 



Destroys : 



General purpose routine to display a portion of 
compacted bitmap image in a window 

pixBuf compacted bitmap image in pseudo-photoscrap 

format. Byte is card width of image. 
Byte 1 and 2 is the pixel height (word) . 
The compacted image data starts at byte 3. 
xOffset card index into bitmap to display 

yOffset pixel index into bitmap to display 

a,x, y, r0-rl2 



WINDOW__X = 4 

WINDOW_Y = 30 

WINDOW_WIDTH » 5 

WINDOW__HEIGHT « 60 

Displaylmage: 

Set up initial parameters **" 

LoadW rO,#PixImage 

LoadB rlL, #WINDOW__X 

LoadB rlH, #WINDOW__Y 

LoadB r2L, #WINDOW_WIDTH 

LoadB r2H, #WINDOW_HEIGHT 

MoveB xOffset^rllL 

MoveW yOffset,rl2 

;*** Clip to window *** 
Ida PixWidth 
sec 

sbc WINDOW__WIDTH 

— following line changed to 

— use zero-page copy 



10$: 



card x-position of window 
pixel y-position of window 
card width of window 
pixel height of window 



rO <- compacted picture data (DATA) 
rlL <- left edge of window (XPOS) 
rlH <- top edge of window (Y) 
r2L <- width of window (W_WIDTH) 
r2H <- height of window (W__HEIGHT) 
rllL <- X offset into bitmap (DX.l) 
rl2 <- y offset into bitmap (DYl) 



get bitmap width 
subtract window width 



sbc 


xOffset , 


? subtract x-index into bitmap 


sbc 


rllL 


? now we have the right edge clip distance 


sta 


rllH 


? rllH <- right edge clip (DX2) 


bpl 


10$ 


? if we're >0, branch to skip x clipping 


adc 


#WINDOW_WIDTH 


? add back the window width 


sta 


r2L 


; ma)ce that the new clip window 


LoadB 


rllH,#0 


? rllH <- $00 (fixes underflow of DX2) 


Ida 


PixHeight 


? subtract window height from bitmap height 


sec 




? (two byte subtractiqn) 


sbc 


#WINDOW_HEIGHT 




sta 


r3L 


; store intermediateresult in r3 


Ida 


PixHeight+1 




sbc 


#0 




sta 


r3H 




Ida 


r3L 


; now subtract y index into bitmap 


sec 






following line changed to 




use zero- 


page copy 




sbc 


yOf f set 




sbc 


rl2L 


; (rl2 = yOffset) 


sta 


r3L 




Ida 


r3H 




following 


line changed to 




use zero- 


page copy 




sbc 


yOf f set+1 





17 



BitmapClip 



20$: 
99$: 



ramsect 
f fset 
• set 

- .. ^ -dth 
Pixhaight 
Piximage 
.psect 



sbc 


rl2H 


sta 


r3H 


bpl 


20$ 


Ida 


r3L 


adc 


#WINDOW__HEIGHT 


sta 


r2H 


jsr 


BitmapClip 


rts 





.block 1 
.block 2 
.block $800 
PixBuf+0 
PixBuf+1 
PixBuf+3 



(rl2 = yOffset) 

value in r3H never used after this 
branch if no underflow 

correct for underflow 



display the bitmap with clipping 
exit 



.:d X index into bitmap (byte) 
i^xel y index into bitmap (word) 
2K picture buffer 
width of picture in cards (byte) 
height of picture in pixels (word) 
start of bitmap image 



18 



BitmapUp 



BitmapUp^ i BitmapUp (Apple, C64, ci28) 



graphics 



Function: 
Parameters: 



Place a compacted bitmap onto the screen. 



Uses: 

Returns: 
Destroys: 



Description: 



128: 



Normal: 
rO DATA 
rlL 



pointer to the compacted bitmap data (word). 
XPOS — X card coordinate: pixeLposition /8 (byte). 
Y — y-coordinate (byte). 
WIDTH — width in cards: pixeLwidth/8 (byte). 
HEIGHT — height in pixels (byte). 



rlH 
r2L 
r2H 

Inline: 

data appears immediately after the jsr i_BitmapUp 
.word DATA pointer to the compacted bitmap data, 
.byte XPOS x card position: pixeLposition /8. 
.byte Y y-coordinate. 
.byte WIDTH width in cards: pixeLwidth/8. 
.byte HEIGHT height in pixels. 

where the upper-left corner of the bitmap is placed at (XP0S*8,Y). The lower- 
right corner is at (XPOS*8+WIDTH^8,Y+HEIGHT). 

dispBufferOn: 

bit? — write to foreground screen if set. 
bit 6 — write to background screen if set 

nothing. 

Commodore: 
a, X, y, rO-r9L 

Apple; 

a, X, y, r0-r2 

BitmapUp uncompacts a GEOS compacted bitmap according to the width and 
height information and places it at the specified screen position. No checks are 
made to detemiine if the data, dimensions, or positions are valid, and bitmaps 
which exceed the screen edge will not be clipped. Be careful to pass accurate 
values. Do not pass a $00 for the WIDTH or the HEIGHT parameter, and pay 
special attention to the fact that both the x-position and the width are specified in 
cards (groups of eight pixels horizontally), not in pixels. 

Under GEOS 128, OR'ing DOUBLE^B into the XPOS and WIDTH parameters 
will automatically double the x-position and the width (respectively) in 80-column 
mode. The first release of GEOS 128 did not properly remove the sprites before 
placing the bitmap on the screen. The easiest way to correct for this is to always 
precede a call to BitmapUp with a call td TempHideMouse. The redundant 
call to TempHideMouse when running under later releases is minimal 
compared to the number of cycles it takes to decompact and draw the bitmap. 



jsr TempHideMouse ; correct for bug in release 1 of GEOS 128 

jsr BitmapUp ;then put up the bitmap 



19 



BitmapUp 
Apple: 



Example: 



See also: 



Under Apple GEOS, DOUBLE^B may be OR'ed into the WIDTH paramter to 

double the bitmap width and INAUX_B may be OR'ed into the XI parameter to f 

specify auxiliary memory. "" 



;Put a bitmap up from an address in 
/auxiliary memory and doubling the 



/picture ' s 


width. 




.if (APPLE) 






LoadW 


rO, #MyAuxBitmap 


/ rO <- aux address of bitmap 


LoadW 


rlL, #(MY_CXPOS|INAUX B) 


/ r3 <- card x-pos + in-aux 


LoadB 


rlH,#MY_YPOS 


/ rlH <-y-coordinate 


LoadB 


r2L, # (MY_CWIDTH 1 DOUBLE 1 W) 


/ r2L <- card width + double bit 


LoadB 


r2H,#MY_HEIGHT 


/ r2H <- height 


jsr 


BitmapUp 


/ put bitmap on screen 



.endif 



•k'kitlt'k-k'kic'klfk-tfk'k'k'k'ti-k 

*** ShowBitmap *** 
****************** 

For C64, C128, or Apple 
if (C128 && C64) 

.echo ShowBitmap cannot assemble for both C64 and C128 at the same time 
endif 



BM_XPOS 
BM_YPOS 

Bitmap; 



(32/8) 
20 



/card x-pos it ion of bitmap 
/y-position of bitmap 



BMJWIDTH 
BM HEOIT 



- PicW 

- PicH 



ShowBitmap: 



Ida 


#(STjm_FORE 1 ST_WRjaACK) , 


> use both screens 


sta 


dispBufferOn i 




.if (C128) 




' bug fix for 128 release 1 


jsr 


TenpHideMouse < 


remove sprites 


•endif 






jsr 


i^BitmpUp , 


* inline bitmap call 


•word 


Bitmap ^ 


♦bitmap address 


.byte 


(BM XPOSI (DOUBIf: B&(!APPLE*- 


-1))); *xpos (can't dbl on apple) 


.byte 


BMJfPOS 


*ypos 


.byte 


(BM WIDTH (DOUBLE B) 


★width 


.byte 


BM HEIGHT 


♦height 



card width of bitmap 
bitmp height 



Place the bitmap on the screen, 
loading the registers with 
inline data (note double-width 
settings) . 



90$: rts 

BitmapCIip, BitOtherClip, NewBitUp. 



exit 



20 



BitOtherClip 



BitOtherClip (Apple, C64, ci28) 



graphics 



Function: Special version of BitmapCIip that allows the compacted bitmap data to come 
from a source other than memory (e.g., from disk). 

Parameters: rO BUFFER — pointer to a 1 34-byte buffer area (word). 

rlL XPOS — x-position in bytes: pixel j)osition /8 (byte), 
r 1 H Y — y-coordinate (byte). 

r2L W_WIDTH — width in cards of clipping window: pixeLwidth/8 
(byte). 

r2H W^HEIGHT — height in pixels of clipping window (byte). 

rllL DXl — delta-xl: offset of left edge of clipping window in cards from 

left edge of full bitmap (byte), 
rl IH DX2 — delta-x2: offset of right edge of clipping window in cards from 

right edge of full bitmap (byte). 
rl2 DYl — delta-yl: offset of top edge of clipping window in pixels from 

top edge of fiill bitmap (word), 
r 1 3 APPINPUT — pointer to application-defined input routine. Called each 

time a byte from a compacted bitmap is needed; data byte is returned in 

the a-register. 

rl4 SYNC — pointer to synchronization routine. Called after each bitmap 
packet is decompressed. Due to improvements in BitOtherClip, this 
routine need only consist of reloading rO with the BUFFER address. 

where the upper-left corner of the clipped bitmap (the window) is placed at 
(XP0S*8, Y). The lower-right corner is at ([XPOS*8]+[WJVIDTH*8], 
Y^WJiEIGHT). 

Uses: dispBufferOn: 

bit? — write to foreground screen if set. 
bit 6 — write to background screen if set 

Returns: nothing. 

Destroys: a, x, y, r0-rl2, and the 134-byte buffer pointed at by rO. 

Description : BitOtherClip allows the application to decompress and display a bitmap without 
storing the compressed bitmap in memory. Call BitOtherClip witii the address 
of an input routine (APPINPUT). Each time BitOtherClip needs another byte, 
it calls this routine. The APPINPUT routine is expected to read data from the disk 
or some other device and return a single byte each time it is called. 

The basic width, height, position, and clipping window parameters the same as 
those for BitmapCIip. Refer to the documentation of that routine for more 
information. 

BitOtherClip calls the user-supplied APPINPUT routine until it has enough 
bytes to form one bitmap packet. APPINPUT must preserve r0-rl3 and return 
the data byte in the accumulator. A typical APPINPUT routine saves any registers 
it might destroy, calls ReadByte to get a byte from a disk file, places die byte in 
the BitOtherClip buffer (pointed at by rO), then returns, as illustrated in the 
following example. 



21 



BitOtherCiip 



128: 
Apple: 

Note: 
Example: 

22 



App Input : 



PushW 


1^1 1 


•save rl, r4, and r5 


PushW 




• (saved for calls to ReadByte routine 


irUSnrr 


TO t 




Movew 


saveRl r rl i 


• rl <- saveRl 


no vcn 


savcKOf ro 


• r5 <— saveRS 


liOaQn 


r4 , fdiSKQlKBut 1 


• r4 <- disk buffer we use 


jsr 


MyReadByte < 


• get a byte from the file 






* (oyte Is in A) 


Sua 


error ^ 


• save any error 


i ^ 1 ADD T V \ 




• Apple needs to use buffer pointer 


sua 




* that is on Alt zero^page 








lay 


A 6 n n 

#900 , 


' null inalrectlon index 


sta 


(rO),y 


• store byte into buffer 


.if (APPLE) 




' Apple needs to 


sta 


ALTZP_OFF 


• restore normal zero-page 


.endif 






MoveW 


r5,saveR5 < 


• r5 -> saveRS 


MoveW 


rl^saveRl , 


• rl -> saveRl 


PopW 


r5 


• restore rl, r4, and r5 


PopW 


r4 




PopW 


rl 




rts 




• exit 



When BitOtherCiip detects a complete packet, it uncompacts the data from the 
buffer to the screen. After the bitmap packet has been uncompacted, 
BitOtherCiip calls the SYNC routine supplied by the caller. The SYNC routine 
prepares the bitmap buffer for the next packet by reloading rO with the address of 
BUFFER and performing an rts. 

Sync: 

LoadW rO, #ClipBuf fer ; reset the pointer 

rts / exit 

Under GEOS 128, OR'ing DOUBLE^B into the and W^WIDTH 

parameters will automatically double the x-position and the width (respecitvely) in 
80-column mode. 

DOUBLE B can be OR'ed into the WIDTH paramter to double the bitmap 
width andlNAUX B can be OR*ed into the XPOS parameter to specify 
auxiliary memory. Also on Apple GEOS, the APPINPUT routine must use the 
alternate zero-page version of rO to index into BitOtherClip*s compaction 
buffer. 



.if (APPLE) 
sta 
Idy 
sta 
sta 

.endif 



ALTZP_ON 
#$00 
(rO),y 
ALTZP OFF 



Apple needs to use buffer pointer 
that is on Alt zero-page 
null indirection index 
store byte into buffer 
restore normal zero-page 



Do not pass a value of $00 for either the WJVIDTH or WJIEIGHT parameters. 



*♦* CONSTANTS *** 

NO PICTURE « -1 ; no picture error. MUST BE NON-ZERO 

;window coordinates and dimensions 



BitOtherClip 



WIN_CRDX = 5 

WIN_CRDWIDTH = 12 

WIN^Y =40 

WIN HEIGHT = 110 



card x-position 
card width 
y-position 
height 



*** VARIABLES 

.ramsect 

saveRl 

saveRS 

leftOff set 

topOf fset 

picWidth 

picLength 

ClipBuffer 

.psect 



.block 
.block 
.block 
.block 
.block 
.block 



.block 135 



DrawPhoto 
DESCRIPTION: 



temp save for GEOS registers that need to 

be preserved between calls to ReadByte 
scroll x-index into bitmap 
scroll y-index into bitmap 
bitmap card width 
bitmap card height 
BitOtherClip buffer (+1 for safety) 



PASSED: 



RETURNS: 



Reads a picture in from a photo album record and draws it 
clipped to a window. Scroll values allow a specific portion 
of the bitmap to be shown. 

Open VLIR album file with photo scraps in records 
curPhoto record to use 
leftOffset scroll value on x 
topOffset scroll value on y 



picWidth 
picLenght 

X 



from photo record 
from photo record 
error 



DrawPhoto: 



99$: 



jsr 


ClearWindow 


/ clear the drawing window 


jsr 


GetPicSize 


; get the size of the picture 


txa 




; check for error 


bne 


99$ 




jsr 


SetUpPhoto 


; set up clipping parameters 






/ carry comes back set if we can 


Idx 


#NO_ERROR 


/ no errors yet 


bcc 


99$ 


; skip drawing if necessary 


jsr 


PutUpPhoto 


; draw photo from the record 


rts 




; exit with error in x 



• * it it* ^r it it ii*iiit*it it ****** It* Ir** it* * It ir**ii it -kit It It* ****** it* it* 

; ClearWindow 

/DESCRIPTION: Erase the window areas where we plan to put the bitmap 

/PASS: Nothing 

/RETURNS: curPattern » 

/DESTROYS: CBM: a, x, y, r5-r8,' rll 

APPLE: a, x, y, rll 

******************************* ********************************* 

ClearWindow: 

LoadB curPattern, #0 /use blank fill pattern 

jsr i_Rectangle 
.byte WIN_Y 



23 



BitOtherClip 



.byte (WIN_Y+WIN_HEIGHT) 

.word {WIN_CRDX * 8) 

.word (WIN_CRDX*8 + WIN_CRDWIDTH*8) 

rts 



SetUpPhoto 

DESCRIPTION: Set up clipping regions and other parameters 



PASS: 



RETURNS: 



DESTROYS 
*********** 

SetUpPhoto: 



8$: 



15$: 



picWidth card width of bitmap 

picLength height of bitmap 

leftOffset card scroll index into bitmap 

rightOffset line scroll index into bitmap 

carry set « OK to draw 

clear = don't draw (lies outside of region.) 
rO BitOtherClip buffer 
rlL Card x-position of window 
rlH y-position of window 

r2L number of cards of bitmap to display in window 
r2H number of lines of bitmap to display in window 
rl2 lines to skip on top 
rllL cards to skip on left 
rllH cards to skip on right 



rO <- buffer for BitOtherClip » s use 
rlL <- window's card x-position 
rlH <- window's y-position 
A <- (picWidth-leftOffset) 

(difference between width of 

picture and offset into picture) 
If offset exceeds width, then skip 

over picture draw 

; If width to display exceeds width 

of bitmap, then display as much as 
; will fit in the window. 

r2L <- card width to display 

A <- (picLength-topOf f set) 

(difference between height of 
picture and offset into picture) 

If offset exceeds height, then skip 
over picture draw 

If height to display exceeds height 
of bitmap, then display as much as 
will fit in the window. 

r2H <- pixel height to display 

rl2 <- lines to skip on top 
rllL <- cards to skip on left 



LoadW 


rO, #ClipBuffer 


LoadB 


rlL, WIN__CRDX 


LoadB 


rlH, WIN_Y 


Ida 


picWidth 


sec 




sbc 


leftOffset 


bcc 


20$ 


beq 


20$ 


cmp 


#WIN CRDWIDTH 


bcc 


8$ 


Ida 


#WIN_CRDWIDTH 


sta 


r2L 


Ida 


picLength 


sec 




sbc 


topOf f set 


bcc 


20$ 


beq 


20$ 


cmp 


#WIN HEIGHT 


bcc 


15$ 


Ida 


#WIN_HEIGHT 


sta 


r2H 


MoveW 


topOf fset,rl2 


MoveW 


leftOffset, rllL 


Ida 


picWidth - 


sec 




sbc 


r2L 


sbc 


leftOffset 


sta 


rllH 



rllH <- cards to skip on right 



24 



BitOtherClip 



20$: 



clc 
rts 

sec 
rts 



flag as OK to draw 
exit 

flag not to draw 



;PutUpPhoto 



/DESCRIPTION: 
/ 

/RETURNS: 
/ 

/DESTROYS: 



Draw photo from record. 
X error 
a,x,y,r0-rl5 



PutUpPhoto: 



99$: 



jsr 


GetPicSize , 


reload picture length and width 


txa 




* check for error or no picture 


bne 


99$ 


leave on error 


jsr 


Sync t 


• rO <- clipBuffer 


LoadW 


rl3, #AppInput , 


• rl3 <- Applnput routine 


LoadW 


rl2, #Sync 


• rl2 <- Sync routine 


LoadB 


error, #NO_ERROR 


• start out with no error 


jsr 


BitOtherclip 


? display photo 


Idx 


error 


? put any error into x 


rts 




? exit 



4r 4r ******** * 



Applnput 



DESCRIPTION: 



APPLE: 



RETURNS : 



Applnput : 
PushW 
PushW 
PushW 
MoveW 
MoveW 
LoadW 
jsr 

stx 
.if (APPLE) 

sta 
.endif 

Idy 

sta 
.if (APPLE) 

sta 
.endif 

MoveW 

MoveW 



Bitmap input routine called by BitOtherClip. Returns a single 
byte of the uncompacted bitmap. 

This routine resides in main memory on the Apple, so the 
ClipBuffer should also be in main memory. 

bitmap byte in BitOtherClip* s buffer (off of rO) 
any error in error 

r************************************************************** 



rl 
r4 
r5 

saveRl, rl 
saveR5, r5 
r4,#diskBlkBuf 
MyReadByte 

error 

ALTZP_ON 

#$00 
(rO),y 

ALTZP__OFF 

r5, saveRS 
rl, saveRl 



save rl, r4, and r5 



rl <- saveRl 
r5 <- saveRS 

r4 <- disk buffer we use 
get a byte from the file 
(byte is in A) 
save any error 

Apple needs to use buffer pointer 
that is on Alt zero-page 

null indirection index 
store byte into buffer 
Apple needs to 
restore normal zero-page 

r5 -> saveRS 
rl -> saveRl 



25 



BitOtherClip 



PopW r5 

PopW r4 

PopW rl 
rts 



restore rl, r4, and r5 



exit 



;Sync 

.*****★*★**★**«★★★*****★***★*************★★**★*****************« 

/DESCRIPTION: Dumb synchronization routine needed by BitOtherClip 

; 

Sync: 

LoadW rO,#ClipBuffer ; reset the pointer 

rts ; exit 



/GetPicSize 

. ********************************************************************* 

/DESCRIPTION: Get picture size and other misc. setup for PutUpPhoto 
; 

•RETURNS: X error 



GetPicSize: 





PushW 


rl 


save rl and r4 




PushW 


r4 






Ida 


curPhoto ; 


get current photo's record number 




jsr 


PointRecord ; 


point to that record 

rl <- block# of first record 




Ida 


rlL ; 


make sure there's something there 


.if 


(APPLE) 








ora 


rlH 


(check both bytes on Apple) 


.endif 








bne 


10$ 


branch if valid record found 




Idx 


#N0 PICTURE 


' otherwise, flag no picture 




Following 


line changed to save bytes 




bra 


40$ 


' and exit 




bne 


40$ 


• unconditional (NO__PICTURE != 0) 


10$: 










jsr 


SetUpReadByte 


r prepare for ReadByte 




txa 




? check status 




bne 


40$ 


? exit on error 




jsr 


ReadSizeBytes 


? read the size bytes out of the record 
? and store them in the photo size 
; variables (error comes back in x) 




MoveW 


rl, saveRl 


; save off rl and r5 




MoveW 


r5, saveRS 




• 


Following line removed to let 


error propagate back 




Idx 


#NO_ERROR 


; we got this far, no errors found... 


40$: 










PopW 


r4 


; restore r4 and r5 




PopW 


r5 






rts 




; exit 



******* ************************************** ******** 

SetUpReadByte 

********** ********************************** ****** ************************* 

DESCRIPTION: Set up variables and stuff for ReadByte 

STRATEGY: 

Special case Apple because it requires an extra step. The first block in 



26 



BItOtherClip 



an Apple VLIR record is actually an index block with pointers to all the 
other blocks in the chain. We read this block into the aux memory buffer 
INDEXBLOCKBUF so ReadByte has something to work with (this requires that 
ReadByte be called from aux memory using JsrToAux) . The general disk 
buffer diskBlkBuf is used for the intermediate blocks since it is in 
high aux memory and is always visible (thus eliminating the need to 
set RWbank) . 



PASS: 



RETURNS: 



APPLE: rl block number of chain's index block 

CBM: rlL, rlH Track/sector of first block in chain 

rl, r4, r5 set up for ReadByte 
X = error code 



DESTROYS: a, y 

SetUpReadByte: 
.if (APPLE) 

LoadW 

LoadB 

jsr 



It***********************-* 



LoadB 
.else ; (CBM) 

Idx 
.endif 

MoveW 

LoadW 

Ida 

sta 

sta 

rts 



r 4, # INDEXBLOCKBUF 
RWbank, #AUX 
GetBlock 

RWbank, #MAIN 

#NO_ERROR 

r4,rl 

r4, diskBlkBuf 

#0 

r5L 

r5H 



r4 <- buffer for index block 
set disk read to proper bank 
read in the chain's index block 
(error now in x) 
restore disk bank to normal 

no error on CBM 

rl <- track/sector of 1st block (CBM) 

<- index block pointer (APPLE) 
r4 <- disk buffer for ReadByte 
r5 <- $0000 (for ReadByte) 



exit with error in X 



MyReadByte 
D-ESCRIPTION: 



PASS: 

RETURNS : 

DESTROYS: 

MyReadByte : 

.if (APPLE) 
Ida 
Idx 
jsr 

.else ; (CBM) 
jsr 



My version of ReadByte that deals with all machine weirdness. 
This routine expects to use the general-purpose disk buffer at 
diskBlkBuf because, since it is in high-aux on the Apple, it 
avoids the bank switching complications. 

Call wherever you would normally call ReadByte. Call 
SetUpReadByte to set the proper parameters prior to calling. 

This would make a good Macro. 

Same as ReadByte 

Same as ReadByte 

Same as ReadByte 

******:r^*******************«**4r ********************************* 



# [ReadByte 
#] ReadByte 
JsrToAux 



ReadByte 



APPLE 

Call ReadByte from aux memory 
so that the aux memory 
INDEXBLOCKBUF is visible 

; CBM 

; just use normal ReadByte 



27 



BitOtherClip 



.endif 

rts ; exit 



Reads! zeBytes 

DESCRIPTION: Read in the first three bytes from the current record and 
store them in the size variables. 

PASS: File open and system ready for calls to ReadByte. 

RETURNS: rl, r4, r5 ready for ReadByte calls to load bitmap data 

X error 
picWidth card width of bitmap 
picLength line height of bitmap 

DESTROYS: a, y 

*«********************************************************« ************ 

ReadSizeBytes : 



99$: 



jsr 
sta 
txa 
bne 
jsr 
sta 
txa 
bne 
jsr 
sta 

rts 



MyReadByte 
picWidth 

99$ 

MyReadByte 
picLength 

99$ 

MyReadByte 
picLength+1 



get photo width 
check for error 
get photo length (low byte) 
check for error 
get photo length (high byte) 

exit error in x 



28 



BidGDirEntry 



BldGDirEntry (Apple, C64, cns) 



mid-level disk 



Function: 



Parameters: 



Returns: 

Alters: 
Destroys: 



Description: 



Apple: 



Example: 



Builds a directory entry in memory for a GEOS file using the information in a file 
header. Apple GEOS version can also build an entry for a folder (subdirectory). 



r6 



Commodore: 

r2 NUMBLOCKS — number of blocks in file (word). 

TSTABLE — pointer to a track/sector list of unused blocks (unused but 
allocated in the BAM), usually a pointer to fileTrScTab; BlkAlIoc 
can be used to build such a list (word). 
FUJEHDR — pointer to GEOS file header (word). 



r9 

Apple: 
r2 

r6 



r7 
r8 
r9 



NUMBLOCKS — number of blocks in file or $0000 to create a 
subdirectory (word). 

INDXBLK — if creating a file, block number of sequential-file index 
block or VLIR master index block; if creating a subdirectory, key block 
number for subdirectory (word). 
FUJEB YTES — number of bytes in file (word). 
HDBLKNUM — block number of the file's header block (word). 
FILEHDR — if creating a file, pointer to GEOS file header, if creating a 
subdirectory, pointer to null-terminated name for the subdirectory (up 
15 characters plus a NULL); must be in main memory, (word). 

Commodore: 

r6 pointer to first non-reserved block in track/sector table (BidGDirEntry 
reserves one block for the file header and a second block for the index 
table if the file is a VLIR file). 

dirEntryBuf contains newly-built directory entry. 

Commodprg: 
a, X, y, rlH. 

App le: 

a, X, y, r3. 

Given a GEOS file header, BidGDirEntry will build a system specific directory 
entry suitable for writing to an empty directory slot. BidGDirEntry takes care 
of differences between Apple and Ctommodore GEOS. 

Most applications create new files by calling SaveFile. SaveFile calls 
SetGDirEntry, which calls BidGDirEntry as part of its normal processing. 

The Apple version of BidGDirEntry can also be used to build subdirectory 
entries by passing $00(X) in r2. The easiest way to create a subdh-ectory is to call 
MakeSubDir. 



.************************************ *************************************** 

;MySetGDirEntry (My Version of Set Geos Directory Entry) 



; This routine duplicates the function of the Kernal's SetGDirEntry for 



29 



BIdGDIrEntry 



demonstration purposes. It shows examples of the following routines: 

BldGDirEntry 
GetFreeDirBlk 
UpdateParent 
PutBlock 

PASS: Same as SetGDirEntry 

DESTROYS: Same as SetGDirEntry 



.if (APPLE) 
DIRCOPYSIZE 
.else (CBM) 
DIRCOPYSIZE 
.endif 



= 39 
= 30 



bytes in directory to copy over 
after BldGDirEntry is called 



MySetGDirEntry : 



jsr 


BldGDirEntry ; 


build directory entry for GEOS file 


jsr 


GetFreeDirBlk / 


get block with free directory entry 






r3 =» 1st byte of free entry 






block number of block in rl 


txa 




test for error code 


bne 


90$ ; 


if error, exit . . . 


.if (APPLE) 






MoveW 


r3,r5 ; 


make r5 point to directory entry 


.else ; (CBM) 






tya 




get offset into diskBlkBuf for dir entry 


clc 






adc 


#[diskBlkBuf 


and get absolute address in buffer 


sta 


rSL 




Ida 


#ldiskBlkBuf 




adc 


#0 


(propagate carry) 


sta 


r5H 




.endif ; (else 


CBM) 


• (r5 = pointer to dir entry in buffer) 


Idy 


#DIRCOPYSIZE 


• copy over some bytes 


10$: 






Ida 


dirEntryBuf ,y 


get byte from directory entry built 


sta 


(r5) ,y 


• store new entry into block buffer 


dey 






bpl 


10$ 


? loop till copied 


jsr 


TimeStampEntry 


? stamp the dir entry with time & date 


LoadW 


r4,#diskBlkBuf 


; write out the new directory entry 


jsr 


PutBlock 




txa 




; get error status 


bne 


90$ 


; if error, exit 



.if (APPLE) 
PushW 

Ida 
jsr 
PopW 



rl 

#(INC_NUM_FILES 

UpdateParent 

rl 



Update parent directory on Apple 
save block number of directory block that 
this file entry is stored in 
MOD_DATE) 

update parent directory's directory entry 
restore block number of directory block 

that this file entry is saved on 
(error status now in x) 



.endif ; (APPLE) 
90$: 

rts 



************* ****************************************************** ******** 

TimeStampEntry 

Add time/date stamp to directory entry 



30 



BldGDirEntry 



TimeStampEntry : 



.if (C64 1 


1 C128) COMMODORE *** 




TDSIZE 






number of bytes in time/date entry 


Idy 




fOFF__YEAR ; 


otrset to time/aate stamp 


10$: 








Ida 




year-OFF_^YEAR, y ; 


get the yr/mo/day/hr/min 


sta 




Cro) , y ; 


store in dir entry 


iny 








cpy 




Jtorr VT A D j-Tne T T 

ffUr r __ILAr\+iUbi^hj / 


done yet? 


bne 




1 V 1 


if not, loop 


rts 








.else ; (APPLE) 


•www ArrLL 




clc 






stamp creation date 


jsr 




StampTimeDate i 




sec 






stamp moaiiicatlon date 


jsr 




StampTimeDate , 


rALL inKUUUn to ot ampTimeDate 


/ rts 








StampTimeDate: 




(carry indicates stamp to modify) 


Ida 




minutes « 


get minutes (0—59) 


Idy 




tOFF__FCTIME , 


• get offset to creation minutes 


bcs 




110$ 1 


if stamping creation time, skip 


Idy 




fOFF__FMTIME i 


get offset to modification minutes 


110$: 








sta 




(r5),y , 


' save hours in directory entry . 


Ida 




hour 1 


' get hours (0-23) 


iny 






' get offset to hours 


sta 

» 




(ro) , y , 


• save minutes in directory entry 


idy 




fOr r_rCDATE i 


get or t set to mmmdaaaa 


bcs 




X ^ U V 


* if stamping creation time, skip 


Idy 








120$: 








Ida 




mont" h 


f geu niunL.n yx ±£} 


asl 








asl 








asl 




a 




asl 




a 




asl 




a 


? carry holds month's msb 


ora 




day 


; combine with day to get mmmddddd 


sta 




(r5),y 


; save mmmddddd 


iny 






; get offset to yyyyyyym 


Ida 




year 


; get year 


rol 




a 


; carry has m's MSB; move it into 








; LSB to get yyyyyyym 


sta 




(r5),y 


; save yyyyyyym 


rts 






; exit 



.endif ; ( .else APPLE) 



See also: SetGDirEntry. 



31 



BIkAlloc 



BlkAUoC (Apple, C64, C128) 



mid-level disk 



Function: Allocate enough disk blocks to hold a specified number of bytes. 



Parameters: r2 



Uses: 



Returns: 



BYTES — number of bytes to allocate space for. Commodore version 
can allocate up to 32,258 bytes (127 CiDmmodore blocks); Apple 
version can allocate up to 65,535 ($ffff) bytes (128 ProDOS blocks) 
(word). 



Commodore: 

r6 TSTABLE — pointer to buffer for building out track and sector table of 
allocated blocks, usually points to fileTrScTab (word). 



curDrive 

Commodore: 

curDlrHead 

dir2Headt 

dirSHeadt 

interleave^ 



Applg: 

VBMBlknot 

numVBMBlkst 

curVBlknot 
VBMchangedt 



currently active disk drive. 



this buffer must contain the current directory header. 
(BAM for 1571 and 1581 drives only) 
(BAM for 1581 drive only) 

desired physical sector interleave (usually 8); used by 
setNextFree. Applications need not set this explicitly — 
will be set automatically by internal GEOS routines. 



Apple GEOS BIkAlloc starts searching for free blocks 
beginning with the block that follows the last VBM block, 
the block following the last VBM block is found by adding 
the value in numVBMBlks to the value in VBMBlkno. 
used by VBM cacheing routines, 
used by VBM cacheing routines 



^used internally by GEOS disk routines; applications generally don't use. 
X error ($00 = no error). 

r2 number of blocks allocated to hold BYTES amount of data. 



Commodore: 

rSL track of last allocated block, 
r 3 H sector of last allocated block. 



Apple; 
r3 



last block allocated. 



Alters: 



Commodore: 
curDirHead 
dir2Headt 
dir3Headt 

Applg; 

curVBlknot 
VBMchangedt 



BAM updated to reflect newly allocated blocks. 
(BAM for 1571 and 1581 drives only) 
(BAM for 1581 drive only) 



used by VBM cacheing routines. 

set to TRUE by VBM cacheing routines to indicate cached 
VBM block has changed and needs to be flushed 



32 



BIkAlloc 



^used internally by GEOS disk routines; applications generally don't use. 

Destroys: Commodore: 
a, y, r4-r8. 

Apple; 

a, y, r4, r6, r7, r8H. 

Description: BIkAlloc allocates enough blocks on the disk for BYTES amount of data. The 
GEOS SaveFile and WriteRecord routines call BIkAlloc to allocate multiple 
blocks prior to calling WriteFile. Most applications do not call BIkAlloc 
direcdy, but rely, instead, on the higher-level SaveFile and WriteRecord. 

BIkAlloc calculates the number of blocks needed to store BYTES amount of 
data, taking any standard overhead into account (such as the two-byte track/sector 
link required in each Commodore block), then calls CalcBlksFree to ensure that 
enough free blocks exist on the disk. If there are not enough free blocks to 
accomodate the data, BIkAlloc returns an INSUFFICIENT^SPACE error 
without allocating any blocks. Otherwise, BIkAlloc calls SetNextFree to 
allocate the proper number of unused blocks. 

C64 & C128: The Commodore version of BIkAlloc builds out a track and sector table in the 
buffer pointed to by TSTABLE. The 256 bytes at fileTrScTab are usually used 
for this purpose. When BIkAlloc returns, the table contains a two-byte entry for 
each block that was allocated: the first byte is the track and the second byte is the 
sector. The last entry in the table has its first byte set to $00, indicating the end of 
the table. The second byte of the last entry is an index to the last byte in the last 
block. This track/sector list can be passed directiy to WriteFile for use in writing 
data to the blocks. 

BIkAlloc does not automatically write out the BAM. See PutDirHead for more 
information on writing out the BAM. BIkAlloc does not allocate blocks on the 
directory track. Refer to GetFreeDirBlk for more information on allocating 
directory blocks. 

Apple: The Apple version of BIkAlloc builds out a list of allocated blocks in the internal 

INDEXBLOCKBUF buffer. This index block is a modified 512-byte ProDOS 
sapling index block. The block is divided into two 256-byte portions. The lower 
half (bytes through 255) represent the low-bytes of the data blocks and the 
upper half (bytes 256 through 511) represent the associated high-bytes.Byte 
and byte 256+0 combine to form the block number of the first data block, byte 1 
and byte 256+1 combine to form the number of the second data block, and so on 
for each allocated block. A block pointer of $0000 ($00 high, $00 low) represents 
the end of the list 

The last two pointers in the index block — the ones in a standard ProDOS sapling 
index that point to the 254tii and 255th blocks in the chain — comprise a four-byte 
size value in GEOS. The four-byte value, which represents the number of bytes 
stored in the allocated blocks, can be accessed using the following offsets into the 
index block: 

DSIZEO Low byte 

DSIZEl 



33 



BIkAiloc 



DSIZE2 

DSIZE3 High byte 

BIkAlIoc does not patch the size information into INDEXBLOCKBUF. The 
application must, therefore, do this itself before writing the index block to disk. 
However, because INDEXBLOCKBUF is in auxiliary memory, applications 
cannot patch the index block direcdy from main memory. MoveAuxData can 
transfer the 5 12 bytes from auxiliary to a buffer visible from main memory. 



LoadW rO, # INDEXBLOCKBUF / copy 

LoadW rl, tdliskBlkBuf / to t 

LoadW 12, #BLOCKSIZE ; move 

Ida #AUXtoMAIN ; copy 

jsr MoveAuxData ; 

The size information can then be patched 
the last two block pointers. 



from index blk 
imp buffer 
a full block 
aux to main 



into the index block, masquerading as 



MoveB dataSize+0,diskBlkBuf +DSIZEO ; transfer size bytes 

MoveB dataSize+l^diskBlkBuf+DSIZEl ; (low to high order) 

MoveB dataSize+2,diskBlkBuf+DSIZE2 ; 

MoveB dataSize+3,diskBlkBuf+DSIZE3 



The block can then be transferred back to INDEXBLOCKBUF. 



LoadW rO, #diskBlkBuf ; copy from buffer 

LoadW rl, # INDEXBLOCKBUF ; back to index block 

LoadW t2, #BL0CKSIZE ; move a full block 

Ida #MAINtoAUX ; copy main to aux 

jsr MoveAuxData ; 



Use the index block to write out the appropriate data, perhaps by calling 
WriteFile, then use PutBIock to write out the index block to a previously 
allocated block. 



MoveW yourlndex^rl ; where to write block (you suppy) 

LoadW tA, # INDEXBLOCKBUF ; where data is 

LoadB RWbank, #AUX ; bank to aux 

jsr PutBIock / write out block 

LoadB RWbank, #MAIN ; back to main 



BlkAlloc does not flush the VBM cache. See PutVBM for more information on 
flushing the cache. 

Note: For more information on the scheme used to allocate successive blocks, refer to 

SetNextFree. 



Example: 



GrabSomeBlocks : 

LoadW* r2,#BUF_SIZE 
.if (C64 I I C128) 

LoadW r6, #f ileTrSecTab 



.endif 

jsr 
txa 
bne 



BlkAlloc 
99$ 



number of bytes to allocate 

CBM needs buffer to build out table 
of links. APPLE will automatically use 
INDEXBLOCKBUF 

allocate the blocks 

check status 

and exit on error 



34 



BIkAlloc 



; more code here 

99$: rts ;exit 
.ramsect 

K « 1024 ;. one kilobyte 

buffer": .block 5*K ; 5K buffer 

BUF_SIZE = (*-buffer)+l ; size of buffer 
•psect 

For a more detailed example, see WritFile. 

See also: NxtBlk Alloc, SetNextFree, GetFreeDirBlk, FreeBIock. 



35 



BlockProcess 



BlOCkPrOCeSS (Apple, C64, C128) 



process! 



Function: 
Parameters: 

Returns: 

Destroys: 

Description: 



Note: 
Example: 



Block a processes events, 

X PROCESS — process to block (0 to n-1, where n is the number of 

processes in the table) (byte)- 

X unchanged. 

a 

BlockProcess causes MainLoop to ignore the runable flag of a particular 
process so that if a process timer reaches zero (causing the process to become 
runable) no process event is generated until the process is subsequently 
unblocked with a call to UnblockProcess. BlockProcess stops the process at 
the MainLoop level. Refer to FreezeProcess to stop the process at the Interrupt 
Level. 

BlockProcess does not stop the countdown timer, which continues to 
decrement at Interrupt Level (assuming the process is not frozen). When the timer 
reaches zero, the runable flag is set and the timer is restarted. As long as the 
process is blocked, though, MainLoop ignores this runable flag and, therefore, 
never generates an event. When a blocked process is later unblockeki, MainLoop 
checks the runable flag. If the runable flag was set during the time the process 
was blocked, this pending event generates a call to the appropriate service 
routine. Only one event is generated when a process is unblocked, even if the 
timer reached zero more than once. 

If a process is already blocked, a redundant call to BlockProcess has no effect. 



SuspendClock: 
Idx 
jmp 



#CLOCK__PROCESS 
BlockProcess 



X <- process number of the clock 
block that parictular process 



See also: 



UnblockProcess, FreezeProcess. 



36 



BMult (Apple, C64, C128) 



BMult 
mathl 



Function: 
Parameters: 

Returns: 

Destroys: 
Description: 

Note: 

Example: 

SeeAIso: 



Unsigned word-by-byte multiply: multiplies an unsigned word and an unsigned 
byte to produce an unsigned word result 

X OPERANDI — zero-page address of word multiplicand (byte pointer to 

a word variable). 

y OPERAND2 — zero-page address of multiplier (byte pointer to a word 
variable — use a word variable; only the low-byte is used in the 
multiplication process, but the high-byte of the word is destroyed). 

Note: result = OPERANDI (word) * 0PERAND2(byte). 

X, y unchanged. 

word pointed to by OPERANDI has its high-byte set to $00, and its low-byte 
unchanged. 

word pointed to by OPERANDI contains the word result, 
a, r6-r8. 

BMult is an unsigned word-by-byte multiplication routine that multiplies the 
word at one zero-page address by the byte at another to produce a 16-bit word 
result. BMult operates by clearing the the high-byte of OPERANDI and calling 
DMult. The result is stored as a word back in OPERANDI. 

Because r6, r7 and r8 are destroyed in the multiplication process, they cannot be 
used to hold the operands. 

Overflow in the result (beyond 16-bits) is ignored. 



Multiply the value in r9 by 87 and store the result back in r9 

(rl is destroyed) 

Idx #r9 ; point to OPERANDI in r9 

LoadB rlL, #87 ; rl <- 87 (0PERAND2) 

Idy #rl / point to 0PERAND2 in rl 

jsr BBMult / r9 <- r9 * rlL 



BBMult, DMult, Ddiv, DSdiv. 



37 



BootGEOS 



BoOtGEOS (C64, C128) 



internal I 



Function: 
Parameters: none. 
Returns: 
Destroys: 
Description 



Restart GEOS from a non-GEOS application. 



Example: 



Does not return, 
n/a 



BootGEOS provides a method for an non-GEOS to run in the GEOS 
environment — starting up from die deskTop and returning to GEOS when done. 
The non-GEOS application need only preserve the area of memory between 
BootGEOS ($cOOO) and BootGEOS+$7f ($c07f). The rest of the GEOS 
Kemal may be overwritten. To reboot GEOS, simply jmp BootGEOS, which 
completely reloads the operating system (either from disk in a "boot" procedure or 
from a RAM-expansion unit in an "rboot" procedure) and returns to the GEOS 
deskTop. 

A program can check to see if it was loaded by GEOS by checking the memory 
starting at $c006 (bootName) for the ASCII (not CBMASCH) string "GEOS 
BOOT". If loaded by GEOS, the program can check bit 5 of $c012 
(sysFlgCopy): if this bit is clear, ask the user to insert their GEOS boot disk 
before continuing, otherwise a boot disk is not needed because GEOS will rboot 
from die RAM expansion unit. To actually return to GEOS, set CPU DATA to 
$37 (KRNL BAS 10 IN) on a Commodore 64 and set config to $40 
(CKRNL BAS I(T iK) on a Commodore 128, tiien jump to BootGEOS 
($cOIO). 



BYTESTOSAVE 
RBOOT BIT 



$80 
5 



; no. of bytes to save at BootGEOS 
; bit in sysFlgCopy to check 



OnEntry : 
Idx 

10$: 

Ida 
sta 
dex 
bne 
rts 
.ramsect 
GEOS__save 
.psect 



#BYTESTOSAVE 

BootGEOS-lr X 
GEOS_save-l,x 

10$ 



.block BYTESTOSAVE 



save bytes GEOS needs so we can use area 
START LOOP 

copy a byte 

count — 

if (count !« 0), then loop 
ENDLOOP 

save area for GEOS restart block 



OnExit: 

.if (C646&C128) 

.echo Warning: expected both C64 and C128 constants TRUE 
.endif 
Ida 
cmp 
bit 
Ida 
bpl 

128$: 

Ida 
sta 



version 
#$13 
64$ 

cl28Flag ' 
64$ 

CKRNL_BAS__IO__IN 
config 



Get, version of GEOS 

If version < 1.3, then branch 
Else, test for GEOS 128 
If GEOS64, then branch 

load 128 memory mapping 



38 



BootGEOS 



bra 


200$ 






Ida 


#KRNL_BAS_IO IN , 


' load 64 memory mapping 




sta 


CPU_DATA 






Idx 


tBYTESTOSAVE 


• restore bytes GEOS needs 


to restart 






' STARTLOOP 




Ida 


GEOS_save-l, X 


• copy a byte 




sta 


BootGEOS-l,x 






dex 




count — 




bne 


10$ 


if (count !=» 0) , then 


loop 






• ENDLOOP 




Ida 


#(%1«RB00T_BIT) 


? check for Rboot flag 




and 


sysFlgCopy 






bne 


99$ 


? if flag is clear, branch 


to rboot 


jsr 


AskForBootDisk 


• else, get user to insert 


boot disk 


jmp 


BootGEOS 







See also: Firstlnit, StartAppI, GetFile, EnterDeskTop. 



39 



This page intentionally left blank to maintain right/left (verso/recto) 
page ordering. Final version will correct this. 



CalcBlksFree (Apple, C64, ci28) 



mid-level disk I 



Function: Calculate total number of free blocks on disk. 

Parameters: Commodore: 

rS DIRHEAD — address of directory header, should always point to 
curDirHead (word). 

Apple: 
none. 



Uses: 



curDrive 

Commodore: 

dirZHeadt 

dirSHeadt 

Apple: 

curVBlknot 

VBMchangedt 

numVBMBIkst 



(BAM for 1571 and 1581 drives only) 
(BAM for 1581 drive only) 



Returns: 



^used internally by GEOS disk routines; applications generally don't use. 
r4 number of free blocks. 



Applg: 

X 



error ($00 = no error). 



Commodore: 

rS unchanged. 

r3 in GEOS vl.3 and later: total number of available blocks on empty disk. 
This is useful because vl.3 and later support disk devices other than the 
1541. GEOS versions earlier than vl.3 leave r3 unchanged. 



Destroys: a, y. 



Description: CalcBlksFree calculates the number of free blocks available on the disk. An 
application can call CalcBlksFree, for example, to tell the user the amount of 
free space available on a particular disk. GEOS disk routines that allocate multiple 
blocks at once, such as Blk Alloc, call CalcBlksFree to ensure enough free 
space exists on die disk to prevent a surprise INSUFFICENT^SPACE error, 
midway through the allocation. (This is why it is usually not necessary to check 
for sufficent space before saving a file or a VLIR record— die higher level GEOS 
disk routines handle this checking automatically.) 

C64 & C128: The Commodore version of CaclBlksFr6e looks at the BAM in memory and 
counts the number of unallocated blocks. The BAM is stored in the directory 
header and the directory header is stored in the buffer at curDirHead. Calling 
CalcBlksFree requires first loading rS with the address of curDirHead. 

LoadW r5, #curDirHead ; point to the directory header 
jsr CalcBlksFree ; before calling CalcBlksFree 



1 



CalcBlksFree 



When checking the total number of blocks (both allocated and free) on a particular 
disk device, call CalcBlksFree with r3 loaded with the number of blocks on a 
1541 disk device. On GEOS vL3 and above, this number is changed to reflect 
the actual number of blocks in the device. On previous versions of GEOS, r3 
comes back unchanged. 



Apple: 
Example: 



N1541_BLOCKS 
LoadW 
LoadW 
jsr 



= 664 

r3, #N1541_BLOCKS 
r5, #curDirHeacl 
CalcBlksFree 



total number of blocks on 1541 devices 
assume 1541 block count for vl.2 Kernals 
point to the directory header 
r3 comes back with total number of blocks 
on this device 



The Apple version of CalcBlksFree looks through the VBM blocks on the disk 
Oarger capacity disks may have more than one) and determines the number of 
unallocated blocks by counting the allocation bits. 



CheckDiskSpace 

DESCRIPTION: Ensures that the current disk has a enough space for a 
minimum number of bytes. Does not take into account any 
index blocks or other blocks needed to maintain the file 
structure. Works with GEOS 64, GEOS 128, and Apple GEOS. 



r2 number of bytes we need 

X = error if any. If not enough space# returns an 
INSUFFICIENT_SPACE error. 

a, y, r2, r3, r8, r9 



PASSED: 
RETURNS: 

DESTROYED: 



; Number of bytes that can be stored in each block on the disk. Accounts for 
; two-byte track/sector link on Commodore versions of GEOS. 
BLOCK BYTES = BLOCK SIZE- ( (C64 I 1 128) *2) 



CheckDiskSpace 




r2 « # of BYTES to check for 


Ida 


r2L 


check if zero bytes requested 


ora 


r2H ; 




beq 


80$ ; 


if so, exit with no error 


LoadW 


r3,#BL0CK BYTES ; 


r3 <- number of bytes per block. 


Idx 


#r2 ; 


divide r2 by r3 to get number of 


Idy 


#r3 ; 


blocks to hold BYTES 


jsr 


Ddiv ; 


r2 <- r3/r2 ; r8L <- remainder 


Ida 


r8L ; 


Any remainder bytes? 


ora 


r8H 




beq 


5$ 


if not, OK 


IncW 


r2 


otherwise 1 more block needed 


5$: 




' r2 « BLOCKS needed to hold BYTES 
• get number of free blocks on dis 


.if (C64I IC128) 


• CBM GEOS requires extra step 


LoadW 


r5,#curDirHead , 


point to directory header 


.endif 






jsr 


CalcBlksFree , 


• r4 <- free blocks on disk 


.if (APPLE) 




• APPLE GEOS must error check here 


txa 




check status 


bne 


100$ 


branch to exit with error... 


.endif 






Idx 


#INSUFFICIENT_SPACE 


; assume not enough space 


CmpW 


r2,r4 


• are there enough free blocks? 



2 



CalcBlksFree 



80$: 



100$: 



bgt 



Idx 



rts 



100$ 

#N0 ERROR 



if not, asssump. correct, branch, 

otherwise, no error 

exit 



See also: 



BIkAlloc, SetNextFree, FreeBlock. 



3 



CallRoutine 



ICallRoutine (Apple, C64, cus) 



utility 



Function: 
Parameters: 

Returns: 

Destroys: 

Description: 



Note: 



Example: 



Perform a pseudo-subroutine call, checking first for a null address (which will be 
ignored). 

a [ADDRESS — low byte of subroutine to call. 

X ] ADDRESS — high byte of subroutine to call. 

where ADDRESS is the address of a subroutine to call. 

depends on subroutine at ADDRESS. 

depends on subroutine at ADDRESS. 

CallRoutine offers a clean and simple way to perform an indirect jsr through a 
vector or call a subroutine with an address from a jump table. Before simulatin a 
jsr to the address in the x and a registers, it also checks for a null address 
($0(XX)). If the address is $(XXX) (x=$00 and a=$(X)), CallRoutine performs rts 
without calling any subroutine address. This makes it easy to nullify a vector or 
an entry in a jump table by using a $(XXX) value. 

GEOS frequentiy uses CallRoutine when calling through vectors. This is why 
placing a $00(X) into keyVector, for example, causes GEOS ignore the vector. 
Other examples of tiiis usage are intTopVec, intBotVec, and mouse Vector. 

CallRoiitine modifies the st register prior to performing the jsr. It, therefore, 
cannot be used to call routines that expect processor status flags as parameters 
(flags may be returned in the st register, however). CallRoutine may be called 
from Interrupt Level (off of routines in IntTopVec and IntBotVec). Do not use 
CallRoutine to call inline (i_) routines, as it will not return properly. 



HandleCommand 



^******-'******<* ****** 



DESCRIPTION: Given a command number this routine handles dispatching 
control to the appropriate routine. 

PASSED: y command number 

RETURNS: depends on command 

DESTROYED: depends on command 

*************************************************************************** 



HandleCommand : 

cpy #T0T_CMDS-1 
bgt 99$ 
Idx CMDtabH,y 
Ida CMDtabL,y 
jsr CallRoutine 

99$: 

rts 



/ check command # against last cmd num 

; exit if command is invalid 

; get high byte routine address 

; get low byte of routine address 

; call the routine 

s 

; exit 



; The table below is a collection of the the high/low bytes of the routine 
; associated with each command number. If a command is not yet implemented. 



4 



CallRoutine 



; use the UNIMPLEMENTED constant (SOOOO) to have it ignored, 
UNIMPLEMENTED » $0000 ; CallRoutine ignores this 



CMDtabH: 

.byte 
.byte 
.byte 
.byte 
.byte 
.byte 



/high bytes 

] UNIMPLEMENTED 

ICmdl 

]Cmd2 

]Cmd3 

)Cmd4 

ICmdS 



command 
command 1 
command 2 
command 3 
command 4 
command 5 



CMDtabL: 

.byte 
.byte 
.byte 
.byte 
.byte 
.byte 



;low bytes 

[UNIMPLEMENTED 

(Cmdl 

[Cmd2 

(Cmd3 

[Cmd4 

(Cmd5 



command 
command 
command 
command 
command 
command 



TOT CMOS 



(CMDtabL-CMDtabH) /total number of commands 



See also: 



JsrToAux 



5 



CancelPrInt 



CancelPrint (Apple) 



printer driver 



Function: 

Parameters: 

Returns: 

Destroys: 

Description: 

Note: 
See also: 



Cancel printing immediately, clearing any buffers on the printer card or printer, 
none. 

X STATUS — printer error code; $00 = no error, 

assume a, y, r0-r4. 

CancelPrint instructs the printer driver to cancel the current printing operation, 
clearing any data already accumulated in a buffer on the printer or the printer card. 
Its main use is to allow tihe application to have the printer really stop printing if the 
user decides to cancel. 

The CancelPrint routine does not work properly in the first and second versions 
of most Apple printer drivers. 

StopPrint. 



I 

i 



6 



ChangeDiskDevice 



ChangePiskPevice (C64, cns) 



very low-level disk] 



Function: 

Parameters: 

Uses: 

Returns: 

Alters: 

Destroys: 
Description: 



Instruct a drive to change its serial device number. 

a hffiWDEVNUM — new device number to give current drive (byte). 

curDrive drive whose device number will change. 

X error ($00 = no error). 



curDrive 
curDevice 

a, y. 



NEWDEVNUM. 
NEWDEVNUM. 



ChangeDiskDevice requests the turbo software to change the serial device 
number of the current drive. Most applications have no need to call this routine, 
as it is in the realm of low-level disk utilities. ChangeDiskDevice is used 
primarily by the deskTop and Configure programs to add, rearrange, and remove 
drives. 



Be aware that changing the device number merely instructs the turbo software in 
the drive to monitor a different serial bus address. Many internal GEOS variables 
and disk drivers expect the original device number to remain unchanged 

Note: If ChangeDiskDevice is used on a RAMdisk, curDrive and curDevice both 

change. However, because of the natiure of the RAMdisk driver, the RAMdisk 
does not respond as this new device. 



Apple: Apple GEOS has no ChangeDiskDevice equivalent. 

See also: SetDevice. 



7 



ChkDkGEOS 



ChkDkGEOS (C64, ci28) 



mid-level disk! 



Function: 
Parameters: 

Returns: 
Alters: 

Destroys: 
Description: 



Check Commodore disk for GEOS format 



Apple: 
Example: 



r5 

nothing 

isGEOS 

st 



DIRHEAD — address of directory header, should always point to 
curDirHead (word). 



set to TRUE if disk is a GEOS disk, otherwise set to 
FALSE. 

set according to valu in isGEOS. 



ChkDkGEOS checks the directory header for the version string that flags it as a 
GEOS disk (at OFF^GEOS^ID). The primary difference between a GEOS disk 
and a standard Commodore disk is the addition of the off-page directory and the 
possiblity of GEOS files on the disk. GEOS files have an additional file header 
block that holds the icon image and other information, such as the author name 
and permanent name string. To convert a non-GEOS disk into a GEOS disk, use 
SetGEOSDisk. 

OpenDisk automatically calls ChkDkGEOS. As long as OpenDisk is used 
before reading a new disk, applications should have no need to call 
ChkDkGEOS. 

All ProDOS disks are GEOS compatible. 



.if (064 I IC128) 

jsr GetDirHead 
txa 

bne 99$ 

LoadW r5, #curDirHead 

jsr ChkDkGEOS 

beq 40$ 
; code here to handle GEOS disk 

bra 99$ 
50$: 

. code here to handle non-GEOS disk 



read in the directory header 
check status 
exit on error 
point to directory header 
Check for GEOS disk 
if not a GEOS disk, branch 

; jump to exit 



See also: 



99$: rts 

SetGEOSDisk. 



exit 



8 



ClearCard 



ClearCardjAppie) 



card driver I 



Function: Instructs the interface card to stop transmitting data and clear its internal buffer if 
it has such a feature. 



Parameters: none. 

Returns: x 

Destroys: a, y. 
Description 



Note: 
See also: 



STATUS — card error code; $00 = no error (byte) 



ClearCard instructs the interface card to immediately stop sending data and clear 
its internal buffer if it has such a feature. ClearCard is designed to be called by 
CancelPrint to abort any buffered print data, but, because this feature is rarely 
supported by interface cards, most printer drivers omit this call to save space. 

ClearCard must be called after an OpenCard and before a CloseCard. 

CancelPrint. 



9 



ClearMouseMode 



CiearMouseMode (Apple, C64, ci28) 



mouse/sprite 



Function: 
Parameters: 
Returns: 
Alters: 

Destroys: 
Description: 



Stop monitoring the input device. 



nothing. 

nothing. 

mouseOn 
mobenble 

a, X, y, r3L 



set to $00, totally disabling all mouse tracking 
sprite M) bit cleared by DisablSprite. 



ClearMouseMode instructs GEOS to totally disable its monitoring of the input 
device. It clears mouseOn to reset mouse tracking to its cleared state and calls 
DisablSprite. Applications will normally not have a need to call this routine. It 
is the functional opposite of StartMouseMode. 



See also: 



StartMouseMode, MouseOff. 



10 



ClearRam 



ClearRam (Apple, C64, cm) 



memoryl 



Function: 
Parameters: 

Returns: 

Destroys: 

Description: 

Note: 

Example: 



Clear a region of memory to $00. 



rl 
rO 

nothing. 



ADDR — address of area to clear (word). 

COUNT — number of bytes to clear (0 - 64K) (word). 



a, y, rO, rl, r2L ' 

ClearRam clears COUNT bytes starting at ADDR to $00. It useful for 
initializing ramsect variable and data sections. 

Do not use ClearRam to initalize rO through r2L. Also, for when space is at a 
premium, it actually takes fewer bytes to call i_FillRam with a fill value of $00. 



initialize buffers and variables to zero 

LoadW rO,#varStart ; clear variable space 

LoadW rl, # (varEnd-varStart) ; 

jsr ClearRam ; 

LoadW rO, #heapStart ; clear heap 

LoadW rl, # (heapEnd-heapStart) / 

jsr ClearRam ; 



See also: 



FiliRam, InitRam. 



11 



Clockint 



ClOCkInt (Apple) 



clock driver! 



Function: 

Parameters: 

Alters: 



Destroys: 
Description: 



Example: 



Qock driver Interrupt Level routine. Called by GEOS during Interrupt Level, 
none. 

(usually) year 
month 
day 
hour 
minutes 
seconds 

assume a, x, y, r0-rl5. 

GEOS calls Ciockint during Interrupt Level, which allows a clock driver to 
have an Interrrupt Level routine.This facility is used primarily by the software 
clock, which expects to be called approximately FRAME RATE times per 
second. Every time Clockint gets called, the software clock decrements a 
counter that is initialized to FRAME^RATE. When the counter reaches zero, 
approximately one second has elapsed. 

Hardware clock drivers usually have a Clockint routine that simply performs an 
rts. 



.if (APPLE) ; clock drivers only exist in Apple GEOS 
.★*★ Sample Clockint clock driver routine *** 

************************************************************** 

;o Clockint 



/Synopsis: 



This is called at interrupt level for the software clock. 



/Author: Andrew Wilson January 1988 

/Called by: Interrupt Level through clock driver jump table 

/Pass: nothing 

/Returns: nothing 

/Alters: assume a, x, y, r0-rl5 

* ***************************** 



o ReadClockInt: 




Ida 


hour 


; if nothing set, exit 


ora 


minutes 




ora 


seconds 




ora 


year 




ora 


month 




ora 


day 




beq 


90$ 




dec 


counter t 


• have a second's worth of int's occurred 


bpl 


90$ 


• branch if it hasn't happened 


/ this code 


happens once a second. 


assuming interrupts weren't shut off 


Idx 


#FRAME__RATE-1 


• counter <- (interrupts/second)-! 


stx 


counter ' < 




Idx 


#60-1 


? X <- seconds/minute (and min/hr) 






• (actually, one less so we can use bge 






r branch, which is smaller) 


inc 


seconds , 


r add one second to clock 



12 



Clockint 



cpx 
bge 



seconds 
90$ 



; do we add another minute? 
; branch if seconds don't roll 



; this code happens roughly once a minute, assuming interrupts weren't off 



Ida 
sta 
inc 
cpx 
bge 



#0 

seconds 
minutes 
minutes 
90$ 



; reset seconds 

; save the new seconds 

; add one to minutes 

; do we add another hour? 

; branch if minutes don't roll 



; this code happens once an hour, assuming interrupts weren't off 



sta 
inc 
Idx 
cpx 
bge 



minutes 

hour 

#24-1 

hour 

90$ 



; reset minutes 

/ add another hour to the software clock 

; x <- (hours/day) -1 

; do we add another day 

; branch if hours don't roll 



; this code happens once a day, assuming interrupts are off 



50$: 



sta hour 

inc day 

Idy month 

Ida #28+1 

sta febMonth 

Ida year 

and #%00000011 

bne 50$ 

inc febMonth 

Ida daysInMonth-l,y 

cmp day 

bne 90$ 



zero hours 
add another day 
get the current month 
febMonth <- days in February+1 

check for leap year 
(nice and convenient that 4 

is a power of 2) 
if leap year, then one more day in Feb. 

; see if the current day ends the month 
; compare 

; branch if month doesn't roll 



; this code happens once a month, assuming the computer lasts that long... 



Idx 
stx 
inc 
Ida 
cmp 
bit 



#1 

day 

month 

month 

#12 

90$ 



first day of month 

save it 

add one month 

see if we're past the last month 



; this code happens once a year. It rolls over in 1999, and so we'll need 
; a new clock driver before then... 



90$: 



Ida 
sta 
inc 

rts 



#1 

month 
year 



first month of the year 

new year 

exit 



See also: 



; daysInMonth is the number of days in each month. It actually co/itains 
; number of days plus one since we increment days before we check. 

daysInMonth: .byte 32 

febMonth: .byte 29 ; February is modified on leap years 

.byte 32,31,32,31,31,32,31,32,31,32 

.endif ; (APPLE) 

ReadClock, AuxDInt. 



13 



CioseCard 



CloseCard (Apple) 



card driver 



Function: 
Parameters: none 
Returns: x 
Destroys: a, y. 
Description 



Qose access to interface card 



STATUS — card error code; $00 = no error (byte) 



Example: 



CloseCard closes access to the interface card. It is the functional opposite of 
OpenCard. The printer driver sends blocks of data to the printer between calls to 
OpenCard and CloseCard. The CloseCard routine in most card drivers 
simply returns without an error, but printer drivers should always bracket their 
access to die card driver between calls to OpenCard and CloseCard. 



.if (APPLE) ; card drivers 
; Initialize the card 



only exist on Apple GEOS 



Dsr 
txa 
bne 



InitCard ; 
90$ 

; Open the card so we access the printer 
OpenCard 



call card driver init routine 
check status 
branch if error 



jsr 

txa ; 
bne 90$ ; 

; Initialize printer 

Idy #PRINITCODE ; 

jsr OutputByte ; 

txa ; 

bne 90$ / 

; Close the card and exit 

jsr CloseCard ; 

90$: 

rts 

.endif ; (APPLE) 



call card driver open routine 
check status 
branch if error 



y <- control code to init printer 
send through card to printer 
check status 
branch if error 



call card driver close routine 
exit with error in x 



See also: OpenCard. 



14 



CloseRecordFile 



CloseRecordFile (Apple, C64, cns) 



VLIR disk 



Function: Close the current VLIR file (updating it in the process) so that another may be 
opened 



Parameters: none. 
Uses: 



Returns: 
Alters: 



curDrive 
fileWrittent 

fileHeader 
fileSize 

dirEntryBuf 



if FALSE, no updating occurs because file has not been 
written to. 

VLIR index table stored in this buffer, 
total number of disk blocks used in file (includes index 
block, GEOS file header, and all records), 
directory entry of VLER file. 



year, month, day, hours, minutes for date-stamping file. 



Cpmrnodorg; 

curType 

curDirHead 

dir2Headt 

dir3Headt 

A pple: 
fileBytes 

curVBlknot 

VBMchangedt 

numVBMBlkst 



GEOS 64 V 1.3 and later for detecting REU shadowing, 
this buffer must contain the current directory header. 
(BAM for 1571 and 1581 drives only) 
(BAM for 1581 drive only) 



total number of bytes in file (written to bytes 254, 255, 511, 
and 512 of the master index block), 
used by VBM cacheing routines, 
used by VBM cacheing routines, 
used by VBM cacheing routines. 



set to FALSE to indicate that file hasn*t been altered since 
last updated. 

used for temporary storage of the directory block. 



Destroys: 
Description: 

C64 & C128: 

Example: 
See also: 



^used internally by GEOS disk routines; applications generally don't use 
X error ($00 = no error). 

fileWrittent 
diskBlkBuf 

^used internally by GEOS disk routines; applications generally don't use. 
a, y, rl, r4, rS. 

CloseRecordFile first calls UpdateRecordFile then closes the VLIR file so 
that another may be opened. 

Because Commodore GEOS stores the BAM in global memory, the application 
must be careful not to corrupt it before the VLIR file is updated or closed. For 
more information, refer to UpdateRecordFile. 

See example at AppendRecord. 

OpenRecordFile, UpdateRecordFile. 



15 



CmpFString 



CmpFString (Apple, C64, ci28) 



string! 



Function: 
Parameters: 



Returns: 

Destroys: 

Description: 



Note: 
Example: 



Compare two fixed-length strings. 

X SOURCE — zero-page address of pointer to source string (byte pointer 

to a word pointer). 

y DEST — zero-page address of pointer to destination string (byte pointer 

to a word pointer). 

a LEN — length of strings (1-255). A LEN value of $00 will cause 

CmpFString to function exacdy like CmpString, expecting a null- 
terminated source string. 

s t status register flags reflect the result of the comparison. 

a, X, y 

CmpFString compares the fixed-length string pointed to by SOURCE to the 
string of the same length pointed to by DEST. 

CmpFString with a LEN value of $00 causes the routine to act exactly like 
CmpString. 

CmpFString compares each character in the strings until there is a non-matching 
pair. The result of the comparison between the non-matching pair is passed back 
in the processor status register (st). If the strings match, the z flag is set. This 
allows the application to test the result of a string comparison with standard test 
and branch operations: 

bne branch if strings don't match 

beq branch if strings match 

bcs branch if source string is greater than or equal to dest string 

bee branch if source string is less than dest string 

The strings may contain internal NULL'S. These will not terminate the 
comparison. 



REG SIZE 



16 



;size of each record 



Find: 



LoadW 


r2,#NUM_RECS 


• r2 <- total number of records 


LoadW 


rO,#Key 


• rO <- pointer to keyword 


LoadW 


rl,#Data , 


• rl <- pointer to start of search list 


10$: 




• DO 


Idx 


#rO 


X <- source string « key , 


Idy 


#rl 


y <- dest string * list 


Ida 


#REC_SIZE 


a <- length of each record 


jsr 


CmpFString < 


r compare key with current record 


beq 


20$ 


if they match, branch 


AddVW 


#REC SIZE^rl 


otherwise point to the next record 


DecW 


r2 


r2 — (decrement counter) 


bne 


10$ 


• WHILE (r2 > 0) 


; code to 


handle no matches goes here 


rts 







16 



CmpFStrIng 



. code to handle a match goes here 

rts 

Key: .byte "alpha " 
Data: 

.byte "ZETA 

.byte "0123456789ABcDeF" ' 

.byte "gAMma over beta " 

.byte "stewardesses " 

.byte "123ABC123abc 

.byte "abcdefghi jklmnop" 

.byte "qrstuvwxyz012345" 

•byte "stewardess " 

.byte "beta " 

.byte "alpha 

.byte "delta " 

.byte "steward " 
EndData: 

NUM__RECS « ( (EndData-Data) /REC_SIZE) 

.if ( (Data + NUM_RECS*REC_SIZE) *) 

.echo Something is wrong with sort data 



.endif 

See also: CmpString, CopyFString. 



17 



CmpStrIng 



CmpString (Apple, C64, cns) string] 

Function: Compares two null-terminated strings. 

Parameters: x SOURCE — zero-page address of pointer to source string (byte pointer 

to a word pointer). 

y DEST — zero-page address of pointer to destination string (byte pointer 

to a word pointer). 

Returns: st status register flags reflect the result of the comparison. 
Destroys: a, x, y 

Description: CmpString compares the null-terminated source string pointed to by SOURCE 
to the destination string pointed to by DEST. The strings are compared a byte at a 
time until either a mismatch is found or a null is encountered in both strings. 
CmpString expects the strings to be the same length; strings of different lengths 
are treated as not matching. 

CmpString compares each character in the strings until tiiere is a non-matching 
pair. The result of the comparison between the non-matching pair is passed back 
in the processor status register (st). If the strings match, the z flag is set. This 
allows the application to test the result of string comparison with standard test and 
branch operations: 



bne branch if strings don't match 

beq branch if strings match 

bcs branch if source string is greater than or equal to dest string 

bee branch if source string is less tiian dest string 



Note: CmpString cannot compare strings longer than 256 bytes (including the null). 

The compare process is aborted after 256 bytes. 

Example: 

Findi2: 





LoadW 


rO,#Original 


; rO <- pointer to original string 




LoadW 


rl, #Copy 


; rl <- pointer to copy 




Idx 


#rO 


; X <- source string =* key 




Idy 


#rl 


; y <- dest string « list 




jsr 


CmpString 


; compare the strings 




beq 


20$ 


/ if they match, branch 




code to 


handle no matches goes here 




rts 








code to 

TZ3 


handle a match 


goes here 


Origi 










.,/ce 


"Mark Charles 


Heartless", NULL 


Copy: 










.byte 


"Mark Charlie 


Heartless", NULL 



See also: CmpFString, CopyString. 



18 



CopyFString (Apple, C64, cns) 



string! 



Function: 
Parameters: 



Returns: 

Destroys: 

Description: 



Note: 
Example: 



Copy a fixed-length string. 

X SOURCE — zero-page address of pointer to source string (byte pointer 
to a word pointer). 

y DEST — zero-page address of pointer to destination buffer (byte pointer 
to a word pointer). 

a LEN — length of string (1-255). A LEN value of $00 will cause 
CopyFString to function exactiy like CopyString, expecting a null- 
terminated source string. 

Buffer pointed to by DEST contains copy of source string. 

a, X, y 

CopyFString copies a fixed-length string pointed to by SOURCE to the buffer 
pointed to by DEST. If Uie source and destination areas overlap, the source must 
be lower in memory for the copy to work properly. 

Because the LEN parameter is a one-byte value, CopyFString cannot copy a 
string longer tiian 255 bytes. A LEN value of $00 causes CopyFString to act 
exacdy like CopyString. 

The source string may contain internal NULL'S. These will not terminate the 
copy operation. 



LoadW 

LoadW 

Idx 

Idy 

Ida 

jsr 

SrcString: 

LENSTRING 

.ramsect 

DestString 

•psect 



r5, #SrcString 

rll,#DestString 

#r5 

#rll 

# LENSTRING 
CopyFString 



point to start of source string 
point to start of destination string 
X <- source register address 
y <- dest register address 
a <- length of string 
DestString <- SrcString (copy) 



.byte -This is a string", CR, LF 
- (*-SrcString) 

.blocJc LENSTRING 



See also: CopyString, CmpFString, M oveData. 



19 



CopyFullScreen 



CopyFullScreen (Apple) 



graphics! 



Function: 
Parameters: 



Destroys: 
Description: 

Note: 
Example: 



Copy a rectangle of the full width of the screen to another position vertically. 
Operates only on the foreground screen. 

rOL SRCYl — top line of source region (byte). 
rOH SRCY2 — bottom line of source region (byte). 
r3L DESTY — top line of destination (byte). 

where (0, SRCYl) defines the upper-left corner of the source rectangle, 
(SCJPIXJVIDTH'1,SRCY2) defines the lower-right corner of the source 
rectangle, and (Oj:>ESTY) defines the upper-left corner of the destination. 

a, X, y, rO, r3L 

CopyFullScreen is optimized to quickly copy a rectangular area of the full 
width of the screen. It copies the desired lines from the source to the destination 
(which may overlap if necessary). The copy only occurs on the foreground 
screen. 

No clipping at the screen top or bottom is performed; the values passed are 
assumed to lie entirely within tiie screen boundaries. 



.if (APPLE) 
SCROLL_TOP 
SCROLL__BOT 
SCROLL INC 



» SC_PIX_HEIGHT-1 
= 2 



top line of scroll region 
bottom line of scroll region 
lines to scroll 



ScrollUp: 

LoadB rOL, #SCROLL_TOP+SCROLL_INC 
LoadB rOH, #SCROLL_BOT 
LoadB r3L, #SCROLL_TOP 
jmp CopyFullScreen 

ScrollDown : 

LoadB rOL, #SCROLL__TOP 

LoadB rOH, #SCROLL_BOT-SCROLL_INC 

LoadB r3L, #SCROLL_TOP+SCROLL_INC 

jmp CopyFullScreen 
.endif ; (APPLE) 



rOL <- top of source 

rOH <- bottom of source 

r3L <- destination 

scroll, let CopyFullScreen rts 



rOL <- top of source 

rOH <- bottom of source 

r3L <- destination 

scroll, let CopyFullScreen rts 



See also: CopyLine, CopyScreenBlock 



20 



CopyLine 



CopyLine (Apple) 



graphics! 



Function: 
Parameters: 



Uses: 

Destroys: 
Description: 

Note: 



Example: 
See also: 



Copy a horizontal line to another pixel location; operates on pixel boundaries. 

r 1 SRCXl — x-co6rdinate of left edge of source line (word). 
r2 SRCXl — x-coordinate of right edge of source line (word). 
rOL SRCY — y-coordinate of source line (byte). 
r4 DESTX — x-coordinate of left edge of destination (word). 
r3L DESTY — y-coordinate of destination (byte). 

where (SRCXl, SRCY) and (SCRC2,SRCY) define the endpoints of the line to 

move to (DESTX,DESTY). 

dispBufferOn: 

bit 7 — copy from foreground screen if set. 
bit 6 — copy from background buffer if set 
If both bits are set, copy occurs on both screens. 

a, X, y 

CopyLine copies pixels from a horizontal source line to a destination line. The 
source and destination coordinates may lie on any pixel boundary. Pixels will be 
shifted if necessary. The source and destination may overlap. 

No clipping at the screen edge is performed; the values passed are assumed to lie 
entirely within the screen boundaries. Also, the copying is appreciably faster if 
the left-edge x-coordinates of the source and destination lie on the same bit- 
boundary. That is, if (SRCXl IP ) == {DESTX II 7). 



CopyFullScreen, CopyScreenBlock 



J 



21 



CopyScreenBlock 



CopyScreenBlock (Apple) 



graphics} 



Function: 
Parameters: 



Uses: 



Copy a rectangular portion of the screen to another area. 

rl SRCXl — x-coordinate of upper-left of source (word), 

rOL SRCYl — y-coordinate of upper-left of source (byte) 

r2 SRCX2 — x-coordinate of lower-right of source line (word). 

rOH SRCY2 — y-coordinate of lower-ri^t of source (byte). 

r4 DESTX — x-coordinate of upper-left of destination (word). 

r3L DESTY — y-coordinate of upper-left of destination (byte). 

where (SRCXl, SRCYl) defines the upper-left corner of the source rectangle, 
(SCRCX2,SRCY2) defines the lower-right corner of the source rectangle and 
(DESTXJDESTY) defines the upper-left corner of the destination. 

dispBufferOn: 

bit 7 — copy from foreground screen if set. 
bit 6 — copy from background buffer if set 
If both bits are set, copy occurs on both screens. 



Destroys: a, x, y 
Description: 



Note: 



CopyScreenBlock copies pixels from a source rectangle to a destination 
rectangle. The source and destination coordinates may lie on any pixel boundary. 
Pixels will be shifted if necessary. The source and destination rectangles may 
overlap. 

No clipping at the screen edge is performed; the values passed are assumed to lie 
entirely within the screen boundaries. Also, the copying is appreciably faster if ^ 
the left-edge x-coordinates of the source and destination lie on the same internal ' 
bit-boundary. That is, if (SRCX1%7) == (DESTX%7). 



Example: 



.if (APPLE) 

;*** Window Coordinate Constants *** 



WIN__X 

WIN_WIDTH 

WIN~Y 

WIN^HEIGHT 

WIN_X2 

WIN_Y2 

SCROLL^INC 

ScrWinUp: 
Jsr 



LoadB 
LoadB 
LoadB 
jmp 

ScrWinDown : 
Jsr 



= 20 
« 85 
» 40 

- 110 

- win_x+win_width 
» win"y+win_hieght 

- 2 

; scroll window up 
SetScrXPositions 



rOL, #WIN_Y+SCROLL_INC 
rOH,#WIN_Y2 
r3L, #WIN_Y 
CopyScreenBlock 

; scroll window down 
SetScrXPositions 



pixel x-position (left edge) 

pixel width 

y-position 

height 

right edge x-position 
bottom edge y-position 

lines to scroll 



set the x-coordinates for scroll 
rl <- left edge source 
r2 <- right edge source 
r4 <- left edge dest (== rl) 

rOL <- top of source 

rOH <- bottom of source 

r3L <- top edge of dest 

scroll, let CopyScreenBlock rts 



set the x-coordinates for scroll 



22 



CopyScreenBlock 



LoadB rOL, #WIN__Y 

LoadB rOH, #WIN_Y2-SCR0LL_INC 

LoadB r3L, #WIN_Y+SCROLL_INC 

jmp CopyScreenBlock 



rl <- left edge source 

r2 <- right edge source 

r4 <- left edge dest («» rl) 

rOL <- top of source 

rOH <- bottom of source 

r3L <- top edge of dest 

scroll, let CopyScreenBlock rts 



SetScrXPositions : ; Set the common dimensions for up or down scroll 
— Following lines changed to save bytes 



LoadW 


rl,#WIN_ 


X 


rl <- left edge of source 


LoadW 


r4,#WIN" 


[x 


r4 <- left edge of dest 


Ida 


#[WIN_x" 




get low byte of left edge 


sta 


rlL 




and store it in low byte of 


sta 


r4L 




source and dest left edge 


Ida 


#)WIN_X 




do the same with the hi byte 


sta 


rlH 






sta 


r4H 






LoadW 


r2, #WIN_ 


_X2 


• r2 <- right edge of dest 


rts 






• exit 



.endif ; (APPLE) 



23 



Dabs (Apple, C64, C128) 



mathl 



Function: Compute absolute value of a two's-complemcnt signed word 

Parameters: x OPERAND — zero-page address of word to operate on (byte pointer to a 

word variable). 

Returns: x,y unchanged 

word pointed to by OPERAND contains the absolute value result 



Destroys: a 

Description: Dabs takes a signed word at a zero-page address and retumes its absolute value. 

The address of the word (OPERAND) is passed in x. The absolute value of 
OPERAND is returned in OPERAND. 



Example: 
SeeAlso: 



The equation involved is: if (value < 0) then value = -value. 



DNegate. 



41 



Ddec 



DdeC (Apple, C64, C128) 



mathl 



Function: 



Decrement a word 



Parameters: x 



OPERAND — zero-page address of word to decrement (byte pointer to a 
word variable). 



Returns: x,y unchanged 

St z flag is set if resulting word is $(XXX). 

zero page word pointed to by OPERAND contains the decremented word. 



Destroys: a 



Description: 



Ddec is a double-precision routine that decrements a 16-bit zero-page word 
Oow/high order), llie absolute address of the word is passed in x. If the result of 
the decrement is zero, then the the z flag in the status register is set and can be 
tested with a subsequent beq or bne. Ddec is useful for loops which require a 
two-byte counter. 



Example: 



COUNT 
counter 
Ida 
sta 
Ida 
sta 
Idx 

10$: 

nop 
jsr 
bne 



- $fffO 

- aO 

# (COUNT 
counter 
# 1 COUNT 
counter+1 
♦counter 



Ddec 
10$ 



/counter value 
•pseudoreg to count with 
;init pseudoregister 
;with counter value 



;tell Ddec which zp reg to use 

;do nothing in loop 

/decrement counter (x > reg addr.) 

;loop until done. 



42 



Ddiv 



Ddiv (Apple, C64, C128) 



math 



Function: Unsigned word-by-word (double-precision) division: divides one unsigned word 
by another to produce an unsigned word result 



Parameters: x 



Returns: 



OPERANDI — zero-page address of word dividend (byte pointer to a 
word variable). 

y 0PERAND2 — zero-page address of word divisor (byte pointer to a 
word variable). 

Note: result = OPERANDI (word) I OPERAND2(word). 

X, y, and word pointed to by OPERANDI unchanged, 
word pointed to by OPERANDI contains the result 
r8 contains the fractional remainder (word). 



Destroys: a, r9 

Description: Ddiv is an unsigned word-by-word division routine that divides the word at one 
zero-page address (the dividend) by the word at another (the divisor) to produce a 
16-bit word result and a 16-bit word fractional remainder The word in 
OPERANDI is divided by the word in OPERANDI and the result is stored as a 
word back in OPERANDI. The remainder is returned in r8. 



Note: Because rS and r9 are used in the division process, they cannot be used to hold 

operands. 

If the divisor {OPERANDI) is greater than the dividend (OPERANDI), then the 
fractional result will be returned as $0000 and OPERANDI will be returned in 
rS. 



Although dividing by zero is an undefined mathematical operation, Ddiv makes 
no attempt to flag this as an error condition and will simply return incorrect 
results. If the divisor might be zero, the application should check for tiiis situation 
before dividing as in: 



Ida 


zpage,y 


;get low byte of divisor 


ora 


zpage-»-l,y 


/get high byte of divisor 


bne 


10$ 


;if either non-zero, go divide 


Jmp 


OivideByZero 


/else, flag error 


jmp 


Ddiv 


/divide (Ddiv will rts) 



There is no possibUity of overflow (a result which cannot fit in 16 bits). 

Example: 

SeeAIso: DSdiv. DMuIt. BMult, BBMult, DivideBySeven. 



43 



DeleteDir 



DeleteDir (Apple) 



high-level disk 



Function: Delete a subdirectory from the current directory by freeing its directory blocks and 
removing its directory entry. The subdirectory must not contain any files to be 
deleted 



Parameters: rO 



DIRNAME — pointer to null-terminated directory name (must be in 
main memory.) (word). 



Uses: 



curDrive 

curKBlkno 

curVBIknot 

VBMchangedt 

numVBMBIkst 



current directory, 
used by VBM cacheing routines, 
used by VBM cacheing routines, 
used by VBM cacheing routines. 



Returns: 
Alters: 



^used internally by GEOS disk routines; applications generally don't use. 
X error ($(X) = no error). 



diskBlkBuf 
curVBIknot 
VBMchangedt 



used for temporary block storage, 
used by VBM cacheing routines. 

set to FALSE by VBM cacheing routines to indicate cached 
VBM block has already been flushed 



Destroys: 



^used internally by GEOS disk routines; applications generally don't use. 
a, y, rl, r4-r7, r8H. 



Description: Given the null-terminated name of an empty subdirectory, DeleteDir will 
remove the subdirectory from the disk by deleting its directory entry and calling 
FreeDir to free its chain of directory blocks. 

DeleteDir first calls FindFile to get the directory entry of the subdirectory. If 
the subdirectory does not exist in Ac current directory, a FILE^NOT^FOUND 
error is returned. A subdirectory is recognized by a PRO DIR in the CjEOS type 
byte in the directory entry (at OFF^FTYPE). 

DeleteDir will not delete a subdirectory that has files in it. A 
DIR_NOT EMPTY error will be returned. (The number of files in tiie 
subdirectoryls stored in the OFFB_FLCNT word of the directory's header. 
This maintains this value by calling UpdateParent when files are added or 
removed) 

C64 & C128: Commodore GEOS does not support a hierarchical file system. 



Example: 
See also: 



DeleteDir, DeleteFile, FreeFile, FreeBIock. 



44 



DeleteFile 



DeleteFile (Apple, C64, ci28) 



high-level disk| 



Function: 

Parameters: 

Uses: 



Returns: 
Alters: 



Destroys: 



Description: 



Delete a GEOS file by deleting the its directory entry and freeing all its blocks. 
Works on both sequential and VLIR files. 

rO FILENAME — pointer to null-terminated name of file to delete (Apple 
GEOS: must be in main memory,) (word). 

curDrive 

Cpmmpijorg; 
curType 

Apple: 

curVBlknot 
VBMchangedt 
numVBMBlkst 



GEOS 64 vl.3 and later for detecting REU shadowing. 



used by VBM cacheing routines, 
used by VBM cacheing routines, 
used by VBM cacheing routines. 



^used internally by GEOS disk routines; applications generally don't use. 
X error ($00 = no error). 



diskBlkBuf 
dirEntryBuf 

Commodore: 

curDirHead 

dir2Headt 

dirSHeadt 

flleHeader 

Apple; 

curVBlknot 
VBMchangedt 



used for temporary block storage, 
deleted directory entry. 



BAM updated to reflect newly freed blocks. 
(BAM for 1571 and 1581 drives only) 
(BAM for 1581 drive only) 

temporary storage of index table when deleting a VLIR file. 



used by VBM cacheing routines. 

set to FALSE by VBM cacheing routines to indicate cached 
VBM block has already been flushed 



^used internally by GEOS disk routines: applications generally don't use. 

Commodore: 
a, y, r0-r9. 

Apple: 

a, y, rl, r2L, r4-r7, rSH, r9. 

Given a null-terminated filename, DeleteFile will remove it from the current 
directory by deleting its directory entry and calling FreeFile to free all the blocks 
in the file. 

DeleteFile first calls FindFile to get the directory entry and ensure the file does 
in fact exist. If the file specified with FILENAME is not found, a 
FILE NOT FOUND error is returned. 



45 



DeleteFile 



C64 & C128: Since Commodore GEOS does not support a hierarchical file system, the "current 
directory" is actually the entire disk. The directory entry is deleted by setting its 
OFF^CFILE^TYPE byte to $00. 

Apple: Will only delete a file from the current directory. To delete a file from another 

directory, the application must change directories (refer to GoDirectory for 
moving to another directory). 

The directory entry is deleted by setting its OFF^FSTORE byte to $00. If this 
directory entry is the last in a particular directory block, the block is removed and 
the previous directory block's next-block pointer (at OFFB_NXTBLK) is 
given the deleted directory's next-block pointer, thereby maintaining the 
continuity of the directory block chain. 

After deleting the directory entry, DeleteFile calls UpdateParent to update the 
status bytes of the parent directory. 

DeleteFile cannot delete a subdirectory. To delete a subdirectory, use 
DeleteDir. 



Example: 
See also: 



DeleteDir, FreeDir, FreeFile, FreeBIock. 



DeleteRecord 



DeleteRecord (Apple, C64, ci28) 



VLIR disk! 



Function: 

Parameters: 
Uses: 



Returns: 
Alters: 



Destroys: 



Removes the current VLIR record from the record list, moving all subsequent 
records upward to fiU the slot and freeing all the data blocks associated with the 
record. 



none. 

curDrive 
fileWrittent 

curRecord 
fileHeader 

Commodore: 

curType 

curDirHead 

dir2Headt 

dir3Headt 

Apple; 

curVBlknot 

VBMchangedt 

numVBMBlkst 



if FALSE, assumes record just opened (or updated) and 

reads B AWVBM into memory. 

current record pointer 

VLIR index table stored in this buffer. 



GEOS 64 V 1.3 and later: for detecting REU shadowing, 
current directory header/B AM. 
(BAM for 1571 and 1581 drives only) 
(BAM for 1581 drive only) 



used by VBM cacheing routines, 
used by VBM cacheing routines, 
used by VBM cacheing routines. 



^used internally by GEOS disk routines; applications generally don't use 
X error ($00 = no error). 

« 

curRecord 
fileWrittent 



fileHeader 
fileSize 

Commodore! 
curDirHead 
dir2Headt 
dir3Headt 

Apple: 
fileBytest 



only changed if deleting the last record in the table, in which 
case it becomes the new last record, 
set to TRUE to indicate the file has been altered since last 
updated. 

new record added to index table. 

decremented to reflect any deleted record blocks. 



current directory header/BAM modified to finee blocks. 
(BAM for 1571 and 1581 drives only) 
(BAM for 1581 drive only) 



decremented to reflea any deleted record data. 
^used internally by GEOS disk routines: applications generally don't use. 
Applg; 

a, y, rl-r2, r4, r6, r7, r8H. 

Commodore: 
a, y, r0-r9. 



47 



DeleteRecord 



Description: DeleteRecord removes the current record from the record list by moving all 
subsequent records upward to fill the current record's slot. Any data blocks 
associated with the record are freed 

DeleteRecord does not update the B AMATBM and VLIR file information on the 
disk. Call CIoseRecordFile or UpdateRecordFile to update the file when 
done modifying. 

Example: 

See also: AppendRecord, InsertRecord. 



48 



DIsablSprite 



DisablSprite (Apple, C64, ci28) 



spritel 



Function: Disable a sprite so that it is no longer visible. 
Parameters: r3L SPRITE — sprite number (byte). 
Returns: nothing. 
Alters: mobenble 
Destroys: a, x 

Description: DisablSprite disables a sprite so that it is no longer visible. Although there are 
eight sprites available, an application should only directly disable sprite #2 
through sprite #7 with DisablSprite. Sprite #0 (the mouse pointer) is always 
enabled when GEOS mouse-tracking is enabled (disable mouse-tracking with 
mouseOff)* and sprite #1 (the text cursor) should be disabled with PromptOff. 



Example: 



See also: 



EnablSprite, MouseOff, PromptOff, DrawSprite, GetSpriteData, 
PosSprite, InitSprite. 



DivideBySeven 



DivideBySeven (Apple) 



graphics 



Function: 

Parameters: 

Returns: 

Destroys: 
Description: 

Note: 
Example: 



Quickly divide a word value (between and 649) by seven for direct screen 
access graphic operations. 

a ]DIVIDEND — high byte of word to divide by seven (byte), 
X [DIVIDEND — low byte of word to divide by seven (byte). 

a quotient (byte), 
y remainder (byte). 
X unchanged. 



DivideBySeven is a highly specialized divide routine designed for applications 
that require direct screen access. The Apple's double high-res screen is based on a 
seven-bit byte which requires dividing the x-posirion by seven to calculate the 
byte-position. The quotient is the byte position in a scanline and the remainder is 
the bit-position in that byte. DivideBySeven uses a series of lookup tables to 
quickly calculate the quotient and the remainder. 

Although the maximum screen x-position on the Apple is 559 
(SC^PIX^WIDTH - 1), DivideBySeven will handle values up to 649 so 
that graphics can be generated for 64()-column printer drivers. 

The average computational time for DivideBySeven is roughly 21 cycles. 



XorPoint — invert a single screen point on Apple. 

« 

Pass: r3 x-coordinate 



rllL y-coordinate 



Uses: 



dispBuf ferOn 



Destroys: 



a, X, rS, r6. 



XorPoint: 



jsr 
Idx 
jsr 
Ida 
Idx 
jsr 
pha 
tya 
tax 
Pla 
jsr 
Ida 



SetCorrectPage 
GrBit Table, X 



TempHideMouse 
rllL 

GetScanLine 



DivideBySeven 



r3H 
r3L 



/turn off sprites temporarily 
;get y-coordinate 

;set r5 and r6 with scanline addressses 
;get hi of x-coordinate 
;get lo of x-coordinate 
/calculate byte and bit offsets 
/save byte offset 

/transfer bit offset to x-register 
/to pass to SetCorrectPage 
/and put byte offset into a-reg 
/ (see GetScanLine reference) 
/get pixel bit-mask 
/xor pixel in first buffer 
/store into both buffers 
/if necessary 



eor 
St a 
sta 
rts 



(r6),y 
(r5),y 
(r6),y 



GrBit Table: 



.byte %00000001,%00000010,%00000100,%00001000 



50 



CONriDENTIAL 



DivideBySeven 



.byte %00010000,%00100000,%01000000,%10000000 

See also: GetScanLine, NormalizeX, DdiV. 



51 



DMult (Apple, C64, C128) 



math 



Function: 
Parameters: 

Returns: 

Destroys: 
Description: 

Note: 

Example: 
SeeAlso: 



Unsigned word-by-word (double-precision) multiply: multiplies two unsigned 
words to produce an unsigned word result 

X OPERANDI — zero-page address of word multiplicand (byte pointer to a 
word variable). 

y 0PERAND2 — zero-page address of word multiplier (byte pointer to a 
word variable). 

Note: result^ OPERANDI (word) * OPERAND2(word). 

X, y, word pointed to by OPERANDI unchanged, 
word pointed to by OPERANDI contains the word result. 

a, r6-r8. 

DMult is an unsigned word-by-word multiplication routine that multiplies the 
word at one zero-page address by the word at another to produce a 16-bit word 
result (all stored in low/high order). The word in OPERANDI is multipliod by the 
word in OPERANDI and die result is stored as a word back in OPERANDI. 

Because r6, r7 and r8 are destroyed in the multiplication process, they cannot be 
used to hold the operands. 

Overflow in the result (beyond 16-bits) is ignored. 



BMult, BBMult, Ddiv, DSdiv. 



This page Intentionally left blank to maintain right /left (verso/recto) 
page ordering. Final version will correct this. 



□negate 



Dnegate (Apple, C64, C128) math 



Function: Negate a signed word (two's complement sign-switch). 

Parameters: x OPERAND — zero-page address of word to operate on (byte pointer to a 

word variable). 

Returns: x,y unchanged 

word pointed to by OPERAND contains the negated word. 

Destroys: a 

Description: DNegate negates a zero-page word. The absolute address of the word 
(OPERAND) is passed in x. The absolute value of OPERAND is returned in 
OPERAND. 

The operation of this routine is: value = (value ^ $ffff) + 1. 

Example: 

SeeAlso: Dabs. 



52 



DoBOp 



DoBOp (C128) 



memory! 



Function : Back-RAM memory move/swap/verify primitive. 

Parameters: rO ADDRl — address of first block in application memory (word). 

r 1 ADDR2 — address of second block in application memory (word), 

r 2 COUNT — number of bytes to operate on (word). 

r3L AlBANK— ADDRl bank: = front RAM; 1 = back RAM (byte). 

r3H A2B ANK — ADDR2 bank: = front RAM; 1 = back RAM (byte), 

y MODE — operation mode: 









move from memory at ADDRl to memory at ADDR2. 





1 


move from memory axADDRl to memory n ADDRl. 


1 





swap memory at ADDRl with memory at ADDRl. 


1 


1 


verify (compare) memory at ADDRl against memory at ADDR2. 



Note: the DoBOp MODE parameter closely matches the low nyblle of the DoRAMOp 
CMD parameter. 

Returns: r0-r3 unchanged. 

When verifying: 

X $00 if data matches; $ff if mismatch. 
Destroys: a, x, y 

Description: DoBOp is a generalized memory primitive for dealing with both memory banks 
on the Commodore 128. It is used by MoveBData, SwapBData, and 
VerifyBData. 

Note: DoBOp should only be used on designated application areas of memory. When 

moving memory within the same bank, the destination address must be less than 
source address. When swapping memory within the same bank. ADDRl must be 
less than i4/?D/?2. 



Example: 
See also: 



MoveBData, SwapBData, VerifyBData, DoRAMOp. 



53 



DoDlgBox 



DoDlgBoX (Apple, C64, C128) dialog box| 

Initializes, displays, and begins interaction with a dialog box. 

rO DIALOG — pointer to dialog box definition (word). 
rS-rlO can be used to send parameters to a dialog box. 

rOL return code: typically the number of the system icon clicked on to exit 
Note: returns when dialog box exits through RstrFrmDialog. 

Destroys: n/a 

Description: DoDlgBox saves off the current state of the system, places GEOS in a near- 
warmstart state, displays the dialog box according to the definition table (whose 
address is passed in rO), and begins tracking the user's interaction with the dialog 
box. When the dialog box finishes, the original system state is restored, and 
control is returned to the application. 

Simple dialog boxes will typically contain a few lines of text and one or two 
system icons (such as OK and CANCEL). When the user clicks on one of these 
icons, the GEOS system icon routine exits the dialog box with an internal call to 
RstrFrmDialog, passing the number of the system icon selected in 
sysDBData. RstrFrmDialog restores the system state and copies 
sysDBData to rOL. 



Function: 
Parameters: 

Returns: 



More complex dialog boxes will have application-defined icons and routines that 

get called. These routines, themselves, can choose to load a value into 

sysDBData and call RstrFrmDialog. 

« 

Dialog boxes cannot be nested. That is, a dialog box should never call 
DoDlgBox. 

Apple: DoDlgBox automatically calls InitForDialog as part of its initialization 

sequence. 

Note: Part of the system context save within DoDlgBox saves the current stack 

pointer. Dialog boxes cannot be nested. DoDlgBox is not reentrant. That is, a 
dialog box should never call DoDlgBox. 

Example: 

See also: RstrFrmDlg, InitForDialog, RestoreSysRam, SaveFG. 



54 



Dolcons 



DoICOnS (Apple, C64, C128) 



icon/men 



Function: Display and activate an icon table. 

Parameters: rO ICONTABLE — pointer to the icon table to use. 

Uses: dispBufferOn: 

bit 7 — draw icons to foreground screen if set. 
bit 6 — draw icons to background screen if set. 

Destroys: r0-rl5, a, x, y 



Description: 



Dolcons takes an icon, draws the enabled icons (those whose 
OFF_PIC_ICON word is non-zero) and instructs MainLoop to begin tracking 
the user's interaction with the icons. This routine is the only way to install icons. 
Every application should install at least one icon, even if only a dummy icon. 

If Dolcons is called while another icon table is active, the new icons will take 
precedence. The old icons are not erased from the screen before the new ones are 
displayed. 



Dolcons is a complex routine which affects a lot of system variables and tables. 
The following is an outline of its major actions: 

1: All enabled icons in the table are drawn to the foreground screen and/or the 
background buffer based on the value in dispBufferOn. 

2: StartMouseMode is called. If the OFF JC XMOUSE word of the icon 
table header is non-zero, then StartMouseMode loads mouseXPosition 
and mouse Yposition with the values in the OFF IC XMOUSE and the 
OFF IC^^YMOUSE parameters of the icon "table header (see 
StartMouseMode for more information). 

4: faultData is cleared to $00, indicating no faults. 

5: If the MOUSEON^BIT of mouseOn is clear, then die MENUON BIT 
is forced to one. Thii is because GEOS assumes that it is in a power-up"state 
and that nniouse tracking should be fully enabled. If the MOUSEON BIT bit 
is set, GEOS leaves the menu-scan alone, assuming that the currenFstate of 
the MENUON^BIT is valid 

6: The ICONSON^BIT and MOUSEON BIT bits of mouseOn are set, 
thereby enabling icon-scanning. " 

When an icon event handler is given control, rOL contains the number of the icon 
clicked on (beginning with zero) and rOH contains TRUE if the event is a 
double-click or FALSE if the event is a single click. 

Example: 

See Also: DoMenu. 



55 



DoinlineReturn 



DoInlineReturn (Apple, C64, cus) 



utility 



Function: 
Parameters: 

Returns: 

Uses: 

Destroys: 

Description: 



Note: 



Return from an inline subroutine. 



a 



DATABYTES — number of inline data bytes following the jsr plus 
one(byte). 

staj:k top byte on stack is the status register to return (execute a php just before 
calling). 

(to the inline jsr) x, y unchanged from the jmp DoInlineReturn. st register is 
pulled from top of stack with a pip. 

returnAddress return address as popped off of stack. 

a 

DoInlineReturn simulates an rts from an inline subroutine call, properly 
skipping over the inline data. Inline subroutines (such as the GEOS routines 
which begin with i ) expect parameter data to follow the subroutine call in 
memory. For example, the GEOS routine i_Rectangle is called in the following 
fashion: 



Jsr 
.byte 
.word 
Jsr 



XI, X2 



i_Rect angle 



; subroutine call 
/Inline data 



FrameRectangle 



; returns to here 



Now if i_Rectangle were to execute a normal rts, the program counter would 
be loaded with the address of the inline data following the subroutine call. 
Obviously, inline subroutines need some means to resume processing at the 
address following the data. DoInlineReturn Provides this facility. The normal 
return address is placed in the global variable returnAddress. This is the return 
address as it is popped off the stack, which means it points to the third byte of the 
inline jsr (an rts increments the address before resuming control). TTie status 
registers is pushed onto the stack with a php, DoInlineReturn is called with 
the number of inline data bytes plus one in the accumulator, and control is 
returned at the instruction following the inline data. 

Inline subroutines operate in a consistent fashion. The first thing one does is pop 
the return address off of the stack and store it in returnAddress. It can then 
index off of returnAddress as in Ida (return Address),y to access the inline 
parameters, where the y-register contains $01 to access the first parameter byte, 
$02 to access die second, and so on (not $00, $01, $02, as might be expected 
because the address actually points to the third byte of the inline jsr). When 
finished, the inline subroutine loads the accumulator with the number of inline 
data bytes and executes a jmp DoInlineReturn. 

DoInlineReturn must be called with a jmp (not a jsr) or an unwanted return 
address will remain on die stack. The x and y registers are not modificnd by 
DoInlineReturn and can be used to pass parameters back to the caller. Inline 
calls cannot be nested widiout saving the contents cf returnAddress. An inline 
routine will not work correctly if not called directly through a jsr (e.g., 
CallRoutine cannot be used to call an inline subroutine). 



56 



DolnlineReturn 



Example: 



; Invert icalLine 

; Inline version of VertlcalLlne. 
;Pass : 

; .word xl 
; . word x2 
; .byte yl 

l^VertlcalLine: 

V_BYTES - 5 /number of Inline bytes In call 

;Save away the inline return address 
PopW returnAddress 

;Load up VertlcalLlne * s parameters 



Idy 
Ida 
sta 



#V_BYTES 

(returnAddress) ,y 
rllL 



;get yl parameter first 



10$: 



dey 
Ida 
sta 
cpy 
bne 



(returnAddress) , y 

r3L-l,y 

#1 

10$ 



/load other params in a loop 
/They occupy consecutive GEOS 
/pseudoregisters, so this will. 
/wor)c correctly 



/Now 



call VertlcalLlne with registers loaded 
jsr VertlcalLlne 



/and 



do an inline return when we come back 
php 

Ida #V_BYTES+1 
jmp DolnlineReturn / 



•save St reg to return 
/# of bytes i 

/jump to inline return. Do not jsr! 




57 



DoMenu 



DoMenu (Apple, C64, cm) 



icon/menu 



Function: 
Parameters: 

Destroys: 
Description: 



Displays and activates a menu structure. 

rO MENU — pointer to the menu structure to display, 
a POINTER_OVER — which menu item (numbered starting with zero) to 
center the pointer over. 

r0-rl3, a, x, y 

DoMenu draws the main menu (the first menu in the menu structure) and 
instructs MainLoop to begin tracking the user's interaction with the menu. This 
routine is the only way to install a menu. 

If DoMenu is called while another menu structure is active, the new menu will 
take precedence. The old menu is not erased from the screen before the new menu 
is displayed. If the new menu is smaller (or at a different position) than the old 
menu, parts of the old menu may be left on the screen. A typical way to avoid this 
is to erase the old menu with a call to Rectangle, passing the positions of the 
main menu rectangle and drawing in a white pattern. However, a more elegant 
solution involves calling Recover AlIMenus, which will erase any extant menus 
by recovering from the background buffer. 

DoMenu is a complex routine which affects a lot of system variables and tables. 
The following is an outline of its major actions: 

1: Menu level (main menu) is drawn to the foreground screen. 

2: StartMouseMode is called. mouseXPosition and mouseYpositlon are 
set so that the pointer is centered over the selection number passed in a. 
Under Apple GEOS, if the the POINTER.OVER number in tiie accumulator 
has its high-bit set, then the mouse will not be repositioned Under GEOS 64 
and GEOS 128, DoMenu always forces the mouse to a new position. If you 
do not want the mouse moved, surround the call to DoMenu with code to 
save and restore the mouse positions. The following code fragment will install 
n>enus widiout moving the mouse. 



DoMenu2 : 



.if (APPLE) 

Ida 4$80 

jsr DoMenu 
.else ; (C64 i I C128) 
php 
sei 

PushH mouseXPos 

PushB mouseYPos 

Ida «0 

jsr DoMenu 

PopB mouseYPos 

PopW mouseXPos 

pip 

.endif 

rts 



;set high-bit so mouse is not repositioned 
;put up the menu 



; disable interrupts around call 



;save mouse x 

;save mouse y 

; dummy menu value 

/install menus (mouse will move) 

/restore original mouse y 

/restore original mouse x 

/restore interrupts 



58 



DoMenu 



3: SIowMouse is called. With a joystick this will kill all accumulated speed in 
the pointer, requiring the user to reacceleratc. With a proportional mouse, this 
will have no effect 

4: fauItData is cleared to $00, indicating no faults. 

5: If the MOUSEON^BIT of mouseOn is clear, then the ICONSON^BIT 
is forced to one. Thii is because GEOS assumes that it is in a power-upTstate 
and that mouse tracking should be fully enabled. If the MOUSEON BIT bit 
is set, GEOS leaves the icon-scan alone, assuming that the ICONSON_BIT 
is valid. 

6: The MENUON_,BIT and MOUSEON^BIT bits of mouseOn are set, 
thereby enabling menu-scanning. 

7: The mouse fault variables (mouseTop, mouseBottom, mouseLeft, and 
mouseRight) are set to the full screen dimensions. 

Example: 

See Also: Dolcons, GotoFirstMenu, DoPreviousMenu, ReDoMenu. 



59 



DoneWithIO 



DoneWithIO (C64, ci28) 



very low-level disk| 



Function: Restore system after I/O across the serial bus. 
Parameters: none. 
Returns: nothing. 
Destroys: a, y. 

Description: DoneWithIO restores the state of the system after a call to InitForlO. It 
restores the interrupt status, turns sprite DMA back on, returns the 128 to its 
original clock speed, and switches out the ROM and I/O banks if appropriate 
(only on C64). 

Disk and printer routines access the serial bus between calls to InitForlO and 
DoneWithIO. 

Apple: Apple GEOS has no DoneWithIO equivalent 

Example: See WriteBIock. 
See also: InitForlO. 



60 



DoPreviousMenu 



DoPreviousMenu (Apple, C64, cns) 



icon/menu 



Function: Retracts the current sub-menu and reactivates menus at the previous level. 

Parameters: none. 

Destroys: assume rO-rlS, a, x, y 



Description: 



Note: 



Example: 
See Also: 



DoPreviousMenu is used by a menu event handler to instruct GEOS to back up 
one level of menus, erasing the current menu from the foreground screen and 
making the parent menu active when control is returned to MainLoop. 
menuNumber is decremented. 

When using DoPreviousMenu, if the parent menu (the one which will be given 
control) is of type UN_CONSTRAINED, then the mouse must be manually 
repositioned over the parent menu. This can be done by loading 
mouseXPosition and mouseYPosition with values calculated from the menu 
structure. If the parent menu is of type CONSTRAINED, then the mouse is 
automatically positioned over the selection in the parent menu which led to tiie 
sub-menu. 

DoPreviousMenu may be called repeatedly to back up more than one level. 

Do not call DoPreviousMenu when the menu is at level (menuNumber = 
$00). The effects may be disasterous. 



DoMenu, GotoFirstMenu, ReDoMenu, RecoverMenu. 



61 



DoRAMOp 



DoRAMOp (C64 vL3 & C128) 



memory I 



Function: 
Parameters: 



Returns: 



Destroys: 



Primitive for communicating with REU (RAM-Expansion Unit) devices. 

rO ADDRl — address in Commodore to start (word). 

rl ADDR2 — address in REU bank to start (word). 

r2 COUNT — number of bytes to operate with (transfer length) (word). 

r3L REUB ANK — REU bank number to use (byte). 

y CMD — command to send to REU (byte). 



r0-r3 unchanged. 
X error code: 



$00 (no error) or DEV^NOT^FOUND if bank or REU 
not available. 
REU status byte and'ed with $60 



Description: DoRAMOp is a very low-level routine for communicating with a RAM- 
expansion unit on a C64 or C128. This routine is a "use at your own risk" GEOS 
primitive 



DoRAMOp operates with the with the RAM-expansion unit direcdy and handles 
all the necessary.communication protocols and clock-speed save/restore (if 
necessary). 

The CMD parameter is stuffed into the REC Command Register 
(EXP_BASE+$01). Although DoRAMOp does no error checking on this 
parameter, it expects the high-nybble to be %1001 (transfer with current 
configuration and disable FFOO decoding). The lower nybble can be one of the 
following: 

%00 Transfer from Commodore to REU. 
%01 Transfer from REU to Commodore. 
%10 Swap. 
%11 Verify. 

Note: the low nybble of the DoRAMOp CMD parameter closely matches the DoBOp 
MODE parameter. 

Note: On a Commodore 128, if the VIC chip is mapped to front RAM (with the MMU 

VIC bank pointer), the REU will read/write using front RAM. Similarly, if the 
VIC chip is mapped to back RAM, the REU will read/write using back RAM. The 
REU ignores the stadard bank selection controls on die 8510. GEOS 128 defaults 
with die VIC mapped to front RAM. 

For more information on the Commodore REU devices, refer to the Commodore 
1764 RAM Expansion Module User's Guide or die 170011750 RAM Expansion 
Module User's Guide. 



Example: 

See also: StashRAM, FetchRAM, SwapRAM, DoBOp. 



62 



DownDlrectory 



DownPirectory (Apple) 



mid-level disk 



Function: 
Parameters: r9 
Uses: 
Returns: 



Makes a subdirectory (child directory) in the current directory the new current 
directory. 

DIRENTRY — pointer to directory entry of subdirectory, usually points 
to dirEntryBuf (must be in main memory) (word). 



curDrive 
curKBlkno 



current directory. 



X error ($00 = no error), 
y pathname status ($00 = OK; BFR^OVERFLOW = pathname longer 
than pathnameBuO- 

Alters: curKBlkno new current directory. 

curDirHead header of new directory. 

pathnameBuf^ system pathname buffer updated to reflect new path. 

curDirTabLot 

curDirTabHit 

^used internally by GEOS disk routines; applications generally don't use. 
Destroys: a, rl, r4. 

Description: DownDirectory moves down one level in the hierarchical file system, making a 
specific child directory the current working directOTy. 

The directory entry of the subdirectory is a standard data structure returned by 
routines such as FindFlle, GetlstDirEntVy and GetNextDirEntry. A 
subdirectory has a PRO^DIR (ProDOS directory) GEOS file type. 

€64 & C128: Comnxxlore GEOS does not support a hierarchical file system. 
Example: 

See also: UpDirectory, GoDirectory. 



63 



PownPirootOFy 



IDrawLine (Apple, C64, ci28) graphksl 

Function: Draw, clear, or recover a line defined by two arbitrary endpoints. 

Parameters: r3 XI — x-coordinate of first endpoint (word). 

rllL Yl — y-coordinate of first endpoint (byte). 
r4 X2 — x-coordinate of second endpoint (word), 
r 1 IH Y2 — y-coordinate of second endpoint (byte). 
St MODE: 



n c Description 



1 


X 


recover pixel from backKfound screen to forejoound. 





1 


set Dixel usine dispBufferOn. 








clear pixel usine dispBufferOn. 



where (XI, Yl) and (X2J2) are the two endpoints of the line. 



Uses: if n is set (drawing, not recovering): 

dispBufferOn: 

bit 7 — write to foreground screen if set. 
bit 6 — write to background screen if set 

Returns: status register (S) unchanged 



Destroys: Commodore 

a, x, y, r3-rl3 



Apple 

a, X, y, r3, r4, rll 



Description: DrawLine will set, clear, or recover the pixels which comprise the line between 
two arbitrary endpoints. Setting a pixel sets its bit value to one, clearing a pixel 
sets its bit value to zero, and recovering a pixel copies the bit value from the 
background buffer to foreground screen. 

DrawLine uses the Bresenham DDA (Digital Differential Analyzer) algorithm to 
determine the proper points to draw. The line will be drawn correctiy regardless 
of which endpoint is used for (Xljl) and which is used for {X2J2). In fact, 
the line is reversible: the same line will be drawn even if the endpoints are 
swapped. 

The carry (c) flag and sign (n) flag in the processor status register (s) are used to 
pass information to DrawLine. The following tricks can be used to set or clear 
these flags appropriately: 

♦ Use sec and cic to set or clear the carry (c) flag. 

♦ Use Ida to set the sign (n) flag. 

♦ Use Ida #0 to clear the sign (n) flag. 



Note: 



Calculates each pixel position on the line and calls DrawPoint repeatedly. 



■ P uw nDlrcet e Fy 



128: Under GEOS 128, or*ing DOUBLE W into theX/ andX2 parameters will 

automatically double the x-position in 8D-column mode. Or'ing in ADDl^W will 
automatically add 1 to a doubled x-position, (Refer to "GEOS 128 X-posiuon and 
Bitmap Doubling" in Chapten@gr@ for more information,) 

Example: 

See also: HorizontaILIne,VerticaILine, InvertLine, ImprintLine, RecoverLine. 



fl ra w Line 



DrawPoint (Apple, C64, cm) 



graphics 



Function: 
Parameters: 



Set, clear, or recover a single screen point (pixel). 

r3 XI — x-coordinate of pixel (word), 
r 1 1 L Y 1 — y-coordinate of pixel (byte). 
St MODE: 



n 


c 


Description 


1 


X 


recover pixel from backjo-ound screen to foreground. 





1 


set pixel using dispBufferOn. 








clear pixel using dispBufferOn. 



Uses: 

Returns: 
Destroys: 



Description: 



128: 



Example: 
See also: 



where (XI, Yl) is the coordinate of the point. 

when setting or clearing pixels: 
dispBufferOn: 

bit 7 — write to foreground screen if set. 

bit 6 — write to background screen if set 

r3, rllL unchanged. 

Commodore 
a, X, y, r5-r6 

Applg 
a, X, y 

DrawPoint will set, clear, or recover a single pixel. Setting a pixel sets its bit 
value to one, clearing a pixel sets its bit value to zero, and recovering a pixel 
copies the bit value from die background buffer to foreground screen. 

The carry (c) flag and sign (n) flag in the processor status register (s) are used to 
pass information to DrawPoint. The following tricks can be used to set or clear 
these flags appropriately: 



• Use sec and cic to set or clear the carry (c) flag. 
Use Ida #[*! to set the sign (n) flag. 



Use Ida #0 to clear the sign (n) flag: 



Under CEOS 128, orlng DOUBLE^W into the XI will automatically double 
the x-position in 80-colunm mode. OFing in ADD1_W will automatically add 1 
to a doubled x-position. (Refer to "CEOS 128 X-po?ition and Bitmap Doubling" 
in Chapter.@grtg) for more information.) 



TestPoint, DrawLine. 



& f awP e i rrt 



DrawSprite (Apple, C64, ci28) 



sprite 



Function: 

Parameters: 

Returns: 

Alters: 

Destroys: 



Description: 



C64: 



C128: 



Apple: 



Example: 
See also: 



Copy a 64-byte sprite image to the internal data buffer that is used for drawing the 
sprites. 

r3L SPRITE — sprite number (byte). 

r4 DATAPTR — pointer to 64-bytes of sprite image data (word), 
nothing. 

internal sprite image. 

Commodore 
a, y, r5 

Applg 

a, y 

DrawSprite copies 64-bytes of sprite image data to the internal buffer that is 
used for drawing the sprites. DrawSprite does not affect the enabled/disabled 
status of a sprite, it only changes the image definition. 

Although there are eight sprites available, an application should limit itself to 
sprites #2 through #7 because GEOS reserves sprite #0 for the mouse cursor and 
sprite #1 for the text prompt. 

The 64 bytes are copied to the VIC sprite data area, which is located in memory 
immediately after the color matrix. The size information byte (byte 64) is unused 
by GEOS 64 but is copied to the data area, nonetheless. A SPRITE value of $00 
can be used to change the shape of the mouse cursor. 

The data is transferred to the VIC sprite area (regardless of the current graphics 
mode). This data is used by the VIC chip in 40-column mode and by the soft- 
sprite handler in 80-column mode. The last byte (byte 64) of the sprite definition 
is used as the size information byte by the soft-sprite handler. In 80-column 
mode, the sprite is not visually updated until the next time the soft-sprite handler 
gets control. To change the mouse cursor, the application can use a SPRITE value 
of $00 in 40-column mode or call SetMsePic in 80-column mode (doing both is 
a simple solution: it will do no harm regardless of the graphics mode). 

The data is transferred to an internal sprite area. The last byte (byte 64) of the 
sprite definition is used as the size information byte. The sprite is not visually 
updated until the next time the soft-sprite handler gets control. The soft-sprite 
handler will draw sprite #1 through sprite #7. In no case should the SPRITE 
parameter be $00; a value of $00 wUl most likely trample GEOS. 

The INAUX_B constant may be or'ed into the SPRITE parameter to indicate 
that the DATAPTR parameter is an address in auxiliary memory. 



GetSpriteData, PosSprite, EnablSprite, DisablSprite, InitSprite. 



DSdiv 



DSdiv (Apple, C64, C128) 



math I 



Function: Signed word-by-word (double-precision) division: divides one two's complement 
word by another to produce a signed word result. 

Parameters: x OPERANDI — zero-page address of signed word dividend (byte pointer 

to a word variable). 

y 0PERAND2 — zero-page address of signed word divisor (byte pointer to 
a word variable). 

Note: result = OPERANDI (word) I OPERAND2(word). 

Returns: y unchanged. 

r8 the fractional remainder (word). 

word pointed to by OPERANDI equals its absolute value. 

word pointed to by OPERANDI contains the word result. 

Commodore: 

X unchanged 

Destroys: a, r9 



A pple: 

X 



Description: DSdiv is a signed, two's complement word-by-word division routine that 
divides the word in one zero-page pseudoregister (the dividend) by the word in 
another (the divisor) to produce a 16-bit word signed result and a 16-bit word 
fractional remainder The word in OPERANDI is divided by the word in 
OPERANDI and the result is stored as a word back in OPERANDI with the 
remainder in r8. 

C64 & C128: The remainder is always positive regardless of the sign of the dividend. This will 
cause problems with some mathematical operations that expect a signed 
remainder. The following code fragment will fixe this problem: 



;NewDSdiv: 


call as you would 


call DSdiv. Returns a 




signed remainder. 


Destroys x! 




sign (remainder) - 


sign (dividend) 


NewDSdiv : 






Ida 


zpage,x 


;save sign of dividend 


php 






Jsr 


DSdiv 


; divide as normal 


pip 




;then get back sign of dividend back 


bpl 


20$ 


/ignore if positive 


Idx 


«r8 


;else, negate remainder 


jsr 


Dnegate 


/(e.g., -10/9 - -1 rem -1) 


20$: 






rts 







The sign of the remainder is the same as the sign of the dividend. 

Because r8 and r9 are used in the division process, they cannot be used to hold 
the operands. 



Apple: 
Note: 



68 



DSdiv 



Although dividing by zero is an undefined mathematical operation, DSdiv makes 
no attempt to flag this as an error condition and simply returns incorrect results. If 
the divisor might be zero, the application should check for this situation before 
dividing: 



Example: 
SeeAlso: 



10$: 



Ida zpage,y ;get low byte of divisor 

ora zpage+l,y ;get high byte of divisor 

bne 10$ ;if either non-zero, go divide 

jmp DivideByZero ;else, flag error 

jmp DSdiv ; divide (DSdiv will rts) 



Ddiv, DMult, BMult, BBMuIt, DivideBySeven. 



69 



I 

DShiftLeft 



DShiftLeft (Apple, C64, C128) 



math 



Function: 
Parameters: 

Returns: 



Arithmetically left-shift a zero-page word 

X 

y 



OPERAND — address of the zero-page word to shift (byte pointer to a 
word variable). 

COUNT — number of times to shift the word left (byte). 



a, X unchanged 
y #$ff 

St c (carry flag) is set with last bit shifted out of word. 

zero page address pointed to hy OPERAND contains the shifted word. 



Destroys: nothing 



Description: 



Note: 

Example: 

SeeAlso: 



DShiftLeft is a double-precision math routine that arithmetically left-shifts a 16- 
bit zero-page word (low/high order). The absolute address of the word is passed 
in X and the number of times to shift the word is passed in y. Zeros are shifted 
into the low-order bit 

An arithmetic left-shift is useful for quickly multiplying a value by a power of 
two. One left-shift will multiply by two, two left-shifts will multiply by four, 
three left-shifts will multiply by eight, and so on: value = value ♦ l^ount^ 

If a COUNT of $00 is specified, the the word will not be shifted. 



DSh:ftRight. 



70 



DShiftRight 



DShiftRight (Apple, C64, C128) 



math 



Function: 
Parameters: 

Returns: 



Arithmetically right-shift a zero-page word. 

X 

y 



OPERAND — zero-page address of word to shift (byte pointer to a word 
variable). 

COUNT — number of times to shift the word right (byte). 



a, X unchanged 
y #$ff 

St c (carry flag) is set with last bit shifted out of word, 
register pointed to by OPERAND contains the shifted word 



Destroys: nothing 



Description: 



Example: 
SeeAlso: 



DShiftRight is a double-precision routine that arithn^tically right-shifts a 16-bit 
zero-page word (low/high order). The address of the word is passed in x and the 
number of times to shift the word is passed in y. Zeros are shifted into the high- 
order bit. 

An arithmetic right-shift is useful for quickly dividing a value by a power of two. 
One left-shift will divide by two, two left-shifts will divide by four, three left- 
shifts will divide by eight, and so on: value = value / 2^^"^^ 



DShiftLeft. 



71 



EnableProcess 



EnableProcess (Apple, C64, ci28) 



process! 



Function: 
Parameters: 

Returns: 



Description: 



Example: 



Makes a process tunable immediately. 

X PROCESS — number of process (0 - n-l, where n is the number of 
processes in the table) (byte). 



unchanged. 



Destroys: a 



EnableProcess forces a process to become runable on the next pass through 
MainLoop, independent of its timer value. 

EnableProcess merely sets the runable flag in the hidden process table. When 
MainLoop encounters an unblocked process with this flag set, it will attempt to 
generate an event just as if the timer had decremented to zero. 

EnableProcess has no priveleged status and cannot override a blocked process.* 
However, because it doesn't depend on or affect the current timer value, the 
process can become runable even with a frozen timer. 

EnableProcess is useful for making sure a process runs at least once, 
regardless of the initialized value of the countdown timer. It is also useful for 
creatingapplication-defined events which run off of MainLoop: a special process 
can be reserved in the data structure but never started with RestartProcess. Any 
time the desired event-state is detected, a call to EnableProcess will generate an 
event on the next pass through MainLoop. EnableProcess can be called from 
Interrupt Level, which allows a condition to be detected at Interrupt Level but 
processed during MainLoop. 



See also: InitProcesses, RestartProcess, UnfreezeProcess, UnblockProcess. 



72 



EnablSprite 



EnablSprite (Apple, C64, cns) 



sprite 



Function: 

Parameters: 

Returns: 

Alters: 

Destroys: 

Description: 



Example: 
See also: 



Enable a sprite so that it becomes visible. 

r3L SPRITE — sprite number (byte). 

nothing. 

mobenble 

a, X 

EnablSprite enables a sprite so that it becomes visible. Although there are eight 
sprites available, an application should only directly enable sprites #2 through #7 
with EnablSprite. Sprite #0 (the mouse pointer) is enabled through MouseOn 
and StartMouseMode, and sprite #1 (the text cursor) should be enabled with 
PromptOn. 



DisablSprite, MouseUp, PromptOn, DrawSprite, GetSpriteData, 
PosSprite, InitSprite. 



73 



EnterDeskTop 



EnterPeskTop (Apple, C64, cus) 

Function: Standard application exit to GEOS dcskTop, 

Parameters: none. 

Returns: never retutms to application. 

Description: An application calls EnterDeskTop when it wants to exit to the GEOS deskTop- 
EnterDeskTop takes no parameters and looks for a copy of the file 
DESK TOP on each drive. Later versions of GEOS are only compatible witii 
the correspondingly later revision of the deskTop and will check the version 
number in the permanent name string of the DESK TOP file to ensure that it is 
in fact a newer version. If after all drives are searched no valid copy of the 
deskTop is found, EnterDeskTop will prompt the user to insert a disk witii a 
copy of the deskTop on it. 

C64 & C128: EnterDeskTop will first search a RAMdisk for a copy of the deskTop to ensure 
the fastest loading tin^e. 

Apple: EnterDeskTop will first search all non-removable media devices (RAMdisk, 

hard disk, etc.) for a copy of the deskTop, then other devices (floppy disk 
devices). These devices are searched in the order that they appear on the deskTop, 
which corresponds to their order in the expansion slots: a device in slot seven will 
be searched before a device in slot six. 

Example: 

See also: RstrAppl, GetFile. 



high-level disk 



74 



EnterTurbo 



EnterTurbo (C64, ci28) 



verylow-level disk I 



Function: 

Parameters: 

Uses: 

Returns: 

Destroys: 

Calls: 

Description: 



Activate disk drive turbo mode, 
none. 



Apple: 
Example: 
See also: 



curDrive 
curType 



currently active disk drive. 

vl.3+: checks disk type because not all use turbo software. 



X 

a, y. 



error ($00 = no error). 



EnterTurbo activates the turbo software in the current drive. If the turbo 
software has not yet been downloaded to the drive, EnterTurbo will download 
it. The turbo software allows GEOS to perform high-speed serial disk access. 

EnterTurbo treats diflferent drive types appropriately. A RAMdisk, for example, 
does not use turbo code so EnterTurbo will not attempt to download the turbo 
software. 

The very-low level Commodore GEOS read/write routines, such as ReadBlock, 
WriteBlock, VerWriteBIock, and ReadLink, expect the turbo software to 
be active. Call EnterTurbo before calling one of these routines. 

Apple GEOS has no EnterTurbo equivalent 

See WriteBlock. 

ExitTurbo, PurgeTurbo. 



75 



-&ftt6 rTurbo 



EraseCharacter (Apple) 



text 



Function: Erase a character from the screen, accounting for the current font and style 
attributes. 

Parameters: a CHAR — character code of character to erase (byte). 

r 1 1 XPOS — x-coordinate of left of character (word), 
r 1 H YPOS — y-coordinate of character baseline (word). 

Uses: same as PutChar. 

Returns: rll, rlH unchanged. 

Alters: lastWidth width of character just erased 

Destroys: Commodore 

rlL, r2-rl0, rl2, rl3, a, x, y. 

Apple 

rlL, r2, a, x, y. 



Description: EraseCharacter calculates the widdi of the character and erases it from the 
screen using the USELAST character and SmallPutChar. 

Note: Uses currentMode to calculate the character width. When deleting multiple 

characters, the application will need to take this into account when backspacing 
from one style to another. Also, does not always work with characters that are 
both bolded and outlined because not all fonts have a wide enough USELAST 
character. 



See also: 
Example: 



SmallPutChar, PutChar, PutString. 



ExitTurbo 



ExitTurbO (C64, cm) very Iow>level disk] 



Function: Deactivate disk drive turbo mode. 
Parameters: none. 

Uses : cur Drive currently active disk drive. 

Returns: x error ($00 = no error). 
Destroys: a, y. 

Description: ExitTurbo deactivates the turbo software in the current drive so that the serial 
bus may access another device. SetDevice automatically calls this before 
changing devices. 

Note: If the turbo software has not been downloaded or is already inactive, ExitTurbo 

will do nothing. 

Apple: Apple GEOS has no ExitTurbo equivalent. 

Example: See WriteBIock. 

See also: EnterTurbo, PurgeTurbo. 



77 



FastDelFile 



FastPelFile (C64, cm) 



mid-level disk 



Function: 
Parameters: 

Uses: 



Returns: 

Destroys: 

Description: 



Note: 



Special Commodore version of DeleteFile that quickly deletes a sequential file 
when the track/sector table is available. 

r FILENAME — pointer to null-terminated file name (word), 
r3 TSTABLE — pointer to track and sector table of file, usually points to 
fileTrScTab (word). 



curDrive. 

curType 

curDirHead 

dir2Headt 

dir3Headt 



GEOS 64 vl.3 and later: for detecting REU shadowing, 
BAM updated to reflect newly freed blocks. 
(BAM for 1571 and 1581 drives only) 
(BAM for 1581 drive only) 



X error ($00 = no error), 
a, y, rO, r9. 

FastDelFile quickly deletes a sequential file by taking advantange of an already 
existing tracl^sector table. It first removes the directory entry determined by 
FILENAME and calls FreeBIock for each block in a track/sector table at 
TSTABLE. The track/sector table is in the standard format, such as that returned 
from ReadFile, where every two-byte entry constitutes a track and sector. A 
track number of $00 terminates the table. 

FastDelFile is fast because it does not need to follow the chain of sectors to 
delete the individual blocks. It can do most of the deletion by manipulating the 
BAM in memory then writing it out with a call to PutDirHead when done. 

FastDelFile will not properly delete VLIR files without considerable work on 
the application's part. Because there is no easy way to build a track/sector table 
that contains all the blocks in all the records of a VLIR file, it is best to use 
DeleteFile or FreeFile for deleting VLIR files or DeleteRecord for deleting a 
single record. 

FastDelFile calls GetDirHead before freeing any blocks. This will overwrite 
any BAM and directory header in memory. 

FastDelFile can be used to remove a directory entry without actually freeing any 
blocks in the file by passing a dummy track/sector table, where the first byte 
(track number) is $00 signifying the end of the table: 

;Pass: rJD pointer to filename 

E>eleteDirEntry : 

LoadW r3,#NullTrScTable ;pass dummy table 

jmp FastDelFile ; delete dir entry 

; never get here — FastDel returns to caller 

This will also work correctly with a VLIR file. 

For freeing (deleting) all the blocks in a file widiout removing the directory entry, 
refer to FreeFile. 



78 



Apple: Apple GEOS has no FastDelFile equivalent because the ProDOS blocks are not 

linked with internal forward pointers. Use DeleteFile. 

Example: 



Read sequential file into memory and then delete it 
from disk 



;Pass: r6 pointer to filename 

r7 where to put data 



r2 size of buffer (max size of file) 



; Returns: 

X error code 



Destroys: 

a, y, r0-r9 



Implementation : 

Call Findfile to get the directory entry of the 
file to load/delete. We pass the directory entry 
to GetFHdrlnfo to get the GEOS header block. We 
check the header to ensure we* re not trying to 
read in a VLIR file. After GetFHdrlnfo, the 
parameters are already set up correctly to call 
ReadFile (f ileTrScTab+0, f ileTrScTab+1 contains 
header block and rl contains first data block) . 
Readfile reads in the file's blocks, building out 
the remainder of the fileTrScTab, which we pass 
to FastDelFile to free all blocks in the file 
(including the file header block, which is the 





first 


entry in the table) . 




ReadAndDelete: 






MoveW 


r6,r0 


;save pointer for FastDel 




Jsr 


FindFile 


;find file on disk 




txa 




;set status flags 




bne 


96$ 


; branch on error 




LoadW 


r9,dirEntryBuf 


;get directory entry 




jsr 


GetFHdrlnfo 


;get GEOS file header 




txa 




;set status flags 




bne 


96$ 


/branch on error 




Ida 


fileHeader+OFF GSTRUCT TYPE 




cmp 


#VLIR 


; check filet ype 




bne 


10$ 


; branch if not VLIR 




Idx 


#STRUCT_MISMAT 


; can't load VLIR 




bne 


96$ 


/branch always for error 


10$: 










jsr 


ReadFile 


;read in file 




txa 




/else set status flags 




bne 


96$ 


/branch on other error 


20$: 










LoadW 


r3,#fileTrScTab 


/track/sector tbl 




jsr 


FastDelFile 


/file read OK, delete it! 


d6$ 










rts 




/error in x 



See also: FreeFile, DeleteFile. 



79 



FdFTypesInPir (Apple) 



high-level disk 



Function: Special Apple GEOS version of FindFTypes that will build the filename list 
using a directory other than the current directory. 

Parameters: r6 BUFFER — pointer to buffer for building-out file list; allow 16 bytes 

for each entry in the list (word), 
r 1 PERMN AME — pointer to permanent name string to match or $0000 to 

ignore permanent name string (word). 
r7H MAXETLES — maximum number of filenames to retum, usually used 

to prevent overwriting end of BUFFER (must be less than 127). If 

INAUX^B is bitwise-or'ed into this parameter, BUFFER will be 

treated as'an address in auxiliary memory. 
r7L FILETYPE — GEOS file type to search for or WILDCARD, which 

will match all types except subdirectories (byte), 
rl DIRBLKNO — block number of directory to search (word). 

curDrive 

X error ($00 = no error). 

r7H decremented once for each file name (Apple GEOS: high-bit is always 
cleared). 

diskBIkBuf used as temporary buffer for directory blocks, 
a, y, rO-r2L, r4-r6. 

FdFTypesInDir performs the same action as FindFTypes, except that 
DIRBLKNO temporarily becomes the current directory. The current directory is 
restored before returning. 

The data area at BUFFER, where the list is built-out, must be large enough to 
accomodate MAXFILES filenames of 16 bytes each. 

C64 & C128: Commodore GEOS does not support a hierarchical file system. 
Example: 

See also: FindFTypes, FndFillnDir. 



Uses: 
Returns: 

Alters: 

Destroys: 

Description: 



CONAkoklisi SAL 



FetchRAM 



FetchRAM (C64 vi.3 & ci28) 



memoryl 



Function: 
Parameters: 

Returns: 

Destroys: 
Description: 



Note: 
Example: 
See also: 



Primitive for transferring data from an REU. 

rO CBMDST — address in Commodore to put data (word), 

r 1 REUSRC — address in REU bank to start reading (word). 

r2 COUNT — number of bytes to fetch (word). 

r3L REUS ANK — REU bank number to fetch from (byte). 



r0-r3 unchanged. 
X error code: 



a 

y 



$00 (no error) or DEV_NOT_FOUND if REUBANK 
or REU not available. ~ 
REU status byte and'ed with $60 ($40 = successful fetch). 



FetchRAM moves a block of data from an REU bank into Commodore 
memory. This routine is a "use at your own risk" low-level GEOS primitive 

FetchRAM uses the DoRAMOp primitive by calling it with a CMD parameter 
of %10010001. 

Refer to DoRAMOp for notes and warnings. 



StashRAM, SwapRAM, VerifyRAM, DoRAMOp, MoveBData. 



81 



FillRam 



FillRam, i FillRam (Apple, C64, ci28) 



memory] 



Function: 
Parameters: 



Returns: 

Destroys: 

Description: 

Note: 
Example: 
See also: 



pais a region of memory with a repeating byte value. 
Nomial: 

rO COUNT — number of bytes to clear (0 - 64K) (word), 
r 1 ADDR — ^address of area to clear (word). 
r2L PILL — byte value to fill with (byte). 

Inline: 

.word CXDUNT — number of bytes to clear (0 - 64K) (word), 

.word ADDR — address of area to clear (word), 

.byte PELL — byte value to fill with (byte). 

r2L unchanged. 

a, y, rO, rl 

FillRam fills COUNT bytes starting at ADDR with the PILL byte. This routine 
is useful for initializing a block of memory to some non-zero or variable value 
(for filling a region with $00, use ClearRam). 

Do not use FillRam to initialize rO-r2L. 



ClearRam, InitRam. 



82 



FindBAMBit 



FindBAMBit (C64, ci28) 



m id.level disk 



Function: 
Parameters: 

Uses: 



Returns: 



Destroys: 



Description: 



Get disk block allocation status. 

r6L TRACK —track number of block (byte). 
r6H SECTOR — sector number of block (byte). 



curDrive 
curDirHead 
dir2Headt 
dirSHeadt 



this buffer must contain the cunent directory header. 
(BAM for 1571 and 1581 drives only) 
(BAM for 1581 drive only) 



^used internally by GEOS disk routines; applications generally don't use, 

St z flag reflects allocation status (1 = free ; = allocated). 
r6 unchanged 

1541 drives onlv: 

X offset from curDirHead for BAM byte. 
r8H mask for isolating BAM bit. 
a BAM byte masked with r8H. 

r7H offset from curDirHead of byte that holds free blocks on track total. 

non-1541 drives: 
a, y, r7H. r8H. 

1541 drives: 

y (a, r7H, and rSH all contain useful values). 

FindBAMBit accesses the BAM of the current disk 'in curDirHead) and 
returns the allocation status of a particular block. If the BAM bit is zero, then the 
block is in-use; if the BAM bit is one, then the block is free. FindBAMBit 
returns with the z flag set to reflect the status of the BAM so that a subsequent 
bne or beq branch instructions can test the status of a block after calling 
FindBAMBit: 



Note: 



Apple: 
Example: 



bne 
beq 



BlocklsFree 

or- 

BlocklnUse 



; branch if block is free 
;branch if block is in-use 



FindBAMBit will return the allocation status of a block on any disk device, 
even those with large or multiple BAMs (such as the 1571 and 1581 disk drives). 
Only the 1541 driver, however, will return useful information in a, y, r7H, and 
r8H. For an example of using these extra 1541 return values, refer to 
AIlocateBlock. 



See FindVBMBit. 



LoadB 
LoadB 
jsr 
beq 



r6L,#TRACK 
r6H,#SECT0R 
FindBAMBit 
BlocklnUse 



; get track and sector number 

; get allocation status 
; branch if already in use 



83 



FindBAMBit 

See also: FindVBMBit, AIlocateBIock, FreeBIock. GetDirHead, PutDirHead. 



84 



FindFile 



FindFilejAppie, C64, ci28) 



high-level disk 



Function: 
Parameters: 

Uses: 



Returns: 



Alters: 

Destroys: 
Description: 



Search for a particular file in the current directory. 

r6 FILENAME — pointer to null-terminated name of file of a maximum of 
ENTRY^SIZE bytes (not counting null terminator). (Apple GEOS: 
must be in main memory.) (word). 

curDrive 

Commp^^Qre; 
curType 

Applg: 

curKBlkno 



GEOS 64 vl.3 and later: for detecting REU shadowing. 



current directory. 
X error ($(X) = no error). 

rl block number (Commodore track/sector) of directory block containing 
entry, 

r5 pointer into diskBIRBuf to start of directory entry. 



diskBIkBuf 
dirEntryBuf 

a, y, r4, r6. 



contains directory block where FILENAME found, 
directory entry of file if found. 



Given a null-terminated filename, FindFile searches through the current 
directory and returns the directory entry in dirEntryBuf. If the file specified 
with FILENAME is not found, a FILE_NOT_FOUND error is returned. 



C64 & C128: Since Commodore GEOS does not support a hierarchical file systeni, the "current 
directory'* is actually the entire disk. The directory entry is deleted by setting its 
OFF^CFILE^TYPE byte to $00. 



Apple: 

Example: 
See also: 



Only the current directory, the directory specified by curKBlkno, is searched. 
To search a directory other than the current one, use FndFillnDir. 



FndFillnDir, GetlstDirEntry, GetNxtDirEntry, FindFTypes. 



85 



FindFTypes 



FindFTypes (Apple, C64, cns) 



high-level dlskl 



Function: 
Parameters: 



Uses: 



Returns: 

Alters: 
Destroys: 



BuUds a list of files of a particular GEOS type from the current directory, 

r6 BUFFER' — pointer to buffer for building-out file list; allow 

. ENTRY_SIZE+1 bytes for each entry in the list (word), 
r 1 PERMN AME — pointer to permanent name string to match or $0000 to 
ignore permanent name string (word). 

Commodore: 

r7H MAXFILES — maximum number of filenames to return, usually used 

to prevent overwriting buffer. 
r7L FILETYPE — GEOS file type to search for (byte). 



Applg; 
r7H 



r7L 



MAXFILES — maximum number of filenames to return, usually used 
to prevent overwriting end of BUFFER (must be less than 127). If 
INAUX_B is bitwise-or'ed into this parameter, BUFFER will be 
treated as"an address in auxiliary memory. 

FILETYPE — GEOS file type to search for or WILDCARD, which 
will match all types except subdirectories (byte). 



curDrive 

Commodore: 
curType 

Apple: 

curKBIkno 



GEOS 64 V 1.3 and later for detecting REU shadowing. 



current directory. 



X error ($00 = no error). 

r7H decremented once for each file name (Apple GEOS: high-bit is always 
cleared). 



diskBlkBuf 



used as temporary buffer for directory blocks. 



CpqTmQ(jorg; 
a, y, rO-r2L, r4, r6. 

Apple; 

a, y, rO-r2L, r4-r6. 

Description: FindFTypes build a list of files that match a particular GEOS file type and, 
optionally, a specific permanent name string. 

The data area at BUFFER, where the list is built-out, must be large enough to 
accomodate MAXFILES filenames of ENTRY_SIZE+1 bytes each. 

FindFTypes first clears enough of the area at BUFFER to hold MAXFILES 
filenames tiien calls GetlstDirEntry and GetNxtDirEntry to go tiirough each 
directory entry in the current directory. When the GEOS file type of a directory 



86 



FIndFTypes 



entry matches the FILETYPE parameter, FindFTypes goes on to check for a 
matching permanent name string. 

If the PERMNAME parameter is $0000, then this check is bypassed and the 
filename is added to the list. If the PERMNAME parameter is non-zero, the null- 
terminated string it points to is checked, character-by-character, against the 
permanent name string in the file's header block. Although the permanent name 
string in the GEOS file header is 16 characters long, the comparison only extends 
to the character before the null-terminator in the string at PERMNAME. 

Since permanent name strings typically end with Vxjc, where xjc is a version 
number (e.g., 2.1), a shorter string can be passed so that the specific version 
number is ignored For example, a program called geoQuiz version 1.3 might use 
"geoQuiz V1.3" as the permanent name string it gives its data files. When 
geoQuiz version 3.0 goes searching for its data files, it can pass a PERMNAME 
string of "geoQuiz V" so data files for all versions of the program will be added to 
the list 



When a match is found, the filename is copied into the list at BUFFER. The 
filenames are placed in tJie buffer as they are found (the same order they appear 
on the pages of the deskTop notepad). With a small buffer, matching files on 
higher-numbered pages may never get added to the list. 

C64 & C128: Since Coninxxiore GEOS does not support a hierarchical file system, the "current 
directory" is actually the entire disk. The filenames appear in the list null- 
terminated even though they are padded with $aO in the directory. 

Apple: Only the current directory specified by curKBIkno is searched. To search a 

directory other than the current one, use FdFTypesInDir. The filenames in the 
list are null-terminated 



To search for subdirectories in the current directory, pass PRO DIR as the 
FILETYPE. When searching for directories, the permanent string check is 
bypassed To match all file types except subdirectories, pass WILDCARD as 
the FILETYPE and $0000 for the PERMSTRING parameter. 

A filename list created with FindFTypes can be sorted alphabetically with a call 
to SortAIpha. 

Example: 

See also: FdFTypesInDir, FindFile, GetlstDirEntry, GetNxtDirEntry. 



87 



FindVBMBit 



FindVBMBitJAppie) 



mid-level diskl 



Function: 



Uses: 



Returns: 



Alters: 



Destroys: 



Get disk block allocation status. 



Parameters: r6 



BLOCK — block number (word). 



VBMBlknot 
curVBlknot 
VBMchangedt 
numVBMBIkst 



first VBM block starts here; set initially by OpenDisk 
used by VBM cacheing routines, 
used by VBM cacheing routines, 
used by VBM cacheing routines. 



^used internally by GEOS disk routines; applications generally don't use. 

X error ($00 = no error). 

St z flag reflects allocation status (1 = fiee; = allocated). 

r8H mask for isolating VBM bit 

r7 offset to BAM byte in current VBM block. 

a BAM byte masked witfi r8H. 

r6 unchanged. 



curVBlknot 
VBMchangedt 



Block that contains the VBM bit for BLOCK. 
changed to FALSE if VBM cache flushed. 



^used internally by GEOS disk routines: applications generally don't use. 

y 



Description: FindVBMBit accesses the VBM of the current disk and returns the allocation 
status of a particular block. If the VBM bit is zero, then the block is in-use; if the 
VBM bit is one, tiien the block is free. FindVBMBit returns witir tiie z flag set 
to reflect the status of the BAM bit so tiiat a subsequent bne or beq branch 
instructions can test the status of a block after calling FindVBMBit: 



bne 
beq 



BloclcIsFree 

or- 

BlocklnUse 



C64 &C128: See FindBAMBit. 



Example: 



LoadW 

jsr 

cpx 

bne 

tay 

beq 



r6,#BL0CK 
FindVBMBit 
#NO_ERROR 
diskError 

BlocklnUse 



/branch if block is free 
/branch if block is in-use 



get block number 
get allocation status 
check for error 
branch on error 
check block status 
branch if block in use 



See also: FindBAMBit, AlIocateBlock, FreeBlock, GetDirHead, PutDirHead. 



88 



FirstI 



Firstlnit (Apple, C64, cm) 



internal 



Function: Simulates portions of the GEOS coldstart procedure without actually rebooting 
GEOS or destroying the application in memory. 

Parameters: none 

Returns: GEOS variables and system hardware in a coldstart state; stack and application 
space unaffected 

Destroys: a, x, y, r0-r2 

Description: Firstlnit is part of the GEOS coldstart procedure. It initializes nearly all GEOS 
variables and data structures (both global and local), including those which are 
usually only done once, when GEOS is first booted, such as setting the 
configuration variables to a default, power-up state. 

GEOS calls this routine intemally. Applications will not find it especially useful. 

Note: The GEOS font variables are not reset by Firstlnit; a call to UseSystemFont 

may be necessary. 

See also: WarmStart, StartAppl. 



89 



FndFillnDir 



FndFillnDir (Apple) 



high-level disk! 



Function: 

Parameters: 

Uses: 
Returns: 

Alters: 

Destroys: 
Description: 



Special Apple GEOS version of FindFile that will search for a file in a directory 
other than die current directory. 

r6 FILENAME — pointer to nuU-terminated name of file (word), 
rl DERBLKNO — block number of directory to search (word). 

curDrive 

X error ($00 = no error). 

rl block number of directory block containing entry. 
rS pointer into diskBIkBuf to start of directory entry. 



diskBIkBuf 
dirEntryBuf 

a, y, r4-r6. 



contains directory block where FILENAME found, 
directory entry of file if found. 



C64 & C128: 
Example: 
See also: 



FndFillnDir performs the same action as FindFile, except tiiat DIRBLKNO 
temporarily becomes the current directory. The current directory is restored before 
returning. FndFillnDir returns the directory entry in dirEntryBuf. If the file 
specified with FILENAME is not found in the DIRBLKNO directory, a 
FILE^NOT^FOUND error is returned. 

Commodore GEOS does not support a hierarchical file system. 



FindFile, FdFTypesInDir, GoDirectory. 



90 



FollowChain 



FollowChain (C64, cus) 



mid-level disk 



Function: 
Parameters: 

Uses: 
Returns: 

Alters: 

Destroys: 

Description: 



Apple: 



Example; 



Follow a chain of Commodore disk blocks, building out a track/sector table. 

rlL START^TRACK — track number of starting block (byte), 
rlH START^SEC — sector number of starting block (byte). 
r3 TSTABLE — pointer to buffer for building out track and sector table of 
chain, usually points to fileTrScTab (word). 



curDrive. 
curType 



GEOS 64 vl.3 and later for detecting REU shadowing. 



X error ($00 = no error). , 
r3 unchanged. 

track/sector built-out in buffer pointed to by TSTABLE. 



diskBlkBuf 
a, y, rl, r4. 



used for temporary block storage. 



FollowChain constructs a track/sector table for a list of chained blocks on the 
disk. It starts with the block passed in START JTR and START^SC and follows 
the links until it encounters the last block in the chain. Each block (including the 
first block at START JTR, START JSC ) becomes a part of the track/sector table. 

Commodore disk blocks are linked together with track/sector pointers. The first 
two bytes of each block represent a track/sector pointer to die next block in the 
chain. Each sequential file and VLIR record on the disk is actually a chained list 
of blocks. FollowChain follows these track/sector links, adding each to the list 
at TSTABLE until it encounters a track pointer of $(X), which terminates the 
chain. FollowChain adds this last track pointer ($00) and its corresponding 
sector pointer (which is actually an index to the last valid byte in the block) to the 
track/sector table and returns to the caller. 

FollowChain builds a standard track/sector table compatible with routines such 
as WriteFile and FastDelFile. 

Apple GEOS has no FollowChain equivalent because ProDOS links blocks 
together, not by pointers within each block, but by a list of blocks in an index 
associated with each sequential file and VLIR record This index is called the 
index block and, as its name implies, occupies a single block on die disk. 



LoadB 

LoadB 

LoadW 

jsr 

txa 

bne 



rlL,#START_TR 
rlH,#START_SC 
r3,#fUeTrScTab 
FollowChain 

HandleError 



; start track 

; and sector 

; buffer for table 

; create tr/sc table 

; set status flags 

; branch if error 



See also: 



91 



i 

F^llowChain 



IFrameRectangle, i FrameRectangle (Apple, C64, cm) graphics] 



Function: 
Parameters: 



Uses: 

Returns: 
Destroys: 



Description: 



Note: 



128: 



Draw a rectangular frame (one-pixel thickness). 
Normal: 

a eight-bit line pattern. 
r3 XI — x-coordinate of upper-left (word). 
r2L Yl — y-coordinate of upper-left (byte). 
r4 X2 — x-coordinate of lower-right (word). 
r2H Y2 — y-coordinateof lower-right (byte). 

where (XI, Yl) is the upper-left corner of the frame and (X2,Y2) is the lower- 
right corner. 

Inline: 

data appears immediately after the jsr i^FrameRectangle 

.byte Yl y-coordinate of upper-left 

.byte Y2 y-coordinateof lower-right, 

.word XI x-coordinate of upper-left 

.word X2 x-coordinate of lower-right. 

.byte PATTERN eight-bit line pattern. 

dispBufferOn: 

bit 7 — write to foreground screen if set. 
bit 6 — write to background screen if set 

r2, r3, and r4 unchanged. 

Commodore 

a, X, y, r5-r9, rll 

Apple 

a,x, y, rll 

FrameRectangle draws a one-pixel rectangular frame on the screen as 
determined by the coordinates of the upper-left and lower-right comers. The 
horizontal and vertical lines which comprise the frame are drawn with the 
specified line pattern. 

FrameRectangle operates by calling HorizontalLine and VerticalLine with 
the desired line-pattern. As with these two routines, the line pattern is drawn as if 
aligned on an eight-pixel boundary. The values of the comer pixels will be 
determined by the vertical sides because they are drawn after the hoi:izontal sides. 

Because all GEOS coordinates are inclusive, framing a filled rectangle requires 
either calling FrameRectangle after calling Rectangle (and thereby 
overwriting the perimeter of the filled area) or calling FrameRectangle with 
iXl'lJl-l) and (X2+1,Y2+1) as the comer points. 

Under GEOS 128, or'ing DOUBLE W into the XI andX2 parameters will 
automatically double the x-position in SD-column mode. Or'ing in ADD1_W will 



FollowChain 



automatically addl to a doubled x-position. (Refer to "GEOS 128 X-position and 
Bitmap Doubling" in Chapter.@gr@ for more information.) 

Example: 

See also: Rectangle, ImprintRectangle, RecoverRectangle, InvertRectangle. 



FYeeBlOCkjApple, C64, C128) 



mid-level diskl 



Function: 
Parameters: 



Uses: 



Returns: 
Alters: 



Free an allocated disk block. 
Commodore: 

r6L track number of block to free (byte). 
r6H sector number of block to free (byte). 

Apple; 

r6 block to free (word). 
curDrive 



Commodore: 
curDirHead 
dir2Headt 
dir3Headt 

A pple: 

curVBlknot 

VBMchangedt 

numVBMBIkst 



this buffer must contain the current directory header. 
(BAM for 1571 and 1581 drives only) 
(BAM for 1581 drive only) 



used by VBM cacheing routines, 
used by VBM cacheing routines, 
used by VBM cacheing routines. 



^used internally by GEOS disk routines; applications generally don't use, 

X error ($00 = no error); returns BAD_B AM if block already free. 

r6L, r6H unchanged. " 



Commodore: 
curDirHead 
dir2Headt 
dir3Headt 

Apple: 

curVBlknot 
VBMchangedt 



BAM updated to reflect newly allocated block. 
(BAM for 1571 and 1581 drives only) 
(BAM for 1581 drive only) 



used by VBM cacheing routines. 

set to TRUE by VBM cacheing routines to indicate cached 
VBM block has changed and needs to be flushed 



Destroys: 
Description: 



^used internally by GEOS disk routines; applications generally don't use. 
a, y, r7, rSH. 

FreeBIock tries to free (deallocate) the block number passed in r6. If the block 
is already free, then FreeBIock returns a BAD_BAM error. 



C64 & C128: FreeBIock was not added to the Commodore GEOS jump table until v 1.3, but it 
can be accessed direcdy under GEOS vl.2. The following routine will check the 
GEOS version number and act correcdy under GEOS vl.2 and later. 

MyFreeBlock — allocate specific block in BAM 
with any GEM device driver. 



FrameRectangle 



• ***************** *«*****4r********* ********************* 



MyFreeBlock: 
Ida 
cmp 
bne 



Jsr 



bne 
Ida 
eor 
sta 
Idx 
inc 
Idx 
rts 



88$: 



10$: 



Idx 
rts 

jmp 



version 

#$12 

10$ 



FindBAMbit 



88$ 
r8h 

curOirHead, x 
curDirHead, x 
r7H 

curDirHead, x 
»0 



#BAD BAM 



FreeBlock 



check GEOS version number 
version 1.2? 

if not, go through jump table 

r6L « track # 
r6h « sector # 

Get mask for BAM byte in r8H 
offset to track in r7h 
offset into bam in X 
masked value A 

if 1, then not allocated, give error 

get mask 

flip BAM bit to show available 
one more free block 
NO ERROR 



; BAM ERROR 



;vl,3+: go thru jump tbl 



FreeBlock does not automatically write out the BAM. See PutDirHead for 
more information on writing out the BAM. 

Apple: FreeBlock does not automatically flushctiie VBM cache. See PutVBM for more 

information on flushing die VBM cache. 

Example: 

See also: FreeFile, AllocateBlock. 



Dir 



FreeDir (Apple) 



mid-level disk! 



Function: 

Parameters: 

Uses: 



Free the chained directory blocks associated with a subdirectory. Does not delete 
the subdirectory's directory entry. The subdirectory must be empty. 

r9 DIRENTRY — pointer to directory entry of subdirectory being freed, 
usually points to dirEntryBuf (must be in main memory.) (word). 



curDrive 
curVBlknot 
VBMchangedt 
numVBMBlkst 



used by VBM cacheing routines, 
used by VBM cacheing routines, 
used by VBM cacheing routines. 



Returns: 
Alters: 



^used internally by GEOS disk routines; explications generally don't use. 
X error ($00 = no error). 



diskBIkBuf 
curVBlknot 
VBMchangedt 



used for temporary block storage, 
used by VBM cacheing routines. 

set to FALSE by VBM cacheing routines to indicate cached 
VBM block has already been flushed 



Destroys: 
Description: 



^used internally by GEOS disk routines; applications generally don't use. 
a, y, rl, r4, r6, r7, r8H. 

Given a valid subdirectory entry, FreeDir will free all the directory blocks 
allocated to the subdirectory. The subdirectory's directory entry, however, is left 
intaa. 

« 

The subdirectory entry is a standard data structure returned by routines such as 
FIndFile, GetlstDirEntry and GetNextDirEntry. A subdirectory is flagged 
by a PRO DIR in the GEOS type byte in the directory entry (at 
OFF^FTYPt). FreeDir is called automatically by DeleteDir. 

FreeDir will not free the blocks of subdirectory that has files in it. A 
DIR^NOT^EMPTY error will be returned. (The number of files in die 
subdSrcctoryls stored in the OFFB_FLCNT word of the directory's header. 
This maintains this value by calling UpdateParent when files are added or 
removed.) 

FreeDir flushes die VBM cache. 
C64 & C128: Commodore GEOS does not support a hierarchical file system. 
Example: 

See also: DeleteDir, DeleteFile, FreeFile, FreeBIock. 



9 6 



FreeFile 



FreeFile (Apple, C64, cns) 



mid-level disk! 



Function: 
Parameters: 

Uses: 



Returns: 
Alters: 



Free all the blocks in a GEOS file (sequential or VLIR) without deleting the 
direaory entry. The GEOS file header and any index blocks are also deleted. 

r9 DIRENTRY — pointer to directory entry of file being freed, usually 
points to dirEntryBuf (Apple GEOS: must be in main memory.) 
(word). 

curDrive 

Cpmmodgrp; 
curType 

Apple; 

curVBIknot 
VBMchanged^ 
numVBMBlkst 



GEOS 64 vL3 and later for detecting REU shadowing. 



used by VBM cacheing routines, 
used by VBM cacheing routines, 
used by VBM cacheing routines. 



^used internally by GEOS disk routines: applications generally don't use. 
X error ($(X) = no error). 



diskBlkBuf 

CpmiTiodorp; 

curDirHead 

dir2Headt 

dirSHeadt 

fileHeader 



used for temporary block storage. 



BAM updated to reflect newly fteed blocks. 
(BAM for 1571 and 1581 drives only) 
(BAM for 1581 drive only) 

temporary storage of the index table when deleting a VLIR 
file. 



Destroys: 



Applg; 

curVBIkno* 
VBMchangedt 



used by VBM cacheing routines. 

set to FALSE by VBM cacheing routines to indicate cached 
VBM block has already been flushed 



Description: 



^used internally by GEOS disk routines;, applications generally don't use. 

Cpmmodorp; 
a, y, r0-r9. 

Apple: 

a, y, rl, r2L, r4, r6, r7, r8H, r9. 

Given a valid directory entry, FreeFilfe will delete (free) all blocks assocatied 
with the file. The GEOS file header and any index blocks associated with the file 
are also be freed. The directory entry on the disk, however, is left intact 

The directory entry is a standard GEOS data structure returned by routines such 
as FindFile, GetlstDirEntry and GetNxtDirEntry. FreeFile is called 
automatically by DeleteFile. 



97 



FreeFile 



C64 & C128: FreeFile calls GetDirHead to get the current directory header and BAM into 
memory. It then checks at OFF GHDR^PTR in the directory entry for a CEOS 
file header block, which it then ffees. 

If the file is a sequential file, FreeFile walks the chain pointed at by the 
OFF_DE_TR_SC track/sector pointer in the directory header and frtcs all the 
bloclcs inlhe chain. FreeFile then calls PutDirHead to write out the new 
BAM. 

If the file is a VLIR file, the index table (the block pointed to by 
OFF JNDEX^PTR) is first read into fileHeader then marked as free in the 
BAMT FreeFife then goes through each record. If the record has data in it, 
FreeFile walks through the chain, fieeing all the blocks in the record. FreeFile 
finishes by calling PutDirHead to write out the new BAM. 

When using GetlstDirEntry and GetNxtDirEntry, do not pass FreeFile a 
pointer into diskBIkBuf. Copy the full directory entry (DIRENTRY^SIZE 
bytes) from diskBIkBuf to another buffer (such as dirEntryBuf) and pass 
FreeFile the pointer to that buffer. Otherwise when FreeFile uses 
diskBIkBuf it will corrupt the directory entry. 

Because FreeFile deletes a block at a time as it follows the chains, it is capable 
of deleting files with chains larger than 127 blocks, which is the standard GEOS 
limit imposed by the size of TrScTable. 

Apple: FreeFile first copies the entire directory entry (ENTRY^SIZE bytes) from 

DIRENTRY (in main memory) to an internal buffer in auxiliary memory. 

If tiie file is a VLIR file, then FreeFile reads the VLIR index block (the ProDOS 
* master index block) into memory and frees all the data blocks in each record. The 
VLIR index block and all the individual record index blocks are then deleted. 
FreeFile finishes by calling PutVBM to flush the VBM cache. 

If the file is a sequential file, FreeFile reads the sequential index block into 
memory, frees all assoiciated data blocks,.then frees the index block itself. 
FreeFile finishes by calling PutVBM to flush the VBM cache. 

FreeFile cannot free a subdirectory. To free a subdirectory, use FreeDir. 

Example: 

See also: DeleteFile, FreeDir, FreeBlock. 



98 



FreezeProcess 



IFreezeProcess (Apple, C64, ci287 



process] 



Function: 
Parameters: 

Returns: 

Destroys: 

Description: 



Note: 



Freeze a process's countdown timer at its current value. 

X PROCESS — number of process (0 - n-1, where n is the number of 
processes in the table) (byte). 



X 

a 



unchanged. 



FreezeProcess halts a process's countdown timer so that it is no longer 
decremented every vblank. Because a frozen timer will never reach zero, the 
process will not become runable except through a call to EnableProcess. When 
a process is unfrozen with UnFreezeProcess, its timer again begins counting 
from the point where it was frozen. 

If a process is already frozen, a redundant call to FreezeProcess will have no 
effect. 



Example: 



See also: 



UnfreezeProcess, BlockProcess. 



GetlstDirEntry 



GetlstPirEntry (Apple, C64, ci28) 



mid-level disk! 



Function: 

Parameters: 
Uses: 



Loads in the first directory block of the current directory and returns a pointer to 
the first directory entry within this block. 



none. 

curDrive 

Commodore: 
curType 

Apple; 

curKBlkno 



GEOS 64 V 1.3 and later for detecting REU shadowing. 



current directory. 



Returns: 

Alters: 
Destroys: 
Description: 



X error ($00 = no error). 

r5 pointer to first directory entry within diskBlkBuf. 



diskBlkBuf 
a, y, rl, r4. 



directory block. 



GetlstDirEntry reads in the first directory block of the current directory and 
returns with r5 pointing to the first directory entry. GetlstDirEntry is called by 
routines like FindFTypes and FindFile. 

To get a pointer to subsequent directory entiles, call GetNxtDirEntry. 

C64 & C128: Since Conmiodore GEOS does not support a hierarchical file systeni, the "current 
directory" is actually the entire disk. 

GetlstDirEntry did not appear in the jump table until version 1.3. An 
application running under version 1.2 can access GetlstDirEntry by calling 
directly into the Kemal. The following subroutine will work on Commodore 
GEOS vl. 2 and later: 

• ************* 



; MyGetlstDirEntry — Call instc^&d of GetlstDirEntry 
; to work on GEOS vl.2 and later 

r 

******************************************************* 

; EQUATE: vl.2 entry point directly into Kernal. Must 
;do a version check before calling. 
o_GetlstDirEntry - $c9f7 



MyGetlstDirEntry: 

Ida version 
cmp #$13 
bge 10$ 

jmp o_GetlstDirEntry 



10$: 



jmp 



GetlstDirEntry 



; exact entry point 

; check version number 

/branch if vl.3 or later 
/direct call 

;go through jump table 



\ 



100 



GetlstDirEntry 



Apple: GetlstDirEntry did not appear in the jump table until version 2.0, release 3. An 

application running under an earlier version can add GetlstDirEntry mto the 
jump table with the patch provided in Appendix @@. 



Example: 

See also: GetNxtDirEntry, FindFTypes. 



101 



GetBlock 



GetBlOCk (Apple, C64, C128) 



low-level disk! 



Function: 
Parameters: 



General purpose routine to get a block from current disk. 

r4 BUFFER — address of buffer to place block; must be at least 
BLOCKSIZE bytes (word). 

Commodore: 

rlL TRACK — valid track number (byte). 
rlH SECrrOR — valid sector on track (byte). 

Applg; 

rl BLOCK — ProDOS block number (word). 



Uses: 



curDrive 

Commodore: 
curType 

Apple; 
RWbank 



currendy active disk drive. 

GEOS 64 vl.3 and later for detecting REU shadowing, 
bank BUFFER is in (MAIN or AUX). 



Returns: 

Destroys: 
Description: 



X error ($00 = no error), 

rl, r4 " unchanged 

a, y. 

GetBlock reads a block from the disk into BUFFER. GetBlock is useful for 
implementing disk utility programs and new file structures. 



C64 & C128: GetBlock is a higher-level version of ReadBlock. It calls InitForlO, 
EnterTurbo, ReadBlock, and DoneWithlO. If an application needs to read 
many blocks at once, ReadBlock may offer a faster solution. If the disk is 
shadowed, GetBlock will read from the shadow memory, resulting in a faster 
transfer. 



Apple: 

Example: 
See also: 



The Commodore 1581 driver has a bug that causes its GetBlock to trash rl and 
r4. 

GetBlock provides the lowest-level block access to a ProDOS compatible 
device. It uses the ProDOS device driver READ block command direcdy. Apple 
GEOS, for this reason, does not have a ReadBlock equivalent. 



PutBlock, ReadBlock. 



102 



GetCharWidth 



GetCharWidth (Apple, C64, cus) 



text 



Function: 

Parameters: 

Uses: 

Returns: 

Destroys: 

Description: 



Example: 
See also: 



Calculate the pixel width of a character as it exists in the font (in its plaintext 
form). Ignores any style attributes. 

a CHAR — character code of character (byte). 

curlndexTable 

a character width in pixels. 



GetCharWidth calculates the width of the character before any style attributes 
are applied. If the character code is less. than 32, $00 is returned. Any other 
character code returns the pixel width as calculated from the font data structure. 

Because GetCharWidth does not account for style attributes, it is useful for 
establishing the number of bits a character occupies in the font data structure. 



GetRealSize. 



103 



GetDimensions 



GetDimensions (C64, cns) 



printer driver! 



Function: 

Parameters: 

Returns: 



Destroys: 
Description: 



Note: 



Get printer resolution, 
none. 

a $00 = printer has graphics and text modes; $ff = printer only has text 

modes (e.g., daisy wheel printers). 
X PGWIDTH — page width in cards: number of 8x8 cards that will fit 

horizontally on a page (1-80, standard value is 80 but some printers 

only handle 60, 72, or 75). 
y PGHEIGHT — page height in cards: number of 8x8 cards that will fit 

vertically on a page (1-255, usually 94). 

The width and height return values are typically based on an 85" x IV* page 
with a 025" margin on all sides, leaving an 8" x 10 J" usable print area. 

nothing. 

GetDimensions returns the printable page size in cards. At each call to 
PrintBuffer, the printer driver will expect at ltdiSXPGWIDTH cards of graphic 
data in the 640-byte print buffer. To print an entire page , the application will need 
to call PrintBuffer PGHEIGHT times. 

Most dot-matrix printers have a horizontal resolution of 80 dots-per-inch and an 
eight inch print width. Eight inches at 80 dpi gives 640 addressable dots per 
printed line, and 640/8 equals 80 cards per line. GEOS assumes an 80 dpi output 
device. 

Drivers for printers with a different horizontal resolution will usually return a 
PGWIDTH value that reflects some even multiple of the dpi. For example, a 
lower resolution 72 dpi printer can only fit 72*8 = 560 dots per line, and 560 
dots reduces to 72 cards. PGWIDTH in this case would come back as 72. 

A 300 dpi laser printer, however, can accomodate 2,400 dots on an eight inch 
line. To scale 80 dpi data to 300 dpi, each pixel is expanded to four times its 
normal width. If the printer driver tried to print the full 640 possible dots at this 
expanded width, it would lose the last 160 dots because the printer itself can only 
handle 2,400 dots in an eight inch space and 640*4 = 2,560. To alleviate this 
problem he printer driver truncates the width at the card boundary nearest to 
2,400 dots, which happens to be 75 cards. Hence, in this case, PGWIDTH 
would come back as 75. 

The size, PGHEIGHT, reflects the number of card rows to send through 
PrintBuffer to fill a full-page. If more rows are sent, then (depending on the 
printer and the driver) the printing will usually continue onto the next page 
(pnniing over the perforation on z-fold paper). The application will usually keep 
an mtemal card-row counter and call StopPrint to advance to the next page. 

It is not necessary to call GetDimensions when printing ASCII text. 
Commodore GEOS printer drivers always assume 80 columns by 66 lines. 



104 



GetDimensions 



Apple: This routine is not supported under Apple GEOS. Apple GEOS offers a more 

sophisticated printer driver scheme. Refer to GetMode for more information. 

See also: StartPrint, StartASCII. 



105 



GetDirHead 



GetPirHead (Apple, C64, cus) 



mid-level disk 



Function: Read directory header from disk. Commodore GEOS also reads in the BAM. 
Parameters: none. 



Uses: 



curDrive 

Commodore: 
curType 

Applg; 

curKBlkno 



GEOS 64 vl.3 and later for detecting REU shadowing. 



current directory key block. 



Returns: 



Alters: 



X error ($00 = no eiror). 

Commodore: 

r4 pointer to curDirHead. 



curDirHead 

Commodore: 

dir2Headt 

dir3Headt 



contains directory header (39 bytes on Apple). 



(BAM for 1571 and 1581 drives only) 
(BAM for 1581 drive only) 



Destroys: 



^used internally by GEOS disk routines; applications generally don't use. 

Comm9<j(3rp; 
a, y, rl. 



Description: 



Appig; 

a, y, rl. r4. 

GetDirHead reads the directory header into the buffer at curDirHead. Because 
of differences in the Commodore and Apple file systems, this can mean different 
things. Commodore GEOS places the full directory header block (256 bytes) into 
curDirHead. This block also includes the BAM (block allocation map) for the 
entire disk. Apple GEOS. on the other hand, only places the 39-byte ProDOS 
directory header for the current directory into curDirHead. 

C64 & C128: GEOS disks, like the standard Ctommodore disks upon which they are based, 
have one directory header. The directory header occupies one full block on the 
disk. The Commodore directory header contains information about the disk, such 
as the location of the directory blocks, the disk name, and the GEOS version 
string (if a GEOS disk). The Commodore directory header also contains the disk 
BAM, which flags particular sectors as used or unused 

GetDirHead calls GetBlock to read in the directory header block into the 
buffer at curDirHead. The directory header block contains the directory header 
and the disk BAM (block allocation map). Typically, applications don't call 
GetDirHead because the most up-to-date directory header is almost always in 
memory (at curDirHead), OpenDisk calls GetDirHead to get it there 



106 



GetDirHead 



initially. Other GEOS routines update it in memory, some calling PutDlrHead to 
bring the disk version up to date. 

Because Commodore disks store the BAM information in the directory header it is 
important that the BAM in memory not get overwritten by an outdated BAM on 
the disk. An application that manipulates the BAM in memory (or calls GEOS 
routines that do so), must be careful to write the BAM back out (with 
PutDirHead) before calling any other routine that might overwrite the copy in 
memory. GetDirHead is called by routines such as OpenDisk, 
SetGEOSDisk, and GpenRecordFile, etc. 

Apple: Apple GEOS disks, like tiie ProDOS disks upon which they are based, have a 

directory header for each directory. The header for the root directory is called a 
volume directory header and the header for a subdirectory is called a subdirectory 
header. These directory headers arc 39-byte structures defined by ProDOS. They 
contain such information as the directory name, the date stamp, and read/write 
access flags. The directory header does not contain the VBM (volume bit map, the 
Apple equivalent of a BAM). 

GetDirHead reads in the key block of the current directory (pointed at by 
curKBIkno) and copies the 39-byte directory header information to 
curDirHead. 



Since Apple GEOS does not store the allocation map (VBM) in die directory 
header Uke Commodore GEOS, it not necessary to be as careful about rereading 
the directory header. For more information on reading the Apple VBM, refer to 
GetVBM. 

Example: 

See also: PutDirHead, GetVBM, PutVBM. 




107 



GetFHdrlnfo 



GetFHdrlnfo (Apple, C64, cns) 



mid-level disk 



Function: 
Parameters: 

Uses: 
Returns: 



Alters: 



Destroys: 
Description: 



Loads the GEOS file header for a particular directory entry. 

r9 DIRENTRY — pointer to directory entry of file, usually points to 
dirEntryBuf (Apple GEOS: must be in main memory) (word). 

curDrive 



Commodore: 
curType 



GEOS 64 vl.3 and later for detecting REU shadowing. 



X error ($00 = no error). 

r7 load address copied from the O^GHST^ADDR word of the GEOS 
file header. 

Commodore: 



rl 



Applg; 
rl 



track/sector copied from bytes +1 and +2 of the directory entry 
(DIRENTRY), This is the track/sector of the first data block of a 
sequential file (OFF DE TR SC) or the index table block of a VLIR 
file (OFF INDEX TPTff). " 



block number of sequential-file index block or VLIR master index block 
as copied from the OFF^FINDX byte of the directory entry. 



fileHeader 

CQmnyyjqrsi 
fileTrScTab 



a, y, r4. 



contains 256-byte GEOS file header. 



track/sector of header added to first ♦wo bytes of this table; a 
subsequent call to ReadFile or similar routine will augment 
this table beginning with the third byte (fileTrScTab+2) so 
as not to disrupt this value. 



Given a valid directory entry, GetFHdrlnfo will load the GEOS file header into 
the buffer at fileHeader. 

The directory entry is a standard GEOS data structure returned by routines such 
as FindFile, GetlstDirEntry and GetNextDirEntry. GetFHdrlnfo is 
called by routines such as LdFile just prior to calling ReadFile (to load in a 
sequential file or record zero of a VLIR). 

GetFHdrlnfo gets the block number (Commodore track/sector) of the GEOS 
file header by looking at the OFF_GHDR_PTR word in the directory entry. 



Example: 
See also: 



108 



GetFile 



GetFile (Apple, C64, C128) 



high-level disk 



Function: General-purpose file routine that can load an application, desk accessory, or data 
file. 



Parameters: r6 



FILENAME — pointer to null-terminated filename (word). 



Uses: 



When loading an application: 
rOL LOAD^OFT: 

bit 0: load at address specified in file header, application will be 
started autmatically 
1 load at address in r7; application will not be staned 
automatically, 
bit?: not passing a data file. 

1 r2 and r3 contain pointers to disk and data file names, 
bit 6: not printing data file. 

printing data file; application should print file and exit 
r7 LOAD_ADDR — optional load address, only used if bit of 

LOAD JOPT is set (word). 
r2 DATA^DISK— only valid if bit 7 or bit 6 of LOAD jOPT is set: pointer 
to name of the disk that contains the data file, usually a pointer to one of 
the DrxCurDkNm buffers (word). 
r3 DATA.FILE — only valid if bit 7 or bit 6 of LOAD jOPT is set: pointer 
to name of the data file (word). 

When iQ^ding a de?k accessory; 

rlOL REGVR^OPTS — no longer used; set to $00 (see below for explanation 
(byte). 

curDrive 



CptpmodoTp; 

curType 

Apple; 
RWbank 



GEOS 64 vl.3 and later for detecting REU shadowing. 



destination bank (MAIN or AUX); always set to MAIN 
when loading an application or desk accessory. 



Returns: When loa(iing ap applicatfon; 

only returns if alternate load address or disk error. 
X error ($(X) = no error). 

rO, r2, r3, and r7 unchanged. 

When loading a desk accessory: 

returns when desk accessory exits with a call to RstrAppl. 
X error ($(X) = no error). 

When loading a data file: 

X error ($(X) = no em)r). 

Passes: When loading an application! 

warmstarts GEOS and passes the following to the application: 



109 



GetFile 



rO as originally passed to GetFile. 
r2 as originally passed to GetFile (use dataDiskName). 
r3 as originally passed to GetFile.(use dataFileName). 
dataDiskName contains name of data disk if bit 7 of rO is set 
dataFileName contains name of data file if bit 6 of rO is set 

When loading a desk accessory: 
warmstarts GEOS and passes the following: 
rIOL as originally passed to GetFile. 

When loading a data file: 
not applicable. 

Alters: When loading an application: 

GEOS brought to a warmstart state. 

Destroys: a, x, y, rO-rlO (only applies to loading a data file). 

Description: GetFile is the preferred method of loading most GEOS files, whether a data file, 
application, or desk accessory. (The only exception to this is a VLIR file, which 
is better handled with the VLIR routines such as OpenRecordFile and 
ReadRecord). Most applications will use GetFile to load and execute desk 
accessories when the user clicks on an item in the geos menu. Some applications 
will use GetFile to load other applications. The GEOS deskTop, in fact, is just 
another application like any odier. Depending on the user's choice of actions — 
open an application, open an application's data file, print an applications' data file 
— die deskTop sets LOADjOPT, DATA^DISK, DATAJFILE appropriately and 
calls GetFile. 



GetFile first calls.FindFile to locate die file at FILENAME, then checks the 
GEOS file type in the directory entry. If the file is type DESK ACC, then 
GetFile calls LdDeskAcc. If die file is type APPLICATIDN or type 
AUTO^EXEC, GetFile calls LdApplic. All odier file types are loaded widi 
the generic LdFile. 

The following GEOS constants can be used to set the LOADjOPT parameter 
when loading an application: 



ST_LD_AT_.ADDR 


Load at address: load application at the address passed in 
r7 as opposed to the address in the file header. 


ST^LD^DATA 


Load data file: aj^lication is being passed the name of a 
data file to load. 


ST^PR^DATA 


Print data file: aiqplication is being passed the name of a 
data file to print 



Note: The RECVRjOPTS flag used when loading desk accessories originally carried 

die following significance: 

bit 7: 1 force desk accessory to save foreground screen area and restore it on return to 
application. 

not necessary for desk accessory to save foreground. 
Commodore only; 

bit 6: 1 force desk accessory to save color memory and restore it on return to 
application. 



110 



GetFile 



not necess^ for desk accessory to save color memory. 

However, it was found that the extra code necessary to make desk accessories 
save the foreground screen and color memory provided no real benefit because 
this context save can just as easily be accomplished from within the application 
itself. The RECVRjOPTS flag is set to $00 by all Berkeley Softworks 
applications, and desk accessories can safely assume that this will always be the 
case. (In fact, future versions of GEOS may force rlOH to $00 before calling 
desk accessories just to enforce this standard! ) 

The application should always set rlOH to $00 and bear the burden of saving and 
restoring the foreground screen and the color memory. (Color memory only 
applicable to GEOS 64 and GEOS 128 in 40-column mode.) 

Apple: Applications and desk accessories arc designed to load into main memory. Ensure 

that RWbank contains MAIN before calling GetFile to load anything but a data 
file. 

Example: 

See also: LdFile, LdDeskAcc, LdApplic. 



111 



GetFreeDirBlk 



GetFreeDirBlk (Apple, C64, ci28) 



mid-level disk 



Function: 
Parameters: 

Uses: 



Search the current directory for an empty, slot for a new directory entry. Allocates 
another directory block if necessary. 

rlOL DIRPAGE — directory page to begin searching for free slot; each 
directory page holds eight files and corresponds to one notepad page on 
the GEOS deskTop. The first page is page one. 

curDrive 

COniniQ<jorg; 

curType GEOS 64 vl.3 and later: for detecting REU shadowing. 

curDirHead this buffer must contain the current directory header. 
dir2Headt (BAM for 1571 and 1581 drives only) 

dirSHeadt (BAM for 1581 drive only) 

interleave^ desired physical sector interleave (usually 8);. applications 

need not set this explicitly — will be set automatically by 
internal GEOS routines. Only used when new directory 
block is allocated 



Returns: 



Alters: 



Apple: 

curKBIkno 
curVBlknot 
VBMchangedt 
numVBMBlkst 



current directory, 
used by \'BM cacheing routines, 
used by VBM cacheing routines, 
used by VBM cacheing routines. 



^used internally by GEOS disk routines; applications generally don't use. 

X error ($00 = no error). 

rlOL page number of empty directory slot. 

rl block (Commodore track/sector) number of directory block in 
diskBlkBuf. 

Commodore: 

y index to empty directory slot in diskBlkBuf. 



Apple; 
r3 

rlOH 



pointer to empty directory slot in diskBlkBuf. This is an absolute 
address, not an index into diskBlkBuf. 

unused directory entry within block in diskBlkBuf. There are 13 
directory entries per ProDOS block, numbered 1-13. 



Commodore: 
curDirHead 
dirlHeadt 
dir3Headt 

Apple; 

curVBlknot 
VBMchangedt 



BAM updated to reflect newly allocated block! 
(BAM for 1571 and 1581 drives only) 
(BAM for 1581 drive only) 



used by VBM cacheing routines. 

set to TRUE by VBM cacheing routines to indicate cached 
VBM block has changed and needs to be flushed 



112 



GetFreeDirBlk 



^used internally by GEOS disk routines; applications generally don't use. 

Destroys: CpiprTKyjorg: 

a, rO, r3, rS, r7-r8. 

Apple: 

a» r4-r5, r7-r8. 

Description: GetFreeDirBlk searches the current directory looking for an empty slot for a 
new directpry entry. A single directory page has eight directory slots, and these 
eight slots correspond to the eight possible files that can be displayed on a single 
GEOS deskTop notepad page. 

GetFreeDirBlk starts searching for an empty slot beginning with page number 
DIRPAGE. If GetFreeDirBlk reaches the last directory entry without finding 
an empty slot, it will try to allocate a new directory block. If DIRPAGE doesn't 
yet exist, empty pages are added to the directory structure until the requested page 
is reached. 

$01 will most often be passed as the DIRPAGE starting page number, so that all 
possible directory slots will be searched, starting with the fiirst page. If higher 
numbers are used, GetFreeDirBlk won't find empty directory slots on lower 
pages and extra directory blocks may be allocated needlessly. 

GetFreeDirBlk is called by SetGDirEntry before writing out the directory 
entry for a new GEOS file. 

C64 & C128: Since Conimodore GEOS does not support a hierarchical file systeni, the "current 
directory" is actually the entire disk. A dkectory page corresponds exacdy to a 
single sector on the directory track. There is a maximum of 18 directory sectors 
(pages) on a Commodore disk. If this 18th page is exceeded, GetFreeDirBlk 
will return a FULL^DIRECTORY error. 

GetFreeDirBlk allocates blocks by calling SetNextFree to allocate sectors on 
the directory track. SetNextFree wUl specid-case the directory track allocations. 
Refer to SetNextFree for more information. 

GetFreeDirBlk does not automatically write out the BAM. See PutDirHead 
for more information on writing out the BAM. 

Apple: ProDOS directory blocks (and therefore GEOS directory blocks) contain 13 

directory slots. This requires Apple GEOS to map GEOS's eight-entry directory 
pages to tiiese 13-entry blocks, sometimes forcing a page to straddle a block 
boundary. Most applications need not worry about this straddling as it is made 
transparent by GEOS routines such as FindFile. 

If an empty directory slot is not found and the end of the last block of the current 
directory is reached, GetFreeDirBlk calls SetNextFree to allocate a new 
directory block. The number of blocks in a ProEKDS directory is limited only by 
space. liF there is no more space on the disk for another directory block, and 
INSUFFICIENT^SPACE error is returned. 



113 



GetFreeOirBlk 



GetFreeDirBIk does not automatically flush the VBM cache. See PutVBM 
more information on flushing the cache. 

Example: 

See also: AIlocateBlock, FreeBIock, BIkAIloc. 



114 



GetLdVars 



GetLdVars (Apple) 



mid-level disk 



Function: Transfers the internal "Ld" variables (those used by LdAppl, LdDeskAcc, and 
LdFile) to GEOS pseudoregisters. 

Parameters: none. 



Returns: 



rOL 



Destroys: 
Description: 



r7 
r2 



r3 

rlOL 



a. 



LOAD.OPT: 

bitO: load at address specified in file header; application will be 
started autmatically 
1 load at address in r7; application will not be started 
automatically, 
bit?: not passing a data file. 

1 r2 and r3 contain pointers to disk and data file names, 
bit 6: not ininting data file. 

printing data file; application should print ^e and exit 
LOAD_ADDR — optional load address, only used if bit of 
WADJDPT is set (word). 

DATA^DISK — only valid if bit 7 or bit 6 of LOAD JOPT is set: pointer 
to name of the disk that contains the data file, usually a pointer to one of 
the DrjcCurDkNm buffers (word). 

DATA^FILE — only valid if bit 7 or bit 6 of LOAD jOPT is set: pointer 
to name of the data file (word). 
RECVR.OPTS (byte). 



GetLdVars transfers the internal load varaibles to GEOS pseudoregisters. 
GetFile, LdApplic, LdDeskAcc, and LdFile call GetLdVars as necessary. 
Most applications will not need to call it direcdy. 



See also: 



SetLdVars. 



CONriDCNTUL 1 1 5 



GetMode 



GetMode (Apple) 



printer driver 



Function: Get printer resolution and setable attributes. 
Parameters: none. 



Returns: 



Destroys: 
Description: 



a ASCnWIDTH — page width for ASCII printing (characters per line), 

assumes 10 cpi pitch (byte). 
X PGWIDTH — page width in cards: number of 8x8 cards that will fit 

horizontally on a page (1-80, standard value is 80 but some printers 

only handle 60, 72, or 75) (byte). If $00, then this is an older driver: 

assume 80 cards. 

y PGHEIGHT — page height in cards: number of 8x8 cards that will fit 

vertically on a page (1-255, usually 94) (byte). 
rO-r2L MODE — flags for possible printer modes and capabilities (five bytes). 

The width and height values are typically based on an 85" xU" page with a 
025" margin on all sides, leaving an 8" x 105" usable print area. 

assume r2H-r4. 

GetMode returns information concerning the resolution and capabilites of the 

nnntpr 



currently installed printer. 



Graphic Printing: 

At each call to PrintBuffer, the printer driver will expect at leastFGW^/Dr// 
cards of linear bitmap data in the 640-byte print buffer. To print an entire page , 
the application will need to call PrintBuffer PGHEIGHT times. 

Most dot-matrix printers have a horizontal resolution of 80 dots-per-inch and an 
eight inch print width. Eight inches at 80 dpi gives 640 addressable dots per 
printed line. Since GEOS printer output is designed to map dirccdy from screen 
graphics, it is sometimes useful to think of it in terms of cards (8x8 pixel blocks). 
There 80 (640/8) 80 cards per printable line. GEOS always assumes an 80 dpi 
output device. 

Drivers for printers with a different horizontal resolution will usually return a 
PGWIDTH value that reflects some even multiple of the dpi. For example, a 
lower resolution 72 dpi printer can only fit 72*8 = 560 dots per line, and 560 
dots reduces to 72 cards. PGWIDTH in this case would come back as 72. The 
printer driver will only ouput the first 72 cards (560 dots) on each line. 

A 300 dpi laser printer, however, can accomodate 2,400 dots on an eight inch 
line. To scale 80 dpi data to 300 dpi, each pixel is expanded to four times its 
normal width. But 640*4 = 2,560, which is 160 dots more than the printer can 
handle. If the printer driver tried to print the full 640 possible dots at this 
expanded width, it would lose the last 160 dots. The printer driver truncates the 
width at the card boundary nearest to 2,400 dots, which happens to be 75 cards 
(75*8*4 = 2400). Hence, in this case, PGWIDTH would come back as 75. 

The size, PGHEIGHT, reflects the number of card rows to send through 
PrintBuffer to fill a full-page. If more rows are sent, then (depending on Ae 



116 



GetMode 



printer and the driver) the printing will usually continue onto the next page 
(printing over the perforation on z-fold paper). The application will usually keep 
an internal card-row counter and call StopPrint to advance to the next page. 

ASCII Printing; 

The printer is capable of printing ASCUWIDTH characters per line and 66 lines 
per page. 

The MODE W^ue^: 

GetMode returns a number of flags in rO-r2L. These flags determine whether a 
specific feature is offered by the current printer and its printer driver. These bits 
correspond to features that may be set with SetMode: 

rOL: (matches currentMode text variable) 



bit 


description 


b7 


^underline. 


b6 




b5 


reverse. 


b4 


^italic. 


b3 


outline. 


b2 


^superscript 


bl 


^subscript 


bO 


reserved for future use. 


(text density) 

bit description 


b7 


+picatype(10 cpi). 


b6 


^elite type (12 cpi). 


b5 


^condensed type (16 cpi). 


b4 


" ^proportional type. 


b3 


^double height 


b2 


^half-height 


bl 


^eighi lines per inch vertical density. 


bO 


^six lines per inch vertical density. 


(miscellaneous features) 
bit description 


b7 


print red or magenta. . 


b6 


print yellow. 


b5 


print blue or cyan. 


b4 


^expanded (double-width) type. 


b3 


*NLO (near letter quality) type. 


b2 


CR always linefeeds, preventing manual overstrike by application 


bl 


reserved for future use. 


bO 


reserved for future use. 



117 



GetMode 



rlH: (internal font availability) 



bit 


description 


b7 


font 7. 


b6 


font 6. 


b5 


font 5. 


b4 


font 4, 


b3 


font 3. 


b2 


font 2 (Roman?). 


bl 


font 1 (Helvetica?). 


bO 


font (Courier?). 


(horizontal graphics density) 
bit description 


b7 


60 dpi. 


b6 


^SOdpi. 


b5 


90 dpi. 


b4 


120 dpi. 


b3 


180 dpi. 


b2 


300 dpi. 


bl 


360 dpi. 


bO 


reserved for future use. 



^This feature implemented in most Berkeley Softworks printer drivers. 
C64 & C128: Refer to GetDimensions. 
See also: SetMode. 



118 



GetNextChar 



GetNextChar (Apple, C64, cns) 



text/keyboard I 



Function: 
Parameters: 
Returns: 
Alters: 

Destroys: 



Retrieve the next character firom the keyboard queue, 
none. 

a keyboard character code of characer or NULL if no characters available. 

pressFIag if the call to GetNextChar removes the last character from 

the queue, then the KEYPRESS^BIT is cleared. 



Description: GetNextChar checks the keyboard queue for a pending keypress and returns a 
non-zero value if one is available. This allows more tihian one character to be 
processed without returning to MainLoop. 



Example: 
See also: 



GetString. 



119 



GetNxtDlrEntry 



GetNxtPirEntry (Apple, C64, cm) 



mid-level disk 



Function: 
Parameters: 

Uses: 



Given a pointer to a directory entry returned by GetlstDirEntry or 
GetNxtDirEntry, returns a pointer to the next directory entry.. 

rS CURDIRENTRY — pointer to current directory entry as returned from 
GetlstDirEntry or GetNxtDirEntry; will always be a pointer into 
diskBlkBuf (word). 



curDrive 
diskBlkBuf 



Commodore: 
curType 



must be unaltered from previous call to GetlstDirEntry or 
GetNxtDirEntry. 



GEOS 64 vl.3 and later, for detecting REU shadowing. 



Returns: 



Alters: 
Destroys: 



X error ($00 = no error). 

rS pointer to next directory entry within diskBlkBuf. 
Commodore: 

y non-zero if end of directory reached 



directory block. 



diskBlkBuf 

Ctommodore: 
a, rl, r4. 

Commodore: 
a, y, rl, r4. 

Description: GetNxtDirEntry increments rS to point to the next directory entry in 
diskBlkBuf. If diskBlkBuf is exceeded, the next directory block is read in 
and r5 is returned with an index into this new block. Before calling 
GetNxtDirEntry for the first time, call GetlstDirEntry. 

C64 & C128: GetNxtDirEntry did not appear in the jump table until version 1.3. An 
application running under version 1.2 can access GetNxtDirEntry by calling 
directiy into the Kemal. The following subroutine will work on Commodore 
GEOS V 1.2 and later: 



MyGetNxtDirEntry — Use instead of GetNxtDirEntry 
to work on GEOS vl.2 and later 



/EQUATE: vl.2 entry point directly into Kernal. Must 
;do a version check before calling, 
©^GetNxtDirEntry = $calO ; exact entry point 



MyGetNxtDirEntry: 

Ida version 
cmp #$13 
bge 10 



; check version number 
/branch if vl.3 or later 



120 



GetNxtDirEntry 



jmp o_GetNxtDirEntry /direct call 

10$: 

jmp GetNxtDirEntry ;thru jump table 

Apple: GetNxtDirEntry did not appear in the jump table until version 2.0, release 3. 

An application running under an earlier version can add GetNxtDirEntry into 
the jump table with the patch provided in Appendix @@. 

Example: 

See also: GetlstDirEntry, FindFTypes. 



121 



GetOffPageTrSc 



GetOffPageTrSc (C64, C128) mid-level diski 



Function: Get track and sector of off-page directory. 



Parameters: none. 

Uses: curDrive 

curType GEOS 64 vl.3 and later: for detecting REU shadowing. 



Returns: x error ($00 = no error). 

y $ff if the disk is not a GEOS disk and therefore has no off-page 

directory block, otherwise $00. 
rlL track of off-page directory, 
r 1 H sector of of f-page directory. 
r4 pointer to curDirHead. 



Alters: 



curDirHead 
dir2Headt 
dir3Headt 
isGEOS 



contains directory header. 

(BAM for 1571 and 1581 drives only) 

(BAM for 1581 drive only) 

set to TRUE if disk is a GEOS disk, otherwise set to 
FALSE. 



^used internally by GEOS disk routines; applications generally don't use. 



Destroys: Commodore: 
a, y, rS. 

Description: Commodore GEOS disks have an extra directory block somewhere on the disk 
called the off-page directory. The GEOS deskTop uses the off-page directory 
block to keep track of file icons that have been dragged off of the notepad and 
onto the border area of the deskTop. The off-page directory holds up to eight 
directory entries. 

GetOffPageTrSc reads the directory header into the buffer at curDirHead and 
calls ChkDkGEOS to ensure that the disk is a GEOS disk. If the disk is not a 
GEOS disk, it returns with $ff in the y register. Otherwise, GetOffPageTrSc 
copies the off-page track/sector from the OFF_OP_TR_SC word in the 
directory header to rl and returns $00 in y. - - - 

Apple: Apple GEOS does not use an off-page directory block. The Apple GEOS 

deskTop manages files that are draggai onto the border area entirely in software. 

Example: 

; Put off-page block into DiskBlkBuf 



jsr GetOffPageTrSc ;get of f-page directory block 

txa ; check for error 

bne 99$ ; 

tya ; check for GEOS disk 

tax /put in x in case error 

bne 99$ 

LoadW r4,#diskBlkBuf ;get off-page block 

jsr Get Block / 

99$: rts / return with error in x 



122 



PutDirHead, GetVBM. PutVBM . 



GetOffPageTrSc 



123 



GetPathname 



GetPathnamejAppie) 



high-level disk 



Function: 
Parameters: 

Uses: 
Returns: 

Alters: 
Destroys: 
Description: 



Builds out an ASCII pathname string to any disk directory. 

rl PATHBUF — pointer to buffer to place pathnanie (word). 
rOL BUFSIZE — size of pathname buffer (byte). 

t2 KEYBLKNO — key block of directory to build path for; pass the value 
in curKBIkno to get the path of the current directory. 

curDrive 

X error ($00 = no error). 

y pathname status ($00 = OK; BFR_OVERFLOW = pathname longer 

than jBC/F5/Z£ bytes). 



diskBlkBuf 
a, rO-r2L, r4. 



used to hold temporary blocks. 



GetPathname works backward from the directory specified by KEYBLKNO, 
building out a pathname in the buffer pointed to by PATHBUF. The pathname is 
built up in ASCII from right to left. If the actual path is larger than BUFSIZE 
bytes, the lowest BUFSIZE characters of the path are placed in the buffer and a 
BFR^O VERFLOW error is returned. 

C64 & C 128 : CtominodoreGEOS does not support a hierarchical file system. 
Example: 

See also: GoDirectory, UpDirectory, DownDirectory. 



124 



GetPattern 



GetPattern (Apple) 



graphics! 



Function: 
Parameters: 

Returns: 

Destroys: 
Description: 



Example: 
See also: 



Copy an eight-byte GEOS pattern definition to an application's buffer. 

a GEOS system pattern number. 

rO pointer to eight-byte destination buffer (word). 

rO unchanged. 

Pattern data in buffer pointed to by rO 

a,y 

GetPattern downloads an eight-byte pattern definition from auxiliary high 
memory to a buffer defined by the application. This is the only convenient way to 
gain access to the system pattern definitions under Apple GEOS. To redefine a fill 
pattern, use SetUserPattern. 



SetPattern, SetUserPattern. 



CONriDCNTIAL 

125 



GetPtrCurDkNm 



GetPtrCurPkNm (Apple, C64, cns) 



high-level dlsk| 



Function: 
Parameters: 

Uses: 
Returns: 

Destroys: 
Description: 



Get pointer to the current disk name. 

X PTR — zero-page address to place pointer (byte pointer to a word 
variable). 



curDrive 



currendy active drive. 



X unchanged. 

zero-page word at $00,x {PTR) contains a pointer to the current disk name. 

GetPtrCurDkNm returns an address that points to the name of the current disk. 
Disk names are stored in the Dr;cCurDkNm variables, where x designates the 
drive (A, B, C, or D). If drive A is the current drive then GetPtrCurDkNm 
would return the address of DrACurDkNm. If drive B is the current drive then 
GetPtrCurDkNm would return the address of DrBCurDkNm. And so on. 

Although the locations of the Dr;cCurDkNm buffers are at fixed memory 
locations, they are not contiguous in memory. It is easier to call 
GetPtrCurDkNm than hardcode the addresses into the application. This will 
also ensure upward compatibilty with future versions of GE(DS that might support 
more drives. 

C64: Versions of GEOS before vl.3 only suport two disk drives and therefore only 

have two disk name buffers allocated (DrACurDkNm and DrBCurDkNm). 
GEOS vl.3 and later support additional drives C and D. GetPtrDkNm will 
return the proper pointer values in any version of GEOS as long as.numDrives 
does not exceed the number of disk name buffers. Trying to get a pointer to 
DrDCurDkNm under GEOS vl.2 will return an invalid pointer because the 
buffer does not exist 

C64 & C128: Ctommoodore disk names are always a fixed-length 16 character string. If the 
name is less than 16 characters, the string is padded with $aO. 



Apple: 

Example: 
See also: 



Apple disk names are null-terminated strings of 16 characters or less (counting the 
null-temiinator). 



126 



GetRandom 



IGetRandom (Apple, C64, cus) 



uti 



mt3 



Function: 

Parameters: 

Uses: 

Alters: 

Destroys: 

Description: 



Note: 



Creates a 16-bit random number, 
none. 

random seed for next random number, 

random contains a new 16-bit random number, 

a 

GetRandom produces a new pseudorandom (not truly random) number using 
the following linear congmential formula: 

random = (2*(random+l) // 65521) 

(remember: II is the modulaus operator) 

The new random number is always less than 65221 and has a fairly even 
distribution between and 65521 . 

GEOS calls GetRandom during Interrupt Level processing to automatically keep 
the random variable updated. If the application needs a random number more 
often than random can be updated by the Kemal, then GetRandom must be 
called manually 



Example: 



127 



GetRealSize 



GetRealSize (Apple, C64, cus) 



Function: Calculate the printed size of a character based on any style attributes. 

Parameters: a CHAR — character code of character (byte). 

X MODE — style mode (as stored in currentMode). 

Uses: curHeight 

baselineOffset 

Apple; 

lastWIdth (if character code is USELAST) 

Returns: y character width in pucels (with attributes). 

X character height in pixels (with attributes), 
a character baseline offset (with attributes). 

Destroys: nothing. 

Calls: GetCharWidth 

Description: GetRealSize calculates the width of the character based any style attributes The 
character code must be 32 or greater. If the character code is USELAST, the 
value in lastWidth is returned. Any other character code returns the pixel width 
as calculated from the font data structure and the MODE parameter. 

C64 & C128: lastWidth is local to the GEOS Kemal and therefore inaccessible to applications. 
It contains the actual width of the most recendy printed character. 

See also: GetCharWidth. 

Example: 

; Calculate size of largest character in current font 

Ida #'W' ; capital W is a good choice 

Idx #(SET_BOLD|SET_OUTLINE ; widest style combo 

jsr GetRealSize ; dimensions come back in x,y 



text 



128 



GetScanLine 



GetScanLine (Apple, C64, cm) 



graphics] 



Function: 

Parameters: 

Uses: 

Returns: 



Destroys: 
Description: 



Calculate the memory address of a particular screen line. 
X Y — y-coordinate of line. 

dispBufferOn: 

bit 7 — calculate foreground screen address, 
bit 6 — calculate background buffer address. 

X unchanged. 

addresses in rS and r6 based on dispBufferOn status: 
bit 7 bit 6 returns 



1 


1 


rS = foreground; i6 s backKround 





1 


r5. r6 = background 


1 





r5. i6 =» foreRTOund 








error: r5/6 = address of screen center 



a 

GetScanLine calculates the address of the first byte of a particular screen line. 
The routine always places addresses in both rS and r6, depending on the value in 
dispBufferOn. This allows an application to automatically manage both 
foreground screen and background buffer writes according to the bits set in 
dispBufferOn by merely doing any screen stores twice, indirectly off both rS 
and r6 as in: 



Note: this code is C64 specific (see notes below for 128 and Apple) 



128: 



Apple: 



Idy 
Ida 
sta 
sta 



xpos 
grByte 
(r5),y 
(r6),y 



byte index into current line 
graphics byte to store 
store using both indexes 



When GEOS 128 is operating in 80-column mode, all foreground writes are sent 
through the VDC chip to its local RAM. In this case, the address of the 
foreground screen byte is actually an index into VDC RAM for the particular 
scanline. For background writes, the address of the background screen byte is an 
absolute address in main memory (be aware, though, that the background screen 
is broken into two parts and is not a contiguous chunk of memory). 

In 40-column mode, GetScanLine operates as it does under GEOS 64. 

Because the Apple double hi-res screen is spread across two memory banks, it is 
sometimes necessary to enable or disable a given bank before accessing the 
screen. The following subroutine >yill swap in the correct memory bank: 

Routine to set correct memory bank in Apple 

Pass: a - byte index into line (xpos) 

Returns: proper memory bank swapped in 

y - corrected index into line 



129 



GetScanLine 



/Destroys: a 

• *****1ir********«******«4r****«r*ir ************ ******* 

SetCorrectPage : 

Isr a ;xpos/2; low-bit into carry 

tay /return correct index in y 

bcs 10$ /Is low-bit set? 

St a PAGE2__0N / — >N0: swap in aux. memory 

rts / return 

10$: 

sta PAGE2_0FF / — >YES: swap in main memory 

rts / return 

Example: 



130 



GetScreenLi 



IGetScreenLine (Apple) 



graphics 



Function: 
Parameters: 



Uses: 

Returns: 

Destroys: 

Description: 



Note: 
Example: 



Copies a byte-aligned horizontal line from the screen, in internal format, to an 
application's buffer. 

rO DATA — address of buffer to copy data to (word). 
rlH XINDX — byte in line to begin with (seven-bit Apple screen byte) (byte). 
r2L XWIDTH — width in bytes of line (seven-bit Apple screen bytes) (byte). 
rIL Y — y-coordinate of line (byte). 

where (XINDX*7,Y) and (XINDX^J-^XWIDTHJ) define the endpoints of the 
line. 

dispBufferOn: 

bit 7 — get data from foreground screen if set 
bit 6 — get data from background buffer if set. 
If both bits are set, foreground screen is used. 

rO address of byte following last byte in line. 

a, X, y, rO, rlH 

GetScreenLine copies bytes direcdy from the screen memory to the specified 
buffer. The screen is treated as a contiguous block of bytes even though, in 
actuality, alternate bytes lie in different memory banks. 

Bytes are copied into the buffer pointed to by rO beginning at the byte-index into 
the line stored in rlH. 

No clipping at the screen edge is performed; the values passed are assumed to lie 
entirely on one screen line. 



131 



GetSerialNumber 



GetSerialNumber (Apple, C64, ci28) internal 



Function: Return the 16-bit serial number or pointer to the serial string for the current GEOS 
kemaL 

Parameters: none. 

Returns: Commodore: 

rO 16-bit serial number. 

Appig; 

rO pointer to serial string. 
Destroys: a. 

Description: GetSerialNumber gives an application access to an unencrypted copy of the 
GEOS serial number or serial string for comparison purposes. You cannot change 
the actual serial string or number by altering this copy. 



132 



GetSpriteData 



GetSpritePata (Apple) 



sprite! 



Function: 

Parameters: 

Returns: 

Destroys: 

Description: 

Note: 



Example: 
See also: 



Copies a 64-byte sprite image from the internal data buffer that is used for 
drawing the sprites to the application's memory space. 

r3L SPRITE — sprite number (byte). 

r4 BUFPTR — pointer to 64-byte buffer (word). 

sprite data in buffer pointed to by BUFPTR. 

a,y 

GetSpriteData is the functional opposite of DrawSprite. It copies 64-bytes of 
sprite image data from the internal buffer that is used for drawing the sprites to a 
buffer in the application memory space. 

In no case should the SPRITE parameter be $00; a value of $00 will return 
incorrect data. 

The INAUX^B constant may be or'ed into the SPRITE parameter to indicate 
that the BUFPTR parameter is an address in auxiliary memory. 



DrawSprite, PosSprite, EnablSprite, DisablSprite, InitSprite. 



133 



GetString 



GetString (Apple, C64, ci28) 



text/keyboard I 



Uses: 



Returns: 



Destroys: 



rlL 

r2L 

rll 
rlH 



r4 



Function: Get a string from the keyboard using a cursor prompt and echoing characters to 
the screen as they are typed Runs concurrently with MainLoop. 

Parameters: rO BUFR — pointer to string buffer. When called this buffer can 

contain a null-terminated default string (if no default string is used, 
the first byte of the buffer must be NULL). This buffer must be at 
least MAX C//+1 bytes long. 

FLAG — "$00 = use system fault routine; $80 = use fault routine 
pointed to by r4 (byte). 

MAX.CH — maximum number of characters to accept (not 
including the nuU-terminator). 
XPOS — x-coordinate to begin input (word). 
YPOS — y-coordinate of prompt and upper-left of characters. To 
calculate this value based on baseline printing position, subtract the 
value in baselineOffset from the baseline printing position (byte). 
FAULT — optional (see FLAG) pointer to fault routine, 
key Vector STRINGDONE — routine to call when the string is terminated by 
the user typing a carriage return. $0000 = no routine provided. 

at call to GetString: 

curHeight for size of text prompt. 

baselineOffset for positioning default string relative to prompt 
any variables used by PutString. 

while accepting characters: 

key Vector vectors off of MainLoop through here with characters. 

stringX current prompt x-position. 

stringY current prompt y-position. 

string pointer to start of string buffer, 

any variables used by PutChar. 

from call to GetString: 

keyVector address of SystemStringService. 

stringFaultVec address of fault routine being used 
StringX starting prompt x-position. 

StringY starting prompt y-position. 

string BUFR (pointer to start of string buffer). 

when done accepting characters: 

X length of string; index to null, relative to address in string, 

string BUFR (pointer to start of string buffer). 

keyVector $0000 
StringFaultVec $0000 

at call to GetString: 
r0-rl3, a, x, y. 

Description: GetString installs a character handling routine into keyVector and returns 
immediately to the caller. During MainLoop, the string is built up a character at a 
time in a buffer. When die user presses [Return], GEOS calls die STRINGDONE 



134 



GetString 



routine with the starting address of the string in string and the length of the 
string in the x-register. 

The following is a breakdown of what GetString does: 

1: Variables local to the.GetString character input routine are initalized. Global 
string input variables such as string, stringX, and stringY are also 
initialized. 

2: PutString is called to output the default input string stored in tiie character 
buffer. If no default input string is desired, the first byte of tiie buffer should 
be a NULL. 

3: The STRINGDONE parameter in key Vector is saved away and the address 
of the GetString character routine (SystemStringService) is put into 
keyVector. 

4: If tiie application supplied a fault routine, install it into StringFaultVec, 
otherwise install a default fauh routine. 

5: The prompt is initalized by calling InitTextPrompt with the value in 
curHeight. PromptOn is also called. 

6: Control is returned to the application. 

C64 &C128: String is not null-terminated until tiie user presses [Return]. To simulate a 
[Return], use die following code: 

/Simulate a CR to end GetString 

LoadB keyData,#CR /load up a (Return) 

Ida keyVector /and go through keyVector 

Idx keyVector+1 /so SystemStringService 

jsr CallRoutine /thinks it was pressed 

Note that tiiis will also terminate tiie GetString input. 
Apple: String is always kept null-terminated. 

Note: This note courtesy of Bill Coleman.. .Because GetString runs off of 

MainLoop, it is a good idea to call GetString from the top level of the 
application code and return to MainLoop while characters are being input. That 
is, while at the top level of your code you can call GetString like this: 

jsr GetString / Start GetString going 

rts / and return immediately to MainLoop so 

/ that string can be input. 

Since the routine specified by the STRINGDONE value stored in key Vector is 
called when the user has finished entering the string, that is where your 
application should again take control and process the input. 

See also: PutChar, PutString, GetNextChar. 

Example: 



135 



GetVBM 



GetVBM (Apple) 



mid-level disk 



Function: 

Parameters: 

Uses: 

Returns: 
Alters: 



Destroys: 
Description: 



Note: 

Example: 
See also: 



Read the first (or only) VBM block into the internal VBM cache, 
none. 



curDrive 
VBMBlknot 



block number of first VBM block. 



error ($00 = no error). 



curVBlkno^ 

VBMchanged^ 

numVBMBlkst 



block loaded into cache. 

set to FALSE; indicates current cache matches disk, 
number of VBM blocks. 



^used internally by GEOS disk routines; applications generally don't use. 
a, y, rl, r4. 

GetVBM reads the first block of the VBM (volume bit map) into the internal 
VBM cache. This cache is inaccessible to applications but is used indirectly by 
routines such as SetNextFree. GetVBM is called automatically by OpenDisk 
and ReOpenDisk to get a valid VBM block into the cache. Specialized 
applications that switch disks or drives without using OpenDisk or 
ReOpenDisk, should call GetVBM to erase any VBM bits from a previous 
disk tiiat might be lurking in the cache. 

For mon information on Apple GEOS VBM-cacheing, refer to PutVBM. 

« 

GetVBM ignores the VBMchanged flag. The block is always read in from 
disk, overwriting whatever is currendy in the cache. 



PutVBM, GetDirHead, PutDirHead. 



135 



GoDirectory 



GoDirectory (Apple) 



mid-level disk I 



Function: 

Parameters: 

Uses: 

Returns: 
Alters: 



Destroys: 



Go to a specific directory on the disk, making it the current directory. 

rO KEYBLKNO — block number of this directory's key block (word). 



curDrive 
curKBlkno 



current directory. 



X error ($00 = no error). 

y pathname stanis ($00 = OK; BFR^OVERFLOW = pathname longer 
than pathnameBuf)- 



curKBlkno 

curDirHead 

pathnameBur 

curDirTabLot 

curDirTabHit 



new current directory, 
header of new directory. 

system pathname buffer updated to reflect new path, 
system directory table 



^used internally by GEOS disk routines; applications generally don't use. 
a, rOL, rl, r2, r4. 



Description: GoDirectory makes the directory at KEYBLKNO the current working directory 
so that all operations happen within it . 

GoDirectory first changes the current key block number, then calls 
GetPathname to build-out the full pathname in pathnameBuf. The current 
directory header is read in with a call to GetDirHead 

€64 & C128: Commodore GEOS does not support a hierarchical file system. 

Example: 

See also: UpDirectory, DownDirectory. 



136 



GotoFirstMenu 



IGotoFirstMenu (Apple, C64, cm) 



icon/menu 



Function: 



Retracts all sub-menus and reactivates nienus at the main menu level 



Parameters: none- 

Destroys: assume r0-rl5, a, x, y 



Description: 



GotoFirstMenu is used by a menu event handler to instruct GEOS to back up 
to the main menu level, erasing the current menu and any parent menus (except 
the main menu) from the foreground screen, making the main menu active when 
control is returned to MainLoop. menuNumber is set to $00. 



GotoFirstMenu can be called from a menu event routine at any menu level, 
including main menu level. It operates by checking for level zero and calling 
DoPreviousMenu in a loop. 

Example: 

See Also: DoMenu, DoPreviousMenu, ReDoMenu, RecoverAIlMenus. 



137 



HideOnlyMouse 



HideOnlyMouse (Apple, cns) 



mouse/sprite! 



Function: Temporarily removes the soft-sprite mouse pointer firom the graphics screen. 
Parameters: nothing. 



Returns: 
Uses: 

Alters: 

Destroys: 

Description: 



128: 



Apple: 



Example: 
See also: 



nothing. 

graphMode 
offFIag 

offFlag 

a, X, y, rl-r6 



(128 only). 
(Apple only). 

set to TRUE (Apple only). 



HideOnlyMouse temporarily removes the mouse-pointer soft-sprite. It does not 
affect any of the other sprites. This can be used as an alternative to 
TempHideMouse when only the mouse pointer need be hidden. The mouse 
pointer will remain hidden until die next pass through MainLoop. Any 
subsequent calls to TempHideMouse before passing through MainLoop 
again will not erase any sprites. 

In 40-column mode (when bit 7 of graphMode is zero), HideOnlyMouse 
exits immediately without affecting the hardware sprites. Also, be aware that any 
subsequent GEOS graphic operation will hide any visible sprites by calling 
TempHideMouse, so this routine is not especially usefuU if using GEOS 
graphics routines. 

This routine sets offFlag to TRUE which will stop TempHideMouse from 
erasing any sprites until the soft-sprite handling code in MainLoop is 
encountered. In some cases this causes problems with graphic operations that 
occur off of MainLoop before this code is executed. The easiest solution to this 
problem is to avoid using HideOnlyMouse and use TempHideMouse with 
noEraseSprites set to TRUE. offFlag can, instead, be set to $40 if die 
application wants the GEOS Interrupt Level to redraw the mouse before the 
application returns to MainLoop. 



TempHideMouse. 



140 



HorizontalLine 



IHorizontalLine (Apple, C64, cns) 



graphics! 



Function: 
Parameters: 



Uses: 

Returns: 
Destroys: 



Draw a horizontal line with a repeating bit-pattern. 

a PATTERN —eight-bit repeating pattern to use (not a GEOS pattern 
number), 

r3 XI — x-coordinate of leftmost endpoint (word). 
r4 X2 — x-coordinate of rightmost endpoint (woid). 
rllL Yl — y-coordinate of line (byte). 

where (XI, Yl) cind (Xljl) define the endpoints of the horizontal line. 

dispBufferOn: 

bit 7 — write to foreground screen if set. 
bit 6 — write to background screen if set 



nothing 

Commodore 
a, X, y, r5-r8, rllH 

Apple 

a, X, y, rllH 

Description: HorizontalLine sets and clears pixels on a single horizontal line according to 
the eight-bit repeating pattern. Wherever a 1-bit occurs in the pattern byte, a pixel 
is set, and wherever a 0-bit occurs, a pixel is cleared 

Bits in'the pattern byte are used left-to-right where bit 7 is at the left .A bit pattern 
of % 1 1 1 100(X) would create a horizontal line like: 



Note: 



128: 



Example: 
See also:. 



The pattern byte is always drawn as if aligned to a card boundary. If the 
endpoints of a line do not coincide with card boundaries, then bits are masked off 
the appropriate ends. The effect of this is that a pattern is always aligned to 
specific pixels, regardless of the endpoints, and that adjacent lines drawn in the 
same pattern will align. 

To draw patterned horizontal lines using the 8x8 GEOS patterns, draw rectangles 
of one-pixel height by calling the GEOS Rectangle routine with identical y- 
coordinates. 

Under GEOS 128, or'ing DOUBLE W into theXi andX2 parameters will 
automatically double the x-posiuon in ^-column mode. Or'ing in ADDl^W will 
automatically add 1 to a doubled x-position. (Refer to "GEOS 128 X-posiBon and 
Bitmap Doubling" in Chapter.® gr@ for more information.) 



VerticalLine, InvertLine, ImprintLine, RecoverLine, DrawLine. 



141 



Printline 



ImprintLine (Apple) 



graphics! 



Function: 
Parameters: 



Returns: 

Destroys: 

Description: 

Note: 



Example: 
See also: 



Imprints a horizontal line fix)m the foreground screen to the background buffer. 

r3 XI — x-coordinate of leftmost endpoint (word). 
r4 X2 — x-coordinate of rightmost endpoint (word), 
r 1 1 L Y 1 — y-coordinate of line (byte). 

where (XI, Yl) and (X2,Y1) define the endpoints of the line to imprint. 

nothing 

a, X, y 

ImprintLine imprints the pixels which fall on the horizontal line whose 
coordinates are passed in the GEOS registers. The pixel values are copied from 
the foreground screen to the background buffer. 

The flags in dispBufferOn are ignored; the pixels are always copied to the 
background buffer regardless of the value in this variable. 

This routine does not exist in GEOS 64 or GEOS 128. Use ImprintRectangle 
with a height of one. 



RecoverLine, HorizontalLine, InvertLine,VerticalLine , DrawLine. 



142 



ImprintRectangle 



ImprintRectangle^ i ImprintRectangle (Apple, C64, cns) graphics] 



Function: 



Parameters: 



Returns: 
Destroys: 



Description: 

Note: 
128: 



Example: 
See also: 



Imprints the pixels within a rectangular region from the foreground screen to the 
background buffer. 

Normal: 

r3 XI — x-coordinate of upper-left (word). 
r2L Yl — y-coordinate of upper-left (byte)- 
r4 X2 — x-coordinate of lower-right (word), 
r 2 H Y2 — y-coordinate of lower-right (byte). 

Inline: 

data appears immediately after the jsr i_ImprintRectangle 
.byte Yl y-coordinate of upper-left. 
.byte Y2 y-coordinate of lower-right, 
.word XI x-coordinate of upper-left, 
.word X2 x-coordinate of lower-right. 

where (XI, Yl) is the upper-left corner of the rectangular area and (X2,Y2) is the 
lower-right corner. 

nothing 

CpmrnodQi? 

a, X, y, r5-r8, rllL 

Apple 

a, x,y, rllL 

ImprintRectangle copies the pixels within a rectangular region from the 
foreground screen to the background buffer by calling ImprintLine in a loop. A 
subsequent call to RecoverRectangle with the same parameters will restore the 
rectangle to the foreground screen. 

The flags in dispBufferOn are ignored; the pixels are always copied to the 
background buffer regaixlless of the value in this variable. 

Under GEOS 128, or'ing DOUBLE W into the XI andX2 parameters will 
automatically double the x-position in SD-column oKxie. Or'ing in ADDl^W will 
automatically add 1 to a doubled x-position. (Refer to "GEOS 128 X-posinon and 
Bitmap Doubling" in Chapter.® gr@ for more information.) 



RecoverRectangle, Rectangle, InvertRectangle. 



143 



InfoCard 



InfoCard (Apple) card driver 



Function: Get information about the cuirent printer card- 
Parameters: none. 

Returns: x STATUS — card error code; $00 = no error (byte) 
y TYPE; 



b7 


0: seven-bit data card. 
1: eight-bit datacard. 


b6 


0: serial interface card. 
1: parallel interface card. 


b5 


0: card only capable of output 
1 : card capable of input and output. 


b4 


0: does not support StatusCard ready-for-output flag. 
1: supports StatusCard ready-for-output flaj?. 


b3 


0: does not support StatusCard input-ready flag. 
1: supports StatusCard input-ready flag. 



Destroys: a. 

Description: InfoCard returns information about the installed card. 

Note: This routine may be called at any time. 

Example: 

See also: StatusCard. 



144 



InitCa 



InitCard (Apple) card driver} 



Function: Initialize printer card- 
Parameters: rO-rlL SERIALCONFIG — card configuration information for serial I/O cards; 

parallel cards do not use this information (three bytes). 

Returns: x STATUS — card error code; $00 = no error (byte) 

Destroys: assume a, y. 

Description: InitCard performs the basic initialization and configuration of a printer card. A 
printer driver will usually perform this operation from InitForPrint. InitCard 
configures the printer card with a three-byte set of CONFIG parameters. 



The COA/F/G Values: 

Most Apple printer cards use die standard 65xx series 6551 ACIA (Asynchronous 
Communications Interface Adapter) to communicate between the Apple bus and 
the printer. The CONFIG bits directly reflect the available configurations for this 
chip. Bits mauriced as unused are either unused on the chip or forced to a specific 
state by the card driver. For more information, refer to the RM 65 Family 
Asynchronous Communications Interface Adapter (ACIA) Module User's Manual 
(Rockwell International). 



rOL: control register. 

bits description 



b7 


0: 


one stop bit. 




1: 


1-1/2 stop bits with five data bits and no parity. 






one stop bit with eight data bits and parity. 






two stop bits in all other cases. 


b6-b5 


00: 


8 data bits. 




01: 


7 data bits. 




10: 


6 data bits. 




11: 


S data bits. 


b4 


mused. 


b3-bO 


0000 


undefined. 




0001 


SO baud. 




0010 


75 baud. 




0011 


109.92 (110) baud. 




0100 


134.56 (135) baud. 




0101 


150 baud. 




Olio 


300 baud. 




0111 


600 baud. 




1000 


1200 baud. 




1001 


1800 baud. 




1010 


: 2400baud. 




1011 


: 3600baud. 




1100 


: 4800 baud. 




1101 


: 7200 baud. 




1110 


: 9600 baud. 




nil 


: 19200 baud (19.2 Kbaud). 



rOH: command register. 

145 



tCard 



bits 


description 


b7-b6 


00 
01 
10 

11 


odd parity, 
even parity, 
marie pari^. 
space parity. 


b5 




1 


parity disabled (no parity, ignore b7-b6). 
parity enabled. 


b4-b0 


undefined. 


handshaking, 
bits description 


b7 



1 


do not check for XOFF. 
detect XOFF. wait for XON. 


b6-b5 


00 

11 


ignore hardware handshaking, 
follow hardware handshaking. 


M 


must be 1. 


b3-bO 


must be 000 



Most serial printers operate with eight data bits, no parity, and one stop bit Some 
printers, like the Apple LaserWriter require two stop bits. 

Note : InitCard must be called before OpenCard. 

Example: 

See also: OpenCard. 



148 



InltForDial 



InitForPialOg (Apple) intcmall 

Function: Saves away the state of GEOS as if about to pass control to a dialog box. 
Parameters: none. 

Returns: system initialized to a near-wamistart state. 
Destroys: a,x, y, r0-r4 

Description: Prior to displaying a dialog box, DoDIgBox saves away the state of the 
application in an internal buffer and then reinitializes GEOS so that the dialog box 
runs as if it were an independent application. This allows a dialog box to use 
nearly all the facilities of GEOS without disrupting the parent application. This 
facility for temporarily suspending the state of GEOS is potentially useful in an 
application and can be accessed by calling InitForDialog. 

InitForDialog saves off the current system state and then places GEOS in a 
near-warmstart state. To return GEOS to its previous state, call 
RecoverSysRam. 

Note: Calls to InitForDialog cannot be nested because GEOS can only buffer its state 

to a depth of one level. A second call to InitForDialog without calling 
RecoverSysRam will overwrite the saved state of the system with the current 
state. Because DoDIgBox calls InitForDialog as part of its normal operation, 
it, too, will overwrite the saved state of the system. 

See also: RecoverSysRam. 



CONriDCNTlAL 



149 



InltForlO 




InitForlO (C64, ci28) 



very low>level disk 



Function: 



Prepare for I/O across the serial bus- 



Parameters: 



none. 



Returns: 



nothing. 



Destroys: a, y. 

Description: InitForlO prepares the system to perform I/O across the Commodore serial bus. 



It disables interrupts, turns sprite DMA off, slows the 128 down to IMhz, 
switches in the ROM and I/O banks if necessary, and performs anything other 
initialization needai for fast serial transfer. 

Call InitForlO before directly accessing the serial port (e.g., in a printer driver) 
or before using ReadBIock, WriteBIock, VerWriteBIock, or ReadLink. 
To restore the system to its previous state, call DoneWithlO. 



Apple: 



Apple GEOS has no InitForlO equivalent 



Example: 



See WriteBIock. 



See also: 



DoneWithlO, SetDevice. 




142 



InitForPrInt 



InitForPrint (Apple, C64, cns) 



Initialize printer. Perform once per document 
none. 

Commodore 
nothing. 

Apple 

X STATUS — printer error code; $00 = no error. 

Commodore 

assume a, x, y, r0-rl5. 
Applg 

assume a, y, r0-rl5. 

InitForPrint performs any initialization necessary to prepare the printer for a 
GEOS document. Often this involves resetting the printer to bring it into a default 
state as well as suppressing automatic margins and perforation skipping. 
InitForPrint does not do any initialization specific to graphic or ASCII printing. 

Commodore: InitForPrint is also used to set the printer baud rate for serial printers. 

Apple: Some printer drivers may try to send a non-printing character to the printer to 

ensure that it is ready to accept data. If the printer is not ready, InitForPrint will 
return a PR TIME_OUT error. This usually means the printer is switched off 
or is not online: Many printer drivers, however, will do no such checking and 
have no facility for detecting a printer time-out 

See also: StartPrint, StartASCII. 



150 



printer driver 



Function: 

Parameters: 

Returns: 

Destroys: 

Description: 



InitMouse 



InitMoUSe (Apple, C64, C128) 



input driver 



Function: 
Parameters: none. 
Returns: nothing 
Alters: 



Initialize the input device. 



Destroys: 
Description: 

See also: 



mouseXPos initialized (typically 8). 

mouse YPos initialized (typically 8). 

mouseData initialized (typically reflects a released button). 

pressFlag initialized (typically set to $00). 

assume a, x, y, r0-rl5 

GEOS calls InitMouse after first loading an input driver. The input driver is 
expected to initialize itself and begin tracking the input device. An application 
should never need to call InitMouse. 

SlowMouse, UpdateMouse, SetMouse, KeyFilter, StartMouseMode, 
MouseUp. 



151 



InitProcesses 



InitProcesses (Apple, C64, cns) 



process 



Function: 
Parameters: 

Returns: 

Destroys: 

Description: 



Note: 



Example: 
See also: 



Initialize and install a process data structure. 

a NUM_PROC — number of processes in table (byte). 

rO PTABLE — pointer to process data structure to use (word). 

rO unchanged. 

a, X, y, rl 

InitProcesses installs and initializes a process data structure. All processes 
begin as frozen, so their timers are not decremented during vblank. Processes can 
be started individually with RestartProcess after the caU to InitProcesses. 

InitProcesses copies the process data structure into an internal area of memory 
hidden from the application. GEOS maintains the processes within this intemd 
area, keeping track of the event routijie addresses, the timer initialization values 
(used to reload the timers after they time-out), the<:urrent value of the timer, and 
the state of each process (i.e., frozen, blocked, runable). The application's copy 
of the process data structure is no longer needed because GEOS remembers this 
information until a subsequent call to InitProcesses. 

Although processes are numbered starting with zero, NUMJPROC should be die 
actual number of processes in the table. To initialize a process table with four 
processes, pass a NUMJPROC value of $04. When refering to those processes 
(i.e., when calling routines such as UnblockProcess), use tiie values $00-$03. 
Do not call InitProcesses with a NUM PROC value of $00 or a NUMJPROC 
value greater than MAX_PROCESSES (the maximum number of processes 
allowable). " 

To disable process handling, merely freeze all processes or call InitProcesses 
with a dummy process data structure. 



Sleep, RestartProcess. 



152 



InitRa 



InitRam (Apple, C64, C128) memory 



Function : Table driven initialization for variable space and other memory areas. 
Parameters: rO TABLE — address of initialization table (word). 
Returns: nothing. 
Destroys: a, x,y, rO-r2L 

Description: InitRam uses a table of data to initialize blocks of memory to preset values. It is 
useful for setting groups of variables to specific values. It is especially good at 
initializing a group of noncontiguous variables in a "two bytes here, three bytes 
there" fashion. 

The initialization table that is pointed to by the TABLE parameter is a data 
structure made up from the following repeating pattern: 

• word addzBss ; start address of this block 

.byte count ;nuxnber of bytes to initialize 

•byte bytel, byte2fJbytGi^ ; count bytes of data 

•word Address^. ; start address for next block 

The table is made of blocks that follow the above pattern, count bytes starting at 
address are initialized with the next count bytes in the table. (A count value of $00 
is treated as 256.) To end the table, use 

.word $0000 ;end table 

where InitRam expects the next address parameter. 
Note : Do not use InitRam to initalize rO-r2L. 

Example: 

See also: FillRam, ClearRam. 



153 



InltTextPrompt 



InitSprite (Apple) 



sprite! 



Function: 
Parameters: 
Returns: 
Alters: 

Destroys: 



Initializes all sprites. 

nothing. 

nothing. 

offFIag set to TRUE. 

noEraseSprites set to $00. 

all mouse and sprite parameters set to $00. 

a, X 



Ml 



Description: InitSprite is called by the GEOS Kemal during the boot and warmstart 
sequences. It is probably not useful to applications. 

See also: DrawSprite, GetSpriteData, PosSprite, EnablSprite, DisablSprite. 



InitTextPrompt (Apple, C64, cus) 



text/keyboard 



Function: 

Parameters: 

Alters: 

Destroys: 

Description; 



See also: 
Example: 



Initialize sprite #1 for use as a text prompt. 

a HEIGHT — pixel height for the prompt (byte) 

alphaFlag %10000011 

a, X, y. 

InitTextPrompt initializes sprite #1 for use as a text prompt. The sprite image is 
defined as a one-pixel wide vertical line of HEIGHT pixth. If HEIGHT is large 
enough, the double-height sprite flags will be set as necessary. HEIGHT is 
usually taken from curHeight so that it reflects the height of the current font. 

The text prompt will adopt the color of the nx)use pointer. 

PromptOn, PromptOff. 



154 



InputByte 



InputByte (Apple) 



card driver! 



Function: 

Parameters: 

Returns: 

Destroys: 
Description: 

Note: 



Example: 
See also: 



Get a byte of input from the interface card, 
none. 



X 

y 

a,y. 



STATUS — card error code; $00 = no error (byte) 
DATA — single input byte as read from card. 



InputByte returns a byte of data from the card, assuming the card supports two- 
way communication. The input-ready flag may be checked with StatusCard 
prior to calling InputByte. 

InputByte must be called after an OpenCard and before a CloseCard. 

Most card drivers always return NO^ERROR from from InputByte due to a 
lack of memory to properly handle coinplex error checking. 



OutputByte, StatusCard. 



155 



InsertRecord 



InsertRecord (Apple, C64, cus) 



VLIR disk 



Function: Adds an empty record before the current record in the index table, moving all 
subsequent records (including the current record) downward 



Parameters: none 
Uses: 



Returns: 
Alters: 



Destroys: 
Description: 



Example: 
See also: 



curDrive 
fileWrittent 

curRecord 
fileHeader 

Commodore: 

curType 

curDirHead 

dir2Headt 

dir3Headt 

Apple; 

curVBlknot 

VBMchanged^ 

numVBMBlkst 



if FALSE, assumes record just opened (or updated) and 

reads B ANVVBM into memory. 

current record pointer 

VLIR index table stored in this buffer. 



GEOS 64 vl.3 and later for detecting REU shadowing, 
current directory header/B AM. 
(BAM for 1571 and 1581 drives only) 
(BAM for 1581 drive only) 



used by VBM cacheing routines, 
used by VBM cacheing routines, 
used by VBM cacheing routines. 



^used internally by GEOS disk routines; applications generally don't use. 
X error ($00 = no error). 

curRecord new lecord becomes the current record. 

flleWritten^ set to TRUE to indicate the file has been altered since last 
updated. 

fileHeader new record added to index table. 

^used internally by GEOS disk routines: explications generally don't use. 

a, y. rOL. 

InsertRecord attempts to insert an empty VLIR record in front of the current 
record in the index table of an open VLIR file, moving all subsequent records 
downward in the record Ust. The new record becomes the current record. A VLIR 
file can have a maximum of MAX VLIR RECS records. If adding a record 
will exceed this value, an OUT^OP^RECORDS error is returned. In the index 
table, the new record is marked as useS but empty. 

InsertRecord does not update the VLIR file information on disk. Call 
CloseRecordFile or UpdateRecordFile to update the file when done 
modifying. 



AppendRecord, DeleteRecord. 



143 



interruptMain 



InterruptMain (Apple, C64, cns) 

Function: Main Interrupt Level processing. 

Parameters: none. 

Returns: nothing. 

Destroys: a, x, y, r0-rl5 

Description: InterruptMain is the main GEOS Interrupt Level processing loop and that 
means different things on different systems. 

C64 & C128: InterruptMain is a subset of the full Interrupt Level process. InterruptMain is 
typically called through the IntTopVec. An application could conceivably 
jsr InterruptMain to "catch up" on some system updating if interrupts have 
been disabled for a considerable period of time. InterruptMain is not re-entrant, 
so it is important that interrupts be disabled around the catch-up calls. 

Apple: InterruptMain is cuirendy the same as IrqMiddle. It is best to use IrqMiddle 

to generate software interrupts because the Apple GEOS InterruptMain may 
change in the future to more closely reflect the operation under the Commodore 
environment At this time, avoid this jump table entry. 

See also: IrqMiddle, MainLoop. 



internal 



156 



InvertLine 



InvertLine (Apple, C64, cm) 



graphics! 



Function: 
Parameters: 



Uses: 

Returns: 
Destroys: 



Description: 



Note: 



128: 



Example: 
See also: 



Invert the pixels on a horizontal line. 

r3 XI — x-coordinate of leftmost endpoint (word). 
r4 X2 — x-coordinate of rightmost endpoint (woid). 
rllL Yl — y-coordinate of line (byte). 

where (Xl,Yl)and (X2,Y1) define the endpoints of the line to invert. 

dispBufferOn: 

bit 7 — invert foreground screen if set 
bit 6 — invert background screen if set. 

nothing 

Commodore 
a, X, y, r5-r8 

Applg 
a, X, y 

InvertLine inverts the pixel state of all pixels which fall on the horizontal line 
whose coordinates are passed in the GEOS registers. Set pixels become clear, and 
clear pixels become set. 

If dispBufferOn is set to invert on the foreground and the background screen, 
both the foreground and the background screen will get the inverted foreground 
pixels. GEOS assumes both screens contain the same image. 

Under GEOS 128, or'ing DOUBLE W into theXi andX2 parameters will 
automatically double the x-position in SD-column mode. Or*ing in ADDl W will 
automatically add 1 to a doubled x-position. (Refer to "GEOS 128 X-posi5on and 
Bitmap Doubling" in Chapter.® gr@ for more information.) 



VerticalLine, HorizontalLine, ImprintLine, RecoverLine, DrawLine. 



157 



InvertRectangle 



InvertRectangle (Apple, C64, ci28) 



graphics! 



Function: 
Parameters: 



Inverts the pixels within a rectangular region. 

r3 XI — x-coordinate of upper-left (word). 

r2L Y 1 — y-coordinate of upper-left (byte). 

r4 X2 — x-coordinate of lower-right (word). 

r2 H Y2 — y-coordinate of lower-right (byte). 



where (XI, Yl ) is the upper-left corner of the rectangular area and (X2,Y2) is the 
lower-right corner. 



Uses : dispBufferOn: 

bit 7 — invert on foreground screen if set. 
bit 6 — invert on background screen if set 



Returns: nothing 

Destroys: Commodore 

a, X, y, r5-r8, rllH 

Applg 

a, X, y, rllH 



Description: InvertRectangle inverts all the pixels within the rectangular area as determined 
by the coordinates of the upper-left and lower-right comers. All set pixels become 
clear and clear clear pixels become set 

InvertRectangle operates by calling InvertLine in a loop. 

InvertRectangle is handy to use for indicating a selected object (as GEOS does 
with icons) or for flashing an area by inverting a rectangle twice, first inverting 
the area and then mverting it back to its original state. 

Note: If dispBufferOn is set to invert on the foreground and the background screen, 

both the foreground and the background screen will get the inverted foreground 
pixels. GEOS assumes both screens contain the same image. 

128: Under GEOS 128, or'ing DOUBLE W into theX/ andX2 parameters will 

automatically double die x-position in SD-column mode. Or'ing in ADDl W will 
automatically add 1 to a doubled x-position. (Refer to "GEOS 128 X-posi"Hon and 
Bitmap Doubling" in Chapter.® gr@ for more information.) 

Example: 

See also: Rectangle, ImprintRectangle, RecoverRectangle, FrameRectangle. 



158 



IrqMiddle 



IrqMiddle (Apple) 



internall 



Function: Interrupt Level processing. 
Parameters: none. 



Returns: 

Destroys: 

Description: 



Example: 
See also: 



nothing, 
a, X, y 

IrqMiddle is the software-interrupts entry into the Apple GEOS Kemal. When 
there is no hardware interrupt source, GEOS generates software interrups by 
calling IrqMiddle. In most cases, as long as the application returns to 
MainLoop frequently enough, the system degradation will only be minor. 
However, applications which do massive anaounts of processing before returning 
to MainLoop may need to generate software interrupts periodically. 



bit 
bne 
php 
sei 

jsr 
pip 



intSource 
10$ 



IrqMiddle 



; check interrupt source 

;do nothing if hard interrupts 

;else, disable interrupts 

;(just in case) because int 

;code is not. re-entrant 

/software interrupt now! 

; restore old interrupt status 



10$: 



InterruptMain. 



159 



IsMselnRegion 



IsMselnRegion (Apple, C64, ci28) 

Function: 
Parameters: 



Returns: 

Destroys: 
Description: 



Note: 



NewIsMselnRegion : 



5$: 
10$: 



Ida 


mouseYPos 


cmp 


r2L 


bit 


10$ 


cmp 


r2H 


bgt 


10$ 


php 




sei 




cmpW 


mouseXPos, r3 


bit 


5$ 


cmpW 


mouseXPos, r4 


bgt 


5$ 


pip 




Ida 


#TRUE 


rts 




pip 




Ida 


#FALSE 


rts 





mouse 



;get mouse y-position 

/compare to top edge 

/branch if outside 

/compare to bottom edge 

/branch if outside 

/disable interrupts around x check 

/so it doesn't change while we're looking 

/compare mousex with left edge 

/branch if outside 

/compare mousex with right edge 

/branch if outside 

/ (restore interrupts before se.tting st reg) 

/return inside region statys 

/exit 

/ (restore interrupts before setting st reg) 

/return outside region status 
/exit 



Checks to see if the mouse is within a specified rectangular region of the screen. 

r3 XI — x-coordinate of upper-left (word), 
r2L Yl — y-coordinate of upper-left (byte). 
r4 X2 — x-c(X)rdinate of lower-right (word). 
r2H Y2 — y-coordinate of lower-right (byte). 

where (XI, Yl ) is the upper-left corner of the rectangle and (X2,Y2) is the lower- 
right corner. 

a TRUE if in region, FALSE if not in region. 

st result of loading TRUE or FALSE into the a register. 

nothing. 

IsMselnRegion tests the position of the mouse against the boundaries of a 
rectangular region (passed in the same GEOS registers as the Rectangle 
routine). It returns TRUE if the mouse is within the region (inclusive) and 
FALSE if the mouse is outside the region. Because the st register reflects the 
result of loading TRUE or FALSE into the accumulator, the call can be 
followed by a branch instruction that tests the result, such as: 

beq InRegion /branch if mouse was in region 

-or- 

bne Not InRegion /branch if mouse not in region 

Interrupts should always be disabled around a call to IsMselnRegion. If the 
php-sei-pip method is used, be aware that the pip will reset the st flags. If this 
is troublesome, it may warrant creating a new version of IsMselnRegion that 
does its own interrupt disable and leaves the values in the st register intact: 



160 



IsMseinRegi 



Example: 



LoadW 

LoadW 

LoadW 

LoadW 

php 

sei 

jsr 

pip 

tax 

beq 



r3, #windowXl 
r2L,#windowYl 
r4,#windowX2 
r2H, #windowY2 



IsMselnRegion 



;get coordinates of window's rectangle 

/disable interrupts around region check 
/check for mouse inside region 



;set status flags that pip killed 
MouseOutsideWindow /branch if outside window area 



161 



JsrToAux 



JsrToAux (Apple only) 



utility 



Function: 
Parameters: 

Returns: 

Destroys: 

Description: 



Example: 
See also: 



jsr*s to a subroutine in auxiliary memory. Returns to main memory. 

a [AUXADDR — low byte of subroutine to call in aux. memory. 
X ] AUXADDR — high byte of subroutine to call in aux memory. 

where AUXADDR is the address of a subroutine to call in aux. memory 

depends on the subroutine. 

depends on the subroutine. 

JsrToAux performs a jsr to a subroutine in application auxiliary memory. 
GEOS will first switch application aux in and application main out, then simulate 
a jsr to the address passed in x and a. When the aux memory subroutine returns, 
control will resume in main memory. JsrToAux does not check for a null 
($0000) address like CallRoutine. 



CallRoutine 



162 



KeyFilter 



IKeyFilter (Apple) 



input driver 



Function: 

Parameters: 

Returns: 

Alters: 



Uses: 

Destroys: 

Description: 



Note: 



Pre-processes keyboard input for filtering out special characters, translating 
others, and updating the mouse variables when positioning keys are pressed. 



a 



a 



KEY — key as scanned from keyboard circuitry, 
translated character or NULL if filtering out 



mouseXPos 

mouseYPos 

mouseData 

pressFIag 

inputData 



mouse x-position. 
mouse y-position. 
state of mouse button. 

MOUSE^BIT and INPUT^^BIT set appropriately, 
depends on device. " 



OPEN^APPLE read-only hardware location; negative if open-apple pressed 
assume x, y 

The Apple GEOS keyboard scanning routine calls KeyFilter at Interrupt Level 
whenever a keypress is detected. This allows the input driver to translate certain 
keypresses into mouse movements. KeyFilter has first dibs on any incoming 
keypress. 

A typical KeyFilter routine will compare the KEY parameter against a table of 
specific keypresses. If there is no match, then KeyFilter returns without altering 
the KEY ccxie. If there is a match, KeyFilter updates the mouse variables 
appropriately and returns a KEY value of NULL. Apple GEOS will ignore the 
null-key, never placing it in the keyboard input queue. 

IfKEY is already NULL when KeyFilter is called, then the keypress has 
already been filtered out by some other prior filter and should be ignored. 

An application should not call KeyFilter direcdy; Apple GEOS will call it 
automatically at Interrupt Level. 

The KEY parameter is not a GEOS key value. It comes almost direcdy from the 
Apple hardware register KEYBD^DATA. The only difference is tiiat the high- 
bit is set to represent the state oflhe closed-apple key. If bit 7 is set, then the 
closed-apple key is pressed. To detect die state of the open-apple key: 



bit 
bmi 



OPEN_APPLE 
OpenPressed 



/check open apple key status 
/branch if pressed 



See also: AuxDKeyFilter. 



163 



LdApplic 



LdApplic (Apple, C64, C128) 



mid-level disk I 



Function: 
Parameters: 



Uses: 



Returns: 
Passes: 

Alters: 

Destroys: 
Description: 



Load and (optionally) run a GEOS application, passing it the standard application 
startup flags as if was launched from the deskTop. 

r9 DIRENTRY — pointer to directory entry of file, usually points to 

dirEntryBuf (Apple GEOS: must be in main memory) (word). 
rOL LOAD.OPT: 

bitO: load at address specified in file header; application will be 
started automatic^y 

load at address in r7; application will not be started 
automatically, 
not passing a data file. 

r2 and r3 contain pointers to disk and data file names, 
not printing data file, 
printing data file; application should print file and exit 
r7 LOAD_ADDR — optional load address, only used if bit of 

LO AD jOPT is set (word). 
r2 DATA^DISK— only validif bit7orbit6ofL<9i4D_0/Tis setrpointer 
to name of the disk that contains the data file, usually a pointer to one of 
the DrxCurDkNm buffers (word). 
r3 DATA^FELE — only valid if bit 7 or bit 6 of LOAD jOPT is set: pointer 
to name of the data file (word). 



bit 7: 
bit 6: 



1 


1 




curDrive 

Commodore: 
curType 

Applg: 
RWbank 



GEOS 64 V 1.3 and later: for detecting REU shadowing. 



destination bank (MAIN or AUX); set to MAIN when 
loading an application. 



only returns if alternate load address or disk error. 
X error ($00 = no error). 

usually doesn't return, but warmstarts GEOS and passes the following: 
rO as originally passed to LdApplic. 
r2 as originally passed to LdApplic (use dataDiskName). 
r3 as originally passed to LdApplic.(use dataFileName). 

GEOS brought to a warmstart state. 

dataDiskName contains name of data disk if bit 7 of rO is set. 
dataFileName contains name of data file if bit 6 of rO is set 

a, X, y, r0-rl5. 

LdApplic is a mid-level application loading routine called by the higher level 
GetFile. Given a directory entry of a GEOS application file, LdApplic will 
attempt load it into memory and optionally run it. LdApplic calls LdFile to load 
the application into memory: a sequential file is loaded entirely into memory but 



164 



LdApplic 



only record zero of a VLIR file is loaded. Based on the status of bit of 
LOADJDPT, optionally runs the application by calling it through StartAppl. 

Most applications will not call LdApplic directly but will go indirectly through 
GetFile. 

Note: Only in extremely odd cases will an alternate load address be specified for an 

application. Loading an application at another location is not particularly useful 
because it will most likely not run at an address other than its specifiec load 
address. When LdApplic returns to the caller, it does so before calling 
StartAppl to wamistart GEOS. 

Apple: Applications are designed to load and run in main memory. Ensure that RWbank 

contains MAIN before calling LdApplic. 

Example: 

See also: GetFile, LdDeskAcc, LdDeskAcc, StartAppl. 



J 



165 



LdDeskAcc 



LdPeskAcC (Apple, C64, C128) 



mid-level disk 



Function: Load and run a .GEOS desk accessory 
Parameters: r9 

rlOL 



DIRENTRY — pointer to directory entry of file, usually points to 
dirEntryBuf (word). 

RECVR^OPTS — no longer used; set to $00 (sec below for explanation 
(byte). 



Uses: 



curDrive 

Cpmrnodpr?; 
curType 

Apple; 
RWbank 



GEOS 64 vl.3 and later: for detecting REU shadowing. 



destination bank (MAIN or AUX); set to MAIN when 
loading a desk accessory. 



Returns: 



Passes: 



Alters: 



returns when desk accessory exits with a call to RstrAppl. 
X error ($00 = no error). 

warmstarts GEOS and passes the following to the desk accessory: 

rlOL as originally passed to LdDeskAcc (should be $(X); see below). 

nothing direcdy; desk accessory may alter some buffers that arc not saved 



Destroys: a, x, y, r0-rl5. 



Description: 



Note: 



LdDeskAcc is a mid-level desk accessory loading routine called by the higher 
level GetFile. Given a directory entry of a GEOS desk accessory file, 
LdDeskAcc will attempt load it into memory and run it. When the user closes 
the desk accessory, control returns to die calling application. 

LdDeskAcc first loads in the desk accessory's file header to get the start and 
ending load address. Under GEOS 64 and Apple GEOS, it will then save out the 
area of memory between these two addresses to a file on the current disk named 
SWAP FILE. The GEOS 128 version saves this area to the 24K desk 
accessory swap area in back RAM. Desk accessories larger than 24K cannot be 
used under GEOS 128 (to date, there are none); a BFR^OVERFLOW error is 
returned. 

After saving the overlay area, the dialog box and desk accessory save-variables 
are copied to a special area of memory, the current stack pointer is remembered, 
and the desk accessory is loaded and executed. When the desk accessory calls 
RstrAppl to return to the application, this whole process is reversed to return the 
system to a state similar to the one it was in before the desk accessory was called. 
The SWAP FILE file is deleted. 

Most applications will not call LdDeskAcc directly, but will go indirectly 
tiirough GetFile. 

The RECVRjOPTS flag originally carried die following significance: 



166 



LdDeskAcc 



C64 : 

Apple: 

Example: 
See also: 



bit 7: 1 force desk acxessory to save foreground screen area and restore it on return to 
application. 

not necessary for desk accessory to save foreground. 
Commodore only: 

bit 6: 1 force desk accessory to save color memory and restore it on return to 
application. 

notnecessary for desk accessory to save color memory. 

However, it was found that the extra code necessary to make desk accessories 
save the foreground screen and color memory provided no real benefit because 
this context save can just as easily be accomplished finom within the application 
itself. The RECVRjOPTS flag is set to $00 by all Berkeley Softworks 
applications, and desk accessories can safely assume that this will always be the 
case. (In fact, future versions of GEOS may force rlOH to $00 before calling 
desk accessories just to enforce this standard!) 

The application should always set rlOH to $00 and bear the burden of saving and 
restoring the foreground screen and the color memory. (Color memory only 
applicable to GEOS 64 and GEOS 128 in 40-column mode.) 

GEOS versions 1.3 and above have a new GEOS file type called 
TEMPORARY. When the deskTop first opens a disk, it deletes all files of this 
type. The SWAP FILE is a TEMPORARY file. 

Desk accessories are designed to load into main memory. Ensure that RWbank 
contains MAIN before calling LdApplic. 



GetFile, LdApplic, LdFile, RstrAppI, InitForDialog, RstrFrmDialog, 
WarmStart. 



167 



LdFile (Apple, C64, C128) 



mid-level disk! 



Function: 
Parameters: 

Uses: 



bitO: 



Given a directory entry, loads a sequential file or record zero of a VLIR record. 

r9 DIRENTRY — pointer to directory entry of file, usually points to 
dirEntryBuf (Apple GEOS: must be in main memory) (word). 

curDrive 

Commodore! 
curType 

A pp l g; 
RWbank 
loadOptt 

1 

loadAddr^ 



GEOS 64 vl.3 and later for detecting REU shadowing. 



destination bank (MAE^ or AUX). 
load option: 

-load at address specified in file header, 
-load at address in loadAddr. 
alternate load address. 



Returns: 
Alters: 



^former local variable; applications will generally not use outside of this context. 

X error ($00 = no error). 

r7 pointer to last byte read into BUFFER plus one. 



fileHeader 



Cpmmodprp; 
fileTrScTab 



contains 256-byte GEOS file header. (This is a 512-byte 
buffer in Apple GEOS, although only 256 bytes are used in 
the GEOS file header for compatibility). 



track/secto^ of header in first two bytes of this table 
(fileTrScTab+O and fileTrScTab+l); As the file is 
loaded, the track/sector pointer to each block is added to die 
file track/sector table starting at fiIeTrScTab+2 and 
fiIeTrScTab+3. 



Destroys: 



Apple: 

INDEXBLOCKBUF 



Apple; 

a, y, rl, r4, r7. 



index block for file if sequential or record if VLIR 
(in auxiliary memory; see ReadFile for information 
on accessing this buffer). 



Description: LdFile is a mid-level file handling routine called by die higher level GetFile. 

Given a directory entry of a sequential file, LdFile will load it into memory. 
Given die directory entry of a VLIR file, LdFile will load its record zero into 
memory. 

Most applications will not call LdFile directiy but will access this routine 
indirectiy tiirough GetFile. 



168 



LdFiie 



C64 &C128: All versions of LdFiie to date under Commodore GEOS are unusable because 
the load variables that are global under Apple GEOS GoadOpt and loadAddr) 
are local to the Kemal and inaccessible to applications. Fortunately this is not a 
problem because applications can always go through GetFile to achieve the same 
effect 

Example: 

See also: GetFile, LdApplic, LdDeskAcc, ToB ASIC. 



^ 



169 



LoadAuxSet 



LoadAuxSet (Apple) 



text 



Function: 
Parameters: 
Returns: 
Alters: 



Begin using a new font that resides in ausiliaiy memory. 
rO FONTPTR — aux. memory address of font header 
rO unchanged 



curHeight 

baselineOffset 

cardDataPntr 

curlndexTable 

curSetWidth 



height of font 

number of pixels ftom top of font to baseline, 
pointer to current font image data, 
pointer to current font index table, 
pixel width of font bitstream in bytes. 



Destroys: a, x, y 
Description: 



Example: 
See also: 



LoadAuxSet operates cxacdy like LoadCharSet except that it lets the font data 
reside in auxiliaiy memory. 



LoadCharSet, UseSystemFont. 



170 



LoadCharSet 



LoadCharSet (Apple, C64, cns) 



text 



Function: 
Parameters: 

Returns: 
Alters: 



Begin using a new font. 



Destroys: 
Description: 

Apple: 
Example: 
See also: 



rO 



rO 



FONTPTR — address of font header. If Apple, address must be in main 
memory (word). 



curHeight 

baselineOffset 

cardDataPntr 

curlndexTable 

curSetWidth 

a.y. 



unchanged 
height of font 

number of pixels fiiom top of font to baseline, 
pointer to current font image data, 
pointer to current font index table, 
pixel width of font bitstrcam in bytes. 



LoadCharSet uses the data in the character set data structure to initalize the font 
variables for the font pointed at by the FONTPTR parameter. 

If the font data is stored in auxiliary memory, LoadAuxSet must be used. 



LoadAuxSet, UseSystemFont. 



171 



MainLoop 



MainLoop (Apple, C64, cus) 



internal I 



Function: Direct entiy into the GEOS MainLoop.. 
Parameters: nothing. 
Returns: n/a 
Destroys: n/a 

Description: Although the term "MainLoop" usually refers to GEOS MainLoop Level 
processing, it also represents an entry in the GEOS jump table. By performing a 
jmp MainLoop, the application would be returning to the top of the MainLoop 
Level without letting it run through its normal course of events. The application is 
expected to return to MainLoop Level with an rts, not with a call to MainLoop. 
Hence, this jump table entry is not terribly useful to applications and is primarily 
used internally by GEOS. 

The MainLoop jump table entry is perhaps useful when debugging. The system 
could, conceivably, be returned to a "known state" by resetting the stack pointer 
and executing a jmp MainLoop. Of course, there is no guarantee that this will 
work. 



Example: 



See also: 



Idx t$ff ; reset stack pointer 

txs 

jmp Mainloop ;try to get back to normal.., 

InterruptMain, Firstlnit. 



172 



MakeSubDIr 



MakeSubPir (Apple) 



high-level disk 



Function: 
Parameters: 



Creates a subdirectory within the current directory. 



rO 



DIRNAME — pointer to null-terminated name for directory, maximum 
of 16-characters including the null terminator (word). 
rlOL DIRPAGE — directory page to begin searching for free slot; each 
directory page holds eight files and corresponds to one notepad page on 
the GEOS deskTop. The first page is page one (byte). 



Uses: 
Returns: 

Alters: 

Destroys: 
Description: 



curDrive 
curKBlkno 



current directory. 



X error ($00 = no error). 

rlOL directory page actually used 

r6 block number of key block of new directory. 



dirEntryBuf 
diskBlkBuf 

a, y, r3-r8. 



contains newly-built directory entry, 
contains directory header just written. 



MakeSubDir creates an empty subdirectory in the current directory. Care must 
be taken not to create two subdirectories with the same name as MakeSubDir 
does not prevent this from happening. 

MakeSubDir first calls SetNextFree to allocate the subdirectory's key block 
then calls SetGDirEntry to build its directory entry, adding it to the current 
directory. MakeSubDir then builds a directory header in diskBlkBuf and 
writes it out to the newly-allocated key block. 

MakeSubDir Hushes the VBM cache. 

€64 & C128: Comnxxiore GEOS does not support a hierarchical file system. 

Example: 

See also: SetGDirEntry, DeleteDir. 



173 



MouseOff 



MoUSeOff (Apple, C64, C128) 



mouse/spritel 



Function: 
Parameters: 
Returns: 
Modifies: 

Destroys: 
Description: 



Example: 
See also: 



Temporarily disables the mouse pointer and GEOS mouse tracking, 
nothing. 



nothing. 

mobenble 
mouseOn 

a 



sprite #0 bit cleared by DisablSprite. 
clears the MOUSEON BIT. 



MouseOff temporarily disables the mouse cursor and GEOS mouse tracking by 
clearing the proper bit in mouseOn and calling DisablSprite. Applications can 
call MouseOff temporarily disable the mouse. The mouse can be reenabled to its 
previous state by calling MouseUp. 



MouseOff» ClearMouseMode. 



CONriDCNTIAL 



174 



MouseUp 



MoUSeUp (Apple, C64, C128) 



mouse/spritel 



Function: 
Parameters: 
Returns: 
Modifies: 

Destroys: 
Description: 

Example: 
See also: 



Reenables the mouse pointer and GEOS mouse tracking. 

nothing. 

nothing. 



mobenble 
mouseOn 

a 



sets enable bit for sprite #0 
sets the MOUSEON BIT. 



MouseUp reenables the mouse cursor and GEOS mouse tracking after a call to 
MouseOff by setting the proper bits in mouseOn and mobenble. 
StartMouseMode calls this routine. 



MouseOff, StartMouseMode. 



175 



MoveAuxData (Apple) 



memoryl 



Function: 
Parameters: 



Special version of MoveData that will move data within either main or auxiliary 
memory (or from one bank to the other). 



rO 
rl 
r2 
a 



SOURCE — address of source block in application memory (word). 
DEST — address of destination block in application memory (word). 
COUNT — number of bytes to move, - 32K (word). 
BANKS — which banks to use, based on the following bit fields: 
b7 b6 Description 









SOURCE and DEST both in main memory. 





1 


SOURCE in main memory. DEST in auxiliary memory. 


1 





SOURCE in auxiliary memory, DEST in main memory. 


1 


1 


SOURCE and DEST both in auxiliary memory. 



Returns: rO, rl, r2 unchanged. 
Destroys: a, x, y 



Description: 



Note: 

Example: 
See also: 



MoveAuxData (formerly Apple MoveBData) is a block move routine that 
allows data to be moved in either main memory, auxiliary memory, or between 
main and auxiliary. Like MoveData, it will move up to 32K (32,768 bytes) from 
one area of memory to another and the source and destination blocks can overlap. 
The move is actually a copy in die sense that the source data remains unalter^ 
unless the destination area is in the same bank and overlaps the source. 

MoveAuxData is especially useful for copying data from main memory to 

auxiliary memory or from auxiliary memory to main memory. 

« 

MoveAuxData should only be used to move data within the application space in 
main and auxiliary memory. This area lies in the 48K block affected by RAMRD 
andRAMWRT. 



MoveData, MoveBData, SwapMainAndAux. 



Mov a AuxDota 



MOVeBData (CnS) memory 



Function: Special version of MoveData that will move data within either front RAM or 
back RAM (or from one bank to the other). 

Parameters: rO SOURCE — address of source block in application memory (word). 

r 1 DEST — address of destination block in application memory (word). 

r2 COUNT — number of bytes to move (word). 

r3L SRCB ANK — source bank: = back RAM; 1 = front RAM (byte). 

r3H DSTBANK — destination bank: = back RAM; 1 = front RAM (byte). 



Returns: r0-r3 unchanged. 
Destroys: a, x, y 

Description: MoveBData is a block move routine that allows data to be moved in either front 
RAM, back RAM, or between front and back (bank 1, the front bank, is the 
normal GEOS application area). If the SOURCE and DEST areas are in the same 
bank and overlap, DEST. must be less than SOURCE. 



MoveBData is especially useful for copying data from front RAM to back RAM 
or from back RAM to front RAM. 



MoveBData uses the DoBOp primitive by calling it with a MODE parameter of 
$00. 

Note: MoveBData should only be used to move data within the designated application 

areas of memory. MoveBData is signifcantiy slower than MoveData and 
should be avoided if the move will occur entirely within front RAM. 

Example: 



See also: 



MoveData, MoveAuxData, SwapBData, VerifyBData, DoBOp. 



MoveData 



MovePata^ i MovePata (Apple, C64, ci28) 



memory I 



Function: 
Parameters: 



Returns: 

Destroys: 

Description: 



64 & 128: 



64: 



128: 



Apple: 



Moves a block data from one area to another 
Normal: 

rO SOURCE — address of source block (word), 
r 1 DEST — address of destination block (word). 
r2 COUNT — number of bytes to move (word). 

Inline: 

data appears immediately after the jsr i MoveData 
.word SOURCE 
.word DEST 
.word COUNT 

rO, rl, r2 unchanged. 

a,y 

MoveData will move data from one area of memory to another. The source and 
destination blocks can overlap in either direction, which makes this routine ideal 
for scrolling, insertion sorts, and odier applications that need to move arbitrarily 
large areas of memory around. The move is actually a copy in the sense that the 
source data remains unaltered unless the destination area overlaps it 

If the DMA MoveData option in the Configure program is enabled (GEOS vl.3 
and later), MoveData will use part of bank of the installed RAM-expansion 
unit for an ultrafast move operation. An application that calls MoveData in the 
normal manner will automatically take advantage of this selection. An application 
that relies upon a slower MoveData (for timing or other reasons) can disable the 
DMA-move by temporarily clearing bit 7 of sysRAMFlg. This bit can also be 
used to read the status of the DMA-move configuration. 

Due to insufficent error checking in GEOS, do not attempt to move more than 
30,976 ($7900) bytes at one time when the DMA-move option is enabled. Break 
the move up into multiple calls to MoveData. 

Due to insufficent error checking in GEOS, do not attempt to move more than 
14,592 ($3900) bytes at one time when the DMA-move option is enabled. Break 
the move up into multiple calls to MoveData. MoveData should only be used 
to move data within the standard front RAM application space. Use MoveBData 
to move memory witiiin back RAM or between front RAM and back RAM. 
Because the RAM-expansion unit DMA follows the VIC chip bank select, an 
application that is displaying a 40-column screen ft'om back RAM must either 
disable DMA-moves or temporarily switch die VIC chip to front RAM before the 
MoveData call. 

MoveData should only be used to move data within application main memory. 
See MoveAuxData for moving data within aux main memory or between 
memory banks. 



Note: 



Do not use MoveData on rOHr6. 



178 



MoveData 



Example: 

See also: MoveAuxData, MoveBData, CopyString. 



179 



NewBltClip 



NewBitClip (Apple) 



graphics 



Function: 
Parameters: 



A special version of BitmapCIip which allows bitmaps of pixel-widths and 
pixel-coordinate x-positioning. 



Uses: 

Returns: 

Destroys: 

Description: 



Note: 



Example: 
See also: 



rO 

r3 

rlH 

r2 

rlL 

rllL 

rllH 



rl2 



DATA — pointer to the compacted bitmap data (word). 
X — x-position in pixels (word). 
Y — y-coordinate (byte). 

W_PWE)TH — width in pixels of clipping window (word), 
W_HEIGHT — height in pixels of clipping window (byte). 
DXl — delta-xl: offset of left edge of clipping window in bytes from left 
edge of full bitmap (byte). 

DX2 — delta-x2: offset of right edge of clipping window in cards from 
right edge of full bitmap (byte). Right pixel-edge of clipping window 
rounded upward to the next card boundary. 

DYl — delta-y 1: offset of top edge of clipping window in pixels from top 
edge of full bitmap (word). 



where the upper-left corner of the clipped bitmap (the window) is placed at 
(X,Y). The lower-right corner is at (X-^WJ'WIDTH, Y-^WJJEIGHT). 

dispBufferOn: 

bit? — write to foreground screen if set 
bit 6 — write to background screen if set 

nothing. 

a, X, y, r0-rl2 

e 

NewBitClip is an enhanced version of BitmapCIip which allows the left edge 
of the bitmap to be placed on a pixel boundary and the bitmap to have a pixel- 
sized width. It is odierwise identical to BitmapCIip. 

No checks are made to determine if the data, dimensions, or positions are valid. 
Be careful to pass accurate values. 

Pay special attention to the fact that DXl, and DX2 are still specified in cards 
(groups of eight pixels horizontally), not in individual pixels. 

Do not pass a value of $00 for either the W^PWIDTH or W^HEIGHT 
parameters. 

DOUBLE B can be or'ed into the W^WIDTH paramter to double the bitmap 
width andlNAUX^B can be or'ed into the X parameter to specify auxiliary 
memory. For morelnformation, refer to "Apple GEOS Bitmap Doubling and 
Aux-memory Bitmaps" in chapter @gn@. 



NewBitOtherCIip, BitmapCIip, BitmapUp, BitOtherClip. 



180 



NewBitOtherClip 



NewBitOtherClip (Apple) 



graphics! 



Function: 



Parameters: 



Uses: 



Returns: 



Special version of NewBitCIip that allows the compacted bitmap data to come 
from a source other than memory (e.g., from disk). 

r BUFFER — pointer to a 1 34-byte buffer area (word). 
r3 X — x-position in pixels (word). 
rlH Y — y-coordinate (byte). 

r2 W^PWIDTH — width in pixels of clipping window (word). 

rlL W^HEIGHT — height in pixels of clipping window (byte). 

rllL DXl — delta-xl: offset of left edge of clipping window in bytes from left 

edge of full bitmap (byte). 
rllH DX2 — delta-x2: offset of right edge of clipping window in cards from 

right edge of full bitmap (byte). Right pixel-edge of clipping window 

rounded upward to the next card boundary, 
r 1 2 D Y 1 — delta-y 1 : offset of top edge of clipping window in pixels from top 

edge of full bitmap (word). 
rl3 APPINPUT — pointer to application-defined input routine. Called each 

time a byte from a compacted bitmap is needed; data byte is returned in the 

a-register. 

rl4 SYNC — pointer to synchronization routine. Called after each bitmap 
packet is decompressed. Due to improvements in NewBitOtherClip, 
this routine need only consist of reloading rO with the BUFFER address. 

where the upper-left corner of the clipped bitmap (the window) is placed at 
PC,Y). The lower-right corner is at (X^WJ'WIDTH, Y+WJIEIGHT). 

dispBufferOn: 

bit? — write to foreground screen if set. 
bit 6 — write to background screen if set 

nothing. 



Destroys: a, x, y, r0-rl2, and the 134-byte buffer pased through rO. 



Description: 



Sometimes the application will need to display a large bitmap but cannot afford to 
store the entire bitmapped object in memory. NewBitOtherClip allows the 
application to specify an input routine (APPINPUT) thai returns the next byte of a 
compacted bitmap each time it is called 

APPINPUT must preserve r0-rl3, it must return die data byte in die a-register, 
and it is expected to exit widi an rts. A typical APPINPUT routine might save 
r0-rl3, call ReadByte to get a byte from a disk file, restore r0-rl3, load die 
data byte into die accumulator, and rts. Note tiiat BitOtherCIipt can be used to 
add another level of compression to the compacted bitmap format. The 
APPINPUT routine can decompress die data into compacted bitmap format and 
pass those bytes back. 

The basic widtii, height, position, and clipping window parameters are identical 
to NewBitCIip. Refer to the documentation of that routine for more 
information. 



181 



NewBitOtherCllp 



NewBitOtherClip calls the APPINPUT routine until it has enough bytes to 
form one bitmap packet. BitOtherCIip stores the bytes in the buffer pointed by 
BUFFER and then uncompacts the data to the screen. After the bitmap packet has 
been uncompacted, BitOtherCIip calls the SYNC routine. This extra call is no 
longer particularyAiseful and can merely consist of reloading rO with the 
BUFFER address and performing an rts. 

Note: DOUBLE^B can be or'ed into the W^WIDTH parameter to double the bitmap 

width. " 

Before resetting rO when, the SYNC routine must switch in the alternate zero 
page: 

SYNC: 

sta ALTZP_ON ; switch in alt zp 

MoveW syncrO,rO ; reload rO 

sta ALTZP_OFF ; switch alt zp back out 

rts /return from sync 

Example: 

See also: BitOtherCIip, NewBitClip» BitmapClip, BitmapUp, BitOtherCIip. 



182 



NewBitOtheFCli p ( 



NewBitUp, i NewBitUp (Apple) graph»cs| 

Function: A special version of BitmapUp that allows bitmaps of pixel-widths and pixel- 
coordinate x-positioning. 

Parameters: Normal: 

rO DATA — pointer to the compacted bitmap data (word). 

r3 X — x-coordinate (word). 

rlH Y — y-coordinate (byte). 

r2 WIDTH — bitmap width in pixels (word). 

rlL HEIGHT — bitmap height in pixels (byte). 

Inline: 

data appears immediately after the jsr i_BmapUp 

.word DATA pointer to the compacted bitmap data. 

.word X x-coordinate. 

.byte Y y-coordinate. 

.word WIDTH bitmap width in pixels. 

.byte HEIGHT bitmap height in pixels. 



Uses: dispBufferOn: 

bit 7 — write to foreground screen if set. 
bit 6 — write to background screen if set 



Returns: nothing. 
Destroys: a, x, y, r0-r4 

Description: NewBitUp uncompacts a GEOS compacted bitmap using the width and height 
information and places it at the specified screen position. No checks are made to 
determine if the data, dimensions, or positions are valid, and bitmaps which 
exceed the screen edge will not be clipped. Be careful to pass accurate values. 

NewBitUp differs from BitmapUp in that it allows bitmaps to be of a pixel- 
width and to be placed at any pixel postion on the x-axis. The data is still 
compacted in card-size (eight-pixel) chunks, but when placed on the screen any 
extra pixels (bits) at the right edge are ignored. 

Note: Neitiier die WIDTH nor die HEIGHT parameter should be $(X). 



DOUBLE B can be or'ed into die WIDTH paramter to double the bitmap width 
and INAUX_B can be or'ed into the XI parameter to specify auxiliary memory. 
For more information, refer to "Apple GEOS Bitmap Doubling and Aux-memory 
Bitmaps" in chapter @gr@. 

Example: 



See also: BitmapUp, NewBitCIip, NewBitOtherClip. 



NewDisk 



NewDisk (C64, cns) 



mid-level disk 



Function: 
Parameters: none 
Uses: 



Returns: 

Destroys: 

Description: 



Note: 

Apple: 
Example: 
See also: 



Tell the turbo software that a new disk has been inserted into the drive. 



curDrive 
curType 



drive that disk is in. 
GEOS 64 vl.3 and later: 
memory is cleared). 



for disk shadowing (shadow 



error ($00 = no error). 



a, y, r0-r3. 

NewDisk informs the disk drive turbo software that a new disk has been 
inserted into the drive. It first calls EnterTurbo then sends an initialize command 
to the turbo code. If the disk is shadowed, the shadow memory is also cleared 

NewDisk gets called automatically when.OpenDlsk opens a new disk. An 
application that does not deal with anything but the low-level disk routines might 
want to call NewDisk instead of OpenDisk to avoid the unnecessary overhead 
associated with reading the directory header and initializing internal file-level 
variables. 

NewDisk has no effect on a RAMdisk. Also, some early versions of the 1541 
turbo code leave the disk in the drive spinning after is first loaded. A call to 
NewDisk during the application's initialization wiU stop the disk. 

Apple GEOS has no NewDisk equivalent 



OpenDisk, SetDevice. 



184 



NextRecord 



NextRecord (Apple, C64, cns) 



VLIR disk 



Function: 
Parameters: 
Uses: 
Returns: 



Alters: 

Destroys: 

Description: 



Makes the next record the current record, 
none. 

flleHeader index table checked to establish whether record exists. 

X error ($00 = no error). 

y if no error, then a value of $00 here means record is empty, 
a new current record number. 

Commodore: 

rl track/sector of first data block in record. 
Appig; 

rl block number of record's index block. 



curRecord 

nothing. 



new record number. 



Example: 
See also: 



NextRecord makes the current record plus one the new current record. A 
subsequent call to ReadRecord or WriteRecord will operate with this record. 

If the record does not exist, then NextRecord returns an INV RECORD 
(invalid record) em)r. " 



PointRecord, PreviousRecord. 




185 



NormalizeX 



NormalizeX (Ci28) 



graphics! 



Function: Adjust an x-coordinate to compensate for the higher-resolution 80-column nKxie. 

Parameters: x GEOSREG — zero-page address of word-length GEOS register which 

contains the word-length X-coordinate to adjust.. 

Returns: x unchanged. 

register passed as GEOSREG parameter contains the adjusted x-coordinate. 



Destroys: a 



Description: 



NormalizeX is used by nearly every GEOS 128 routine that writes to the 
screen. It adjusts an x-coordinate (two's complement signed word) based on the 
graphics mode (40- or 80-column) and the status of the special bits in the 
coordinate. NormalizeX allows an application to run in botii 40- and 80-column 
modes with a minimum of programming effort If the proper bits in a 40-column 
coordinate is set, NormalizeX will automatically double the value when in 80- 
column mode. 

Since GEOS graphics operations automatically call NormalizeX to adjust the 
coordinates, most applications will not need to call it direcdy. 

Bit 15 of the coordinate specifies doubling. Bit 13 adds one to a doubled 
coordinate (allowing odd-pixel addressing). Bit 12 is a pseudo-sign bit. Use the 
DOUBLE^W and ADD1_W constants to access tiiese bits. 

If die coordinate might be negative, the DOUBLE_W and ADDl^W constants 
should be exclusive-or'ed into the x-position so""that the sign Ts preserved. 
However, if die coordinate is guaranteed to be a positive numl^r, the constants 
may simply be or'ed in. 

The GEOSREG parameter is an actual zero-page address. Usually this will be a 
GEOS register (r0-rl5) or an application's register (a0-al5). If, for example, an 
application had a value in r9 which it wanted normalized, it would first exclusive- 
or in the special bits, then call NormalizeX in the following manner: 



Idx 
jsr 



#r9 ;load x with addr of r9 

NormalizeX /normalize the val in r9 



The following breakdown of the word-length x-coordinate illustrates how the 
special bits affect the adjustment process. 



15 14 13 12 11 



I bl5 |bl4|bi7T 



10 



x-pixel coordinate (b0-bl2) 



] 



b0-bl2 x-coordinate in pixels (two's comp. number). 

bl3 add one to doubled x-coordinatc (flag). 

bl4 x-coordinate sign-extension from bl2 (pseudo sign-bit). 

b 15 double x-coordinate (flag). 



186 



NormallzeX 



If in 40-column mode, then the special bits arc ignored and the x-coordinatc is 
returned to its original state (the state it was in before any special constants were 
exclusive-or'ed in). 

If in 80-column mode, then the following applies: 



bl5 


bl4 


bl3 


Effect 


6 





n 


X value unchanged (nomial positive). 


1 


1 


n 


X value unchanged (normal negative). 





1 


n 


X = x*2hi (doubled negative). 


1 





n 


X = x*2+n (doubled positive). 



Note: 
Example: 



For more information, refer to "GEOS 128 X-position and Bitmap Doubling" in 
Chapter @gr@. 



187 



NxtBlkAiloc 



NxtB Ik Alloc (Apple, C64, C128) 



mid-level disk 



Function: Special version of BlkAIIoc that begins allocating from a specific block on the 
disk. 



Parameters: r2 



Uses: 



Returns: 



Alters: 



BYTES — number of bytes to allocate space for (word). Commodore 
version can allocate up to 32,258 bytes (127 Commodore blocks); 
Apple version can allocate up to 65,536 bytes (128 ProDOS blocks). 



Commodore: 

r3L START^TR — start allocating from this track (byte). 

r3H START^SC — start allocating from this sector (byte). 

r6 TSTABLE — pointer to buffer for building out track and sector table of 

the newly allocated blocks, usually a position within fileTrScTab 

(word). 

Apple; 

r3 START3LK— start allocating from tiiis block (word). 
curDrive 



Commodore: 

curDirHead 

dir2Headt 

dir3Headt 

interleave^ 



Apple; 

curVBlkno^ 

VBMchangedt 

numVBMBlkst 



this buffer must contain the current directory header. 
(BAM for 1571 and 1581 drives only) 
(BAM for 1581 drive only) 

desired physical sector interleave (usually 8); used by 
setNextFree. Applications need not set this explicidy — 
will be set automatically by internal GEOS routines. 



used by VBM cacheing routines, 
used by VBM cacheing routines, 
used by VBM cacheing routines. 



^used internally by GEOS disk routines; explications generally don't use. 
X error ($00 = no eiror). 

r2 number of blocks allocated to hold BYTES amount of data. 
Commodore: 

r3L track of last allocated block. 
r3H sector of last allocated block. 



Apple; 
r3 



last block allocated 



Commodore: 
curDirHead 
dir2Headt 
dir3Headt 



BAM updated to reflect newly allocated blocks. 
(BAM for 1571 and 1581 drives only) 
(BAM for 1581 drive only) 



188 



NxtBlkAlloc 



curVBIknot used by VBM cacheing routines. 

VBMchangedt set to TRUE by VBM cacheing routines to indicate cached 
VBM block has changed and needs to be flushed 

^used internally by GEOS disk routines; applications generally don't use. 



Destroys: Commodore: 
a, y, r4-r8. 

Apple: 

a, y, r4, r6, r7, rSH, 

Description: NxtBlkAlloc begins allocating blocks from a speciflc block on the disk, 
allowing a chain of blocks to be appended to a previous chain while still 
maintaining the sector interleave. NxtBlkAlloc is essentially a special version of 
BlkAlIoc that starts allocating blocks from an arbitrary block on the disk rather 
than from a fixed block. NxtBlkAlloc is otherwise identical to BlkAlIoc. 



C64 & C128: The Commodore version of NxtBlkAlloc for appending more blocks to a list of 
blocks just allocated with BlkAlIoc, thus circumventing the 32,258-byte barrier. 
Point TSTABLE at the last entry in a track/sector table (the terminator bytes which 
we can overwrite), load the BYTES parameter with the number of bytes left, and 
call NxtBlkAlloc. The START TR and START^SC parameters in r3L and 
r3H will contain the correct values on return from BlkAlIoc. NxtBlkAlloc 
will allocate enough additional blocks to hold BYTES amount of data, appending 
them in the track/sector table automatically. This combined list of track and 
sectors can then be passed directiy to WriteFile to write data to the full chain of 
blocks. 



NxtBlkAlloc does not automatically write out the BAM. See PutDirHead for 
more information on writing out the BAM. Also, the START 7R parameter 
should not be track number of the directory track. Refer to GetFreeDirBlk for 
more information on allocating blocks on the directory track. 

Apple: The Apple version of NxtBlkAlloc builds out a list of allocated blocks in the 

internal indexBIock buffer just as if BlkAlIoc had been called: it starts filling 
up the table from the beginning, overwriting any block pointers that may abready 
be there. The only difference between BlkAlIoc and NxtBlkAlloc is that 
BlkAlIoc forces SetNextFree to start searching for free blocks beginning at 
the block following the VBM, whereas NxtBlkAlloc instructs it to stan 
searching from the START JBLK block. NxtBlkAlloc could be used to append 
blocks to an existing file or record, but the application would need to manually 
append the new block pointers (built-out in indexBIock) to the end of the 
original index block. For this reason, the Apple GEOS version of NxtBlkAlloc 
is not especially useful. 

NxtBlkAlloc does not automatically flush the VBM cache. Sec PutVBM for 
nx)re information on flushing the cache. 

Note: For more information on the scheme used to allocate successive blocks, refer to 

SetNextFree. 



J Example: 



189 



NxtBlkAlloc 

See also: BIk Alloc, SetNextFree, AIIocateBlock, FreeBlock. 



190 



OpenCard 



OpenCard (Apple) 



card driver 



Function: 



Open printer card for access. 



Parameters: none. 



Returns: 



X 



STATUS — card error code; $00 = no eiror (byte) 



Destroys: assume a, y. 

Description: OpenCard opens access to the printer carcL The printer driver calls this routine 



to switch in the printer card's ROMs. This operation may be necessary before 
each block of data because another card's ROMs may be enabled (thQ disk 
controller ROMs, for example). 

The printer driver sends blocks of data to the printer between calls to OpenCard 
and CloseCard. 



Note: 



Do not call OpenCard without having called InitCard. 



Example: 



See also: 



InitCard, CloseCard. 



191 



OpenDisk 



OpenPisk (Apple, C64, cns) 



high>levcl disk] 



Function: 

Parameters: 

Uses: 

Returns: 
Alters: 



Open the disk in the cunent drive 



Destroys: 



none 

curDrive 

Commodore: 
driveType 



drive that disk is in. 



type of drive to open (for shadowing information). 



X error ($00 = no error). 

r5 pointer to disk name buffer as returned from GetPtrCurDkNm. This 
is a pointer to one of the Dr;cCurDkNm arrays. 



DracCurDkNm 
curDirHead 

Commodore; 
isGEOS 

dir2Headt 
dir3Headt 
driveType 

Apple; 

sysDirBlkno 



curKBlkno 

totNumBIkst 

pathnameBuft 

curVBlknot 

numVBMBIkst 

VBMchangedt 

curDirTabLo 

curDirTabHi 



current disk name array contains disk name, 
current directory header. 



set to TRUE if disk is a GEOS disk, otherwise set to 
FALSE. 

(BAM for 1571 and 1581 drives only) 
(BAM for 1581 drive only) 



block number of /SYSTEM directory. If system directory 
not found on disk, then this number is same as 
curKBlkno. 

block number of root directory's key block, 
total number of blocks in volume, 
reset to root directory. 

block currendy cached in VOLUMEBITMAP 
number of VBM blocks on disk, 
set to FALSE, 
set to root directory, 
set to root directory. 



Description: 



^used internally by GEOS disk routines; applications generally don't use. 

CommQdor;>; 
a, y» r0-r4. 

Applg; 

a, y, rl, r4. 

OpenDisk initiates access to the disk in Ae current drive. OpenDisk is meant to 
be caUed after a new disk has been inserted into the disk drive. It prepares the 
drive and disk variables for deaUng with a new disk. An application will usually 
call OpenDisk immediately after calling SetDevice. 



192 



OpenDisk 



Note: Because GEOS uses the same allocation and file buffers for each drive, it is 

important to close all files and update the BAMA^BM if necessary (use 
PutDirHead or PutVBM, respectively) before accessing another disk. 

C64 & C128: OpenDisk first calls NewDisk to tell the disk drive a new disk has been 
inserted (if the disk is shadowed, the shadow memory is also cleared). 
GetDirHead is then called to load the disk's header block and BAM into 
curDirHead. With a valid header block in memory, ChkDkGEOS is called to 
check for the GEOS I.D. string and set the isGEOS flag to TRUE if the disk is 
a GEOS disk. Finally, OpenDisk copies the disk name string from 
curDirHead to the disk name buffer returned by GetPtrCurDkNm. 

Apple: Apple GEOS OpenDisk resets the path to the root directory, then reads the disk 

header into the curDirHead array. The volume disk name is copied from this 
buffer into the disk name buffer returned by GetPtrCurDkNm. This disk name 
is also used to build out the initial pathname in pathnames uf (the inital 
pathname is a slash 7" character followed by Ae null-terminated disk name.). 
OpenDisk also initializes the VBM cache and its associated variables, computing 
the total number of VBM blocks and reading the first block into the cache. The 
flag VBMchanged is set to FALSE to indicate tiiat the cached VBM block in 
memory matches its copy on the disk. When all this is done, OpenDisk searches 
the root directory for the /SYSTEM directory (using FndFillnDir) and stores 
the resulting block number into sysDirBlkno. 

Example: 

See also: ReOpenDisk, SetDevice, NewDisk. 



193 



nRecordFlle 



OpenRecordFile (Apple, C64, cns) 



VLIR disk 



Function: 

Parameters: 

Uses: 



Returns: 



Alters: 



Destroys: 
Description: 



Open an existing VUR file for access. 

rO FILENAME — pointer to null-terminated name of file (word). 
curDrive 



CpmrncKlQi?; 
curType 

Apple: 

curKBlkno 



GEOS 64 vL3 and later for detecting REU shadowing. 



current directory. 

^used internally by GEOS disk routines; applications generally don't use. 
X error ($00 = no error). 

rl block number (Commodore track/sector) of directory block containing 
entry. 

rS pointer into diskBlkBuf to start of directory entry. 



fileHeader 
usedRecords 
cur Record 

fileWrittent 
fileSize 

dirEntryBuf 

Apple; 
fileBytes 



buffer contains VLIR index table. 

number of records in file that are currendy in use. 

current record set to 1 by default or -1 ($ff) if there are no 

records in the file. 

set to FALSE to indicate VLIR file has not been written to. 
total number of disk blocks used in file (includes index 
block, GEOS file header, and all records), 
directory entry of VLIR file. 



total number of bytes in file (as picked up from last from 
bytes 254, 255, 511, and 512 of the master index block. 



^used internally by GEOS disk routines: applications generally don't use. 
a, y, rl, r4-r6. 

Before accessing the data in a VLIR file, an application must call 
OpenRecordFile. OpenRecordFile searches the current directory for 
FILENAME and, if it finds it, loads the index table into fileHeader. 
OpenRecordFile initalizcs the GEOS VLIR variables (both local and global) to 
allow other VLIR routines such as WriteRecord and ReadRecord to access 
the file. Only one VLIR file may be open at a time. A previously opened VLIR 
file should be closed before opening another. 

If an application passes a FILENAME of a non-VLIR file, OpenRecordFile 
will renim a STRUCT^MISMATCH error. 



Note: 



An application can create an empty VLIR file with SaveFile. 



194 



OpenRecordFile 



C64 & C128: Since Commcxiorc GEOS does not support a Mcrarchical fUe system, the "cu^ 
directory" is actually the entire disk. 

Apple: Once a VLIR file is opened, the current directory may be changed without 

affecting access to the file because the index information is kept in fileHeader. 

Example: 

See also: CIoseRecordFile, UpdateRecordFile. 



195 



OutputByte 



OutputByte (Apple) 



card driver I 



Function: 

Parameters: 

Returns: 

Destroys: 

Description: 

Note: 



Example: 
See also: 



Put a byte of output data to the interface canL 

y DATA — single ouput byte to send to card (byte) 

X STATUS — card error code; $00 = no error (byte) 

a, y. 

OutputByte sends a byte of data to the card. The ready-for-output flag may be 
checked with StatusCard prior to calling OutputByte. 

OutputByte must be called after an OpenCard and before a CloseCard. 

Most card drivers always return NO_ERROR from from OutputByte due to a 
lack of memory to properly handle complex error checking. 



InputByte, StatusCard. 



196 



Panic 



Panic (Apple, C64, C128) 



internal I 



Function: 
Parameters: 



Display "system error" dialog box. 
Apple &C»f; 

top word on stack is the system error address+2. 

top eight bytes on stack are unused, next word on stack is the system error 
address+2 



Returns: 
Description: 



Example: 



Never returns. 

Panic puts up a system error dialog box. It is usually not called directly by an 
application. Usually the global GEOS variable BRKVector will contain the 
address of this routine When GEOS encounters a brk (opcode: $00) instruction 
in memory, it jumps indirecdy through BRKVector with system-specific status 
values on die stack. This usually results in a system error dialog box. The hex 
address in the dialog box is the address of the offending brk instruction. 

An application that patches into BRKVector processes brk instructions on its 
own may need to simulate the normal GEOS course of events by performing a 
jmp Panic. 

Although this is not a typical use, an application can use Panic as a means of 
communicating fatal error messages. This may be useful in a beta-test version of a 
software product, for example. 



FatalError : 

use Panic to send a fatal error message to the user 



Pass: 



rO 



Error number 



See also: 



FatalError: 
IncW 
IncW 



rO 
rO 



.if (C64 I I APPLE) 
PushW rO 

.else; (C128) 



Idx #5-1 

10$: 

PushW rO 
dex 

bne 10$ 
.endif 

jmp Panic 

DoDlgBox. 



;add 2 to error number 
;to compensate for Panic 

; apple & c64 only expect an address 
;push error number onto stack 

;128, however, expects all kinds of internal 
; machine-state information (10 bytes total) on the 
; stack. It ignores all but the bottomost word. 
;place 5 words (10 bytes) total onto stack 

;push error number onto stack 

; (use error number repeatedly as dummy value) 

;loop until all done. 



•go put up the panic dialog box 



CONnBEhO'lAL 



197 



1 <J 



PointRecord (Apple, C64, ci28) 



VLIR disk 



Function: 
Parameters: 
Uses: 
Returns: 



Alters: 

Destroys: 

Description: 



Make a particular recoijd the current record 
a RECORD — ^ record number to make current (byte). 

fileHeader index table checked to establish whether record exists. 

X error ($00 = no error). 

y if no error, then a value of $00 here means record is allocated but not in 

use (has no data blocks), 
a new current record number. 



Commodore: 
rl $0000 
$ff00 

other 

Applg; 

rl $0000 
$ffff 

other 



curRecord 



record is not allocated 

record is allocated but not in use (has no data blocks); this 
information is already flaged in y. 
track/sector of first data block in record 

record is not allocated 

record is allocated but not in use (has no data blocks); this 
information is already flaged in y. 

block number of the index block that corresponds to the 
record (Apple). 

new record number. 



nothing. 



PointRecord makes RECORD the current record so that a subsequent call to 
ReadRecord or WriteRecord will operate with RECORD. VLIR records are 
numberd zero tiirough MAX_VLIR_RECS-1. 

If the record does not exist (you pass a record number that is larger tiian the 
number of currently used records), then PointRecord returns an 
INV RECORD (invalid record) error. 



Example: 



See also: NextRecord, PreviousRecord. 



PosSprite 



PosSprite (Apple, C64, C128) 



spritej 



Function: 
Parameters: 

Returns: 
Alters: 



Destroys: 
Description: 



C64: 



C128: 



Apple: 

Example: 
See also: 



Positions a sprite at a new GEOS (x,y) coordinate. 

r3L SPRITE — sprite number (byte). 
r4 XPOS — x-position of sprite (word). 
rSL YPOS — y-position of sprite (byte). 



nothing. 

mobNxpos 
msbNxpos 
reqXposN 
mobnypos 



(64 and 128 only) sprite x-position (lower 8-bits) 
(64 and 128 only) sprite x-position (bit 9). 
(Apple only) sprite x-position. 
(all versions) 



where N is the number of the sprite being positioned. 
a, X, y, r6 

PosSprite positions a sprite using GEOS coordinates (not C64 hardware sprite 
coordinates). PosSprite does not affect the enabled/disabled status of a sprite, it 
only changes the cuirent position. 

Although there are eight sprites available, an application should only directiy 
position sprites #2 through #7 with PosSprite. Sprite #0 (the mouse pointer) 
should not be repositioned (except, maybe through mouseXPos and 
mouse YPos), and sprite #1 (the text cursor) should only be repositioned witii 
stringX and stringY. 

The positions are translated to C64 hardware coordinates and then stuffed into the 
VIC chip's sprite positioning registers. The C64 hardware immediately redraws 
the sprite at die new position. 

The positions are translated to C64 hardware coordinates and then stuffed into the 
VIC chip's sprite positioning registers. This data is used by the VIC chip in 40- 
column mode and by the soft-sprite handler in 80-column mode. In 80-column 
mode, the sprite is not visually updated until the next time the soft-sprite handler 
gets control. 

The y-position is stuffed, unaltered, into mobnypos (simulated hardware 
register), and the x-position is stuffed, unaltered, into reqXposn. The sprite is 
not visually updated until the next time the soft-sprite handler gets control. 



DrawSprite, GetSpriteData, EnablSprite, DisablSprite, InitSprite. 



199 



PreviousRecord 



PreviousRecord (Apple, C64, cm) 



VLIR disk 



Function: 
Parameters: 
Uses: 
Returns: 



Alters: 

Destroys: 

Description: 



Makes the previous record the current record, 
none* 

fileHeader index table checked to establish whether record exists. 
X error ($00 = no error). 

y if no error, then a value of $00 here means record is empty, 
a new current record number. 

CpmrnQ^ore; 

r 1 track/sector of first data block in record 
Apple; 

rl block number of record's index block. 



curRecord 

nothing. 



new record number. 



Example: 
See also: 



PreviousRecord makes die current record minus one the new current record. A 
subsequent call to ReadRecord or WriteRecord will operate with this record. 

If the record does not exist, then PreviousRecord returns an INV RECORD 
(invalid record) error. 



PointRecord, NextRecord. 



200 



PrintASCIi 



Print ASCII (Apple, C64, C128) 



printer driver | 



Function: 
Parameters: 



Uses: 



Send ASCn string to the printer. 

rO PRINTDATA — pointer to null-terminated ASCII string (word). 

rl WORKBUF — pointer to a 640-byte work buffer for use by the printer 
driver (word). This is the same buffer that was established in 
StartASCn and must stay intact throughout the entire page. 



Apple 
rO 



PRINTDATA — pointer to null-terminated ASCII string (word). 



Apple 
RWbank 



the memory bank that the PRINTDATA buffer is in. Valid 
settings aie MAIN and AUX. 



Cpmm«I(?rp 
nothing. 

Apple 

X STATUS — printer error code; $00 = no error. 

Commodore 

assume a, x, y, r0-rl5. 
Apple 

assume a, y, rl-r4. 

« 

Description: PrintASCIi sends a null-terminated ASCII string to the prinier. The application 
must call StartASCII before sending ASCII data to the printer with 
PrintASCIi. It is the job of the application to keep track of the number of 
possible lines per page and call StopPrint to formfeed when necessary (or 
desired). 

In order to begin printing on the next line, the string must contain a CR character 
to signify a carriage return. A NULL character marks the end of the string. 

C64 & C128: The data passed in PRINTDATA is in regular ASCII format (not Conmiodore 
ASCII), The text is printed using the printer's standard character set. Some 
printer drivers allow switching the printer into high-quality print mode with 
SetNLQ. Commodore GEOS printer drivers are set to print 80 characters per 
line and 66 lines per page. 

The data passed in PRINTDATA is in regular ASCII format. The text is printed 
using the printer's standard character set unless some other option has been 
selected with the SetMode conmiand. The page width and height can be 
determined with GetMode. Because a new line is not staned until a CR 
character is encountered an NULL can be inserted mid-string. When 
PrintASCIi encounters it and returns, the application can call SetMode to 
change the modes mid-line. 



Returns: 



Destroys: 



Apple: 



PrintASCII 



Example: 

See also: PrintASCII, StartPrlnt, StopPrint, InitForPrint. 



202 



PrintBuffer (Apple, C64, cns) 



PrintBuffer 



printer driver 



Function: Print one cardrow (eight lines) of graphics data. 

Parameters: Commodore 

rO PRINTDATA — pointer to 640 bytes of graphic data in Commodore 
card format (8x8 pixel blocks). This is one row of 80 cards, which 
amounts to eight lines of printer data (word), 
rl WORKBUF — pointer to the 1,920-byte woric buffer established with 
StartPrint (word). 

r2 COLRDATA — pointer to 80 bytes of Ci)mmodore card color data (40- 
colunm screen format) for the cardrow; pass $0000 for normal black 
and white printing (word). 

Apple 

rO PRINTDATA — pointer to 640 bytes of graphic data in linear bitmap 

format This is eight 640-bit rows of printer data (word). 
rlL LF.SUPPRESS — set to TRUE to suppress automatic linefeed after 
printing buffer (for overlayed printing); normally set to FALSE. 

Apple 

RWbank the memory bank that the PRINTDATA buffer is in. Valid 

settings are MAIN and AUX. 

Commodorg 

nothing. 
Applg 

X STATUS — printer error code; $00 = no error. 

assume a, x, y, r0-rl5. 

Apple 

assume a, y, r0-r4. 

Description: PrintBuffer prints eight lines of graphic data on the printer. The maximum 
width of each line is determined by the capabilites of the printer and its driver. 
640 dots per line is standard, but some printers and drivers handle less. The 
application can determine the capabilities of the printer with a call to 
GetDimensions (Commodore) or GetMode (Apple). If the printer cannot 
handle the full 640 dots, PrintBuffer will ignore any pixels at the end of each 
line. 

The application must call StartPrint before sending graphic data to 
' PrintBuffer. It is also the job of the application to keep track of the number of 
possible cardrows per page and call StopPrint to formfeed when necessary. 

C64 & C128: The data passed in PRINTDATA is in Commodore card format, where data is 
stacked into 8x8-pixel blocks. Graphic printer data can be built-up direcdy on the 
40-column graphics screen using GEOS routines and sent direcfly to the printer 
(calcinating the address using GetScanLine). Because one printer cardrow is 



Uses: 
Returns: 

Destroys: 



203 



PrIntBuffer 



equivalent to two screen caixirows the full 640-dot printer cardrow can be created 
using two sequential screen cardrows.The sequential memory organization of the 
40-column screen wraps the end of one screen cardrow around to the beginning 
of the next screen cardrow. In the 80-column mode of GEOS 128, one screen line 
is equivalent to one printer line. However, the data must first be converted from 
linear bitmap format into card format (a simple operation). Also, since the 
foreground screen can only be accessed indirectiy through the VDC chip, the 
printer data is usually built-up in the background screen buffer. 

Apple: The data passed in PRINTDATA is in linear bitmap format, where the first 80 

bytes represent the 640 bits that are printed on the first line, the next 80 bytes 
represent the 640 bits on the next line, and so on to fill out eight lines. Printer data 
can be created using the GEOS graphics routines, then converted from Apple 
internal screen format to linear bitmap format using GetLine and 
GetBackLine. 

With the proper printer and driver, color output can be created by setting making 
three passes per line, each time printing in a different color (cyan, yellow, 
magenta). The first color is set with SetMode and PrintBuffer is called witii 
the LF_SUPPRESS flag set to TRUE, which will return the print carriage 
without performing an linefeed. The next color can then be printed on top of what 
is already there. When calling PrintBuffer for the third time (the last color), set 
the LFJUPPRESS flag to FALSE, which will carriage return and linefeed. 

Example: 



See also: PrintASCII, StartPrint, StopPrint, InitForPrint. 



PrOmptOff (Apple, C64, C128) 



text/keyboard I 



Function: 

Parameters: 

Alters: 

Destroys: 
Description: 



Example: 
See also: 



Turn off the prompt (remove the text cursor from the screen), 
none. 



alphaFlag 



a, X, r3L 



(($cO & (alphaFlag & $40) I PROMPT.DELAY),wA^re 
PROMPT DELAY = 60. 



PromptOff removes the text prompt from the screen. To ensure the prompt will 
remain invisible until a subsequent call to PromptOn, interrupts must be 
disabled before calling PromptOff: 



KillPrompt : 
php 
sei 
jsr 
LoadB 
pip 
rts 



PromptOff 
alphaFlag, #0 



;save i status 
/disable interrupts 
/prompt » off 
/clear alpha flag 
/restore i status 
/exit 



InitTextPrompt, PromptOn. 



PromptOff - 



PrOmptOn (Apple, C64, Cmy ^ text/keyboard 

Function: Turn on the prompt (show the text cursor on the screen). 
Parameters: none. 

Uses : strlngX cursor x-position (word). 

stringY cursor y-position (byte). 

Alters: alphaFlag (($cO & (alphaFlag I $40) I PROMPT_DELAY),w/z^r^ 

PROMPT JfELAY = 60. 

Destroys: a, x, r3L. 

Description: PromptOn makes the text prompt visible and active at the position specified by 
stringX and stringY. The prompt will flash once every second 
(PROMPT^DELAY). If stringX or StringY are changed, the cursor will 
repositioned automatically the next time the cursor flashes. To make the update 
immediate, call PromptOn. Before PromptOn is called for the first time, 
InitTextPrompt should be called. 

See also: InitTextPrompt, PromptOff. 



Example: 



PurgeTurbo 



IPurgeTurbo (C64, cns) 



very low«levcl disk] 



Function: Completely deactivate and remove disk drive turbo code from current drive, 
rctuming to standard Commodore DOS mode. 

Parameters: none. 

Uses : curDrive currcndy active disk drive. 

Returns: x error ($00 = no error). 
Destroys: a, y, r0-r3. 

Description: PurgeTurbo deactivates and removes the turbo software from the current drive, 
returning control of the device to the disk drive's internal ROM software. This 
allows access to normal Commodore DOS routines. An application may want to 
access the Commodore DOS to perform disk functions not offered by the GEOS 
Kemal such as formatting. 

Apple: Apple GEOS has no PurgeTurbo equivalent 

See also: EnterTurbo, ExitTurbo. 



207 



PutBlock 



PutBlOCk (Apple, C64, C128) 



low-level disk] 



Function: 
Parameters: 



Uses: 



Returns: 

Destroys: 
Description: 



General purpose routine to write a block to disk with verify. 

r4 BUFFER — address of buffer to get block from; must be at least 
BLOCKSIZE bytes (word). 

Commodore: 

rlL TRACK — valid track number (byte), 
r IH SECTOR — valid sector on track (byte). 

Applg; 

r 1 BLOCK — ProDOS block number (word). 
curDrive currently active disk drive to write to. 



Commodore: 
curType 



GEOS 64 vl.3 and later for detecting REU shadowing. 



Applg: 

RWbank bank BUFFER is in (MAIN or AUX). 

numDiskRetries number of times to attempt rewrite if verify fails. If $(X), no 
verify will be perfomied. 

X error ($00 = no error), 

rl, r4 unchanged 

a, y. 

PutBlock writes a block from BUFFER to the disk. PutBlock is useful for 
implementing disk utility programs and new file structures. 



C64 & C128: PutBlock is a higher-level version of WriteBlock. It calls InitForlO, 
EnterTurbo, ReadBlock, and DoneWithlO. If an application needs to write 
many blocks at once, WriteBlock may offer a faster solution. If the disk is 
shadowed, PutBlock will also write the data to the shadow memory. 



Apple: 

Example: 
See also: 



PutBlock provides the lowest-level block access to a ProDOS compatible 
device. It uses the ProDOS device driver WRITE block command directly. 
Apple GEOS, for this reason, does not have a WriteBlock equivalent. 



GetBlock, WriteBlock, BIkAlloc. 



208 



PutChar (Apple, C64, C128) 



text 



Function: 
Parameters: 

Uses: 



Returns: 
Destroys: 



Process a single character code (both escape codes and printable characters). 

a CHAR — character code (byte). 

r 1 1 XPOS — x-coordinate of left of character (word). 

r 1 H YPOS — y-coordinate of character baseline (word). 



dispBufferOn 

currentMode 

leftMargin 

rightMargin 

(following set by 

curHeight 

baseiineOffset 

cardDataPntr 

curlndexTable 

curSetWidth 



display buffers to direct output to. 
character style. 

left margin to contain character, 
right margin to contain characters. 
LoadCharSet and LoadAuxSet). 
height of current font. 

number of pixels from top of font to baseline, 
pointer to current font image data, 
pointer to current font index table data, 
pixel width of font bitstream in bytes. 



r 1 1 x-position for next character. 

rl H y-position for next character (usually unchanged). 

Commodore: 

a, X, y, rlL, r2-rl0, rl2, rl3 



Applg; 

a, X, y, rlL, r2 



" Description: PutChar is the basic character handling routine. If the character code is less than 
32, PutChar will look-up a routine address in an internal jump table to process 
the escape code. Only send implemented escaped codes to PutChar. 

If the character code is 32 or greater, PutChar treats it as a printable character. 
First it establishes the .printed size of the character with any style attributes 
(currentMode) then checks the character position against the bounds in 
leftMargin and rightMargin. If the left edge of the character will fall to the left 
of leftMargin, then the width of the character is added to the x-position in rll 
and PutChar vectors through StringFaultVec. If the right edge of the characer 
will fall to the right of rightmargin, then PutChar vectors through 
StringFaultVec without altering the x-position. The character is not printed in 
either case. 

Assuming no margin fault, PutChar will print the character to the screen at the 
desired position. Any portion of the character that lies above windowTop or 
below windowBottom will not be drawn. 

PutChar cannot be used to directly process multi-byte character codes such as 
GOTOX or ESC^GRAPHICS unless rO is maintained as a string pointer 
when PutChar is called (as it is in PutString). See PutString for more 
information. 



PutChar 



See also: SmallPutChar, PutString, PutDecimal. 



i 



210 



F U I U II ai 



PutDecimal (Apple, C64, ci28) 



text 



Function: 
Parameters: 

Uses: 
Returns: 

Destroys: 



Description: 



Format and print a 16-bit positive integer. 

a FORMAT — formatting codes (byte) — see below. 

rO NUM — 16-bit integer to convert and print (word), 

rl 1 XPOS — x-coordinate of leftmost digit (word), 

r 1 H YPOS — y-coordinate of baseline (word). 

same as PutChar. 

r 1 1 x-position for next character. 
rlH unchanged. 

Commodore: 

a, X, y, rO, rlL, r2-rl0, rl2, rl3 

Applg; 

a, X, y, rO, rlL, r2 

PutDecimal converts a 16-bit positive binary integer to ASCII and sends the 
result to PutChar. The number is formatted based on the FORMAT parameter 
bytes in the a-registers as follows: 

FORMAT: 



NOTE: 

Example: 
See also: 



7 6 5 

I b7 I b6 I 



bO-b5 



b7 justification: 1 = left; = right. 

b6 leading zeros: 1 = suppress; = print. 

b5-bO field width in pixels (only used if right justifying). 

The following constants may be used: 

SET LEFTJUST 
SET"RIGHTJUST 
SET"SUPPRESS 
SET^NOSUPPRESS 

The maximum 16-bit decimal number is 65535 ($ffff), so the printed number will 
never exceed five characters. 



PutChar. 



PutDirHead 



IPutPirHead (Apple, C64, cns) 



mid-level disk I 



Function: Write directory header to disk. Commodore GEOS also writes out the BAM. 
Parameters: none. 



Uses: 



curDrive 
curDirHead 



current directory header. 



Returns: 



Destroys: 



Commodore: 

curType GEOS 64 vL3 and later for detecting REU shadowing. 

dir2Headt (BAM for 1571 and 1581 drives only) 

dIrSHeadt (BAM for 1581 drive only) 

^used internally by GEOS disk routines; applications generally don't use. 

Apple: 

curKBlkno current key block to write directory header to. 

X error ($00 = no error). 

Commodore: 

r4 pointer to curDirHead. 

Commodore: 
a,y, rl. 

Appig; 

a, y. rl, r4. 



Description: 



PutDirHead writes the directory header to disk from the buffer at curDirHead. 
Because of differences in the Commodore and Apple file systems, this can mean 
different things. Commodore GEOS writes out the full directory header block, 
including the BAM (block allocation map). Apple GEOS only writes out the 39- 
byte ProDOS directory header for die cuntnt directory's key block. 

C64 & C128: GEOS disks, like the standard Commodore disks upon which they are based, 
have one directory header. The directory header occupies one full block on the 
disk. The Commodore directory header contains information about the disk, such 
as the location of the directory blocks, the disk name, and the GEOS version 
string (if a GEOS disk). The Commodore directory header also contains the disk 
BAM, which flags particular sectors as used or unused 

PutDirHead calls PutBlock to write out the directory header. block from die 
buffer at curDirHead. The directory header block contains the directory header 
and the disk BAM (block allocation map). Applications that are working with die 
mid- and low-level GEOS disk routines may need to call PutDirHead to update 
die BAM on die disk widi die BAM in memory. Many useful, mid-level GEOS 
routies, such as BlkAUoc, only update the BAM in memory (for sp^d and ease 
of error recovery). When a new fdc is written disk, GEOS allocates die blocks in 
the in-memory BAM, writes the blocks out using the track sector table, then, as 
die last operation, calls PutDirHead to write die new BAM to die disk. An 



212 



PutDfrHead 



application that uses the mid-level GEOS routines to build its own specialized 
disk file functions will need to keep track of the status of the BAM in memory, 
writing it to disk as necessary. 

It is important that the BAM in menx>ry not get overwritten by an outdated BAM 
on the disk. Applications that manipulate the BAM in memory (or calls GEOS 
routines that do so), must be careful to write out the new BAM before calling a 
routine that might overwrite it. Routines that call GetDirHead include 
OpenDisk, SetGEOSDisk, and OpenRecordFile. 

GEOS VLIR routines set the global variable fileWritten to TRUE to signal that 
the VLIR file has been written to and that the BAM in menx)ry is more recent than 
the BAM on the disk. CloseRecordFile checks this flag. If fileWritten is 
TRUE, CloseRecordFile calls PutDirHead to write out the new BAM. 

Apple: Apple GEOS disks, like the ProDOS disks upon which they are based, have a 

directory header for each directory. The header for a root directory is called a 
volume directory header and the header for a subdirectory is called a subdirectory > 
header. These directory headers are 39-byte structures defined by ProDOS. They 
contain such information as the directory (or volume) name, the date stamp, and 
any read/write access flags. The directory header does not contain the VBM 
(volumen bit map, the Apple equivalent of a BAM). 

PutDirHead first reads in the key block of the current directory (pointed at by 
curKBIkno) and copies the 39-byte directory header information from 
curDirHead to the key block, then rewrites the key block to disk. Only these 
39-bytes in the key block are changed. 

Since Apple GEOS does not store the allocation map (VBM) in the directory 
header 10:e Commodore GEOS, it not necessary to be as careful about rereading 
the directory header. PutDirHead only needs to be called when an application 
explicidy wants to change the directory header, which few applications (outside 
of the deskTop) will ever do. For information on writing the Apple VBM, refer to 
PutVBM. 

Example: 

See also: GetDirHead, GetVBM, PutVBM. 



V. 



213 



PutScreenLine 



PutScreenLine (Apple) 



graphics! 



Function: 
Parameters: 



Uses: 

Returns: 

Destroys: 

Description: 



Note: 

Example: 
See also: 



Copies data from the application's buffer, in internal format, to a byte-aligned 
horizontal line on the screen. 

rO DATA — address of buffer to copy data from (word). 
rlH XINDX — byte in line to begin with (seven-bit Apple screen byte) (byte). 
r2L XWIDIH — width in bytes of line (seven-bit Apple screen bytes) (byte). 
rlL Y — y-coordinate of line (byte). 

where (XINDX^J.Y) and (XINDX^7+XWIDTH,Y) define the endpoints of the 
line. 

dispBufferOn: 

bit 7 — get data from foreground screen if set 
bit 6 — get data from background buffer if set 
If both bits are setjoreground screen is used. 

rO address of byte following last byte in the buffer. 

a, X, y, rO, rlH, r2L, r5-r6 

PutScreenLine copies bytes directly from the specified buffer to the screen 
memory. The screen is treated as a contiguous block of bytes even though, in 
actualiQ^, alternate bytes lie in different memory banks. 

Bytes are copied from the buffer pointed to by rO and stored in screen memory 
beginning at the byte-index into the line stored in rlH. 

No clipping at the screen edge is performed; the values passed are rssumed to lie 
entirely on one screen line. 



GetScreenLine. 



214 



■ PulOtiHuiiLiiie 



PutString^ i PutString (Apple, C64, cns) 



text 



Function: 
Parameters: 



Uses: 
Returns: 

Destroys: 
Calls: 

Description: 



Print a string to the screen. 
Normal; 

rO STRING — pointer to string data (word). 

r 1 1 XPOS — x-coordinate of left of first character (word). 

r 1 H YPOS — y-coordinate for character baselines (word). 

Inline: 

data appears immediately after the jsr i^PutString 

.word XPOS x-coordinate. 

.byte YPOS y-coordinate. 

.byte STRINGDATA null terminated string (no length limit) 

same as PutChar. 

r 1 1 x-position for next character. 

r 1 H y-position for next character (usually unchanged). 

CQmmQjprp 

a, X, y, rlL, r2-rl0, rl2, rl3 

Apple 

a, X, y, rlL, r2 
PutChar. 

PutString passes a full string of data to PutChar a character at a time. It 
maintains rO as a running pointer into the string and so supports multi-byte 
escape codes such as GOTOXY. 

If a character exceeds one of the margins, PutChar will vector through 
stringFaultVec as appropriate. rO, rll, and rlH will all contain useful values 
(current string pointer, x-position, and y-position, respectively). For more 
information, refer to "String Faults (Left or Right Margin Exceeded)'* in Chapter 
XX. 

Basic operation of PutString: 



PutString: 
5$: 



Idy 

Ida 

beq 

jsr 

IncW 

bra 



#0 

(rO),y 
10$ 

PutChar 



;use zero offset 
;get character 



;exit if NULL terminator 
/otherwise process char. 



rO 
5$ 



;move to next byte in string 
;and loop through again 



10$: 

rts 



/exit 



C64 & C128: Unless a special string fault routine is placed in stringFaultVec prior to calling 
PutString, a margin fault will be ignored and PutString will attempt to print 
the next character. 



Pur SriUMC^ 
PulGereenLIno 



Apple: If stringFaultVec contains $0000 when PutString is called, Apple GEOS 

installs a temporary string fault routine that fast-forwards through the string to the 
null-terminator whenever a fault is generated. stringFaultVec is restored with a 
$0000 when PutString exits. 



Example: 
See also: 



PutChar, GraphicsString. 



PutVBM (Apple) 



P u 1 Q I r i n s 



mid-level disk 



Function: Flush the currently cached VBM block, writing it out to disk. 

Parameters: none. 

Uses: curDrive 

curVBlkno^ block to write cache to. 

Returns: x error ($00 = no error). 

Alters : VBM changed^ set to FALSE; indicates current cache matches disk. 

^used internally by GEOS disk routines; applications generally don't use. 
Destroys: a, y, rl, r4. 

Description: PutVBM writes the currently cached VBM block to its proper spot on the disk. 

This cache is inaccessible to applications but is used indirecdy by routines such as 
SetNextFree. PutVBM is called by high-level GEOS routines to automatically 
flush the cache, bringing the copy of the VBM on the disk up-to-date with the 
copy in memory. Specialized applications that call mid- and low-level disk 
routines may need to flush the cache manually. 

Apple GEOS disk routines cache a single VBM block in an internal memory 
buffer. This speeds up disk operations by allowing the VBM to be accessed 
quickly during multiple-sector disk operations. This parallels the way 
Commodore GEOS buffers the BAM in the directory header. In fact, wherever a 
Commodore GEOS application calls PutDirHe^d to update the BAM on the 
disk, an Apple GEOS application can usually substitute a call to PutVBM. 

But there are differences between the Commodore buffering and the Apple 
buffering. Because higher-density storage devices (a hard disk, for example) will 
have more than one VBM block, the entire VBM cannot be stored in memory. 
The Apple GEOS routines that manage the disk cache will automatically flush the 
currentiy cached VBM block before loading in another. But if another VBM block 
is never loaded, the cache may not necessarily get flushed. For example, some 
mid-level routines, such as BlkAlIoc and AllocateBlock, do not explicitly 
flush the cache O'ust as their Commodore counterparts do not call PutDirHead), 
which may mean that the block in the cache may be more up-to-date than the 
block on the disk. An application that uses these mid-level routines should flush 
the cache manually with a calls to PutVBM. 

The less often the cache is flushed, the faster a multiple-sector disk operation will 
run. GEOS VLIR routines, for example, do not flush the cache until 
CioseRecord is called. At the very least, the application must be careful to flush 
the VBM cache before calling any other routine that might call Get VBM because 
GetVBM will overwrite die cached block before it is used to update the disk 
copy. GetVBM is called by routines such as OpenDisk and BlkAlIoc. 



Note: 



PutVBM will write out the cached VBM block even if VBMchanged is 
FALSE. 



PutVBM 



Example: 

See also: GetVBM, GetDirHead, PutDirHead. 



218 



ReadBackLine 



ReadBackLine (Apple) 



graphics 



Function: 

Parameters: 

Returns: 

Destroys: 

Description: 

Example: 



Translates a screen line in the background buffer from internal format to linear 
bitmap format 

rO DATA — address of buffer to copy data to (word), 
r IL Y — y-coordinatc of line (byte). 

rO address of byte following last byte in the buffer. 

a,x, y, rO 

ReadBackLine reads bytes direcdy from the background buffer and converts 
them into linear bitmap foraiat in the application's buffer. The buffer pointed to 
by DATA must be at least SC PIX WIDTH/7 = 80 bytes long. 




219 



ReadBlock 



ReadBlock (C64, cns) 



very low«level disk} 



Function: 
Parameters: 

Uses: 

Returns: 

Destroys: 

Description: 



Apple: 
Example: 



Very low-level read block from disk. 

rlL TRACK — valid track number (byte), 
rlH S ECTO R — valid sector on track (byte). 

r4 BUFFER — address of buffer of BLOCKSIZE bytes to read block into 
(word). 



curDrive 
curType 



currently active disk drive. 

GEOS 64 vl.3 and later, for detecting REU shadowing. 



error ($00 = no error). 



a, y. 



ReadBlock reads the block at the specified TRACK and SECTOR into 
BUFFER. If the disk is shadowed, ReadBlock will read from the shadow 
memory. ReadBlock is a pared down version of GetBlock. It expects the 
application to have already called EnterTurbo and InitForlO. By removing 
this overhead from GetBlock, multiple sector reads can be accomplished 
without the redundant initialization. This is exacdy what happens in many of the 
higher-level disk routines that read multiple blocks at once, such as ReadFile. 

ReadBlock is useful for multiple-sector disk operations where speed is an issue 
and the standard GEOS routines don't offer a decent solution. ReadBlock can 
function as the foundation of specialized, high-speed disk routines. 

Apple GEOS has no ReadBlock equivalent Use GetBlock instead. 



Read sector from disk into diskBlkBuf . 
very-low level disk primitives. 



Demonstrates use of 



Pass: 

track 
sector 

Returns: 

X 

MyGetBlock: 



track number 
sector on track 



error code 



99$: 



LoadW 


r4,«diskBlkBuf 


MoveB 


rlLrtrack 


MoveB 


rlH, sector 


jsr 


EnterTurbo 


txa 




bne 


99$ 


jsr 


InitForlO 


jsr 


ReadBlock 


jsr 


DoneWithIO 


rts 





; where to get data from 
; track number 
; sector number 
;go into turbo mode 
;set status flags 
/branch if error found 
/prepare for serial I/O 
/primitive read block 
/restore after I/O done 

/ exit 



See also: GetBlock, WriteBlock, VerWriteBlock. 



220 



■R eadBlook 



IReadByte (Apple, C64, cns) 



mid-level disk 



Function: Special version of ReadFile that allows reading a chained list of blocks a byte at 

a time- 
Parameters: on initial call only: 

r4 BLOCKBUF — pointer to temporary buffer of BLOCKSIZE bytes for 
use by ReadByte, usually a pointer to diskBlkBuf (Apple GEOS: must 
be in main memory) (woid). 
rS $0000 (word). 

Commodore: 

r 1 START^TRSC — track/sector of first data block (word). 
App le: 

rl INDXBLKPTR — pointer to index buffer that contains index block of 
chain to read (must be in main memory) (word). 



Uses: 



curDrive 

Commodore: 
curType 

Apple: 
RWbank 



GEOS 64 V 1.3 and later for detecting REU shadowing, 
bank BUFFER is in (MAIN or AUX). 



Returns: 



Destroys: 
Description: 



a byte returned 

X error ($00 = no error). 

rl, r4, rS contain internal values that must be preserved between calls to 
ReadByte. 



ReadByte allows a chain of blocks on the disk to be read a byte at a time. The 
first time ReadByte is called, rl, r4, and r5 must contain the proper 
parameters. When ReadByte returns without an error, tiic a register will contain 
a single byte of data fix^m the chain. To read another byte, call ReadByte again. 
Between calls to ReadByte, the application must preserve rl, r4, r5, and the 
data area pointed to by BLOCKBUF. Apple GEOS applications must also 
preserve the 512-byte index block pointed to by INDXBLKPTR and the status of 
RWbank. 

ReadByte loads a block into BLOCKBUF and returns a single byte from the 
buffer at each call. After returning die last byte in the buffer, ReadByte loads in 
the next block in the chain and starts again from the beginning of BLOCKBUF. 
This process continues until there are no more bytes in the file. A 
BFR OVERFLOW error is then returned. 



ReadByte is especially useful for displaying very large bitmaps with 
BitOtherCIip and NewBitOtherCIip. 



ReadBlock 



C64 & C128: Reading a chain a byte at a time under Commodore GEOS involves finding the 
first data block and passing its track/sector to ReadFile. The tracl^sector of the 
first data block in a sequential file is returned in rl by GetFHdrlnfo. TTie first 
data block of a VLIR record is contained in the VLIR^s index table. 

Apple: Because the ProDOS filing system is different from the Commodore filing 

system, different steps are involved in using ReadByte. The Apple GEOS 
version of GEOS expects an entire index block for the chain, not merely an initial 
track/sector as the Commodore version does. The index block for a sequential file 
is returned in rl by GetFHdrlnfo, but it must be loaded into memory with 
GetBIock. The index block for a VLIR record is contained in the VLIR's index 
table. 

Example: 

See also: GetFile, WriteFile, ReadRecord. 



ReadClock (Apple) 



clock driver 



Function: Causes the clock driver to update the global GEOS clock variables with the 
current time. Called during MainLoop Level by GEOS. 



Parameters: none. 

Returns: nothing. 

Alters: year 
month 
day 
hour 
minutes 
seconds 
alarmOn 



updated firom clock device 
updated firom clock device 
updated firom clock device 
updated from clock device 
updated firom clock device 
updated firom clock device 

if bit 7 set and time for alarm to trigger, then bit 7 is cleared 
and bit 6 is set (byte is shifted right once). 



Destroys: assume x, y, r0-rl5. 

Description: GEOS calls ReadClock during MainLoop Level. ReadClock is expected to 
update the global clock variables with the current time. It also checks for an alarm 
trigger and sets alarmOn appropriately. (Depending on the clock, an alarm 
trigger may be flagged automatically in hardware or may have be generated in 
sofD^are by comparing the current time with an internal alarm time.) 



See also: 



Clockint, SetTimeDate, SetAlarm, ResetAlarm. 



223 



neadCloek 



ReadFile (Apple, C64, ci28) 



mid-Ievel disk 



Function: 
Parameters: 



Uses: 



Read a chained list of blocks into memory, 

r7 BUFFER — pointer to buffer where data will be read into (word). 

r2 BUFSIZE — size of buffer Commodore version can read up to 32,258 
bytes (127 Commodore blocks); Apple version can read up to the 
maximum two-byte number that can be passed in r2: 65,535 ($ffff) bytes 
(word). 

CpmmpdQTg; 

rl START.TRSC— track/sector of first data block (word). 
Apple; 

r 1 INDXBLXDCK — block number of index block for chain (word). 
curDrive 



Cpmrnodore; 
curType 

Apple; 
RWbank 



GEOS 64 vl.3 and later for detecting REU shadowing, 
bank BUFFER is in (MAIN or AUX). 



Returns: x error ($00 = no error). 

r? pointer to last byte read into BL/FFfi? plus one. 

Commodore: 

rl if BFR^OVERFLOW error returned, contains the track/sector of the 
block that, had it been copied from diskBlkBuf to the application's 
buffer space, would have exceeded the size of BUFFER. The process of 
copying any extra data from diskBlkBuf to the end of BUFFER is left 
to the application. The data starts at diskBlkBuf+2. If no error, then rl 
is destroyed. 

rSL byte index into fileTrScTab of last entry (last entry = fileTrScTab 
plus value in rS). 

App le: 

r 1 if BFR_OVERFLOW error returned, contains the number of die block 
that would have overwritten the end of BUFFER had the entire block been 
read direcdy into memory. BUFFER is filled with as much data from the 
block as will fit. If no error, then rl is destroyed. 



Alters: Commodore: 

fileTrScTab As the chain is followed, the track/sector pointer to each 
block is added to die file track/sector table. The track and 
sector of the first data block is added at fiIeTrScTab+2 and 
fiIeTrScTab+3, respectively, because die first two bytes 
(fileTrScTab+0 and fileTrScTab+1) are reserved for the 
GEOS file header track/sector. 



Redi l Cluck 



Apple; 

INDEXBLOCKBUF index block for chain (in auxiliary memory; see 

below for information on accessing this buffer). 

Destroys: Apple: 

y, (rl), r3-r4 (see above for rl). 

CPTnmpdore; 

y, (rl), r2-r4 (see above for rl). 

Description: ReadFile reads a chain of blocks from the disk into memory at BUFFER. 

Although the name implies that it reads "files" into memory, it actually reads a 
chain of blocks and doesn't care whether this chain is a sequential file or a VLIR 
record — ReadFile merely reads blocks until it encounters the end of the chain 
or overflows the memory buffer. 

ReadFile can be used to load VLIR records from an unopened VLIR file. 
geoWrite, for example, loads different fonts while another VLIR file is open by 
looking at all the font file index tables and remembering the index information for 
records that contain font data. When a VLIR docimient file is open, geoWrite 
can load a different font by passing one of these saved values in rl to ReadFile. 
ReadFile will load the font into memory without disturbing the opened VLIR 
file. 

For reading a file when only the filename is known, use the high-level GetFile. 

C64 & C128: The Conimodore filing system links blocks together with track/sector links: each 
block has a two-byte track/sector forward-pointer to the next sector in the chain 
(or $00/$ff to signal the end). Reading a chain involves passing the first 
track/sector to ReadFile. The first block contains a pointer to the next block, and 
so on. The whole chain can be followed by reading successive blocks. 

ReadFile reads each 256-byte block into diskBlkBuf and copies the 254 data 
bytes (possibly less in the last block of the chain) to the BUFFER area and copies 
the two-byte track/sector pointer to flleTrScTab. This process is repeated until 
the last block is copied into the buffer or when there is more data in diskBlkBuf 
than there is room left in BUFFER. 

when there is more data in diskBlkBuf than there is room left in BUFFER, 
ReadFile returns with a BFR_OVERFLOW error without copying any data 
into BUFFER. The applicatioiTcan copy data, starting at diskBlkBuf+2, to fill 
the remainder of BUFFER manually. 

Because of the limited size of fileTrScTab (256 bytes), ReadFile cannot load 
more than 127 blocks of data. (256 total bytes divided by two bytes per 
track/sector minus two bytes for the GEOS file header equals 127.) 127 blocks 
can hold 127 * 254 = 32,258 bytes of data. 

Apple: Unlike die Commodore filing system, die ProDOS filing system links blocks 

together with entries in an index block: each entry in the index block holds a two- 
byte block number. Going through each entry constitutes walking die chain. For 



floadClook 



this reason, reading a chain involves passing, not the first data block, but the 
block number of the index block. 

Apple GEOS first reads the index block into the internal buffer 
INDEXBLOCKBUF (in auxiliary memory), then reads in the blocks specified 
in the index. 

Applications cannot direcdy access the auxiliary buffer INDEXBLOCKBUF. 
However, MoveAuxData can be used to copy the block into the appliciation's 
memory space if access to it is necessary: 



AUXtoMAIN 
MAINtoAUX 



%10000000 
%01000000 



LoadW rO, # INDEXBLOCKBUF 

LoadW rl, #diskBlkBuf 

LoadW r2, #BLOCKSIZE 

Ida #AUXtoMAIN 

jsr MoveAuxData 



;copy from index blk 
;to temp buffer 
;move a full block 
;copy aux to main 



Apple GEOS ReadFile could conceivably load up to 65,536 bytes of data into 
memory. This is of litde use, however, because the absence of large, usable 
memory blocks functionally limits reads to 32K or 64 blocks. 



Example: 
See also: 



GetFile, WriteFile, ReadRecord. 



R 9 adFil 9 



ReadLink (C64, ci28) 



very low-level disk 



isk] 



Function: 
Parameters: 

Uses: 

Returns: 

Alters: 

Destroys: 

Description: 



Apple: 

Example: 
See also: 



Read link (first two bytes) from a Commodore disk block 

rlL TRACK — valid track number (byte), 
r 1 H S ECTO R — valid sector on track (byte). 

r4 BUFFER — address of buffer of at least BLOCKSIZE bytes, usually 
points to diskBIkBuf (word). 

curDrive currently active disk drive. 

X error ($00 = no error). 

diskBIkBuf 

a, y. 

ReadLink returns the track/sector link from a disk block as the first two bytes in 
BUFFER. The remainder of BUFFER (BLOCKSIZE-2 bytes) may or may not 
be altered, 

ReadLink is useful for following a multiple-sector chain in order to build a 
track/sector table. It mainly of use on 1581 disk drives, which walk through a 
chain significantly faster when only the links are read. Routines such as 
DeleteFile and FollowChain will automatically take advantage of this 
capability of 1581 drives. 

Disk drives that do not offer any speed increase through ReadLink will simply 
perform a ReadBIock. 

Apple GEOS has no ReadLink equivalent; ProDOS blocks are linked by the 
index block. 



ReadBIock, FollowChain. 



Wore; Does *vo«a: isHI Oltr\jsnij (/S€ tt^/umiac^ 



ReadRecord 



ReadRecord (Apple, C64, ci28) 



VLIR disk 



Function: 
Parameters: 



Uses: 



Read in the current VLIR record. 

r7 BUFFER — pointer to start buffer where data will be read into (word), 
r2 BUFSIZE — size of buffer: Commodore version can read up to 32,258 
bytes (127 Commodore blocks); Apple version can read up to the 
maximum two-byte number that can be passed in r2: 65,535 ($ffff) bytes 
(word). 



curDrive 

curRecord 

fileHeader 

Commodorp; 
curType 

Apple; 
RWbank 



current record pointer 

index table holds first block of record 



GEOS 64 vl.3 and later, for detecting REU shadowing, 
bank RECDATA is read into (MAIN or AUX). 



Returns: 



Alters: 



X error ($(X) = no error). 

a $00 empty record, no data read. 

$ff = record contained data. 
r7 pointer to last byte read into BUFFER plus one if not an empty record, 

otherwise unchanged. 

ComPOdprp; 

rl if BFR OVERFLOW error returned, contains the track/sector of the 
block tfiat, had it been copied from diskBlkBuf to the application's 
buffer space, would have exceeded the size of BUFFER. The process of 
copying any extra data from diskBlkBuf to the end of BUFFER is left 
to the application. The data starts at diskBlkBuf+2. If no error, then rl 
is destroyed 



Apple; 
rl 



if BFR_0 VERFLOW error returned, contains the number of the block 
that would have overwritten the end of BUFFER had the entire block been 
read directly into memory. BUFFER is filled with as much data fix)m the 
block as will fit. If no error, then rl is destroyed. 



CpmmcKlorg; 
fileXrScTab 



As the chain blocks in the record is followed, the track/sector 
pointer of each block is added to the file track/sector table. 
The track and sector of the first block in the record is added 
at fiIeTrScTab+2 and fiIeTrScTab+3. Refer to 
ReadFile for more infOTmatibn. 



Destroys: Apple: 

y, (rl),r3-r4 (see above for rl). 



Commodore: 



228 



ReadRecord 



y, (rl), r2-r4 (sec above for rl). 

Description: ReadRecord reads the current record into memory at BUFFER. If the record 
contains more than BUFSIZE bytes of data, then a BFR_OVERFLOW error is 
returned. 

ReadRecord calls ReadFile to load the chain of blocks into memory. 

Example: 

See also: WriteRecord, ReadFile. 



229 



ReadScanLine 



ReadScanLine (Apple) 



graphics! 



Function: 

Parameters: 

Returns: 

Destroys: 

Description: 

Example: 



Translates a screen line on the foregorund screen from internal format to linear 
bitmap format 

rO DATA — address of buffer to copy data to (word), 
r IL Y — y-coordinatc of line (byte). 

rO address of byte following last byte in the buffer, 

a,x,y, rO 

ReadScanLine reads bytes direcdy from the foreground screen and converts 
them into linear bitmap format in the application's buffer. The buffer pointed to 
by DATA must be at least SC PIX WIDTH/7 = 80 bytes long. 



230 



RecoverAIIMe 



RecoverAllMenus (Apple, C64, cns) 



icon/menu 



Function: 

Parameters: 

Destroys: 

Description: 



Example: 
See Also: 



Removes all menus (including the main menu) from the foreground screen by 
recovering from the background buffer. 

none. 

assume r0-rl5, a, x, y 

RecoverAllMenus is a very low-level menu routine which recovers the area 
obscured by the opened menus from the background buffer. Usually this routine 
is only called internally by the higher-level menu routines. It is of little use in 
most applications and is included in the jump table mainly for historical reasons. 

RecoverAllMenus operates by loading the proper GEOS registers with the 
coordinates of the menu rectangles and calling the routine whose address is in 
recoverVector (normally RecoverRectangle) repeatedly. 



DoPreviousMenu, ReDoMenu, GotoFirstMenu, RecoverMenu. 



233 



RecoverFG 



ReCOVerFG (Apple) graphics/utiUty 



Function: Restores a portion of the foreground screen from data saved with SaveFG. 

Parameters: rO FGSTRUCT — pointer to an FG data structure (word). 

rl FGDATA — pointer to SaveFG data to restore (word). 

Returns: Foreground screen restored. 

Destroys: a, x, y, rl-r6. 

Description: RecoverFG restores a rectangular area of the foreground screen saved with 
SaveFG. 

FGSTRUCT points to an FG data structure, which is in the following format: 

FGSTROCTl : 

• word XI ; pixel x-position of left edge 

• byte Yl ; pixel y-position of top edge 

.word X2 ;pixel x-position of right edge (XI + WIDTH) 

.byte HEIGHT ;pixel height (Y2 - Yl) 

The FG data structure used to restore an area should be the same as the one used 
to save the area. 

Example: 

See also: SaveFG. 



234 



RecoverLine (Apple, C64, cns) 



graphics 



Function: 
Parameters: 

Returns: 
Destroys: 

Description: 

Note: 
128: 

Example: 
See also: 



Recovers a horizontal line from the background buffer to the foreground screen. 

r3 XI — x-coordinate of leftmost cndpoint (word). 
r4 X2 — x-coordinate of rightmost endpoint (word). 
rllL Yl — y-coordinate of line (byte). 

where (X1,Y1) and (X2,Y1) define the endpoints of the line to recover. 

nothing 

Commodore 
a, x, y, r5-r8 

Applg 
a, X, y 

RecoverLine recovers the pixels which fall on the horizontal line whose 
coordinates are passed in the GEOS registers. The pixel values are copied from 
the background buffer to the foreground screen. 

The flags in dispBufferOn are ignored; the pixels are always copied to the 
foreground screen regardless of the value in this variable. 

Under GEOS 128, oring DOUBLE W into theXi andX2 parameters will 
automatically double the x-position in SD-column mode. Or*ing in ADDl W will 
automatically add 1 to a doubled x-position. (Refer to "GEOS 128 X-posiuon and 
Bitmap Doubling" in Chapter.® gr@ for more information.) 



ImprintLine, HorizontalLine, InvertLine^VerticalLine , DrawLine. 



RecoverMenu 



RecoverMenu (Apple, C64, cns) 



icon/menu 



Function: Removes the current menu from the foreground screen by recovering from the 
background buffer. 

Parameters: none. 

Destroys: assume r0-rl5, a, x, y 



Description: 



RecoverMenu is a very low-level menu routine which recovers the rectangular 
area obscured by the current menu. Usually this routine is only called internally 
by the higher-level menu routines such as DoPreviousMenu. It is of little use 
in most applications and is included in the jump table mainly for historical 
reasons. 



RecoverMenu operates by loading the proper GEOS registers with the 
coordinates of the current menu's rectangle and calling the routine pointed to by 
recoverVector (normally RecoverRectangle). 

Example: 

See Also: DoPreviousMenu, ReDoMenu, GotoFirstMenu, RecoverAllMenus. 



Recover Rectan^e 



RecoveriRectangle^ i Recoveif^ectangle (Apple, C64, ci28) graphkTI 

Function: Recovers the pixels within a rectangular region fSrom the background buffer to the 
foreground screen. 

Parameters: Normal: 

r3 XI — x-coordinate of upper-left (word). 
r2L Y 1 — y-coordinate of upper-left (byte). 
r4 X2 — x-coordinate of lower-right (word). 
r2H Y2 — y-coordinateof lower-right (byte). 

Inline: 

data appears immediately after the jsr i_RecoverRectangIe 
.byte Yl y-coordinate of upper-left. " 
.byte Y2 y-coordinate of lower-right 
.word XI x-coordinate of upper-left 
.word X2 x-coordinate of lower-right 

where (XI, Yl ) is the upper-left corner of the rectangular area and (X2,Y2) is the 
lower-right corner. 

Returns: r2, r3, and r4 unchanged. 

Destroys: Commodore: 

a, X, y, r5-r8, rllL 

Appig; 

a, X, y, rllL 

« 

Description: RecoverRectangle copies the pixels within a rectangular region from the 
background buffer to the foreground screen by calling RecoverLine in a loop. 

Note: The flags in dispBufferOn are ignored; the pixels are always copied to the 

foreground screen regardless of the value in this variable. 

128: Under GEOS 128, orlng DOUBLE W into theX7 andX2 parameters will 

automatically double the x-position in SD-column nxxie. (Dr'ing in ADDl W will 
automatically add 1 to a doubled x-position. (Refer to "GEOS 128 X-posi'Hon and 
Bitmap Doubling" in Chapter.® gr@ for more information.) 

Example: 



See also: 



ImprintRectangle, Rectangle, InvertRectangle. 



RecoverSysRam 



RecoverSysRam (Apple) int^^ 

Function: Restores the system state after a call to InitForDialog. 
Parameters: none. 

Returns: system restored to its prior state. 
Destroys: a,x, y, rl, r2, r3Ly r4. 

Description: RecoverSysRam restores the state of GEOS that was saved with 
InitForDialog. 

See also: InitForDialog. 



238 



RaadScgnl Ine- 



[Rectangle, i Rectangle (Apple, C64, cns) graphics! 



Function: 
Parameters: 



Uses: 



Returns: 
Destroys: 



Description: 



Note: 



Draw a rectangle in the current fill pattern. 
Normal: 

r3 XI — x-coordinate of upper-left (word). 
r2L Yl — y-coordinate of upper-left (byte). 
r4 X2 — x-coordinate of lower-right (word). 
r2H Y2 — y-coordinate of lower-right (byte). 

where (XI, Yl ) is the upper-left corner of the rectangle and (X2,Y2) is the lower- 
right corner. 

Inline: 

data appears immediately after the jsr i^Rectangle 
.byte Yl y-coordinate of upper-left 
.byte Y2 y-coordinate of lower-right, 
.word X 1 x-coordinate of upper-left 
.word X2 x-coordinate of lower-right 

dispBufferOn: 

bit 7 — write to foreground screen if set. 
bit 6 — write to background screen if set 

nothing 

Commodore: 
a, X, y, r5-r8 

Apple: 
a, x, y 

Rectangle draws a filled rectangle on the screen as determined by the 
coordinates of the upper-left and lower-right comers. The rectangle is filled with 
the current 8x8 (card-sized) fill pattern. 

The 8x8 pattern within the rectangle is drawn as if it were aligned to a card 
boundary: that is, the bit-pattem is synchronized with (0,0), and, since the 
patterns are 8x8, they are aligned with every eighth pixel thereafter. This allows 
the patterns in adjacent or overlapping rectangles to line-up regardless of the 
actual pixel positions. 

Rectangle operates by calling HorizontalLine in a loop, changing the bit- 
pattem byte after every line based on the current 8x8 fill pattern. 

Because all GEOS coordinates are inclusive, framing a filled rectangle requires 
either calling FrameRectangle after calling Rectangle (and thereby 
overwriting the perimeter of the filled area) or calling FrameRectangle with 
(Xi-l,y7-l) and (X2+l,y2+l) as the comer points. 



128: 



Under GEOS 128, or'ing DOUBLE W into theX7 andX2 parameters will 
automatically double the x-position in ^D-column mode. Or'ing in ADD1_W will 



irgaBScaTTfcfne- 



automaticaUy add 1 to a doubled x-position. (Refer to "GEOS 128 X-position and 
Bitmap Doubling • in Chapter.@gr@ for more information.) 

See also: FrameRectangle, SetPattern. ImprintRectangle. RecoverRectangle 
InvertRectangle. * ' 



ReDoMenu 



ReDoMenu (Apple, C64, ci28) 



icon/menu 



Function: 
Parameters: none 
Destroys: 
Description 



Reactivate menus at the current level. 



Example: 
See Also: 



assume r0-rl5, a, x, y 



ReDoMenu is used by the application's menu event handler to instruct GEOS to 
leave all menus (including the current menu) open when control is returned to 
MainLoop. menuNumber is unchanged. Keeping the current menu open 
allows anotiier selection to be made immediately. 

ReDoMenu will redraw the current menu. If menu event routine changes the text 
in the menu (adding a selection asterisk, for example), a call to ReDoMenu will 
redraw the menu with the new text wliile leaving the menu open for another 
selection. 



DoMenu, GotoFirstMenu, DoPreviousMenu. 



239 



RenameFile 



RenameFile (Apple, C64, ci28) 



high-level disk| 



Function: 
Parameters: 

Uses: 



Returns: 
Alters: 



Destroys: 



Renames a file that is in the current directory. 
r6 
rO 



OLDNAME — pointer to null-terminated name of file as it appean on the 
disk (Apple GEOS: must be in main memory) (word). 
NEWNAME — pointer to new null-terminated name (Apple GEOS: must 
be in main memory) (word). 



curDrive 

Commodore: 
curType 

Apple: 

curVBlknot 

VBMchangedt 

numVBMBlkst 



GEOS 64 vl.3 and later, for detecting REU shadowing. 



used by VBM cacheing routines, 
used by VBM cacheing routines, 
used by VBM cacheing routines. 



^used internally by GEOS disk routines: applications generally don't use. 
X error ($00 = no error). 



diskBlkBuf 
dirEntryBuf 

ComnKxlore: 
curDirHead 
dirlHeadt 
dirSHeadt 

Apple; 

curVBlkno^ 
VBMchangedt 



used for temporary block storage, 
old directory entry. 



BAM updated to reflect newly freed blocks. 
(BAM for 1571 and 1581,drives only) 
(BAM for 1581 drive only) 



used by VBM cacheing routines. 

set to FALSE by VBM cacheing routines to indicate cached 
VBM block has already been flushed 



^used internally by GEOS disk routines; applications generally don't use. 
a, y, rl, r4-r6. 



Description: RenameFile searches the current directory for OLDFILE and changes the name 
string in the directory entry to NEWFILE. 

RenameFile first calls FindFile to get the directory entry and ensure the 
OLDFILE does in fact exist. (If it doesn't exist, a FILE_NOT_FOUND error 
is returned.) 

The directory entry is read in, the new file name is copied over the old file name, 
and the directory entry is rewritten. The date stamp of the file is not changed, but 
the modification date stamp of the directory (Apple GEOS only) is updated. 



240 



RenameFile 



When using GetlstDirEntry and GetNextDirEntry to establish the old file 
name, do not pass RenameFile a pointer into diskBlkBuf. Copy the file name 
from diskBlkBuf to another buffer (such as dirEntryBuf) and pass FreeFile 
the pointer to that buffer. Otherwise when FreeFile uses diskBlkBuf it will 
corrupt the file name. . 

C64 & C128: Since Conirnodorc GEOS does not support a hierarchical file system, the "current 
directory" is actually the entire disk. The call to FindFile also reads the BAM in 
from disk. 

Apple: Will only rename a file in the current directory. To rename a file from another 

directory, the application must change directories (refer to GoDirectory for 
moving to another directory). 

Example: 

See also: DeleteDir, FreeDir, FreeFile, FreeBlock. 



241 



ReOpenDisk 



IReOpenPisk (AppieT 



high-level disk| 



Function: 

Parameters: 

Uses: 

Returns: 

Alters: 



Reopen a disk to the most recent directory. 



Destroys: 
Description: 



Note: 



Example: 
See also: 



none 

curDrive 

curDirTabLo 

curDirTabHi 



drive that disk is in. 
last current directory, 
last current directory. 



X error ($00 = no error). 

rS pointer to disk name buffer as returned from GetPtrCurDkNm. This is 
a pointer to one of the Dr;cCurDkNm arrays. 



DrxCurDkNm 
curDirHead 
curKBIkno 
sysDirBlkno 



totNumBlkst 

pathnameBur 

curVBIknot 

numVBMBIkst 

VBMchangedt 



current disk name array contains disk name. 

current directory header. 

block number of current directory's key block. 

block number of /SYSTEM directory. If system directory 

not found on disk, then this number is block of the root 

directory. 

total number of blocks in volume, 
set to last logged directory, 
block currently cached, 
number of VBM blocks on disk, 
set to FALSE. 



^used internally by GEOS disk routines; applications generally don't use. 
a, y, r0-r2, r4. 

ReOpenDisk reopens a disk to its current directory (for each drive, GEOS 
keeps track of the block of the current directory).. ReOpenDisk allows an 
application to quickly switch back and forth between files on different drives, as 
is often the case when an application and its data are on different disks. It saves 
the application from calling GoDirectory every time drives are changed. It 
otherwise performs the same initialization as OpenDisk. 

ReOpenDisk assumes the user has not switched disks since the last time the 
drive was accessed. If a new disk is placed in the drive, the current directory 
block number associated with the drive will no longer be valid The application 
may want remember the volume name when first opening the disk and then 
compare the volume name after each call to ReOpenDisk with the original. If 
they match, its a fairly safe assumption that the disk has not changed. 

Because GEOS uses the same allocation and file buffers for each drive, it is 
important to close all files and update tiie VBM (calling PutVBM if necessary) 
before accessing another disk. 



OpenDisk, SetDevice. 



242 



ResetAlarm 



ResetAlarm (Apple) dock dmerl 



Function: Qock driver routine to disable the alamx 

Parameters: none. 

Returns: nothing. 

Alters: alarmOn $00 

Destroys: assume a, x, y, r0-rl5. 

Description: ResetSetAlarm is a clock driver routine for disabling an alarm. 

See also: SetAlarm, SetTimeDate, Ciockint, ReadCIock. 



CGNrtBE!NTt4L 



243 



ResetHandle 



ResetHandle (C64, cns) internal I 



Function: Internal routine used during the GEOS boot process. 
Parameters: none. 
Returns: does not return. 

Description: ResetHandle is only used during the GEOS boot process. It is not useful to 
applications and is documented here only because it exists in the jump table. 

See also: BootGEOS. 



244 



This page intentionally left blank to maintain right/left (verso/recto) 
page ordering. Final version will correct this. 



RestartProcess 



RestartProcess (Apple, C64, ci28) proccssi 



Function: Reset a process's timer to its starting value then unblock and unfreeze the 
process. 

Parameters: x PROCESS — process to restart (0 - n-1, where n is the number of 

processes in the table) dbytc). 

Returns: x unchanged 

Destroys: a 

Description: RestartProcess sets a process's countdown timer to its initialization value then 
unblocks and unfreezes it Use RestartProcess to initallj^ start a process after a 
call to InitProcesses or to rewind a process to the beginning of its cycle. 

Note: RestartProcess clears the runable flag associated with the process, thereby 

losing any pending call to the process. 

RestartProcess should always be used to start a process for the first time 
because InitProcesses leaves Ae value of the countdown timer in an unknown 
state. 

Example: 

See also: InitProcesses, EnableProcess, UnfreezeProcess, UnblockProcess. 



244 



RestoreFontPata (Apple) 



RestoreFontData 



text 



Function: 

Parameters: 

Returns: 

Destroys: 
Description: 

Example: 
See also: 



Restore internal font data from saveFontTab, 
none. 

curHeight 

baselineOffset 

cardDataPntr 

curlndexTable 

curSetWidth 

a, X. 

RestoreFontData reverses the effect of SaveFontData by restoring the 
internal font variables from saveFontTab. 



SaveFontData. 



245 



RstrAppI 



RstrAppI (Apple, C64, C128) 

Function: Standard desk accessory return to application. 

Parameters: none. 

Uses: curDrive. 

Returns: never retutrns to desk accessory. 

Description: A desk accessory calls RstrAppI when it wants to return control to the 
application that called it. RstrAppI loads the swapped area of memory from the 
SWAP FILE, restores the saved state of the system from the internal buffer, 
resets the stack pointer to its original position, and returns control to the 
application. 

It is the job of the desk accessory to ensure that if the current drive (curDrive) is 
changed that it be returned to its original value so that RstrAppI can And 
SWAP FILE. Under Apple GEOS it is not necessary to save the current 
directory. 

Note: If a disk error occurs when reading in SWAP FILE, the remainder of the 

context switch (restoring the state of the system, etc.) is bypassed and control is 
immediately returned to the caller of the desk accessory. The application will have 
only a moderate chance to recover, however, because the area of memory that the 
desk accessory overlayed may very well include the area where the jsr to 
GetFile or LdDeskAcc resides. The return, therefore, may end up in the 
middle of desk accessory code. 

Example: 

See also: StartAppl, GetFile. 



high-level disk 



246 



RstrFrmDialog 



RstrFrmPialog (Apple, C64, cns) dialog box| 

Function: Exits from a dialog box, restoring the system to the state prior to the call to 
DoDlgBox. 

Parameters: none. 

Returns: Returns to point where DoDlgBox was called. System context is restored. ROL 
contains sysDBData return value. 

Uses: sysDBData. 

Destroys: assume a, x, y, rOH-rlS 

Description: RstrFrmDialog allows a custom dialog box routine to exit from the a dialog 
box. RstrFrmDialog is typically called internally by the GEOS system icon 
dialog box routines. However, it may be called by any dialog box routine to force 
an immediate exit 

RstrFrmDialog first restores the GEOS system state (context restore) and then 
calls indirecdy through recoverVector to remove the dialog box rectangle firom 
the screen. The routine in recoverVector is called with the r2-r4 loaded for a 
call to RecoverRectangle. By default recoverVector points to 
RecoverRectangle, which will automatically recover the foreground screen 
from the background buffer. However, if the application is using background 
buffer for data, it will need to intercept the recover by placing the address of its 
own recover routine in recoverVector. If there is no shadow on the dialog box, 
then recoverVector is only called through once with r2-r4 holding the 
coordinates of the dialog box rectangle. However, if the dialog box has a 
shadow, then recoverVector will be called through two ♦imes: first for the 
patterned shadow rectangel and second for the dialog box rectangle. The 
application may want to special-case these two recovers when recovering. 

If recoverOnce is set to TRUE, RstrFrmDialog will only call through 
recoverVector once as if there were no shadow box (even if there is one). 
RstrFrmDialog automatically calls RestoreSysRam. 

RstrFrmDialog restores the sp register to value it contained at the call to 
DoDlgBox just before returning. This allows RstrFrmDialog to be called witii 
an arbitrary amount of data on top of the stack (as would be the case if called from 
within a subroutine). GEOS will restore the stack pointer properly. 



DoDlgBox, InitForDialog, RestoreSysRam, RecoverRectangle, 
RestoreFG. 




247 



Apple: 
Note: 

Example: 
See also: 



SaveFG (Apple) 



graphics/utility I 



Function: Saves a portion of the foreground screen to a buffer. 

Parameters: rO FGSTRUCT — pointer to an FG data structure (word). 

rl FGBUF — pointer to buffer to place foreground data (word). 

Returns: Buffer pointed to by FGBUF contains foreground data in a form that 
RestoreFG can restore. 

Destroys: a,x, y, rl-r6. 

Description: SaveFG saves a rectangular area of the foreground screen to a temporary buffer. 

This buffer can later be restored to the foreground screen with RestoreFG. The 
SaveFG and RestoreFG duo allow the application to save and restore areas of 
the foreground screen without imprinting them to the background buffer. This 
capability lets the application use the background buffer for data while still using 
dialog boxes and menus, which depend on recovering from the background 
buffer. The application need only saveFG the proper areas of the screen prior to 
putting up a dialog box or letting a menu drop, patch into recoverVector, and 
RestoreFG as necessary. 

FGSTRUCT points to an FG data structure, which is in the following format: 

.word XI ;pixelx-position of left edge 

.byte Yl ;pixel y-position of top edge 

.word X2 ;pixel x-position of right edge (XI + WIDTH) 

.byte HEIGHT ;pixel height (Y2 - Yl) 



The amount of data stored into the buffer at FGBUF depends on die size of the 
saved region. The following relationship applies: 

bufBytes = HEIGHT ♦ (Xl/7 - X2/7 +1) 

Most GEOS applications will reserve 5,712 bytes for the save buffer, which will 
hold the largest standard dialog box or about three levels of submenus. 

Note: It is useful to set recoverOnce to TRUE when using SaveFG, which will 

cause dialog boxes witii shadows to only call through recoverVector once, 
rather than the noraial twice. 

Example: 

See also: RecoverFG. 



246 



SaveFile 



SaveFile (Apple, C64, cns) 



high-level diskj 



Function: 
Parameters: 



Uses: 



General purpose save file routine that will create a GEOS sequential file and save 
a region of memory to it or create an empty GEOS VLIR file. 

r9 HEADER — pointer to GEOS file header for file. The first two bytes of 
the file header point to the filename (word). 

rlOL DIRPAGE — GEOS directory page to begin searching for fiee directory 
slot; each directory page holds eight files and corresponds to one 
notepad page on the GEOS deskTop. The first page is page one. 



curDrive 

year, month, day, hours, minutes 



for date-stamping file. 



Commodore: 

curType 

interleave^ 



GEOS 64 vl.3 and later for detecting REU shadowing, 
desired physical sector interleave (usually 8);. applications 
need not set this explicitly — will be set automatically by 
internal GEOS routines. 



Returns: 



Alters: 



Apple; 
RWbank 

curKBlkno 
curVBlknot 
VBMchangedt 
numVBMBikst 



source bank for sequential data and HEADER (MAIN or 
AUX). 

current directory, 
used by VBM cacheing routines, 
used by VBM cacheing routines, 
used by VBM cacheing routines. 



^used internally by GEOS disk routines; applications generally don't use. 
X error ($00 = no error). 

r9 pointer to fileHeader, which contains file header block as written to 
disk. 

Commpdorg; 

r6 pointer to fileTrScTab, which contains track/sector table for the file. 



dirEntryBuf 
diskBlkBuf 
curDirHead 

Commodore: 
fileTrScTab 



dir2Headt 
dir3Headt 



contains newly-built directory entry. 

used for temporary storage. 

this buffer contains die current directory header. 



Contains track/sector table for file as returned from 
BlkAUoc. The track and sector of the file header block is at 
fileTrScTab+O and fileTrScTab+1. The end of the table 
is marked with a track value of $00. 
(BAM for 1571 and 1581 drives only) 
(BAM for 1581 drive only) 



Applg: 



247 



SaveFile 



INDEXBLOCKBUFt index block for chain as created by BlkAlloc (in 

auxiliary memory; see BlkAlloc for information on 
accessing it). 

^used internally by GEOS disk routines; applications generally don't use. 

Destroys: Commodore: 
a, y, r0-r8. 



Apple: 

a, y, rl-r8. 

Description: SaveFile is the most general -pupose write data type routine in GEOS. It creates 
a new file, either sequential or VLIR. If the file is a sequential file, it will write 
out the range of memory specified in the header to disk. If the file is a VLIR file, 
it will create an empty file (just a file header and an index table; all records in the 
index table are marked as unused). 

Not only does the file header pointed to by HEADER act as a prototype for the 
file, it also holds all the information needed to create the file. This includes the file 
type (SEQ or VLIR) and other pertinent information, such as the start and end 
address, which are used when creating a sequential file. The file header pointed to 
by HEADER has one element, however, that is changed before it is written to 
disk: the first word of the fileheader points to a null-terminated filename string. 
SaveFile patches this word in its own copy in fileHeader before it is written to 
disk. 

SaveFile calls SetGDirEntry and BlkAlloc to construct the basic elements of 
the file, then calls WriteFile to put die data into it. After the file is written, the 
BAMA^BM is written to disk (PutDirHead under Commodore GEOS; 
PutVBM under Apple GEOS.) 

Example: 



See also: GetFile, GpenRecordFile. 



248 



SaveFontData 



SaveFontPata (Apple) 



text! 



Function: 
Parameters: 
Returns: 
Uses: 



Destroys: 
Description: 

See also: 
Example: 



Save internal font data to saveFontTab. 

none. 

nothing. 

curHeight 

baselineOffset 

cardDataPntr 

curlndexTable 

curSetWidth 

a, X. 

SaveFontData saves the internal font variables to the area at saveFontTab. 
This allows a font to be temporarily changed and then restored. saveFontTab is 
FONTLEN bytes long. 

RestoreFontData. 



249 



SetAlarm 



SetAlarm (Apple) 



clock driver 



Function: Qock driver routine to set the clock's alarm time. 

Parameters: rOL HOUR — hour (0-23) (byte), 

rOH MINUTE — minute (0-59) (byte). 

Returns: nothing. 

Alters: alarmOn %10000000 (alarm enabled but not triggered). 

Destroys: assume a, x, y, r0-rl5. 

Description: SetAlarm is a clock driver routine for setting a new alarm time. Most clock 
drivers do no error checking on the parameters and expect valid values. 

Note: To be sure the alarm is triggered correcdy, disable interrupts around the call to 

SetAlarm. 

See also: ResetAIarm, SetTimeDate, Clocklnt, ReadClock. 



250 



SetDevice 



SetDevice (C64, cns) 



high'level disk| 



Function: 
Parameters: 

Uses: 

Returns: 

Alters: 

Destroys: 
Description: 



Note: 



Establish communication with a new peripheral (disk or printer). 

a DEVNUM — DRIVE^A through DRIVE D for disk drives, 
PRINTER for serial pnhtcr, or any other valid serial device bus 
address (byte). 

curDevice currcndy active device. 

X error ($00 = no error). 



curDevice 

curDrive 

curType 



a. y. 



new current device number. 

new current drivcnumber if device is a disk drive. 

GEOS vl.3 and later: current drive type (copied from 

driveType table). 



SetDevice changes the currcndy active Commodore device and is used primarily 
to switch from one disk drive to another. SetDevice also allows a printer driver 
to gain access to the serial bus. 

Each I/O device has an associated device number that distinguishes its I/O from 
the I/O of other devices. At any given time only one device is active. The active 
device is called the current device and to change the current device an application 
calls SetDevice. 

Because SetDevice was originally designed to switch between serial bus 
devices, DEVN^Af reflects the architecture of Commodore serial bus: disk drives 
arc numbered 8 through 1 1 and the printer is numbered 4. However, not all I/O 
devices are actual serial bus peripherals. A RAMdisk, for example, uses a special 
device driver to make a cartridge port RAM-expansion unit emukte a Commodore 
disk drive. SetDevice switches between these devices just as if they were daisy- 
chained off of the serial bus. 

Commodore GEOS up through vl.2 supports two disk devices, DRIVE A and 
DRIVE B. Commodore GEOS vl.3 and later supports up to four disk devices, 
DRIVE^A through DRIVE^D, within the Kemal disk routiines but not from the 
dcskTopT (The current version of the deskTop will never pass numDrives with 
a value greater than two.) GEOS always addresses the first drive as DRIVE^A, 
the second as DRIVE_B, and so on regardless of the physical device settings? 

Because most printers attach to the Commodore through the serial port, printer 
drivers wUl call SetDevice with a DEVNUM value of PRINTER to make the 
printer the active device. 

SetDevice calls ExitTurbo to ensure that the old device is no longer actively 
sensing the serial bus then rearranges the device drivers as necessary to make the 
new device {DEVNUM) the current device. Witii more than one type of device 
attached (e.g., a 1541 and a 1571), Commodore GEOS must switch the internal 
device drivers, making die the driver for die selected device active. GEOS stores 



251 



SetDevice 



inactive device drivers in the Conunodore 128 back RAM and in special system 
areas in an REU. For these reasons it is important that Commodore GEOS 
applications use SetDevice to change the active device. An application should 
never direcdy modify curDrive or curDevice. 

Apple: SetDevice does not exist in Apple GEOS because die task of switching between 

devices is not complicated by daisy-chained I/O devices and inactive device 
drivers (as it is on the Commodore computers). To specify a new disk drive, 
store the new drive number diiecdy into curDrive. 

To make porting disk routines easier, the following Apple equivalent of 
SetDevice can be used: 

.if (APPLE) /Apple GEOS SetDevice equivalent 

SetDevice: 

sta curDrive ;make the requested drive current 

Idx #NO_ERROR ;and return a good status 

rts 

•endif 

See also: OpenDisk, ChangeDiskDevice. 



252 



9 



SetGDirEntry (Apple, C64, cus) 



mid-levd disk 



Function: Builds a system specific directory entry from a GEOS file header, date-stamps it, 
and writes it out to the current directory. Apple GEOS version will also create and 
write out subdirectories. 

Parameters: rlOL DIRPAGE — directory page to begin searching for free slot; each 

directory page holds eight files and corresponds to one notepad page on 
the GEOS deskTop. The first page is page one. 

r2 NUMBLOCKS — number of blocks in file (word). 

r6 TSTABLE — pointer to a track/sector list of unused blocks (unused but 

allocated in the BAM), usually a pointer to fileTrScTab; BlkAUoc 

can be used to build such a list (word). 
r9 FILEHDR — pointer to GEOS file header (word). 



Apple; 

r2 NUMBLOCKS — number of blocks in file or $(XXX) to create a 

subdirectory (word). 
r6 INDXBLK — If creating a file: block number of sequential-file index 

block or VLIR master index block. If creating a subdirectory: key block 

of subdirectory (word). 
r7 FILEB YTES — number of bytes in file (word). 
r8 HDBLKNUM — block number of this file's header block (word). 
r9 FILEHDR — if creating a file, pointer to GEOS file header, if creating a 

subdirectory, pointer to 16-character max. null-terminated name for 

subdirectory (16 characters including NULL) (must be in main 

memory) (word). 



Uses: 



curDrive 

year, month, day, hours, minutes 



for date-stamping file. 



curType 

curDirHead 

dir2Headt 

dir3Headt 

interleave^ 



GEOS 64 vl.3 and later, for detecting REU shadowing, 
this buffer must contain die current d^ectory header. 
(BAM for 1571 and 1581 drives only) 
(BAM for 1581 drive only) 

desired physical sector interleave (usually 8);. applications 
need not set this explicitiy — will be set automatically by 
internal GEOS routines. Only used when new directory 
block is allocated 



Returns: 



Apple: 

curKBIkno 
curVBlknot 
VBMchanged^ 
numVBMBlkst 



cunent directory, 
used by VBM cacheing routines, 
used by VBM cacheing routines, 
used by VBM cacheing routines. 



^used internally by GEOS disk routines; applications generally don't use. 
X error ($(X) = no error). 



253 



SetGDIrEntry 



Commodore: 

r6 pointer to first non-reserved block in track/sector table (SetGDIrEntry 
reserves.one block for the file header and a second block for the index 
table if the file is a VLIR file). 



Appig; 
rl 

rlOL 
rlOH 



block number that directory entry was added to. 
directory page actually used. 

unused directory entry within block in diskBIkBuf. There are 13 
directory entries per ProDOS block, numbered 1-13. 



Alters: 



Destroys: 



dirEntryBuf 
diskBIkBuf 

Commodore: 

a, y, rO-rS, r7-r8. 



contains newly-built directory entry, 
used for temporary storage of the directory block. 



Commodore: 

a, y, rl, r3-r5, r7-r8. 

Description: SetGDirEntry calls BIdGDirEntry to build a system specific directory entry 
form the GEOS file header, date-stamps the directory entry, calls 
GetFreeDirBlk to find an empty directory slot, and writes the new directory 
entry out to disk. The Apple version of SetGDirEntry can also be used to create 
subdirectory entries by passing a NUMBLOCKS value of $0000. 

Most applications will create new files by calling SaveFile and new 
subdirectories by calling MakeSubDir. Both these routines call SetGDirEntry 
as part of their normal processing. 



Example: 
See also: 



BIdGDirEntry . 



254 



SetGEOSDisk 



SetGEOSDisk (C64, cns) 



high-level disk] 



Function: 



Convert Commodore disk to GEOS format. 



Parameters: none. 



Uses: 

Returns: 
Alters: 



curDrive 
curType 



GEOS 64 vl.3 and later for detecting REU shadowing, 
error ($00 = no error). 



curDirHead directory header is read from disk. 
dir2Headt (BAM for 1571 and 1581 drives only) 

dir3Headt (BAM for 1581 drive only) 



Destroys: a, y, rOL, rl, r4-r5. 



Description: 



Apple: 
Example: 
See also: 



SetGEOSDisk converts a standard Commodore disk tinto GEOS format by 
writing the GEOS ID string to the directory header (at OFF^GEOS ID) and 
creating an off-page directory block. An application can call SetGEOSCisk after 
OpenDisk returns the isGEOS flag set to FALSE. Typically the user is 
prompted before the conversion. 

SetGEOSDisk expects the disk to have been previously opened with 
OpenDisk. It first calls GetDirHead to read the directory header into memory 
then calls CalcBlksFree to to see if there is block available for the off-page 
directory (if there isn't, an INSUFFICIENT^SPACE error is returned). 
SetNextFree is then called to allocate the off-page directory block. The off-page 
directory block is written with empty directory entries and a pointer to it is placed 
in the directory header (at OFF^OP TR SC). Finally PutDirHead is called to 
write out the new BAM and directoryTieader. 

All ProDOS disks are already GEOS compatible. 



ChkDkGEOS. 



255 



SetLdVars 



SetLdVars (Apple) 



mid-level disk I 



Function: 
Parameters: 



Sets the internal "Ld" variables (those used by LdAppI, LdDeskAcc, and 
LdFile). 

rOL LOAD.OPT: 

bitO: load at address specified in file header, application will be 
started autmadcally 
1 load at address in r7; application will not be started 
automatically, 
bit?: not passing a data file. 

1 r2 and r3 contain pointers to disk and data file names, 
bit 6: not printing data file. 

printing data file; application should print file and exit 
r7 LOAD.ADDR — optional load address, only used if bit of 

LOADJ)PT is set (word). 
r2 DATA^DISK — only valid if bit 7 or bit 6 oiWADJ)PT is set: pointer 
to name of the disk tiiat contains the data file, usually a pointer to one of 
the DrxCurDkNm buffers (word). 

DATA^FILE — only valid if bit 7 or bit 6 olLOADJ)PT is set: pointer 
to name of the data file (word). 
RECVR^OPTS (byte). 



Returns: 

Destroys: 

Description: 

Note: 



r3 

rlOL 

nothing. 



SetLdVars sets the internal load variables from GEOS pseudoregisters. 
GetFile, LdApplic, LdDeskAcc, and LdFile call SetLdVars as necessary. 
Most applications will not need to call it direcdy. 

LdDeskAcc does not properly set the internal "Ld** variables when it is called 
direcdy (as opposed to indirecdy through GetFile, in which case the variables 
are set properly). SetLdVars may be used to properly set the internal "Ld" 
variables prior to calling LdDeskAcc. 



See also: GetLdVars. 



256 



COKTIDCNTIAL 



SetMode 



SetMode (Apple) 



printer driver | 



Function: Set printer mode. 

Parameters: rO-r2L MODE — flags for possible printer modes and capabilities (five bytes). 
Returns: x STATUS — printer error code; $00 = no eiror (byte) 
Destroys: assume r0-r4. 

Description: SetMode allows an application to access special printer capabilities. Features are 
selected through five MODE bytes. The bits in the MODE bytes correspond to the 
list of available features returned by GetMode. 

SetMode operates intelligently. It first compares the requested MODE setting 
against the current state of the printer. If a bit setting is different and the driver 
supports the associated feature, then the proper codes are sent to the printer to 
establish the new mode. 

TheA/OPgVaiyes; 



bit 


description 


b7 


^underiine. 


b6 


tbold. 


b5 


reverse. 


M 


^italic. 


b3 


outline. 


b2 


tsuoerscript 


bl 


^subscript 


bO 


reserved for future use. 


(text density selection) 
bit description 


b7 


^pica type (10 cpi). 


b6 


^elite type (12 cpi). 


b5 


^condensed type (16 cpi). 


b4 


^proportional type. 


b3 


^double heishL 


b2 


^f-heisht 


bl 


^eisht lines per inch vertical density. 


bO 


^six lines per inch vertical density. 



rOH: 



rlL: 



(miscellaneous features) 
bit description 



257 



SetMode 



b7 


print red or masenta. 


b6 


print yellow. 


b5 


print blue or cyan. 


M 


^expanded (double-widih) type. 


b3 


^NLO (near letter quality) type. 


b2 


reserved for future use. 


bl 


reserved for future use. 


bO 


reserved for future use. 


(internal font selection) 
bit description 


b7 


font?. 


b6 


font 6. 


b5 


fonts. 


b4 


font 4. 


b3 


font 3. 


b2 


font 2 (Roman?). 


bl 


font 1 (Helvetica?). 


bO 


font (Courier?). 


(hoTizontal graphics density selection) 
bit description 


b7 


60 dpi. 


b6 


^SOdpi. 


b5 


90 dpi. 


b4 


120 dpi. 


b3 


180 dpi. 


b2 


300 dpi. 


bl 


360 dpi. 


bO 


reserved for future use. 



^This feature implemented in most Berkeley Softworks printer drivers. 



Note: Most printer drivers only support a small subset of these features even if the 

printer they are driving supports more. 

Example: 

See also: GetMode, SetNLQ. 



258 



SetMouse 



ISetMouse (Ci28) 



input driver 



Function: 



Input device scan reset. 



Parameters: 



none. 



Returns: 



nothing 



Destroys: assume a, x, y, r0-rl5 

Description: GEOS 128 calls SetMouse during Interrupt Level, immediately after the 



keyboard is scanned for a new key, to reset the pot (potentiometer) scanning lines 
so that they will recharge with the new value of. It is primarily of use with the 
Commodore 1351 mouse, which requires having the pot lines reset regularly. 
Other input drivers will have a SetMouse routine that merely performs an rts. 
An application should never need to call SetMouse. 



See also: SIowMouse, UpdateMouse, InitMouse, KeyFilter. 



259 



SetMsePic 



SetMsePic (Apple, cns) 



sprite/mouse! 



Function: 
Parameters: 

Returns: 

Destroys: 

Description: 



Note: 
Example: 



Uploads and pre-shifts a new mouse picture for the software sprite handler. 

rO MSEPIC —r pointer to 32 bytes of mouse sprite image data or one of the 
following special codes: 

ARROW Arrow pointer (Apple and C128) 

HOURGLASS Busy (Apple only) 

nothing. 

a, X, y, r0-rl5 

The software sprite routines used by GEOS 128 in 80-column mode and Apple 
GEOS treat the mouse sprite (sprite #0) differently than the other sprites. Sprite 
#0 is optimized and hardcoded to provide reasonable mouse-response while 
minimizing the flicker typically associated with erasing and redrawing a fast- 
moving object. The mouse sprite is limited to a 16x8 pixel image. The image 
includes a mask of the same size and both are stored in a pre-shifted form within 
internal GEOS buffers. For these reasons, a new mouse picture must be installed 
with SetMsePic (as opposed to a normal DrawSprite). SetMsePic pre-shifts 
the image data and lets the soft-sprite mouse routine know of the new image. 

SetMsePic accepts one parameter: a pointer to the mask and image data or a 
constant value for one of the predefined shapes. If a user-defined shape is used, 
the data that MSEPIC points to is in the following fonnat: 



16 bytes 



16 bytes 



16x8 "cookie cutter" mask. Before drawing the software mouse sprite, 
GEOS and*s this mask onto the foreground screen. Any zero bits in the 
mask, clear the corresponding pixels. One bits do not'affect the screen. 



16x8 sprite image. After clearing pixels with the mask data, the sprite 
image is or*ed into the area. Any one bits in the sprite image set the 
corresponding pixels. Zero bits do not affect the screen. 



GEOS treats the each 16-byte field as 8 rows of 16 bits (two bytes per row). 
SetMsePic calls HideOnlyMouse. 



Put up a new mouse picture 



ArrowUp: 

LoadW rO, #DnArrow ; point at new image 

jsr SetMsePic ; install it 

Its 

;macro to store a word value in high/low order 
.macro , HILO word 

.byte J word, [word 

• endm 

/Mouse picture definition for down-pointing arrow 
DnArrow: 



260 



SetMsePic 



;mas)c 



HILO %1111111110000000 

HILO %1111111001111110 

HILXD %0001100111111001 

HILO %0110011111100111 

HILO %0111111110011111 

HILO %01H111110011111 

HILO %0111111111101111 

HILO %0000000000001111 



; image 

HILO %0000000000000000 

HILO %0000000001111110 

HILO %0000000111111000 

HILO %0110011111100000 

HILO %0111111110000000 

HILO %0111111110000000 

HILO %0111111111100000 

HILO %0000000000000000 

See also: TempHideMouse, DrawSprite. 



261 



SetNewMode 



SetNewMode (Ci28) 



graphicsj 



Function: Changes GEOS 128 from 40-column mode to SO-column mode, or vice-versa. 

Parameters: graphMode . GRMODE — new graphics mode to change to: 

40-column: GR 40 
80-column: GR^80 

Returns: nothing. 
Destroys: a, x, y, r0-rl5. 

Description: SetNewMode changes the operating mode of the Commodore 128. 
|40-column mode (graphMode — GR 40)1 

1: 8510 clock speed is slowed down to IMhz because VIC chip cannot operate 
at2Mhz. 

2: rightMargin is set to 319. 

3: UseSystemFont is called to begin using the 40-column font 

4: 40-column VIC screen is enabled. 

5: 80-column VDC screen is set to black on black, effectively disabling it 



Example: 



180-column mode (graphMode == GR sUTl 
1: 8510 clock speed is raised to 2Mhz. 
2: rightMargin is set to 639. 

3: UseSystemFont is called to begin using die 80-column font 
4: 40-column VIC screen is disabled 
5: 80-column VDC screen is enabled 



ChangeMode : 
jsr 
Ida 
eor 
jsr 
jsr 
rts 

GREYPAT 

GreyScreen: 
jsr 
.byte 
.byte 



GreyScreen 

graphMode 

«%10000000 

SetNewMode 

GreyScreen 



;grey out old screen 
/switch mode by flipping 
; 40/80 bit 

;and calling SetNewMode 
;grey out new screen 
;exit 

;grey pattern to use 



i_GraphicsString 

NEWPATTERN, GREYPAT ;set to grey pattern 
MOVEPENTO ;put pen in upper left 



262 



CONriUENTIAL 



SetNewMode 



.word »x 

.byte ;y 

.byte RECTANGLETO ;grey out entire screen 

.word (SC_40_WIDTH-1) 1 DOUBLE_W| ADD1_W 

.byte SC_PIX_HEIGHT 

.byte NULL 

rts 



263 



SetNextFree 



SetNextFree (Apple, C64, ci28) 



mid-level disk I 



Function: 

Parameters: 

Uses: 



Returns: 
Alters: 



Destroys: 



Description: 



Search for a nearby free block and allocate it. 

r3 block (Commodore track/sector) to begin search (woid). 

curDrive 



Cpmrnodorp; 

curDirHead 

dir2Headt 

dirSHeadt 

interleave^ 



Apple: 

curVBlknot 
VBMchangedt 
numVBMBlkst 
totNumBlockst 



this buffer must contain the current directory header. 
(BAM for 1571 and 1581 drives only) 
(BAM for 1581 drive only) 

desired physical sector interleave (usually 8);. applications 
need not set this explicidy — will be set automatically by 
internal GEOS routines. 



used by VBM cacheing routines, 
used by VBM cacheing routines, 
used by VBM cacheing routines, 
for detecting last block on disk. 



^used internally by GEOS disk routines; explications generally don't use. 

X error ($00 = no error). 

r3 block (Commodore track/sector) allocated. 



Commp<[OTP; 
curDirHead 
dir2Headt 
dirSHeadt 

Apple: 

curVBIknot 
VBMchangedt 



BAM updated to reflect newly allocated block. 
(BAM for 1571 and 1581 drives only) 
(BAM for 1581 drive only) 



used by VBM cacheing routines. 

set to TRUE by VBM cacheing routines to indicate cached 
VBM block has changed and needs to be flushed 



^used internally by GEOS disk routines; applications generally don't use. 

Commodore: 

a, y, r6-r7, r8H. 

Apple; 

a, y, r6, r7, rSH. 

Given the current block as passed in r3, SetNextFree searches for the next free 
block on the disk. The "next" free block is not necessarily adjacent to the previous 
block because SetNextFree may interleave the blocks. Proper interleaving 
aUows the drive to read and write data as fast as possible because it minimizes the 
time the drive spends waiting for a block to spin under the read/write head. It 
means, however, that sequential data blocks may not occupy adjacent blocks on 



264 



SetNextFree 



the disk. As long as an application is using the standard GEOS file structuies, this 
interleaving should not be apparent 

After determining the ideal sector from any interleave calculations, SetNextFree 
tries to allocate the block it if it is unused. If the block is used, SetNextFree 
picks another nearby sector (jumping to another track if necessary) and calls tries 
again. This process continues until a block is actually allocated or the end of the 
disk is reached, whichever comes first. If the end of the disk is reached, an 
INSUFFICIENT^SPACE error is returned. 

Notice that SetNextFree only searches for free blocks starting with the current 
block and searching towards the end of the disk. It does not backup to check 
other areas of the disk because it assumes they have abeady been filled. (Actually, 
under Commodore GEOS,.SetNextFree will backtrack as far back as beginning 
of the current track but will not go to any previous tracks.). Usually this is a safe 
assumption because SetNextFree is called by BlkAlIoc, which always begins 
searching for free blocks from the beginning of the disk. 

It is conceivable, however, that an application might want to implement an 
AppendRecord function (or something of that sort), which would append a 
block of data to an already existing VLIR record without deleting, reallocating, 
and then rewriting the record like WriteRecord. 

In order to maintain any interleave from the last block in the record to the new 
block, the AppendRecord routine passes the track and sector of the last block in 
the record to SetNextFree. SetNextFree will start searching from this block. 
If a free block cannot be found, an INSUFFICIENT SPACE error is 
returned. Since SetNextFree only searched from the currenttlock to the end of 
the disk, the possiblility exists that a free block lies somewhere on a previous, 
still unchecked disk area. The following alternative to SetNextFree will 
circumvent this problem: 

My Set Next Free: 

;Look for a free block starting at the current block 

;so that we continue the interleave if possible 

jsr SetNextFree ; look for block to allocate 

cpx #INSOFFICENT_SPACE ; check for no blocks 

beq 10$ /start from beginning if none 

rts ;exit on any other error or 

; valid block found. 

;We got an insufficient space error. Start the search 

; again from the beginning of the disk. 

10$: 





APPLE 




LoadW 


r3,#0 


/start at block 




;CBM 




LoadB 


r3H,#0 


/always sector 


Idx 


#1 


/assume track 1 


Idy 


curDrive 


/but special case 1581 


Ida 


driveType-8,y 


/because of outer /inner track 


and 


#$0f 


/searching scheme 


cmp 


#DRV_1581 




bne 


20$ 


/branch if not 1581 


Idx 


#39 


/1581 counts down on inner (39-1) 






/then up on outer (41-80) 



265 



SetNextFree 



stx r3L /track number 

•endif 

jmp SetNextFree ;go search, let it return 

C64 & C128: SetNextFree uses the value in interleave to establish the ideal next sector. A 
good interleave will arrange successive sectors so as to minimize the time the 
drive spends stepping the read/write head and waiting for the desired sector to 
spin around. The value in interleave is usually set by the Configure program 
and internally by GEOS disk routines. The application will usually not need to 
worry about the value in interleave. 



Because Commodore disks store the directory on special tracks, SetNextFree 
will automatically skip over these special tracks unless r3L is started on one of 
these tracks, in which case SetNextFree assumes that this was intentional and a 
block on the directory track is allocated. (This is exactly how GetFreeDirBlk 
operates.) The directory blocks for various drives can be determined by the 
following constants: 



1S81 


DIR 


1581 TRACK 


(one track) 


1541 


DIR 


TRACK 


(one track) 


1571 


DIR 


TRACK 


(two tracks) 




DIR" 


:track+n_tracks 



SetNextFree does not automatically write oiit the BAM. See PutDirHead for 
more information on writing out the BAM 



Apple: The Apple version of SetNextFree does no interleave calculations because 

ProDOS devices handle physical interleaving when they map block numbers to 
physical sectors. SetNextFree on the Apple merely increments the block 
number. 

SetNextFree does' not automatically flush tiie VBM cache. 3ee PutVBM for 
more information on flushing the cache. 

Example: 

See also: AllocateBIock, FreeBiock, BlkAlloc. 



266 



SetNLQ 



SetNLQ (C64, C128) 



printer driver | 



Function: Enter high-quality printing mode. 
Parameters: rl 



WORKBUF — pointer to a 640-byte work buffer for use by the printer 
driver (word). 



Returns: nothing. 

Destroys: assume a, x, y, r0-rl5. 

Description: SetNLQ sends the appropriate control codes to place the printer into high-quality 
print mode (as opposed to the default draft mode). SetNLQ is called after 
StartASCn has been called to enable text output 



See also: 



StartASCII, PrintASCII, SetMode. 




267 



SetPattern 



SetPattern (Apple, C64, cns) 



graphics] 



Function: 

Parameters: 

Returns: 

Alters: 

Destroys: 

Description: 



Apple: 

Example: 
See also: 



Set the current fill pattern. 

a GEOS system pattern number (must be between and 3 1 ) (byte), 
nothing. 

curPattern Contains an address pointing to the eight-byte pattern, 

a 

Sets the current fill pattern. There are 34 system patterns (numbered 0-33) in 
GEOS 64 and GEOS 128; Apple GEOS adds a 35th, user-defined pattern 
(number 34). Unfortunately, SetPattern will only work correcdy with patterns 
numbered 0-31. To access higher number patterns, call SetPattern with a value 
of 31 and add 8 to curPatttern to access pattern 32, add 16 to access pattern 33, 
and so on. 

Although curPattern will contain a valid address, it is an address in auxiliary- 
high memory, and this memory bank is all but inaccessible to user applications. 
Use GetPattern and SetUserPattern to access the pattern data. 



GetPattern, SetUserPattern. 



268 



SetTimeDate 



SetTimeDate (Apple) 



clock driver I 



Function: Qock driver routine to set the clock's time and date. 

Parameters: rOL YEAR — ^.current year (calendar year -19(X)) (byte). 

rOH MONTH — current month (Q-12) (byte). 

rlL DAY — day of month (1-28, 29, 30, 3 1) (byte). 

rlH HOUR — hour (0-23) (byte). 

r2L MINUTE — minute (0-59) (byte). 

r2H SECOND — seconds (0-59) (byte). 

Returns: nothing. 

Destroys: assume a, x, y, r0-rl5. 

Description: SetTimeDate is a clock driver routine for setting a new time and date. Most 
clock drivers do no error checking on the parameters and expect valid values 
(passing a nonexistent day in a month is a no-no). 

Note: To be sure the time is set correctly, disable interrupts around the call to 

SetTimeDate. 

See also: ReadClock, Clocklnt, SetAlarm, ResetAIarm. 



270 



SetUserPattern 



ISetUserPattern (AppieT 



graphics] 



Function: 
Parameters: 

returns: 
Alters: 

Destroys: 
Description: 

Example: 
See also: 



Upload an cight-byte pattern definition to a GEOS system pattern. 

a GEOS system pattern number to alter. 

rO pointer to eight-byte pattern definition (word). 



nothing. 
curPattern 

a,y 



altered so that the new pattern becomes the current pattern. 
rO is unchanged. 



SetUserPattern uploads an eight-byte pattern definition to the system pattern 
space in auxiliary high memory. This is the only convenient way to modify the 
system pattern definitions under Apple GEOS. 



GetPattern, SetPattern. 



271 



Sleep 



Sleep (Apple, C64, C128) 



process 



Function: 

Parameters: 

Returns: 

Destroys: 

Description: 



Note: 



Pause execution of a subroutine ("go to sleep") for a given time interval. 
rO DELAY — number of vblanks to sleep (word), 
nothing: does not return direcdy to caller (see description below). 
a,x, y 

Sleep stops executing the current subroutine, forcing an early rts to the routine 
one level lower, essentially putting the current routine "to sleep." At Interrupt 
Level, the DELAY value assocated with each sleeping routine is decremented. 
When the the DELAY value reaches zero, MainLoop- removes the sleeping 
routine from the sleep table and perfomrs a jsr to the instruction following the 
original jsr Sleep, expecting a subsequent rts to return control back to 
MainLoop. For example, in the normal course of events, MainLoop might call 
an icon event service routine (after an icon is clicked on). This service routine can 
perform a jsr Sleep. Sleep will force an early rts, which, in this case, 
happens to return control to MainLoop. When the routine awakes (after DELAK 
vblanks have occurred), MainLoop performs a jsr to the instruction that follows 
tiie original jsr Sleep. When this wake-up jsr occurs, it occurs at some later 
time the contents of the processor registers and GEOS pseudoregisters are 
uninitialized. A subsequent rts will return to MainLoop. 

Sleeping in Detail: 

\: The application calls Sleep with a jsr Sleep. The jsr places a return 
address on the stack and transfers the processor to the Sleep routine. 

2: Sleep pulls the return address (top two bytes) from the stack and places those 
values along with the DELAY parameter in an internal sleep table. 

4: Sleep exectues an rts. Smce the original caller's return address has been 
pulleid from the stack and saved in the sleep table, this rts uses the next two 
bytes on the stack, which it assunxs comprise a valid return address. (Note: it 
is imperitive that tiiis is in fact a return address; do not save any values on die 
stack before calling Sleep.) 

5: At Interrupt Level GEOS decrement sthe sleep timer until it reaches zero. 

6: On every pass, MainLoop checks the sleep timers. If one is zero, then it 
removes that sleeping routine from the table, adds one to the return address it 
pulled from the stack (so it points to the instruction following the 
jsr Sleep), and jsr's to this address. Because no context information is 
saved along with the sleep address, the awaking routine cannot depend on any 
values on the stack, in the GEOS pseudoregisters, or in the processor's 
registers. 

A DELAY value of $0(XX) will cause the routine to sleep only until the next pass 
through MainLoop. 



CONflDENTIAL 

272 



Sleep 



When debugging an application, be aware that Sleep alters the nonnal flow of 
control- 



Example: 

See also: InitProcesses* 



273 



SlowMouse 



SlOWMOUSe (Apple, C64, C128) input driver| 

Function: Kills any accumulated speed in a non-proportional input device. 
Parameters: none. 
Returns: nothing 

Alters: internal input-driver speed variables, if any. 

Destroys: assume a, x, y, rO-rlS 

Description: Input drivers for non-proportional input devices, such as a joystick, will often 
internally associate a speed and velocity with movement This way the pointer can 
speed up when the user is trying to move large distances. SlowMouse will tell 
the input driver to kill any accumulated speed, effectively stopping the pointer at a 
specific location and forcing it to regain momentum. Depending on the input 
driver, SlowMouse may or may not have an effect on the pointer's movement 
The standard mouse driver, for example, simply performs an rts but some other 
input driver may actually copy the value in minMouseSpeed to its own internal 
speed variable. 

GEOS calls SlowMouse when it drops menus down. A driver that has velocity 
variables should adjust the current speed so that the pointer does not immediately 
jump off Ae menu. An application may want to call SlowMouse when the user 
is required to make precise movements. 

See also: UpdateMouse, InitMouse, SetMouse, KeyFilter. 



274 



SmailPutChar 



ISmallPutChar (Apple, C64, cns) 



text! 



Function: 
Parameters: 

Uses: 
Returns: 

Destroys: 



Description: 



Note: 



Example: 
See also: 



Print a single character without the PutChar overhead 

a CHAR — character code (byte). 

r 1 1 XPOS — x-coordinate of left of character (word). 

rlH YPOS — y-coordinate of character baseline (word). 

same as PutChar. 

rl 1 x-position for next character. 
rlH unchanged 

CpmmodQT?; 

a, X, y, rlL, r2-rl0, rl2, rl3 

Apple: 

a, x, y, rlL, r2 

SmailPutChar is a bare bones version of PutChar. SmailPutChar will not 
handle escape codes, does no margin faulting, and does not normalize the x- 
coordinates on GEOS 128. 

SmailPutChar will assume the character code is a valid and printable character 
Any portion of the character that lies above windowTop or below 
windowBottom will not be drawn. If a character lies partially outside of 
leftMargin or rightMargin, SmailPutChar will only print the portion of the 
character lies within the margins. SmailPutChar will also accept small negative 
values for the character x-position, allowing characters to be clipped at the left 
screen edge. 

Partial character clipping at die left margin, including negative x-postion clipping, 
is not supported by early versions of GEOS 64 (earlier than vl.4) — the entire 
character is clipped instead. Full left-margin clipping is supported on all other 
versions of GEOS: GEOS 64 vl.4 and above, GEOS 128 (both in 64 and 128 
mode), and Apple GEOS. 

Like PutChar, 159 is the maximum CHAR value tfiat SmailPutChar will 
handle correctiy. Most fonts will not have characters for codes beyond 129. 



PutChar, PutString. 



r J 



275 



SoftSprHandler 



SoftSprHandler (Apple) 



sprite 



Function: Software. sprite handler. 
Parameters: none. 



Uses: 



Returns: 
Alters: 
Destroys: 
Description: 



Note: 



mobenble 

moby2 

niobx2 

reqlxpos-reqTxpos 
moblypos-mob7ypos 

nothing. 

of f Fla g $40 Flag to Redraw mouse at next interrupt, 

a, X, y, r0-rl5 

SoftSprHandler is the routine MainLoop calls to update die software sprites. 
This involves redrawing them if diey have been temporarily removed (by a call to 
TempHideMouse, perhaps) or erasing and redrawing them if they have moved. 
An application will normally have no need to call this routine direcdy, assuming 
MainLoop is being returned to normally. 

This is where sprites are physically repositioned. A call to PosSprite, for 
example, only updates the reqXposN and mobNYpos request position 
variables associated with the sprite. The actual physical position does not change 
until SoftSprHandler is called (usually at MainLoop) to redraw the sprites. 

SoftSprHai\.dIer draws higher numbered sprites first so that sprites with lower 
numbers will appear on top of sprites with higher numbers. Sprite #5, for 
example, will appear on top of sprite #4 when they are drawn together. 

SoftSprHandler does not use reqXposO and mobOypos because the mouse 
sprite is redrawn at intenrupt level. 



See also: TempHideMouse, HideOnlyMouse. 



276 



SortAlpha 



SortAlpha (Apple) 



utility 



Function: Casc-inscnsitive alphanumeric sort 

Parameters: rO LIST — pointer to unsorted list (word). 

rl NUMRECS — number of 16-byte records in the list 

Returns: list sorted 



Destroys: a, x, y, rl-r4. 



Description: 



Note: 



SortAlpha sorts an arbitrarily large list of 16-byte ASCII records. The record 
size is currendy fixed at 16-bytes (the number of characters in a GEOS filename), 
although future versions of Apple GEOS will probably make the record size 
variable. 

SortAlpha uses a selection sort algorithm, which works well with small records 
and has a running time proportional to NUMREC^. SortAlpha ignores letter 
case in its comparisons. 

SortAlpha correctiy handles the trivial cases where NUMRECS is either zero or 
one. 



Example: 



REC_SI2E — 16 

LoadW 
LoadW 
jsr 
rts 



/always 16 in Apple GEOS vl.O 

rO^lData ;point to record list 

rl,#NDM_RECS /number of records to sort 

SortAlpha :qo sort them 

;exit 



Data: 

.byte "ZETA " 

.byte -0123456789ABcDeF'« 

.byte "gAMma over beta ** 

.byte "stewardesses " 

.byte -123ABC123abc 

.byte "abcdefghi jklmnop" 

.byte ••qrstuvwxy2012345'' 

.byte "stewardess *" 

.byte "beta 

.byte "alpha " 

.byte "delta " 

.byte "steward 

NUM^RECS - ((*-Data)/REC_SIZE) 

.if"" ( (Data + NUM_RECS*REC_SIZE) !- *) 

.echo Something is wrong with sort data 
.endif 



277 



StartAppI (Apple, C64, C128) 



mid-level disk! 



Function: Warmstart GEOS and start an application that is already loaded into memory. 
Parameters: These are all passed on to the application being started. 



rOL 



Tl 



r3 



START.ADDR — start address of application (word). 
OPTIONS : 
bit?: not passing a data file. 

1 r2 and r3 contain pointen to disk and data file names, 
bit 6: not printing data file. 

printing data file; application should print file and exit 
DATA^DISK — only valid if bit 7 or bit 6 of OPTIONS is set: pointer 
to name of the disk that contains the data file, usually a pointer to one of 
the Dr;cCurDkNm buffers (word). 

DATA.FILE — only valid if bit 7 or bit 6 of OPTION is set: pointer to 
name of the data file (word). 



Returns: 
Passes: 



never retutrns. 

warmstarts GEOS and passes the following to the application at START^ADDR: 
rO as originally passed to StartAppI. 
r2 as originally passed to StartAppI (use dataDiskName). 
r3 as originally passed to StartAppl.(use dataFileName). 
dataDiskName contains name of data disk if bit 7 of rO is set. 
dataFileName contains name of data file if bit 6 of rO is set 

Alters : GEOS brought to a warmstart state. 

Destroys: n/a 



Description: 



Example: 
See also: 



StartAppI warmstarts GEOS and jsr's to START_ADDR as if the application 
had been loaded from the deskTop. GetFile and LdAppIic call StartAppI 
automatically when loading an application. 

StartAppI is useful for bringing an application back to its startup state. It 
completely warmstarts GEOS, resetting variables, intializing tables, clearing the 
processor stack, and executing the application's initialization code with a jsr from 
MainLoop. 



LdAppIic, GetFile, WarmStart. 



282 



StartASCII 



StartASCII (Apple, C64, cm) 



printer driver I 



Function: Enable ASCII text mode printing. 



Parameters: 



Commodore 

rl WORKBUF — pointer to a 640-byte work buffer for use by the printer 
driver.(word). PrintASCII uses this work area as an intermediate 
buffer, the buffer must stay intact throughout the entire page. 



Apple 
none. 



Returns: 
Destroys: 



STATUS — printer error code; $00 = no error. 



Description: 



Commodore 
assume a, y, r0-rl5. 

Applg 

assume a, y, r0-r4. 

StartASCII enables ASCII text mode printing. An application calls 
StartASCII at the beginning of each page. It assumes that InitForPrint has 
already been called to initialize the printer. 



C64 & C128: StartASCII takes control of the serial bus by opening a fake Commodore file 
structure and requests the printer (device 4) to enter listen mode. It then sends the 
proper control sequences to place the printer into text mode. 



Apple: 



Example: 



StartASCII sends the proper control sequences to place the printer into ASCII 
mode. It reestablishes the proper text mode as set by SetMode, but it does not 
reset the printer. This allows an application to mix graphics and ASCII text on the 
same page. 



See also: PrintASCII, StopPrint, StartPrint 



279 



StartMouseMode 



StartMoUSeMode (Apple, C64, C128) mouse/sprite| 

Function: Instructs GEOS to start or restart its monitoring of the input device (usually a 
mouse but depending on the input driver may be a joystick or other device). 

MOUSEX — x-position to start mouse at (word) If this parameter is 
$(X)00, then the mouse position is not changed and the mouse velocity is 
not altered 

MOUSEY — y-position to start mouse at (byte), 
cany flag: = same as setting MOUSEX to $0(XX). 
1= no effect 



Parameters: rll 



y 

St 



loaded with address of SystemMouseService. 
loaded with address of SystemFaultService. 
$00 



MOUSEON^BIT set by MouseUp. 
sprite #0 bit set by MouseUp. 

Destroys: a, x, y, r0-rl5 

Description: StartMouseMode Instructs GEOS to start or restart its monitoring of the input 
device. Most normal GEOS applications will not need to call this routine because 
it is called internally by both DoMenu and Dolcons. If an application is not 
using icons nor menus, it should call StartMouseMode during its initialization. 

StartMouseMode does the following: 

1: If the carry flag is set and the MOUSEX parameter is non-zero, then 
MOUSEX is copied into mouseXPos, AfOt/5£y is copied into 
mouseYPos, and the input driver SlowMouse routine is called. If running 
under GEOS 128, MOUSEX is first passed through NormalizeX before 
getting loaded into mouseXPos. 



Alters: mouseVector 

mouseFauItVec 
faultData 
mouseXPos 
mouseYPos 
mouseOn 
mobenble 



2: The address of the internal SystemMouseService routine is loaded into 
mouseVector and the address of the internal SystemFaultService routine 
is loaded into mouseFauItVec. 



3: A $00 is stored into faultData, clearing any mouse faults. 

4: MouseUp is called to enable the mouse. 

64 & 128: If the mouse will be repositioned, then disable interrupts around the call to 
StartMouseMode. It is not necessary to disable intermpts under Apple GEOS. 

Example: 

/Intialize the mouse and start it at screen center 
Mouselnit: 

LoadW rllr#(SC_PIX_WIDTH/2) ; screen center 

Idy * (SC_PIx2hEIGHT/2) 

sec ;set to move mouse 

.if (C64 I I C128) 



278 



StartMouseMode 



php 
sei 

jsr StartMouseMode 
pip 

•else ; (APPLE) 

jsr StartMouseMode 
.endif 

rts 



See also: ClearMouseMode, MouseUp, MouseOff, SlowMouse, DoMenu, 
Dolcons, TempHideMouse, HideOnlyMouse. 



279 



StartPrint 



StartPrint (Apple, C64, ci28) 



printer driver | 



Function: Enable graphics-mode printing- 



Parameters: 



CbmmcKjQrp 

rl WORKBUF — pointer to a 1,920-byte work buffer for use by the 
printer driver. (word). PrintBuffer uses this work area as an 
intermediate buffer, this buffer must stay intact throughout the entire 
page. 



Apple 
hone. 



Returns: 
Destroys: 



STATUS — printer error code; $00 = no error. 



Description: 



assume a, y, r0-rl5. 

Apple 

assume a, y, r0-r4. 

StartPrint enables graphic printing. An application calls StartPrint at the 
beginning of each page. It assumes that InitForPrint has already been called to 
initialize the printer. 



C64 & C128: StartPrint takes control of the serial bus by opening a fake Commodore file 
structure and requests the printer (device 4) to enter listen mode. It then sends the 
proper control swiuences to place the printer into graphics nxxle. 



Apple: 



Example: 
See also: 



StartPrint sends the proper control sequences to place the printer into graphics 
mode. It reestablishes the proper graphics mode as set by SetMode, but it does 
not reset the printer. This aUows an application to mix ASCII text and graphics on 
the same page. 



StopPrint, StartASCII. 



283 



StashRAM 



StashRAM (C64 vi.3 & ci28) 



memory 



Function: Primitive for transferring data to an REU, 

Parameters: rO CBMSRC — address in Conimodore to start reading (word). 



r 1 REUDST — address in REU bank to put data (word). 
r2 COUNT — number of bytes to stash (word), 
r3L REUB ANK — REU bank number to stash to (byte). 

r0-r3 unchanged. 

X error code: $00 (no error) or DEV_NOT_FOUND if bank or REU 

not available. " 
a REU status byte and'ed with $60 ($40 = successful stash). 



Destroys: y 

Description: StashRAM moves a block of data from Commodore memory into an REU 
bank. This routine is a "use at your own risk" low-level GEOS primitive 



StashRAM uses the DoRAMOp primitive by calling it with a CMD parameter 
of%10010000. 



See also: FetchRAM, SwapRAM, VerifyRAM, DoRAMOp, MoveBData. 



Note: 



Refer to DoRAMOp for notes and warnings. 



Example: 




280 



This page intentionally left blank to maintain right/left (verso/recto) 
page ordering. Final version will correct this. 



StatusCard 



StatusCard (Apple) 



card driver! 



Function: 

Parameters: 

Returns: 

Destroys: 
Description: 

Note: 
Example: 
See also: 



Get the current input/output status of the printer card, 
none. 



X 
St 



a, y. 



STATUS — card error code; $00 = no error (byte) 
sign flag: set if card ready to accept output, 
carry flag: set if card has input ready. 



StatusCard returns information about the current state of the card. The input- 
ready and ready-for-output flags are only valid if the card is capable of returning 
this type of information. This capability can be checked with a call to InfoCard. 

StatusCard must be called after an OpenCard and before a CloseCard. 



InfoCard. 



284 



StopPrint 



IStOpPrint (Apple, C64, C128) 



printer driver | 



Function: 
Parameters: 



Returns: 
Destroys: 



Flush output buffer and formfeed the printer (called at the end of each page). 
Commodore 

rO TEMPBUF — pointer to a 640-byte area of memory that can be set to 
$00 (word). 

rl WORKBUF — pointer to a 1,920-byte work buffer used by 
PrintBuffer (word). 



Applg 
rlL 



Apple 

X 



FF.SUPPRESS — set to TRUE to suppress automatic formfeed after 
flushing the buffer, normally set to FALSE. 



STATUS — printer error code; $00 = no enror. 



Description: 

C64 & C128: 
Apple: 



Example: 
See also: 



ComtnwlQrp 

assume a, x, y, r0-rl5. 

Apple 

assume a, y, r0-r4. 

StopPrint instructs the printer driver to flush any internal buffers and end the 
page. 

StopPrint ends both graphic and ASCII printing. 

Commodore GEOS printer drivers always formfeed when StopPrint is called. 

Apple GEOS printer drivers can suppress the normal StopPrint formfeed, 
thereby flushing the print buffers but allowing the application to resume printing 
at the cuirent Une. This way ASCII text and graphics can be mixed on a page with 
alternating calls to StartASCII. StopPrint, and StartPrint. 



StartPrint. StartASCII. 



285 



SwapBOata 



SwapBData (C128) memoryl 



Function: Swaps two regions of memory within either front RAM or back RAM (or 
between one and the other). 

Parameters: rO ADDRl — address of first block in application memory (word). 

r 1 ADDRl — address of second block in application memory (word). 

r2 COUNT — number of bytes to swap (word). 

r3L AlBANK— ADDRl bank: = front RAM; 1 = back RAM (byte). 

r3H A2BANK — ADD/?2 bank: = front RAM; 1 = back RAM (byte). 

Returns: rO-r3 unchanged. 

Destroys: a, x, y 

Description: SwapBData is a block swap routine that allows data to be swapped in either 
front RAM, back RAM, or between front and back. If the ADDRl and ADDRl 
areas are in the same bank and overlap, ADDRl. must be less than ADDRl. 

SwapBData is especially useful for swapping data from front RAM to back 
RAM or from back RAM to front RAM. 

SwapBData uses the DoBOp primitive by calling it with a MODE parameter of 
$02. 

Note: SwapBData should only be used to swap data within the designated application 

areas of memory. 

Example: 

See also: MoveBData, VerifyBData, DoBOp. 



286 



SwapMainAndAux 



ISwapMainAndAux (Apple) 



memory I 



Function: 

Parameters: 

Destroys: 
Description: 



Example: 
See also: 



Swaps a block of memory on a byte-by-bytc basis between application main 
memory and application aux memory. 

r SOURCE — address of block to swap (word). 
r2 COUNT— number of bytes to swap (0~48K). 

a, y» rO, rlL, r2 

SwapMalnAux swaps a block of bytes that lie at the same address in both main 
and auxiliary application memory. This is really only useful in the area between 
$6000 and $8C<X), where application main and application aux memory occupy 
the same address space. 



MoveAuxData, MoveBData, SwapBData, SwapRAM. 



287 



SwapRAM 



SwapRAM (C64 vL3 & cns) 



memoryl 



Function: 
Parameters: 

Returns: 



Destroys: 
Description: 



Note: 
Example: 
See also: 



Primitive for swapping data between Commodore memory and an REU, 

rO CBMADDR — address in Commodore to swap (word), 

rl REUADDR — address in REU to swap (word). 

r2 COUNT — number of bytes to swap (word). 

r3L REUS ANK — REU bank number to fetch from (byte). 

r0-r3 unchanged. 

X em)rcode: $00 (no error) or DEV^NOT^FOUND if REUBANK 

or REU not available. " 
a REU status byte and'ed with $60 ($40 = successful swap). 



SwapRAM swaps a block of data in an REU bank with a block of data in 
Commodore memory. This routine is a "use at your own risk" low-level GEOS 
primitive 

SwapRAM uses the DoRAMOp primitive by calling it with a CMD parameter 
of % 10010010. 

Refer to DoRAMOp for notes and warnings. 



StashRAM, FetchRAM, VerifyRAM, DoRAMOp, SwapBData. 



288 



TempHideMouse 



TempHideMouse (Apple, ci28) 



mouse/sprite] 



Function: Temporarily removes soft-sprites and the mouse pointer from the graphics screen. 
Parameters: nothing. 



Returns: 
Uses: 

Alters: 



Description: 



128: 
Apple: 



Example: 
See also: 



nothing. 

graphMode 
offFlag 

noEraseSprites 
offFlag 



(128 only). 
(Apple only). 
(Apple only). 

set to TRUE (Apple only). 



Destroys: a, x 



TempHideMouse temporarily removes all soft-sprites (mouse pointer and 
sprites 2-7) unless they are already removed. This routine is called by all GEOS 
graphics routines prior to drawing to the graphics screen so that software sprites 
don't interfere with the graphic operations. An application that needs to do direct 
screen access should call tins routine prior to modifying screen memory. 

The sprites will remain hidden until the next pass through MainLoop. 

In 40-column mode (bit 7 of graphMode is zero), TempHideMouse exits 
immediately without affecting the hardware sprites. 

If bit 7 of offFlag is set, offFlag is set to TRUE (reaffirming the fact that the 
sprites and mouse are marked as hidden) and exits without affecting any sprites. 
If noEraseSprites is set to TRUE, sprites 2-7 are not erased from the screen. 
This is useful for keeping sprites on the screen (and, therefore, avoiding any 
flicker) if the application is confident that the graphic operation will not be in the 
area of a sprite. 



HideOnlyMouse. 



289 



TestPoint 



TeStPoint (Apple, C64, C128) 



Function: Test and return the value of a single point (pixel). 

Parameters: r3 XI — x-co6ridnate of pixel (word). 

rllL Yl — y-coordinate of pixel (byte). 

where (XI, Yl) is the coordinate of the point to test. 

Uses: dispBufferOn 

bit 6 — if set, test pixel in foreground screen, 
bit 7 — if set, test pixel in background buffer. 

(If both bit 6 and bit 7 are set, then only the pixel in the background 
screen is tested.). 

Returns: r3, rllL unchanged. 

s t carry flag set if point set; cleared if point clear. 

Destroys: a, x, y, r5-r6 

Description: TestPoint will test a pixel in either the foreground screen or the background 
buffer (or both simultaneously) and return the pixel's status by either setting or 
clearing the carry (x) flag accordingly. The jsr TestPoint is usually followed 
immediately by a bcc or bcs so that a set or clear pixel may be handled 
appropriately. 

128: Under GEOS 128, or'ing DOUBLE W into the XI will automatically double 

the x-position in 80-column mode. 0?ing in ADDl W will automatically add 1 
to a doubled x-position. (Refer to "GEOS 128 X-po?ition and Bitmap Doubling" 
in Chapter.® gitg) for more information.) 

Example: 

See also: DrawPoint. 



graphics 



290 



ToBasiC (€64^128) 



utility 



Function: Removes GEOS and passes control to Commodore BASIC with the option of 
loading a non-GEOS program file (BASIC or assembly-language) and/or 
executing a BASIC command 



Parameters: rO 
rS 

r7 



CMDSTRING — pointer to null-terminated command string to send to 
BASIC interpreter. 

DIR.ENTRY — pointer to the directory entry of a standard Commodore 
file (PRG file type), which itself can be either a BASIC or ASSEMBLY 
GEOS-type file. If this parameter is $0000, then no file will be loaded. 
LOADADDR — if rS is non-zero, then this is the file load address. For a 
BASIC program, this is typically $801. If rS is zero and a tokenized 
BASIC program is akeady in memory, then this value should point just 
past the last byte in the program. If rS is zero and no program is in 
memory, this value should be $803, and the three bytes at $80O-$802 
should be $00. 



Returns: n/a 
Destroys: n/a 

Description: ToBasic gives a GEOS application the ability to run a standard Commodore 
assembly-language or BASIC program. It removes GEOS, switches in the 
BASIC ROM and I/O bank, loads an optional file, and sends an optional 
command to the BASIC interpreter. 

Once ToBasic has executed, there is no way to return directly to the GEOS 
environment unless the RAM areas from $cOOO through $c07f are preserved 
(those bytes may be saved and restored later). To return to GEOS, the called 
program can execute a jump to $cOOO (BootGEOS). 



A program in the C64 environment can check to see if it was loaded by GEOS by 
checking the memory starting at $c006 for the ASCII (not CBMASCH) string 
"GEOS BOOT'. If loaded by GEOS, the program can check bit 5 of $c012: if 
this bit is set, ask the user to insert their GEOS boot disk; if this bit is clear, 
GEOS will reboot from the RAM expansion unit To actually return to GEOS, set 
CPU DATA to $37 (KRNL BAS 10 IN) and jump to $cOOO 
(BootGEOS). - - - 



Example: 



LoadBASIC: 

Loads a Conunodore BASIC program and starts it 
running. Assumes that the program is a standard BASIC 
file that loads at $801. This example does little 
error checking. 



Pass: 



r5 



pointer to BASIC program's directory 
entry. 



LoadBASIC: 
LoadW 
LoadW 



rO, IRunCommand 
r7,#$801 



; point at command string 
/assume standard address 



291 



jsr ToBasic 
brJc 



/expect to not return 
/should never get here 



/Text command to send to BASIC interpeter so BASIC 

/program is started up properly, 

RunCommand: 

.byte "RUN", NULL 



UnblockProcess 



lUnblockProcess (Apple, C64, cns) 



process! 



Function: 
Parameters: 

Returns: 

Destroys: 

Description: 



Note: 

Example: 
See also: 



Allow a process's events to go through. 

X PROXIES S — number of process (0 - n-1, where n is the number of 
processes in the table) (byte). 

X unchanged 

UnblockProcess causes MainLoop to again recognize a process's runable 
flag so that if a process timer reaches zero (causing the process to become 
runable) an event will be generated 

Because the GEOS Intemipt Level continues to decrement the countdown timer as 
long as the process is not frozen, a process may become runable while it is 
blocked. As long as the process is blocked, however, MainLoop will ignore the 
runable flag. When the process is subsequently unblocked, MainLoop will 
recognize a set runable flag as a pending event and call the appropriate service 
routine. Multiple pending events are ignored: if a blocked process's timer reaches 
zero more than once, only one event will be generated when it is unblocked. To 
prevent a pending event from happening, use RestartProcess to unblock the 
process. 

If a process is not blocked an unnecessary call to UnblockProcess will have 
no effect 



BlockProcess, UnfreezeProcess, EnableProcess, RestartProcess. 



293 



UnfreezeProcess 



UnfreezeProcess (Apple, C64, ci28) processi 



Function: Resume (unfreeze) a process's countdown timer. 

Parameters: x PROCESS — number of process (0 - where n is the number of 

processes in the table) (byte). 

Returns: x unchanged 

Destroys: a 

Description: UnfreezeProcess causes a frozen process's countdown timer to resume 
decrementing. The value of the timer is unchanged; it begins decrementing again 
from the point where it was frozen. If a process is not frozen, a call to 
UnfreezeProcess will have no effect. 

Note: If a process is not frozen, a call to UnfreezeProcess will have no effect. 

Example: 

See also: FreezeProcess, BlockProcess. 



294 



UpdateMouse 



UpdateMouse (Apple, C64, cns) 



input driver! 



Function: Update the mouse variables based on any changes in the state of the input device. 



Parameters: Commodore: 
none. 



Appig; 

St cany flag: 
1 



interrupt was caused by mouse card 
interrrupt was not caused by mouse card 



Returns: 
Alters: 



nothing 

mouseXPos 
mouseYPos 
mouseData 

pressFlag 
inputData 



mouse x-position. 
mouse y-position. 

state of mouse button: high bit set if button is released; clear 
if pressed 

MOUSE^BIT and INPUT^BIT set appropriately, 
depends on device. 



Destroys: assume a, x, y, r0-rl5 

Description: GEOS calls UpdateMouse at Interrupt Level to update the GEOS mouse 
variables with the actual state of the input device. An application should never 
need to call UpdateMouse. 

A typical input driver's UpdateMouse routine will scan the device hardware and 
update MouseXPos and MouseYPos with new positions if the coordinates 
have changed It will also update mouseData with the current state of the input 
button (high-bit set if released; cleared if pressed) ani set MOUSE BIT in 
pressFlag if the button state has changed since the last call to UpdatelVlouse. 

The four byte inputData field, which was originally for device-dependent 
information, has adopted the following standard offsets: 



inputData+0 



(byte) 8-position device direction (joystick direction; mouse 
drivers convet a moving mouse to an appropriate direction): 

2 

3 I 1 
6 



inputData-f 1 (byte) cuircnt speed (Comnaodore joystick drivers only). 

Standard GEOS input drivers should set the INPIIT_BIT of pressFlag if 
inputData+O has changed since the last time UpdateMouse was called. 



295 



UpdateMouse 



Because most GEOS applications leave in put Vector set to its default $0000 
value, setting this bit will usually have no effect 

Apple: The Apple GEOS version of UpdateMouse will treat mouseYPos as a two- 

byte value, propagating any underflow into the high-byte at mouseYPos+1. 
TTiis gives the subsequent mouse-fault check enough precision to detect whether 
the user moved the mouse off the top or the bottom of the screen (a negative 
number = off the top edge). The GEOS mouse fault routine will always clear this 
high-byte after constraining the mouse to the screen edges. 

See also: SIowMouse, InitMouse, SetMouse, KeyFilter. 



296 



UpdateParent 



UpdateParent (Apple) 



mid-level disk 



Function: Update data om current directory header. 



Parameters: a 



UPDATE^FLAGS — operations to perform (word). 
DEC NUM FILES — decrement file count 



INC NUM FILES 
MOD DATE 
CREATE DATE 
DEC DIR BLKS 
DEC^DIR^BLKS 



— increment file count 
— update modification date. 

— set creation. 

— decrement directory block count 
_ — increment directory block count 

multiple changes can be made in one call by bitwise or'ing these constants 
together. 



Uses: 
Returns: 



Alters: 



curDirHead 



should contain current directory header. 



X 

rlOL 



error ($00 = no error), 
directory page actually used. 



curDirHead 
diskBlkBuf 



contains newly-changed current directory header, 
contains newly-changed parent directory header unless 
current directory is volume directory (in which case there is 
no parent header). 



Destroys: a, y, rl, r4, r5. 



Description: 



UpdateParent upates the current and parent directory headers according to the 
flags passed in UPDATEJPLAGS. Whenever a the contents of a subdirectory are 
altered — whether adding or deleteing files or other subdirectores — the current 
and parent directory headers need to be updated to reflect their new contents. The 
high-level GEOS routines will automatically call UpdateParent when they alter 
the contents of a subdirectory. 

C64 & C128: Commodore GEOS does not support a hierarchical file system. 



Example: 




297 



UpdateRecordFIle 



UpdateRecordFile (Apple, C64, cm) 



VLIR disk 



Function: Update the disk copy of the VLIR index table, BAM or VBM, and otfier VLIR 
information such as the file's time/date-stamp. This update only takes place if the 
file has changed since opened or last updated. 



Parameters: none. 



Uses: 



Returns: 
Alters: 



curDrive 
fileWrittent 

fileHeader 
fileSize 

dirEntryBuf 



if FALSE, no updating occurs because file has not been 
written to. 

VLIR index table stored in this buffer, 
total number of disk blocks used in file (includes index 
block, GEOS file header, and all records), 
directory entry of VLIR file. 



year, month, day, hours, minutes for date-stamping file. 



Cpmmodorp; 

curType 

curDirHead 

dir2Headt 

dir3Headt 

Applg; 
fileBytes 

curVBlkno* 

VBMchanged^ 

numVBMBlkst 



GEOS 64 vl.3 and later, for detecting REU shadowing, 
this buffer must contain the current d^tory header. 
(BAM for 1571 and 1581 drives only) 
(BAM for 1581 drive only) 



total number of bytes in file (written to bytes 254, 255, 511, 
and 5 1 2 of the master index block), 
used by VBM cacheing routines, 
used by VBM cacheing routines, 
used by VBM cacheing routines. 



^used internally by GEOS disk routines; applications generally don't use. 
X error ($00 = no error). 

fileWrittent set to FALSE to indicate that file hasn't been altered since 
last updated. 



^used internally by GEOS disk routines; applications generally don't use. 
Destroys: a, y, rl, r4, r5. 



Description: 



UpdateRecordFile checks the fileWritten flag. If die flag is TRUE, which 
indicates the file has been altered since it was last updated, UpdateRecordFile 
writes the various tables kept in memory out to disk (e.g., index table, 
B AMA^BM) and time/date-stamps the directory entry. If the fileWritten flag is 
FALSE, it docs nothing. 

UpdateRecord writes out the index block, adds the time/date-stamp and 
(ileSize information to the directory entry, and writes out the new BAM/VBM 
witfi a call to PutDirHead or PutVBM (Commodore GEOS and Apple GEOS, 
respectively). 



298 



UpdateRecordFile 



C64 & C128: Because Commodore GEOS stores the BAM in global memory, the application 
must be careful not to corrupt it before the VLIR file is updated. If the 
fileWritten flag is TRUE and the BAM is reread from disk, the old copy (on 
disk) will overwrite the current copy in memory. In the normal use of VLIR disk 
routines, where a file is opened, altered, then closed before any other disk 
routines are executued, ho conflicts will arise. 



Example: 

See also: CloseRecordFile, OpenRecordFile. 



UpDirectory 



UpDirectory (Apple) 



high-level diskl 



Function: 

Parameters: 

Uses: 

Returns: 
Alters: 



Makes the parent directory the current directory, 
none. 



curDrive 
curKBIkno 



current directory. 



X error ($00 = no error). 

y pathname status ($00 = OK; BFR^OVERFLOW = pathname longer 
than pathnameBuO- 



curKBIkno 

curDirHead 

pathnameBur 

curDirTabLo^ 

curDirTabHit 



new current directory, 
header of new directory. 

system pathname buffer updated to reflect new path. 



Destroys: 



^used internally by GEOS disk routines: applications generally don't use. 
a, rOL, rl, r2, r4. 



Description: UpDirectory moves up one level in the hierarchical file system, making the 
parent directory the current working directory. If UpDirectory is called when 
the root directory is active, an AT_ROOT_DER error is returned. 

UpDirectory first changes the current key block number, then updates the 
pathname in pathnameBuf calling GetPathname if necessary. The current 
directory header is read in with a call to GetDirHead 

C64 & C128: Commodore GEOS does not support a hierarchical file system. 

Example: 

See also: SetGDirEntry, DeleteDir. 



300 



UseSystemFont 



lUseSystemFont (Apple, C64, ci28) text| 

Function: Begin using default system font (BSW 9) 
Parameters: none. 
Returns: nothing. 

Alters: curHeight height of font 

baselineOffset number of pixels fix>m top of font to baseline. 

cardDataPntr pointer to current font image data, 

cu r In dexTa ble pointer to current font index table. 

curSetWidth pixel width of font bitstream in bytes. 

Destroys: a» x, y, rO. 

Description: UseSystemFont calls LoadCharSet with the address of the always-resident 
BSW 9 font. . 

128 : In 80-column mode a double-width BSW 9 font is substituted. 

Example: 

See also: LoadCharSet, LoadAuxSet. 



o 



301 



VerifyBData 



VerifyBData (Ci28) 



Function: Compares (verifies) two regions of memory against each other. The regions may 
either be in firont RAM or back RAM (or one in front and the other in back). 

Parameters: rO ADDRl — address of first block in application memory (word). 

rl ADDR2 — address of second block in application memory (word). 

r2 COUNT — number of bytes to compare/verify (word). 

r3L AlBANK— ADD/?7 bank: = front RAM; 1 = back RAM (byte). 

r3H A2B ANK — ADDRl bank: = front RAM; 1 = back RAM (byte). 

Returns: r0-r3 unchanged. 

X $00 if data matches; $ff if mismatch. 



Destroys: a, y 

Description: VerifyBData is a blpck verify routine that allows the data in one region of 
memory to be compared to the data in another region in memory. The regions 
may be in either front RAM, back RAM, or in front and back. The ADDRl and 
ADDRl areas may overlap even if they are in the same bank. 

VerifyBData uses the DoBOp primitive by calling it with a MODE parameter 
of $03. 

Note: VerifyBData should only be used to compare data within the designated 

application areas of memory. 

Example: 

Ss^^ also: MoveBData, SwapBData, DoBOp. 



302 



VerifyRAM 



VerifyRAM (C64 vu & cns) mtl^ 



Function: Primitive for verifying (comparing) data in Commodore memory with data in an 
REU. 

Parameters: rO CBMADDR — address in Commodore to start (word)- 
rl REUADDR — address in REU bank to start (word). 
r2 COUNT — number of bytes to verify/compare (word). 
r3L REUS ANK — REU bank number to compare with (byte). 

Returns: r0-r3 unchanged. 

X error code: $00 (no error) or DEV_NOT_FOUND if bank or REU 

not available. " 
a REU status byte and*ed with $60: $40 data match 

$20 data mismatch 

Destroys: y 

Description: VerifyRAM compares a block of data in Commodore memory with a block of 
data in an REU bank. This routine is a "use at your own risk" low-level GEOS 
primitive 

VerifyRAM uses the DoRAMOp primitive by calling it with a CMD parameter 
of %10010011. 

Note: Refer to DoRAMOp for notes and warnings. 

Example: 

See also: StashRAM, FetchRAM, SwapRAM, DoRAMOp, VerifyBData. 



303 



VerticaiLine 



VerticalLine (Apple, C64, cns) 



graphics 



Function: 
Parameters: 



Draw a vertical line with a repeating bit-pattern. 

a eight-bit repeating pattern to use (not a GEOS pattern number). 

r4 XI — x-coordinate of line (word), 

r3L Yl — y-coordinate of topmost endpoint (byte). 

r3 H Y2 — y-coordinate of bottomost endpoint (byte). 

where (X1,Y1) and (XI, Y2) define the endpoints of the vertical line. 

dispBufferOn: 

bit 7 — write to foreground screen if set. 
bit 6 — write to background screen if set 

r3L, r3H, r4 unchanged. 

Commodore: 
a, X, y, r5L-r8L 

Apple; 
a, X, y 

Description: VerticalLine sets and clears pixels on a single vertical line according to the 
eight-bit repeating pattern. Wherever a 1-bit occurs in the pattern byte, a pixel is 
set, and wherever a 0-bit occurs, a pixel is cleared. 

Bits in the pattern byte are used top-to-bottom, where bit 7 is at the top.A bit 
pattern of % 1 1 1 10000 would create a vertical line like: 



Uses: 

Returns: 
Destroys: 



I 



i 



The pattern byte is always drawn as if aligned to a card boundary. If the 
endpoints of a line do not coincide with card boundaries, then bits are masked off 
the appropriate ends. The effect of this is that a pattern is always aligned to 
specific pixels, regardless of the endpoints, and that adjacent lines drawn in the 
same pattern align. 

Note: To draw patterned vertical lines using the 8x8 GEOS patterns, draw rectangles of 

one-pixel width by calling the GEOS Rectangle routine with identical x- 
coordinates. 



304 



VerWriteBlock 

VerWriteBIock (C64, C128) very low-level disk I 



Function: Very low-level verify block on disk. 

Parameters: rlL TRACK — valid track number (byte). 

rlH SE CTO R — valid sector on track (byte). 

r4 BUFFER — address of buffer of BLOCKSIZE bytes that contains data 
that should be on this sector (word). 

Uses: curDrive currently active disk drive. 

curType GEOS 64 v 1.3 and later for detecting REU shadowing. 

Returns: x error ($00 = no error). 

Destroys: a» y. 

Description: VerWriteBIock verifies the validity of a recently written block. If the block 
does not verify, the block is rewritten by calling WriteBlock. VerWriteBIock 
is a low-level disk routine and expects the application to have already called 
EnterTurbo and InitForlO. 



VerWriteBIock can be used to accelerate die verifies that accompany multiple- 
sector writes by first writing all the sectors and then verifying tiiem. This is often 
faster than verifying a sector immediately after writing it b5:ause when writing 
sequential sectors, the GEOS turbo code will catch the sector interleave. If a 
sector is written and then immediately verified, the turbo code will need to wait 
for the disk to make one complete revolution before die newly- written sector will 
again pass under the read/write head. By writing all the sectors first and catching 
the interleave, then verifying all the sectors (again, catching die interleave), the 
dead time when the turbo code i:> Waiting for the disk to spin around is 
minimized. Many of the higher-level disk routines that write multiple blocks do 
just this. 

VerWriteBIock is useful for multiple-sector disk operations where speed is an 
issue and the standard GEOS routines don't offer a decent solution. 
VerWriteBIock can function as the foundation of specialized, high-speed disk 
routines. 



Note: VerWriteBIock docs not always do a byte-by-byte compare with the data in 

BUFFER. Some devices, such as the Commodore 1541, can do a cyclic 
redundancy check on the data in the block, and this intemal checksum is sufficient 
evidence of a good write. Other devices, such as RAM-expansion units, have 
built-in bytc-by-byte verifies. 

Apple: VerWriteBIock docs not exist in Apple GEOS. To verify a block, read it into a 

general purpose buffer (diskBlkBuf, for example). If the block reads without 
an error, it verified. The ProDos device driver does its own checksum on data 
blocks, so a bytc-by-byte comparison of the data isn't necessary to determine if 
the block was properly written — rereading the block without an error is 
sufficient evidence of a good write. See PutBIock for more information. 



Example: Sec WriteBlock. 



VerWriteBlock 



See also: WriteBlock, PutBIock. 



307 



WarmStart 



WarmStart (Apple) Internal 



Function: Executes portions of the GEOS warmstart procedure (the same warmstart 
executed before a new application, desk accessory, or dialog box is started up). 

Parameters: none 

Returns: GEOS variables in a warmstart state; stack and application space unaffected 
Destroys: a, x, y, r0-r2 

Description: WarmStart is part of the GEOS warmstart procedure. It resets some GEOS 
variables and data structures (both global and local) to their default state, the state 
they are in when an application, desk accessory, or dialog box is started up. 
GEOS calls WarmStart internally, and is of Uttie use to an application. An 
application that needs to place GEOS in a warmstart state (for restarting, for 
example), is better off using StartAppI. 

See also: Firstlnit, StartAppI. 



308 



WriteBiock 



WriteBlock (C64, ci28) 



very low«level disk] 



Function: 
Parameters: 

Uses: 

Returns: 

Destroys: 

Description: 



Apple: 



Example: 



Very low-level write block to disk. 

rlL TRACK — valid track number (byte). 
rlH S ECTO R — valid sector on track (byte). 

r4 BUFFER — address of buffer of BLOCKSIZE bytes that contains data 
to write out (word). 



curDrive 
curType 



currently active disk drive. 

GEOS 64 vl.3 and later for detecting REU shadowing. 



error ($00 = no error). 



a, y. 



WriteBlock writes the block at BUFFER to the specified TRACK and 
SECTOR. If the disk is shadowed, WriteBlock will also write the data to the 
shadow memory. WriteBlock is pared down version of PutBlock. It expects 
the application to have already called EnterTurbo and InitForlO, and it does 
not vcnfy the data after writing it 

WriteBlock can be used to accelerate multiple-sector writes and their 
accompanying verifies by writing all the sectors first and then verifying them. 
TTiis is often faster than verifying a sector immediately after writing it because 
when writing sequential sectors, the GEOS turbo coidc will catch the sector 
interleave. If a sector is written and then immediately verified, the turbo code will 
need to wait for the disk to make one complete revolution before the newly- 
written sector will again pass under the read/write head. By writing all the sex:tors 
first and catching the interleave, then verifying all the sectors (again, catchirg tfie 
interleave), the dead time when the turbo code is waiting for the disk to spin 
around is minimized Many of the higher-level disk routines that write multiple 
blocks do just this. 

WriteBlock is useful for multiple-sector disk operations where speed is an issue 
and the standard GEOS routines don't offer a decent solution. WriteBlock can 
function as the foundation of specialized, high-sp^d disk routines. 

Apple GEOS has no WriteBlock equivalent Use PutBlock instead. To write a 
block without verifying the data, set numDiskRetries to $00 before calling 
PutBlock. See PutBlock for more information. 



;Write sector from diskBlkBuf to disk and then verify 
if necessary. 



Pass: 



track 

sector 

verify 



Returns: 

X 



track number 
sector on track 
verify data? (TRUE 



error code 



YES) 



309 



WriteBlock 



MyPutBlock : 



80$: 
99$: 



Loaaw 






MoveB 


r xJ^r uracK 


i WJLOlwl\ ilUlllMCX 


noveo 




ifi©ctor number 


jsr 




;ao Into turbo tnocie 


txa 




;set status flags 


bne 


99$ 


/branch if error found 


jsr 


InitFbrlO 


/prepare for serial I/O 


jsr 


WriteBlock 


/primitive write block 


tixa 




/set status flags 


bne 


80$ 


/branch if error found 


Ida 


verify 


/check verify flag 


beq 


80$ 


/branch if not verifying 


jsr 


VerWriteBlock 


/verify block we wrote 


jsr 


DoneWithIO 


/restore after I/O done 


rts 




/exit 



See also: PutBIock, ReadBlock, VerWriteBlock. 



310 



WriteFile 



WriteFile (Apple, C64, cns) 



mid-level disk 



Function: Write data to a chained list of disk blocks. 
Parameters: r7 DATA — pointer to start of data (word). 
Commodore: 

r6 TSTABLE — pointer to a track/sector list of blocks to wnte data to 
(unused but allocated in the BAM), usually a pointer to 
fi!eTrScTab+2; BlkAUoc can be used to build such a list. Apple 
GEOS uses the table in INDEXBLOCKBUF (word). 



Uses: 



curDrive 

CQiinmcK^prg; 
curType 



GEOS 64 vl.3 and later for detecting REU shadowing. 



Returns: 
Destroys: 



Appig; 

RWbank bank BUFFER is in (MAIN or AUX). 

INDEXBLOCKBUF index block for chain (in auxiliary memory; see 

below for information on accessing this buffer). 

X error ($00 = no error). 



Apple; 

a, y, rl, r4. 

Commodorg; 
• a, y, rl-r2, r4, r6-r7. 

Description: WriteFile writes data from memory to disk. The disk blocks are verified, and 
any blocks that don't verify are rewritten. 

Although the name "WriteFile" implies that it writes "files," it actually writes a 
chain of blocks and doesn't care if this chain is an entire sequential file or merely 
a VLIR record. 

C64 & C128: WriteFile uses the track/sector table at TSTABLE as a list of linked blocks that 
comprise the chain. The end of the chain is marked with a track/sector pointer of 
$00,$ff. WriteFile copies the next 254 bytes from the data area to 
diskBlkBuf+2, looks two-bytes ahead in the TSTABLE for the pointer to the 
next track/sector, and copies those two-bytes to dskBIkBuf+0 and 
dskBlkBuf+1. WriteFile then writes this block to disk. This is repeated until 
the end of the chain is reached 

WriteFile does not flush the BAM (it does not alter it eidier — it assumes the 
blocks in the track/sector table have already b^n allocated). See BlkAUoc, 
SetNextFree, and AlIocateBIock for information on allocating blocks. See 
PutDirHead for more information on writing out the BAM. 



Apple: 



Apple GEOS uses the internal index block buffer INDEXBLOCKBUF (in 
aujoliary memory) as a list of blocks that comprise the chain. Applications cannot 



311 



WriteFile 



directly access this buffer, but MoveAuxData can be used to copy the index 
block from the appliciation's memory space to INDEXBLOCKBUF: 



AOXtoMAIN 
MAINtoAOX 

LoadW 

LoadW 

LoadW 

Ida 

jsr 



%10000000 
— %01000000 

rO, ImylndexBlock 
rl, # INDEXBLOCKBUF 
r2, «BLOCKSIZ£ 
#MAINtoAOX 
MoveAuxData 



;copy from app. main 
;to temp high aux 
;move a full block 
;copy main to aux 



WriteFile does not write the index block out to disk, 

WriteFile does not flush the VBM cache (it does not alter it either — it assumes 
the blocks in the index block have akeady been allocated). See BlkAlIoc, 
SetNextFree, and AlIocateBIock for information on allocating blocks. See 
PutVBM for more information on flushing the VBM cache. 

WriteFile first writes the blocks out in a tight loop, then makes a second pass, 
rereading each into diskBikBuf to verify the data. If a verify error occurs, the 
entire file is rewritten. 



Example: 
See also: 



SaveFile, WriteRecord, ReadFile. 



312 



WriteRecord 



WriteRecord (Apple, C64, ci28) 



VLIR disk 



Function: 



Write data to the cunent VLER record. 



Parameters: r2 



Uses: 



Returns: 
Alters: 



r7 



BYTES — data bytes to write to record. Commodore version can write 
up to 32,258 bytes (127 Commodore blocks); Apple version can write 
up to 64,512 (126 ProDOS blocks) (word). 
RECD ATA — pointer to start of record data (word). 



curDrive 
nieWrittent 

curRecord 
fileHeader 

Cpmmcxlprp; 

curType 

curDirHead 

dir2Headt 

dirSHeadt 

App le: 

RWbank 

curVBikno+ 

VBMchangedt 

numVBMBIkst 



if FALSE, assumes record just opened (or updated) and 

reads BAMATBM into memory. 

current record pointer. 

VLIR index table stored in this buffer. 



GEOS 64 vl.3 and later for detecting REU shadowing, 
current directory header/B AM. 
(BAM for 1571 and 1581 drives only) 
(BAM for 1581 drive only) 



bank RECD ATA is written from (MAIN or AUX). 
used by VBM cacheing routines, 
used by VBM cacheing routines, 
used by VBM cacheing routines. 



^used internally by GEOS disk routines; applications generally don't use. 
X error ($00 = no error). 



fileWrittent 

fileHeader 

fileSize 

Commodore: 
fileTrScTab 



curDirHead 

dir2Headt 

dirSHeadt 

Applg; 
fileBytes 



set to TRUE to indicate the file has been altered since last 
updated 

index table adjusted to point to new chain of blocks for 
current record. 

adjusted to reflect new size of file. 



Contains track/sector table for record as returned from 

B Ik Alloc. The track and sector of the first block in the 

record is at fileTrScTab+0 and fileTrScTab+l. The end 

of the table is marked with a track value of $00. 

current directory header/B AM modified by write operation. 

(BAM for 1571 and 1581 drives only) 

(BAMfor 1581 drive only) 



adjusted to reflect new size of file. 
^used internally by GEOS disk routines; applications generally don't use. 



313 



WriteRecord 



Destroys: 



Description: 



Note: 



Apple: 



Apple: 

a, y, rl-r4, r6, r7, r8H. 

ComiTiodgre; 
a, y, r0-r9. 

WriteRecord writes data to the current record All blocks previously associated 
with the record are freed. BIkAIloc is then used to allocate enough new blocks 
to hold BYTES amount of data (Apple GEOS will allocate one ProDOS index 
block in addition to the data blocks). The data is then written to the chain of 
sectors by calling WriteFile. The flleSize variable is updated to reflect the new 
size of the file. Apple GEOS also updates fileBytes* 

WriteRecord does does not write the BAMA^BM and internal VLIR file 
information to disk. Call CIoseRecordFile or UpdateRecordFiie when done 
to update the disk with this information. 

WriteRecord correctly handles the case where the number of bytes to write 
{BYTES, R2) is zero. The record is freed and marked as allocated but not in use. 

When WriteRecord returns, the index block of the record just written is in the 
aux. memory buffer INDEXBLOCKBUF. Applications cannot access this 
buffer direcdy. MoveAuxData can be used, however, to copy the block into the 
appliciation's memory space if access to it is necessary: 



AUXtoMAIN 
MAINtoAUX 

LoadW 

LoadW 

LoadW 

Ida 

jsr 



%10000000 
== %01000000 

rO, # INDEXBLOCKBUF 
rl, #diskBlkBuf 
r2, #BLOCKSIZE 
#APXtoMAIN 
MoveAuxData 



/copy from index blk 
;to tiemp buffer 
;move a full block 
;copy aux to main 



Example: 
See also: 



ReadRecord, WriteFile. 



314 



GEOS Quick Reference 



Name 


€64 


C128 


Apple 


Description 


AllocateBIock 


$9048 


S9048 


S0300 


Mark a disk block as in-use. 


AppendRecord 


$c289 


$c289 


S0330 


Insert a new VLIR record after the current record. 


AuxDExil 


n/a 


n/a 


Sefa9 


Aux-driver deinstall and exit routine. 


AuxDInt 


n/a 


n/a 


Sefa3 


Aux-driver interrupt level routine. 


AuxDKevFilter 


n/a 


n/a 


Sefa6 


Aux-driver keypress filter. 


AuxDMain 


n/a 


n/a 


SefaO 


Aux-driver MainLoop level routine. 


BBMult 


$cl60 


Scl60 


Sfecc 


Byte by byte (single-precision) unsigned multiply. 


Bell 


n/a 


n/a 


Sff86 


1000 Hz Bell sound. 


BitmapClip 


$c2aa 


Sc2aa 


SfeSa 


Display a compacted bitmap, clipping to a sub-window. 


BiimapUp 


$cl42 


$cl42 


Sfe54 


Display a compacted bitmap without clipping. 


BilOlherClip 


$c2c5 


$c2c5 


SfeSd 


BitmapClip with data coming from elsewhere (e.g.. disk) 


BldGDirEntiy 


$clf3 


$clf3 


$036f 


Build a GEOS directory entry in memory. 


BlkAlIoc 


Sclfc 


Sclfc 


S0351 


Allocate space on disk. 


BlockProcess 


SclOc 


SclOc 


$feb4 


Block process from running. Does not freeze timer. 


BMuIt 


$cl63 


$cl63 


Sfecf 


Byte by word unsigned multiply. 


BootGEOS 


ScOOO 


ScOOO 


n/a 


Reboot GEOS. Requires only 128 bytes at ScOOO. 


CalcBlksFree 


Scldb 


Scldb 


$0324 


Calculate total number of free disk blocks. 


CallRouline 


$cld8 


Scld8 


$ff08 


pseudo-subroutine call. $0000 aborts call. 


CancelPrinl 


n/a 


n/a 


$6018 


Cancel printing, clearing printer and I/O card buffers. 


ChangeDiskDevice 


$c2bc 


Sc2bc 


n/a 


Instruct CBM drive to change its serial device address. 


ChkDkGEOS 


Sclde 


Sclde 


n/a 


Check CBM disk for GEOS format. 


ClearCard 


n/a 


n/a 


$6715 


Clear any buffered I/O operations. 


ClearMouseMode 


Scl9c 


Scl9c 


$fe9f 


Slop input device monitoring. 


ClearRam 


$cl78 


$cl78 


$fefc 


Clear memory to $00. 


Clocklni 


n/a 


n/a 


$0803 


Clock driver interrupt level routine. 


CloseCard 


n/a 


n/a 


$670c 


Close access to I/O card. 


CloseRecordFile 


$c277 


$c277 


$0333 


Qosc currently open VLIR file. 


CmpFString 


$c26e 


$c26e 


$fefO 


Compare two fixed-length strings. 


CmpString 


$c26b 


Sc26b 


$feed 


Compare two null-terminated strings. 


CopyFString 


$c268 


Sc268 


Sfeea 


Copy a fixed-length string. 


Copy Full Screen 


n/a 


n/a 


$ff92 


Fast vertical screen copy. 


CopyLinc 


n/a 


n/a 


SffSf 


Bit-boundary horizontal line copy. 


CopyScreenBlock 


n/a 


n/a 


$ff5c 


Bit-boundary rectangle copy. 


Copy String 


$c256 


Sc256 


$fee7 


Copy a null-terminated string. 


CRC 


$c20e 


Sc20e 


$ffl4 


Cyclic Reduncancy Check calculation. 


Dabs 


$cl6f 


$cl6f 


$fedb 


Double -precision signed absolute value. 


Ddec 


$cl75 


$cl75 


$feel 


Double-prccison unsigned decrement. 


Ddiv 


$cl69 


$cl69 


$fed5 


Double-precision unsigned division. 


DeleteDir 


n/a 


n/a 


$037c 


Delete directory. 


DeleteFile 


$c238 


$c238 


$0357 


Delete file. 


DeleteRecord 


$c283 


Sc283 


$0336 


Delete current VLIR record. 


DisablSprile 


$cld5 


Scld5 


$feab 


Disable sprite. 


DivideBySeven 


n/a 


n/a 


$ff68 


Quick division by seven for direct screen access. 


DMull 


$cl66 


$cl66 


$fed2 


Double-precision unsigned multiply. 


Dnegate 


$cl72 


Scl72 


Sfede 


Double-precision signed negation. 


DoBOp 


n/a 


$c2ec 


n/a 


C128-backram memory primitive. 


DoDlgBox 


$c256 


Sc256 


Sffl7 


Display and begin interaction with dialog box. 


Dolcons 


$cl5a 


Scl5a 


$feOc 


display and begin interaction with icons. 


DoInlineRetum 


Sc2a4 


Sc2a4 


$fe09 


Return from inline subroutine. 


DoMenu 


$cl51 


SclSl 


$feOf 


Display and begin interaction with menus. 


DoneWithIO 


$c25f 


Sc25f 


n/a 


Restore system after I/O across CBM serial bus. 


DoPreviousMenu 


$cl90 


$cl90 


$fel5 


Retract sub-menu and reactivate menus up one level. 


DoRAMOp 


$c2d4 


Sc2d4 


n/a 


CBM RAM-expansion unit access primitive. 


DownDirectory 


n/a 


n/a 


$0381 


Open subdirectory. 


DrawLine 


$cl30 


Scl30 


$fe33 


Draw, clear, or recover line between two endpoints. 


DrawPoint 


$cl33 


Scl33 


$fe21 


Draw, clear, or recover a sinf^le screen point. 


DrawSprite 


Sclc6 


Sclc6 


$fea2 


Define sprite image. 



1 



GEOS Quick Ref- 



Name C64 C128 Apple Description 



Uouiv 




sir 1 




LAJUDiC'prcvlslUlX algllCvX UlViSIUIl* 










rVMihlA.nrACicinn l^ft chift /7Ame chiftA/1 ^n^ 
Li/\^UUlcpi wwiaiv/ix icil 911111 ^^ClUa 911111CU Ul^« 


1111 llxl {^UL 


$c262 


$c262 


Sfec9 


Oouble-Drecision richt shift (7&t(^^ shifted in^ 

(KTWUk'tW 1^1 W^iA IV/tl I Jlll&fc dlUlbWU lily* 




$cl09 


$cl09 


$fec3 


Make a process ninable immediately. 


Ciiauiopn W 


Scld2 


$cld2 


t91 vOO 


Fnable snrite 


cnicr L</CdJv,i \jy 


Sc22c 


$c22c 


Sff59 


l^ave annlication and return to GPOS rfe^VTmi 


cnici 1 uruo 




Sc9l4 


n'/fl 
11/ tt 


Artivflt^ r^RM Hiclf tiirtv^ nn nirrAnt HriVA 

/^wlXvttVC ^X^ITI V41dl^ lUX U\/ Ull VUXIwlll UXi*v* 




n/a 


n/a 


$ff3e 


Frase text character from screen 


CaH 1 lUUU 


$c232 


$c232 


n/a 


Deactivate CBM dislc turbo on current drive 




$c244 


Sc244 


n/a 


Ouiclc file delete ^renuires full track/sector Hst^ 


I7Tvrr%A e Tn D 1 r 

1 ur 1 ypcsini«/ix 


11/ a 


n/a 
11/ a 


S0363 


FinH fllAC in rfirActorv nthAr fhsin nirrAnf rfir<»/*torv 

rUlU X11C9 Xil UtiCWlWljr VJUICl UIOJI WUllClll vlllCvlvljT* 


CptrViR AM 


Sc2cb 


Sc2cb 


n/a 


Transfer data from CRM R AM-exnansion unit 




$cl7b 


$cl7b 


$feff 


Fill memorv with a tiarticular bvte 


r inoD Mjvi o 1 1 




Sc2ad 


n/a 


Get allocation statue of narticular CRM disk block 
vjwv oitv^ttuvit dMiiua %jl pcuuwuittx y^oiyk ui9iw l/jv/wil* 


rinanie 


SclOb 


SclOb 


S0369 


^Anrrh for a nnrtinilaT* filA 


rinur i ypes 






S0366 


FinH all files of a nartimlar GFO^ tvTV* 
1 liiu cux xuca vix a }j<uuvui<u vJbvyo ijr^^* 


Firiii V dviJDii 


11/ a 


n/a 


$03 6c 


Get allocation status of narticular ProDOS disk block 


nrsiinii 


$c271 


$c271 


$ffll 


GFOS startUD entrv ooint 


rnariiinjL/ir 


n /a 

11/ A 


n /fl 
11/ a 


S036c 


Finrf a file in a directorv other than current rfirectorv 


roiiuw\^naiTi 




$c905 


n/a 


Follow chain of f^R^4 sectors hiiilHina traclf /sector table 


rraiTic ivcciajigic 


«9ir 1^1 






TV*aw a rActanaular frame ^011flinA^ 
§1^1 aw a icvuuif^uiax xiOJiic yuuiiiiicy* 








$039fl 

«9w J ^tt 


Mflrlr a Hislr hloclr as not.in.iicA 
ivinxiw tf uisjw uiiyviw sd iivi*iJi"U9C» 


rreeuir 


n/fl 

n/a 


n/a 


^uJ ua 


Ptaa all hlnoVc accf%/*i9tAH u/itK o eiiYv4irA/^f/^T\/ 
nCC all UlUvKa odbUCIalCU Wiui a suuuirvduiy. 


FrecFile 






«9 vJ J tt 


FrAA all hlocire accocatiatAH ti/ith a filA 
1 ICC OJX Ulv/Ui^a ttddU^aiialcu wiui tt XllC* 


FrcczcProcess 


1 1 ^ 




SIfAhfl 


PaiiCA a nrfYCACC cmmtHi^u/n ftmA^ 
1 ausc tt piuwcaa vuumuuwii uinci* 


vj c 1 1 s 1 1^ I r cn uy 






S039c 


Ga? first HirAcforv Antrv 

VJCi XlXdi UlXCvlUljr ClllXjr* 








S0300 


RabH sinolA Hislr hloclr info mAmorv 
xxcau dxiigic vxiaiw uiuviw xiiiu iiiciiiuiy* 








«91CO / 


GnlciilatA wiHth of characfAT vi/ithoiif ct\/lA attrihiitAC 
Vvttiii^uiaic wiuui ux wiittittwici wiuiuuL aijic aiuiuuicSt 


At III An c t An c 




d> # 7V/V 


n /fl 
11/ tt 


GAt GT)M nrintAr nnoe HimAnsione 
wci \^ovn piiiiicx pa^c uiiiiciuiuua* 


/^Atr\trUA4<4 
vjciL/irneau 






S0379 


RAttH HirActorv hAaHAT into mATTmr\/ 
ixcau uiicviuxjr iicttvici xiiiu luciiiury* 


O At P14 rfrTn f r> 




$c92Q 


S0390 

«9 V J 7 W 


RAaH a GFO^ file hearlAr into mAmnrv 
xvcttu tt vjbvyo xxic iicaucx xiiiw iiiciiiuiy« 


vjcinie 






S030f 


Load GEOS file 


nAtFrAAnirRIk 

VJCltiCCLi/lI OlIW 


$clf6 


$clf6 


$0375 


Find an emotv directorv slot 

1 iiiu cut ^tn\jvy uiiv>wv\jijr ^tw^* ^ 


VJCULAA T <U 9 


n/a 


n/a 


$ff44 


Transfer internal Ld variables to GEOS nseudorecisters 




n/a 


n/a 


$6012 


Return current orintcr resolution anH setahle attributes 


GetNextChar 


Sc2a7 


Sc2a7 


$fe75 


Get next character from character aueue 


OptMY tnirFntrv 


$9033 


$9033 


$039c 


Get directorv entrv other than first 


GAtPatViTiAmA 


n/a 


n/a 


$0384 


Return current oath strini? 


r«AtPflttf>m 

VJvll Alien t 


n/a 


n/a 


$ff7d 


Get eieht-bvte GEOS nattem definition 




$c298 


$c298 


$ff56 


Return nointer to current disk name 


vjcilx aJiQOTTl 


SIrl 87 




Sfee4 

«91CC*T 


f^alcitlatA nAU/ ranHom numt^r 
\^aiwuiaic new xaJiuuiii iiuiiiia?i* 




«9U i U 1 


$clbl 


$fe84 


Calculate actual character si7e with attributes 






«9V X .^V 


$fe66 


CalciilatA ccanlinA aHHrACC 
v^ttiwuittic a^ojiiiiic Buvxxcaa* 


^AtQ^^AAnT inA 


n/fl 
n/ tt 


n /o 
11/ tt 


Sff62 


. Conv Annie ccrAAn Hata to huff at 

' VfUpjr /^ppiC 9V1CC11 UBltt lU uuxxcx* 


^AtC Ariiil^iimKAT 




«JW X7U 


$4b38 


Return GFO^ CArial number or nointer to namA ctrino 
ixwiuiii VifCrWO 5Ciiax iiixjiiucx ui puxiiici uj jittjiic auuij^. 


r^At^TYrif ADfttn 


.11/ a 


n /tt 
11/ tt 


$ff6e 


Get cnrifA imnoe Hafa 
vjci dpi lie xjiittj^c uaitt* 


OAiQtrino 
VJcio u lliK 


Sclba 


t9W X l/tt 


$fe72 


Get 'strinv innut from user 

VJCt SUlllJ^ llipUL XlVIXII U9wl» 


nAtVRM 


n/a 


n /tt 
11/ tt 


$03 le 


Read first VRM block into VRM cache 

ixwau xiidi T oivx v/ivAi'^ liiiv/ TijiTX va^iic* 


vjo L/ireciury 


n/a 


n/fl 
11/ tt 


$03 9 f 


Go Hirectorv to a STV*cific suhHirActoin/ 
vjv uxxcviuxy lu tt d^i^vtxxw dui/uixcviuiy* 


ftotoPircf K^Ami 
vju lu ni^ uviciiu 


Sclbd 




$fel8 


Retract all sub.menus and reactivate at main level 
i\vu aw oil auu iiiwiius oiiu icawixvttic tti iiiaxii iwvei* 


vjiapnicso u 




X JO 


Sfe60 


pYACIltA o ctTincT of (TTanhicc rommanrle 

bACvuic tt SIX Ills ^k {^lapiiiva vununaiius* 


HideOnlyMouse 


n/a 


$c2f2 


$ff7a 


Temporarily remove soft-sprite mouse pointer. 


Horizontal Line 


Sells 


$cll8 


$fe27 


Draw a patterned horizontal line. 


i_BitmapUp 


Sclab 


$clab 


$fe57 


Inline BiimapUp. 


i_FillRam 


Sclb4 


$clb4 


$ff02 


Inline FillRam. 


i_FrameReciangle 


Scla2 


$cla2 


$fe42 


Inline FrameRectangle. 


i_GraphicsString 


SclaS 


$cla8 


$fe63 


Inline GraphicsString. 


iJmprintRectangle 


Sc253 


Sc253 


$fe51 


Inline ImprintRectangle. 



2 



GEOS Quick Reference 



Name C64 C128 Apple Description 



i MoveData 


$clb7 


$clb7 


$fef9 


Inline MoveData. 


i NewBitUo 


n/a 


n/a 


$ff9c 


Inline NewBilUp. 


LPuiSlring 


Sclae 


$clae 


$fe6c 


Inline PutString. 


i RecoverRectanKle 


$cla5 


$cla5 


$fe4b 


Inline RecoverRectanRlc. 


i Rectanf^le 


$cl9f 


$cl9f 


$fe3c 


Inline Rectangle. 


ImprintLine 


n/a 


n/a 


$ff8f 


Imprint horizontal line to background buffer. 


ImprinlRectanKle 


$c250 


$c250 


$fe4e 


Imprint rectangular area to background buffer. 


InfoCard 


n/a 


n/a 


$670f 


Get I/O card attributes. 


InitCard 


n/a 


n/a 


$6700 


Intialize I/O card. 


InilForDialoK 


n/a 


n/a 


$ff4a 


Internal pre-dialog box intialization. 


InitForlO 


$c25c 


$c25c 


n/a 


Prepare CBM system for I/O across serial bus. 


InitForPrint 


$7900 


$7900 


$6000 


Initialize printer (once per document). 


InitMouse 


$fe80 


$fe80 


$fOOO 


Initialize input device. 


InitProcesses 


$cl03 


$cl03 


$feae 


Intialize processes. 


InilRam 


$cl81 


$cl81 


$ff05 


Initialize memory areas from table. 


InitSprile 


n/a 


n/a 


$ff32 


Initialize software sprites. 


InitTexiPrompl 


SclcO 


$clcO 


$fe78 


Initialize text prompt. 


InputByle 


n/a 


n/a 


$6709 


Read byte from I/O card. 


InseriRecord 


Sc286 


$c286 


$0339 


Insert new VLIR record in front of cuncnt record. 


IntemiptMain 


SclOO 


$clOO 


$fe03 


Main interrupt level processing. 


InvcrtLine 


Scllb 


$cllb 


$fe2d 


Invert the pixels on a horizontal screen line. 


InvertRectangle 


$cl2a 


$cl2a 


$fe45 


Invert the pixels in a rectangular screen area. 


IrqMiddle 


n/a 


n/a 


$ff20 


Software interrupts entry point. 


IsMselnRej^ion 


$c2b3 


$c2b3 


$fe9c 


Check if mouse is within a screen region. 


JsrToAux 


n/a 


n/a 


$03b4 


Call aux -memory subroutine. 


KeyFiller 


n/a 


n/a 


$f009 


Input driver keypress filter. 


LdApplic 


$c21d 


Sc21d 


$03 8d 


Load GEOS application. 


LdDeskAcc 


$c217 


$c217 


$035d 


Load GEOS desk accessory. 


LdFile- 


$c211 


$c211 


$0312 


Load GEOS data file. 


IjoadAuxSet 


n/a 


n/a 


$fn7 


Use aux-memory character set. 


LoadCharSet 


Sclcc 


$clcc 


$fe8a 


Use main-memory character set. 


MainLoop 


$clc3 


$clc3 


$feOO 


GEOS MainLoop processing. 


MakeSubDir 


n/a 


n/a 


$0387 


Create ProDOS subdirectory. 


MouseOff 


Scl8d 


$cl8d 


$fe96 


Disable mouse pointer and GEOS mouse tracking. 


MouscUp 


$cl8a 


$cl8a 


$fe99 


Enable mouse pointer and GEOS mouse tracking. 


MoveAuxData 


n/a 


n/a 


$ff6b 


Apple aux-memory memory move routine. 


MoveBData 


n/a 


$c2e3 


n/a 


128 backram memory move routine. 


MoveData 


$cl7c 


$cl7e 


$fcf6 


Memory move routine. 


NewBitClip 


n/a 


n/a 


$ff95 


Bit-boundary BitmapClip. 


NewBitOlherClip 


n/a 


n/a 


$ffOe 


Bit-boundary BiiOtherClip. 


NewBiiUp 


n/a 


n/a 


$ffld 


Bit-boundary BitmapUp. 


NewDisk 


Sclel 


$clel 


n/a 


Tell CBM disk turbo software that a new disk is in drive. 


NexiRecord 


Sc27a 


$c27a 


$0336 


Make next VLIR the cuncnt record. 


NormalizeX 


n/a 


$c2e0 


n/a 


Normalize CI 28 X-coordinates for 40/80 modes. 


NxtBlkAlloc 


$c24d 


$c24d 


$0354 


Version of BlkAlloc diat starts at a specific block. 


OpenCard 


n/a 


n/a 


$6703 


Open I/O card for access. 


OpenDisk 


$c2al 


$c2al 


$0399 


Open disk in current drive. 


OpenRecordFile 


$c274 


$c274 


$033f 


Open VLIR file on current disk. 


OuipuiByte 


n/a 


n/a 


$6706 


Write byte to I/O card. 


Panic 


$c2c2 


$c2c2 


$fef3 


System-error dialog box. 


PointRecord 


$e280 


$c280 


$0342 


Make specific VUR record the current record. 


PosSprite 


$clcf 


$clcf 


$fea5 


Position sprite. 


PreviousRecord 


$c27d 


$c27d 


$0345 


Make previous VLIR record the current record. 


PrinlASCU 


$790f 


$790f 


$600c 


Send ASCII data to printer. 


PrintBuffer 


$7906 


$7906 


$6009 


Send graphics data to printer. 


PromptOff 


$c29c 


$c29e 


$fe7c 


Turn off text prompt. 


PrompiOn 


$c29b 


$c29b 


$fe7b 


Turn on text prompt. 


PurgeTurbo 


$c235 


$c235 


n/a 


Remove CBM disk turbo software from drive. 



3 



GEOS Quick Reference 









Apple 


L/cScripiion 


PutBlock 


$cle7 


$cle7 


C Al Al 

$0303 


Write singel disk block from memory. 


PutChar 


$Cl45 


$Cl45 


SfeSl 


Display a single character to screen. 


PutDecimal 


Cm 1 QA 

ChClo4 


5Clo4 


5teof 


Format and display an unsigned double-precison number. 


PulDirrleaa 


^^OA t> 

«>cz4a 


%bc24a 


C Al 11m. 

50370 


Write directory header to disk. 


PutScreenLine 


n/a 


n/a 


5lio5 


Copy buffer data to Apple screen memory. 


PutString 


)Cl4o 


5Cl4o 


5ieoy 


Print string of characters to screen. 


PUlVBM 


n/a 


n/a 


CA10 1 

50321 


Flush VBM cache; write currently cached block to disk. 


ReadBackLine 


n/a 


n/a 


cm A 
511/4 . 


Get data from background screen in linear bitmap format. 


ReadBlocK 


ScZla 


shc2la 


n/a 


CBM get disk block primitive. 


ReadByte 


ChCZDO 


OCZDO 




Read disk file a byte at a time. 


ReadCIocK 


n/a 


n/a 


CAQ AA 

50oOO 


Update ObUo time/date variables from clock hardware. 


Read rile 


)ClIi 


5CllL 


CA1 1 < 

50J ID 


Read chained list of blocks into memory. 


ReadLinx 


CQAy* U 


Q Ail U 


n/a 


DmoJ f^^\M CwMmI* /oMM^MM IZ^tv 

Keaa k^dM tracK/sector iiruc. 


Read Record 


$c2oc 


$c2oC 


CA1 O 

50348 


Read current VLIR record into memory. 


ReadScanLme 


n/a 


n/a 


5ll95 


Get data from foreground screen in linear bitmap format. 


RecoverAllMenus 


5cl57 


$C1D7 


CTmI M 

5iele 


Recover all menus from background buffer. 


RecoverFG 


n/a 


n/a 


CA'5 «M 

503 ae 


Restores foreground screen from data created with SaveFG. 


RecoverLine 


«hci le 


Pm 11m 

5ci le 


5iejo 


Recover horizontal screen line from background buffer. 


RecoverMenu 


JiCl j4 


C*»1 CA 
v>Cl J4 


^tei 


Recover single menu from background buffer. 


RecoverRectangle 


)ciza 


C/*1 


5ie4o 


Recover rectangular screen area from background buffer. 


RecoverSysRam 


n/a 


n/a 


5tl53 


Restore system after dialog box or desk accessory. 


Rectangle 


Scl24 


Cm 1 i4 

5cl24 


5ie39 


Draw a filled rectangle. 


ReDoMenu 


Scl93 


ff ^ 1 A1 

$cl93 


5iel2 


Reactivate menus at the current level. 


Renamerile 


$c23*^ 


Sc2j9 


C A*! 0*5 

50393 


Rename ObUo disk rile. 


ReOpenDisk 


n/a 


n/a 


C Al 

503 a2 


Reopen disk to previous directory. 


ReseiAlarm 


n/a 


n/a 


C AO Am 

50oOC 


Disable clock driver alarm. 


ResetHandle 


5cv}03 


CmAAI 

5 c 003 


n/a 


Internal bootstrap entry point. 


RestartProcess 


SclOo 


C M 1 A^ 

5clOo 


5reDl 


Unblock, unfreeze, and restart process. 


ResloreFontData 


n/a 


n/a 


c en o 

5ir3o 


Restore font variables from saveFontTab. 


RstrAppl 


Sc23e 


5c23e 


C A1 ^ A 

50360 


Leave desk accessory and return to calling application. 


RstrFrmDialog 


Sc2bf 


$c2bi 


$rila 


Exit dialog box. 


SaveFG 


n/a 


n/a 


CA1 >U 

503aD 


Save foreground screen data for RestoreFG. 


5aveFile 


Scled 


CmI m,J 

Scled 


CA1 1 O 

503 1 5 


Save/create a ObUS file. 


• SaveFontData 


n/a 


n/a 


cm< 


Copy font variables to saveFontTab. 


SetAlann 


n/a 


n/a 


ff AQ AA 

50ooy 


Set clock driver alarm. 


SeiDevice 


^CZDU 


5CxD0 


n/a 


Establish communication with a new serial device. 


SetGDirEntry 


$ClfO 


Cm 1 fi\ 

5clrO 


CAO "7U 

5037D 


Create and save a new GEOS directory entry. 


SetGEOSDisk 


Sclea 


CmI mm 

5clea 


. /m 

n/a 


Convert normal CoM disk mto GEOS format disk. 


SelLdVars 


n/a 


n/a 


5li47 


Set internal Ld variables from GEOS pseudoregisters. 


SetMode 


n/a 


n/a 


C ^ A t C 

$6015 


Set print mode. 


SetMouse 


n/a 


5feoy 


n/a 


Reset input device scanning circutry. 


SeiMsePic 


n/a 


5c2da 


5rr2i 


Set and preshift new soft-sprite mouse picture. 


SetNewMode 


n/a 


5c2da 


n/a 


Lnange UbUo 12o graphics mode (40/80 switch). 


SeiNextFree 


ff-^'^ A'^ 

Sc292 


5c292 


CA1U 

5032a 


Search for nearby free disk block and allocate it. 


SetNLQ 


57915 


(PT A 1 < 

$7915 


n/a 


Begin near-letter quality printing. 


SeiPaitem 


$cl39 


$cl39 


5iejo 


Set current fill pattern. 


SetTimeDate 


n/a 


n/a 


C AO AiC 

50oOO 


Set clock driver time and date. 


SeiUserPattem 


n/a 


n/a 


5lIoO 


ueime new ubUo pattern image. 


Sleep 


$clV9 


CmI AA 

5cl99 


5teco 


Put current subroutine to sleep for a specified time. 


SlowMouse 


$feo3 


Sfe83 


5 too J 


Reset mouse velocity* variables. 


SmallPuiChar 


$C2U2 


Cm'^ A*^ 

5c202 


5ievo 


Fast character print routine. 


SoitSprHandler 


n/a 


n/a 


5li2C 


Apple soft- sprite drawing routine. 


SorlAlpna 


n/a 


n/a 


CAI A< 

50 J a3 


Insertion sort. 


StartAppl 


$c22f 


$c22f 


$fe06 


Warmstart GEOS and start application in memory. 


StartASCn 


$7912 


$7912 


$6006 


Begin ASCII mode printing. 


StartMouseMode 


$cl4e 


$cl4e 


$fe93 


Start monitoring input device. 


SiartPrint. 


$7903 


$7903 


$6003 


Begin graphics mode printing. 


StashRAM 


$c2c8 


$c2c8 


n/a 


Transfer memory to CBM RAM-expansion unit. 



4 



GEOS Quick Reference 



Name 


C64 


C128 


Apple 


Description 


StatusCard 


n/a 


n/a 


$6712 


Get current status of I/O card. 


StopPrint 


$7909 


$7909 


$600f 


End page of printer output. 


SwapBData 


n/a 


$c2e6 


n/a 


C128 memory swap between front/back ram. 


SwapMainAndAux 


n/a 


n/a 


$ff71 


Apple memory swap between main and aux. 


SwapRAM 


$c2ce 


$c2ce 


n/a 


CBM RAM -expansion unit memory swap. 


TempHideMousc 


n/a 


$c2d7 


$ff29 . 


Hide soft-sprites before direct screen access. 


TestPoint 


$cl3f 


$cl3f 


$fe24 


Test status of single screen point (on or off?). 


ToBasic 


$c241 


$c241 


n/a 


Call Commodore BASIC. 


UnblockProcess 


SclOf 


$clOf 


$fcb7 


Unblock a blocked process, allowing it to run again. 


UnfrcezeProcess 


Scll5 


$cll5 


$febd 


Unpause a frozen process timer. 


UpdateMouse 


$fe86 


$fe86 


$f006 


Update mouse variables from input device. 


UpdateParent 


n/a 


n/a 


$03 b7 


Update parent directory to reflect any changes. 


UpdateRecordFile 


$c295 


$c295 


$034b 


Update currently open VLIR file without closing it. 


UpDireciory 


n/a 


n/a 


$03 8 a 


Close current directory and move up one level. 


UseSystemFont 


$cl4b 


$cl4b 


$fe8d 


Use default system font (BSW 9). 


VerifyBData 


n/a 


$c2e9 


n/a 


CI 28 backram verfiy. 


VerifyRAM 


$c2dl 


$c2dl 


n/a 


CBM RAM-expansion unit verify. 


VerticalLine 


$cl21 


$cl21 


$fe2a 


Draw a patterned vertical line. 


VerWriteBlock 


$c223 


$c223 


n/a 


CBM disk block verify primitive. 


WarmStart 


n/a 


n/a 


$ff4d 


Bring GEOS to a warmstart state. 


WriieBlock 


$c220 


$c220 


n/a 


CBM write disk block primitive. 


WriieFilc 


$clf9 


$clf9 


$03 lb 


Write chained list of blocks to disk. 


WrileRecord 


$c28f 


$c28f 


$034c 


Write current VLIR record to disk. 



NOTES: The following routines have had there names changed to avoid confusion and/or make them unique in 
the first eight characters: 



Ctfmnt Namg 

Clocklnt 

CopyLine 

i.NewBitUp 

LoadAuxSet 

MoveAuxData 



Fgrmgrly 

ReadQockInt 

CopyScreenLinc 

i_NewBitmapUp 

LoadAuxCharSet 

MoveBData 



Current Namg 

NewBitClip 

NewBitUp 

PutChar 

RstrFrmDialog 

SetMsePic 



Fgrmgrly 

NewBitmapClip 

NewBitmapUp 

Putchar 

RstrFrmDialogue 
SetMousePicture 



CBM 



Apple: The following routines were not added to the jump table until version 2.0.3 (version 2.0. release 3). 
To call these routines in v2.0.2 (the initial public release) requires a patch to the jump ubles. 

NewBitOtherClip, i.NewBitUp, AUocatcBloct GetlstDirEniry, GetNxtDirEntiy 

The following routines do not have jump table entries in the 1541 device driver. The device type must 
be checked before calling any of these routines. Sec the actual routine reference for more information 
and 1541 alternatives. 

AllocateBlock. ReadLink 

The following routines do not exist in version 1.2 and below of CBM GEOS: 

GetlstDirEntry. GetNxiDirEntry, FreeBlock . 

They require calling directly into the GEOS Kemal. See the actual routine reference for more 
information. 



5 



file! kernalPatch, page 0, tiae Tue Apr 19 12>58U} 1988 



APPLE CEOS «2.0.2 KERNAL PATCH (reuision 3) 
Hatt Loueless 
Robert Boudidge 
April 6, 1988 

Reuision History 



ssssssssssssssss 



03/22/88 il/rb First hacked up 

03/23/88 al/rb Fixed aux/»ain snafu 

04/06/88 al/rb Added iJeuBitaapUp for 'ol uargas. 

04/08/88 aau Used oatch and aade aisc bug fixes. Called routine 

i NeuBitaaptlp and it seesed to work fine. 
4/18/88 aau CKanged references to GetNextDirEntry to EetHxtOirEntry. 



Notes This patch inforaation has not yet been thoroughly tested. If anybody has probleas, please direct thea to Robert 
and/or Hatt. 

The fol loving routines were inaduertently left out of the Apple GEOS juap table in the first production release (u2.0, rel. !]• 

HevBitOtherClip 
AllocateBlock 
GetlstDirEntry 
GetNxtOirEntry 
i NeuBitaapUp 



Applications that uish to use these routines aust patch the Kernal ]uap tables in order to run under v2.0, rel. 2. 
Startino uith u2.0, release 3, these routines^are guaranteed to be in «he^)uap table. Applications flUST check the 



nuaber Before patching in order to be coapatible uith future versions of Apple GEOS 
The following unused juap table slots uill be used' 



version 



HeuBitOtherClip 
AllocateBlock 
GetlstDirEntry 
GetNxtOirEntry 
i HeuBitaapUp 



SffOe 
I 030c 
i;039i 
i;039c 
$ff9e 



old ToBasic] 
old ReadChain) 
old ChkOkGEOS 
old SetGEOSOisk) 
old ageos RaaDD) 



These equates uill not change and uill ensure an application is upuard coapatible uith future versions of Apple GEOS. 
Patch info for u2.0, release 2i 



Routine 

sssssss 

HeuBitOtherClip 

AllocateBlock 

GetlstDirEntry 

GetNxtOirEntry 

iJetBitaapUp 



Address 

ssssssm 

IffOe 
030c 
0396 
039c 
ff9e 



In aux 

ap Sdf9a 
ap i45cl 
ap 4e<6 
ap i4e78 
ap Panic 



In aain 

sr ifcl6 
sr l0900 
sr S0900 
sr i0900 
, sr iecb3 



aux > altzp) 
aux « raaurt 
aux • raaurt 
aux • raaurt 
aux » raaurt 



(Note that i NeuBitaapUp cannot be run uhile the alternate zero page (ALTZP JH) is suitched in. The juap table entry 
juaps to the Panic routine. This routine aust be called uhen the aain zero page is in.) 

And in codes 



;Patch 
ffiiiff 



Patch GEOS v2.0.2 



It" EQUATES 

^Locations in juap table 

HeuBitOtherClip • $ff0e 

AllocateBlock « $030c 

GetlstDirEntry - $0396 

GetNxtOirEntry ' i039c 

i.HeuBitaapUp « $ff9e 

lOirect entry points into v2.0.2 kernal 

j.NeuBitOtherClip * Sdf9a 

oJllocateBlock ■ i45cl 

GetlstDirEntry « l4e66 

©"GetNxtOirEntry • i4e78 

iT HeuBitaapUp « iecb3 



;pixe1 boundary version of BitOtherClip 

lal locate block in VBH (opposite of FreeBlock) 

iget 1st directory entry in current directory 

iqet next directory entry 

100 an inline HeuBitaapUp. Hike likes this call. 



SuitchAllRegs 



mi 



ifor aux-high bank graphics switch 



fi1e> kernalPatch, page 1, tiK Tue Apr 19 12<58:45 1968 



LouSuitch • $0900 if or aux bank (low juip table) 

GOODJERSION « S20 {version 2.0.3 does not need to be patched 

GOOOJELEASE • $03 ^ 

.■aero PatchJapTable dest, source (copies three bytes froi source to dest 
Ida source 
sta dest 
Ida source^l 
sta destM 
Ida source^2 
sta dest^2 

.endi 

$Notet Can be lunged to use less bytes by table driving the patch. Done this uay here for 
I demonstration purposes only. 

Patch* 

I Check version to ensure that ue don't patch Kernals that are already 

t fixed, ye check for version 2.0.3 (good version) explicitly because 

f 2.0.2 is the first release of the Apple Kernal and 2.0.3 has the fixes 

i in it. 

Ida version 

csp tGOODJERSION 

bne 10$ 'ibranch if current version >2.0. If 

I not then it is 3.xx uhich is fixed. 

Ida release 

cnp tGOODJELEASE 

bge 10$ (branch if this release >* good release 

bra 20$ ibra to do the patch 



10$t 



rts 



fThis is a version that needs to be patched. Go patch it. 

ffirst patch addresses in nain 

20$« 

PatchJMpTbl NeuBitOtherClip, n HeuBitPatch 
PatchJipTbl AllocateBlock, fl AllocBIkPatch 
PatchJnpTbl GetlstDirEntry, H GetlstPatch 
PatchJapTbl GetHxtDirEntry? fl'GetNxtPatch 
PatchJipTbl i.NeuBitiapUp, fIjNeuBitiapUp 

fpatch graphics in high auxiliary 

sta ALTZPJN I suit ch in high aux 

PatchJnpTbl NeuBitOtherClip. A HeuBitPatch 
Patch Jap Tb I i NeuBitaapUp, A iHeuBitaapUp 

sta AUTZPJFF " ; suitch out high aux 

(patch others in nornal aux 

sta RAfiyRTJN I send urites to aux bank 

PatchJnpTbl . AllocateBlock, A AllocBIkPatch I read froa aain, write to aux 

PatchJapTbl GetlstDirEntry, K GetlstPatch \ read froa aain, write to aux 

PatchJapTbl GetNxtDirEntry, AjetNxtPatch ( read froa aain, write to aux 

sta RAHURTJFF I send urites back to aain 



99$: 



rts 



fflain aeaory patches 
n NeuBitPatcht 

jsr SwitchAIIRegs 

n AllocBlkPatchi 

tl-GetlstPatchi 

nlGetNxtPatch* 

jap LowSwitch 
n.iNeyBitaapUps 

jap ii.HeuBitaapUp 

iAux aeaory patches 
A.NeuBitPatcM 

jap j NeuBitOtherClip 
AJllocBlkPatch" 

jap AilocateBlock 
A GetlstPatchi " 



file' kcrnalPatch, page 2, tiie Tuc Apr 19 12558M3 1988 



jip GetlstDirEntry 
flJetHxtPdUh« " , ^ 

EetHxtDirEntry 



lap o.betnxcuirtniry 
A iHeuBi{aapUp> 

jip Panic 5can't call this routine froi aux •e«ory. 



This page Intentionally left blank to maintain right/left (verso/recto) 
page ordering. Final version will correct this. 



Mtn^t R^'ftin'^'' (^niirth f *'* ' "'^l ) 5/2/88 



11:18 AM 



GEOS Text Escape Character Codes 



Code Constant Description 






NULLV 


String termination character. 


1 




unused 


2 





unused 


3 




unused 


4 


J 


unused 


D 






6 


t 


unused 


7 




unused 


8 


BACKSPACE 


erase tne previous cnaracter (APP^g vjcuo uses me wiain ui lasiwiain;. 


9 


rORWARDSrALb 


rfot unpiemenieci in kjcUo oh or %jt,uo i^o. iviovc current pruiung 
position rightwaid the width of a space character. This escape code is used 

K\/ oAnVk/ritA tn ri*nrf»c^nf A tnH TAR cnnctflnt^ 


10 


LF 


Linefeed: move current printing position down one line (value in 
currentHeight). 


1 1 


HOME 


Move current printing position to upper-left screen comer. 


12 


T mf Txrr? 

UPLINE 


Move current printing position up one line (value in currentHeight). 
inis escape cooe is usevi oy geoTYmc lo represeiii a pagc-urca& ^uac 
PAGE BREAK constant). 


1 D 




carnage reium. move currcni priiiLijig posiuon uowii une iinc oiiu uvci w 
the left margin (value in leftMargin). 


1 A 




T^AOin iinHArlinmfy 

OCJ^lIl UllUCillllUI}^. 


15 


UUNEOFF 


End underlining. 


16 


ESC.GRAPfflCS ¥ 


Escape code for graphics string: remainder of this string is treated as input 
lO uie vvrapnicsoirinK rouiine. 


1 / 




unintp lenient ed This escape code is ignored by GEOS text routines. This 

ACCiinA ccsAa ic iice<l Hv o^cs^^ryt^ Xf\ rAnrpcAnt a nilAr Acr^anA ^iicp 

ESC RULER constant). 


18 


REVON 


Begin reverse video printing (white on black). 


19 


REVOFF 


End reverse video printing. 


20 


GOTOX Y 


Change the x^coordinate of the current printing position to the word value 
stored in the following two bytes. 


21 


GOTOY ¥ 


Change the y-coordinate of the current printing position to the byte value 
in the following byte. 


22 


GOTOXY ¥ 


Change the x-coordinate of the current printing position to the word value 
stored in the following two bytes and change the y-coordinate to the value 
in the third byte. 


23 


NEWCARDSET ¥ 


unimplemented. This does nothing but skip over the following two bytes. 


24 


BOLDON 


Begin boldface printing. 


25 


ITAUCON 


Begin italicized printing. 


26 


OimiNEON 


Begin outlined printing. 


27 


PLAINTEXT 


Begin plain text printing (turns off all type style attributes). 


28 


t 


unused 


29 


t 


unused 


30 


t 


unused 


31 


t 


unused 



tshould never be sent to a GEOS text routine unless the application is running under a future version of 
GEOS that explicitly supports this character code. 
^For use with PutString; not directly supported by PutChar. 




1 



5/2/88 



11:18 AM 



GEOS ASCII Character Codes 



Code 


Character 


Code 


Character 






32 


space 




65 


A 




97 


a 


33 


1 




66 


B 




98 


b 


34 


n 




67 


C 




99 


c 


35 


# 




68 


D 




100 


d 


36 


$ 




69 


E 




101 


e 


37 


% 




70 


F 




102 


f 


38 






71 


G 




103 




39 


1 




72 


H 




1 /\A 

104 


h 


40 


( 




73 


I 




105 


i 


41 


) 




74 


J 




106 


i 


A O 

42 






75 


K 




107 


k 


43 


+ 




76 


L 




108 


1 


A A 

44 






77 


M 




109 


m 


A C 

45 






78 


N 




110 


n 


46 






79 







111 





47 






80 


P 




112 




i4 O 

48 


U 




81 


9 




113 


q 


4y 


1 




82 


R 




11/1 
114 


r 


50 


2 




83 


S 




lie 

115 


s 


51 


3 




84 


T 




116 


t 


52 


A 

4 




85 


U 




117 


u 


53 


5 




86 


V 




1 1 o 

lis 


V 


j4 







87 


W 




110 


w 


55 


7 




88 


X 




IZU 


X 


56 


8 




89 


Y 




121 


y 


57 


9 




90 


Z 




122 


z 


58 






91 


[ 




123 


f 


59 






92 


\ 




124 


1 


60 


< 




93 


1 




125 


) 


61 






94 


A 




126 




62 


> 




95 






127 


deletion character 


63 


7 




96 








USELAST 


64 


(a 






128 


short-cut key: 












SHORTCUT 



2 



file! ageosU2.0.2JernalPatch, page 0, tiae Thu Har 24 10:57202 1988 



■ > 



iifi UPDATES PREUIOUS PATCH INFORHflTION HAD BANK INFORHATION SUITCHED 
iiif USE THIS VERSION TO PATCH KERNAL AND DISREGARD EARLIER i«>i 

APPLE GEOS V2.0.2 KERNAL PATCH (revision 2) 
Hatt Loveless 
flarch 23, 1988 

Note: This patch inforaation has not yet been thoroughly tested. If anybody has problens, please direct then to Robert 
and/or Hatt, 

The following routines were inadvertently left out. of the Apple GEOS jump table in the first production release (u2.0, rel. 2) 

NeuBitOtherClip 
AllocateBlock 
GetlstOirEntry 
GetNextDirEntry 

Applications that wish to use these routines Must patch the Kernal junp tables in order to run under v2.0, rel. 2. 
Starting with v2.0, release 3, these routines are guaranteed to be in the juap table. Applications tlUST check the version 
nunber before patching in order to be conpatible with future versions of Apple GEOS. 

The following unused junp table slots uill be used> 



NeuBitOtherClip iffOe 

AllocateBlock i050c 

GetlstOirEntry i0396 

GetNextDirEntry $039c 



old ToBasic) 
old ReadChain) 
old ChkDkGEOS) 
old SetGEOSDisk) 



These equates uill not change and uill ensure an application is upward conpatible with future versions of Apple GEOS. 
Patch info for v2.0, release 2* 

Routine Address In aux In nain 

8ZSSSSS SSSSS3X SSS3Z3SSS SSSSSSSS 

NeuBitOtherClip SffOe m Sdf9a isr SfcK (aux » altzp) 

AllocateBl&ck i030c Imp i45cl Isr i0900 aux * ranwrt) 

GetlstOirEntry 40396 pp f4e66 jsr i0900 aux « raaurt 

GetNextDirEntry $039c jnp $4e78 jsr ^0900 (aux « raniwrt) 

And in codes 

;ffii«i«ifliffffiiiiiffiiiiiiiiiiiiiif fiiif iiffiiffiiiiiiif«iiiiiit««i«iiii«ifiiitfifiiiiiiiffiiifiifi« 

HewBitOtherCIip » iffOe ;pixel boundary version of BitOtherClip 

AllocateBlock ' i030c lal locate block in UBI1 (opposite of FreeBlock) 

GetlstOirEntry « f0396 ;get 1st directory entry in current directory 

GetNextDirEntry » $039c 5get next directory entry 

fOirect entry points into u2.0.2 kernal 

j NeuBitOtherClip - idf9a 

AllocateBlock > i45cl 

GetlstOirEntry * Ue6i 

oJetNextOir Entry » $4e78 

SuitchAllRegs " ^fcl6 ;for aux-high bank qraph^ics switch 

LowSwitch ' $0900 ;for aux bank (low junp table) 

GOOD VERSION ' $20 iversion 2.0.3 does not need to be patched 

GOODlRELEASE « $03 

.nacro PatchJapTable dest, source icopies three bytes froa source to dest 

Ida source 

sta dest 

Ida source*! 

sta dest*l 

Ida source*2 

sta dest*2 

) .endn 



iNote: Can be nunged to use less bytes by table driving the patch. Done this way here for 
I demonstration purposes only. 

Patch? 

fCheck version to ensure that we don't patch Kernals that are already fixed 
Ida version 



file* ageosVZ.O.Z.KernalPatch, page 1, tine Thu flar 24 10:57:02 1988 



bq^ m ibranch if current version >« good version 

Ida release 

cap IGOOOJELEflSE , ^ , 

5g^ J9] ;branch if current release >« good release 

;Thi5 is a version that needs to be patched. Go patch it. 
;fir5t patch addresses in Haln 

"^PatchJalpTbl NevBitOtherClip, fl NeuBitPatch 

PatchJwpTbl flllocateBlock, H ftTlocBIkPatch 

PatchJmpTbl GetlstDirEntry, A GetlstPatch 

PatchJapTbl GetHextOirEntry, RjetNextPatch 

5Datch qraphics in high auxiliary ^ l . c. l 

PatchJrapTbl NeuBitOtherClip, flJeuBitPatch 

sta . flLTZPJFF 5 switch out high aux 

5patch others in nor.al aux^^^ ^ ^^^^ ^^.^^^ ^^^^^ 

PatchJmpTbl flllocateBlock, fl flllocBlkPatch 5 read froa aain, urite to aux 

PatchJapTbl GetlstOirEntry, ff JetlstPatch ; read froa aain, urite to aux 

PatchJapTbl GetHextOirEntry, flJetNextPatch I read froa aain, write to aux 

RfltliiRT OFF « send writes back to aain 



99$: 



sta 



rts 



;Hain aemory patches 
(1 NeuBitPatch: 

jsr SuitchflllRegs 

n flllocBlkPatch: 

nletlstPatch: 

n"GetNextPatch: 

jap LowSuitch 

;ftux aeaory patches 
fl NeuBitPatch: . ^ _ . . ... 
imp ] NeuBitOtherClip 

fl flllocBlkPatch: 



jnp flllocateBlock 
flJetlstPatch: " ^ ^. ^ 

* jap GetlstOirEntry 
fl GetHextPatch: 

jmp GetHextOirEntry 



files forfipplications/diskRH, page 0, time Hon Feb 22 10:22:24 1988 
Summary of desired disk read/write operations and what routines to call 



Read a block from disk into FlfllN memory, qiuen block number 

ReadBlock or GetBlock with RUbank set to SHAIN (default) 

Read a block from disk into DUX memory, given block number 

ReadBlock or GetBlock uith RVbank set to lAliX (set, call, reset) 

ilrite a block from HfllN memory to disk, given block number 

UriteBlock or PutBlock uith RUbank set to IIII^IN (default) 

Urite a block from AUX memory to disk, given block number 

yriteBlock or PutBlock uith RUbank set to tflUX (set, call, reset) 

Read (and execute, if possible) a SEQUENTIAL file into HRIH memory, given its 
filename 

GetFile uith RVbank set to miH (default) 

Reed a SEQUENTIAL data file into AUX memory, given its filename (filename must 
be in nAIN) (note: datafiles only? cannot read Desk Accessories or Applications 
into AUX and have them execute) 

GetFile uith RUbank set to tAUX (set, call, reset) 

Read a SEQUENTIAL file into flAIN memory, given its directory entry 
LdFile uith RUbank set to inAIN (default) 

Read a SEQUENTIAL file into AUX memory, given its directory entry (directory 
entry must be in flAIN) 

LdFile uith RUbank set to lAUX (set, call, reset) 

Open a VLIR file and read (and execute, if possible) it's first record into 
HhIN memory, given its filename 

GetFile uith RUbank set to SHAIN (default) 

Open a ULIR data file and read it's first record into AUX memory, given its 
filename (filename must be in tIAIN) (note: cannot run OA's or ftpplic's in AUX) 
GetFile uith RUbank set to DhUX (set, call, reset) 

Read current ULIR record into flAIN memory 

ReadRecord uith RUbank set to ttlAIN (default) 

Read current ULIR record into AUX memory, given record number 
ReadRecord uith RUbank set to im (set, call, reset) 

Read a single VLIR record into RAIN memory, given record number 

PointRecord then ReadRecord uith RUbank set to tllAIN (default) 

Read a single VLIR record into AUX memory, given record number 

PointRecord then ReadRecord uith ftUbank set to |AUX (set, call, reset) 

Read a single VLIR record into nAIN memory, given block number of record's 
index block (must handle VLIR variables yourself) 
Readhle uith RUbank set to inAIN (default) 

Read a single VLIR record into AUX memory, given block number of record's 
index blocR [must handle VLIR variables yourself) 
ReadFile uith RUbank set to lAUX (default) 

Urite an indexed 'chain' from HAIN memory, given a pre-al located index table 
(in internal indexBlock buffer) 

UriteFile uith RUbank set to tllAIN (default) 

Urite an indexed 'chain' from AUX memory, given a pre-al located index table 
(in internal indexBlock buffer) 

UriteFile uith RUbank set to lAUX (set, call, reset) 

Urite a file from flAIN memory, given the header block for it 
SaveFile uith RUbank set to ItlAIH (default) 

Urite a file from AUX memory, given the header block for it 
SaveFile uith RUbank set to tAUX (set, call, reset) 

Urite current VLIR record from RAIN memory 

UriteRecord uith RUbank set to StIflIN (default) 

Urite current VLIR record from AUX memory, given record number 
UriteRecord uith RUbank set to lAUX (set, call, reset) 



.7 * 



reset) 



1 



file: General/SYSTEHdir, page 0, time Hon Feb 22 10:21:51 1988 
Specifications proposal for inplementation of /SYSTEH directory 



10/27/87 



All disks from uhich the flppIeGEOS DeskTop runs an application will 
either already have a /SYSTEM directory or have one created. The /SYSTEM 
directory (a subdirectory nawed SYSTEM of the root directory) is a special 
GEOS subdirectory where systea data files (files of type SYblEM, scraps, and 
fonts), desk accessories, and applications can reside. In addition to the 
/SYSTttt directory, these kinds of files can also reside anywhere else on any 
other directory on the disk. 



Kernals 

The kernal support planned for the /SYSTEM directory is in the routine 
OpenOisk. In addition to its normal function, OpenOisk will also find the 
/System direcotry and store the block number of it's key block in the global 
variable sysDirBlkno. If there is no /SYSTEM directory found, a wilt be 
returned in this word. 

Another place where kernal support laiqht be needed is with Desk 
Accessories. Uhen a desk accessory is run, it will be assumed that the 
current directory will be the directory with the desk accessory (i.e. that 
the Desktop and applications will do a GoOirectory before LdOeskAcc or GetFile). 
If no change are made to the desk accessory routines, the OA's Swap File will 
be saved to the current directory. If the desk accessory were to change the 
current directory, then when RstrAppl is called, RstrAppI will not know where 
to find the Swap File. The solution to this is to always save and load the 
Swap File to/from a fixed location, either the /SYSTEM directory or the root 
directory. This will require that both LdOeskAcc and RstrAppl make calls to 
GoOirectory to make to the root directory or the /SYSTEM the current directory. 
Unfortunately, this will increase overall desk accessory access time. 



Applications: 

Application handling of the /SYSTEM directory is flexible. It is up 
to each application to determine how much support for the /SYSTEM directory 
is necessaru. For example, if scraps are supported, then they should be saved 
and loaded from the /SYSTEM directory. This is not mandatory, as the saving 
and directory oanrpulation must be done by the application, but this allows 
other applications to find them. To actually save something to the /SYSTEM 
directory will be very simple. Merely use the following code: 



Pushy curKBlkno 

MoveV sysDirBlkno, rO 

isr GoOirectory 
txa 

bne ErrorHandle 

(set up registers for SaueFile) 

isr SaveFile 
txa 

bne ErrorHandle 

Popy rO 

isr GoOirectory 
txa 

bne ErrorHandle 



fsave current directory 
•goto to /SYSTEM directory 

•check for errors! 



•fSave file to /SYSTEM directory 

icheck for errors! 

;pop saved curKBlkno into rO 

•return to original directory 

•check for errors! 



For fonts and desk accessories, an application also has a choice of 
using any directory or group of directories ic wants. However, to be consistent 
with other appUcations it is suggested that only the current directory and the 
/SYSTEM directory be used. Then, when a font or desk accessory is to be loaded, 
the above code could be used by replacing SaveFile with GetFile. GetFile will 
automatically determine whether to use LdOeskAcc or LdFile. 

yhen an application wants to gather a list of desk accessories (for the 
GEOS menu) or fonts available, it wilt have to do a FindFTypes with both the 
current directory and the /SYSTEM directory. Since the /SYSTEM directory is 
known from the global variable sysDirBlkno, this is an ideal situation to use 
the new Kernal routine FdFTypesInOir which searches in a given directory. The 
application will have to keep track of which of the files it finds are from 
the /SYSTEM directory and which are from the current directory so it can switch 
to the correct directory when it wants to load an arbitrary file from the list. 
The sample application will handle this for the desk accessories in the GEOS 
menu. This will probably be all that most applications will need. 



file! General/SYSTEfidir, pace I, time Hon Feb 22 10?21j51 1988 



fin application's data files can, of course, be loaded and saued to any 
directory that the application desires, but again, for consistency, only the 
current directory should be used. Uhen opening a data file at the start of an 
application, the standard NEyDBGETFILES dialog'box routine can be used. The 
desktop will aaintain this interface by going to the directory of a data 
file that is double-clicked on uhen the parent application is launched. 



Desktop** 

The Desktop will deal uith the /SYSTEH directory to a greater extent 
than either the Kernal or applications. 

In addition to hauing to nanaqe the list of Desk Accessories in the 
GEOS menu and setting of the current directory for double-clicked data files 
mentioned aboue, the desktop will also have to create the /SYSTEfl directory 
if none exists, manage a list of applications for a new menu item, handle 
dialog boxes with application and desk accessory selection boxes for new 
uieu-By-text modes, and qettina printer drivers, input drivers, preference, 
and configuration files from tne /SYSTEH directory. 



file: forKernal/RUile, page 0, tiae (Ion Feb 22 10:22:25 1988 



Interleauing issues 



\ The Main issue uith reading and writing files is whether we will be 

' able to 'catch the interleave', ft ProOOS disk^s physical sectors are 
contiguous, but a ProDOS block, which is Biade up of two sectors has both 
inter-block interleauinq and intra-block interleauing. Inter-block 
interleauing seperates the two sectors of each block by a single sector. 
Intra-block interleauing seperates the two sectors of a block (in addition to 
the inter-block interleauinq sector in between theml by a single sector. 

The disk spins at 300 rpm and the ftpple 650l runs a 1 Hhz so there are 
200,000 cycles per reuolution. fit 16 sectors per track, this works out to 
about 12,500 cycles per sector. This means that we haue about 12,500 cycles to 
process both between fetching the two sectors of a block (while we're in the 
deuice driver) and between fetching contiguous blocks (while in the read and 
write file routines). 

The deuice driuer is such that there will be uery little tifine to 
process data if the interleave is to be taken aduantage of. This means there 
must be uery little overhead between calls to ReadBlock (or one of the related 
routines) during Readfile or between calls to llriteBlock during llriteFile. 

The obuious solution is read or write blocks directly to the 
destination address or directly from the source address. The problen with this 
is that if complete blocks are read into a destination buffer, bytes after the 
end of the buffer will be trashed if the buffer is not a multiple of the block 
and the size of the ualid data in the file being read is the sane size as the 
buffer. ^ 

The method used by appleGEOS ReadFile eliminates this Droblem and still 
can read blocks directly into their destination. Since a complete list of the 
blocks in the file is available beforehand, all blocks but the last can be read 
directly into the destination while the final block can be read into some 
intermediate buffer for partial copying to the destination. This is done by 
scanning ahead in the list of file blocks. This allows us to catch the 
interleave if the blocks of a file are contiguous. For the last block, there 
will be no more blocks to read, so catchinq the interleave is not important. 
This works with reading into both the HfllN'and flUX banks of memory. 

For ilriteFile, such a scheme is not possible because the disk routines 
can only write to disk from ftUX memory. Therefore, every 512-byte block of 
flAIN memory that is to be written to disk must first be copied to HIGH memory 
or AUX memory. Vriting from RUX memory can be done without missing the 
interleave because no copying is necessary. But writing from HftlN memory 
requires copyinq of 512 bytes, which along with the fact that the deuice driuer 
has to do work before writing a block eliminates the possibility of catching the 
interleave. 



file: forKernal/RyjiIe2, page 0, tiwe Hon Feb 22 10:22:25 1988 



Oeffiory features of file reading and writing routines 

Kith the 128K flpple couies the picture of that 128K mettory as t«o 
individual 64K baniis. This liaits the use of the memory because switching 
between the two banks in an organized manner is non-trivial. 

To alleviate this probiera and still provide the flexibility that more 
memory allows, the appleGEDS disk routines allowing reading and writing files 
from both the I1AIN and AUXILIARY banks, fl flag, RHbank, controls which bank 
files will be read/written to/froia. Generally, this flag will be set to flfllN 
for normal applications work. 



files forKernal/VBiVoutines, page 0, time Hon Feb 22 10!22s25 1988 



The GEOS/Comnodore Block fli location Hap (Bflfl) is replaced uith the 
ProOOS Volune Bit flap (VBtl) in the Apple version of GEOS. The VBI1 has the 
same function as the BflU, showing uhich blocks on a disk are allocated and 
^ uhich are free to be allocated. There are, houeuer, seueral changes in the 
f allocation nap foroiat and in the routines that deal uith it. 

The UBn is configured as one or nore blocks on the disk it naps. Each 
byte of each block represents the status of 8 blocks on the disk, iiithin a 
byte, the bits are »apped HSB->LSB to blocks X->X*7 uhere X is some nultiple of 
8. So, for example, the first byte of the UBfl represents disk blocks to 7. 
Each additional byte represents the next 8 blocks on the disk. 

The UBM is allotted at least one block on the disk. So euen if the VBH 
reguires only 35 bytes (as it does on a 143K 5.25" flopoy), it use and entire 
5iZ-byte block. Since blocks contain 512 bytes, this aiious a single l/Bfl block 
to represent (8«512=j 4096 disk blocks. This is the case for 143.K 5.25' 
floppies and 800K 3.$' microfloppies. Hard disks, uith upwards of 5 megabytes, 
uili require more than on VBH block. 

In a normal ProDOS formatted disk, the UBtl usually begins at block i. 
For multiple block UBHs, the other blocks occupy blocks sequentially after 
block 6. These blocks are allocated at format time, and the size or a disk 
is fixed, so there can be no problem uith ever needing to allocate more VBM 
blocks. 

Therefore, the differences between the ProOOS UBfl and the Commodore Bflfl 
are its location, its possible size, and its format. The location of the VBfl 
is not in the directory header. The size of the VBfl, although fixed for a 
giuen drive type, is different for different capacity driues. The VBH does 
not contain a count of free blocks. 

These differences affect the GEOS disk routines that deal uith the 
m/m. These routines ares CalcBlksFree. FreeBlock, SetNextFree, SetlfFree, 
and FindUBIIBit (FindBflHBitl. For example, CalcBlksFree can no longer just 
add up the number of free blocks per track (which is stored in the Commodore 
Bflfl). In the Apple version, CalcBlksFree has to explicitly check each bit of 
the VBfl, and do the appropriate calculations to determine the number of free 
blocks on a disk. It might even have to read in another disk block. 

The routines, as a group have changed because of a combination of two 
of the differences, the location and the size. The routines now employ a type 
of cache for the VBtl. The routines have a single block buffer in memory that 
it uses to hold the 'current' VBfl block. This makes sense in multiple«block 
VBHs, but uith 143K 5.25' floppies and BOOK 3.5' microfloppies, this buffer 
aluays holds the one and only llBfl block. The routines aluays maintain a correct 
copy of the current VBfl block in the buffer. Ilheneuer access is needed to a 
different VBfl block, the current block, if it has changed, is uritten out to 
disk before reading in the neu block. 



■»?:: 
ii:: 

s;Oiu 






; 


; KE?>^L 








BACKGROUND SCREEN 




j^f^PLlCA'IO^ SFhCE 


1 

1 

i 
1 

i 

i 


KEiv^iA-^E-^ITE E^F'ESr , 




FCri:TC-'.^i' SCr.EE.\ ^ 




liCRE ^ERf-^1 i 





r1f\? 



»=■::»: - 

5:;oo - 
5e:c: - 

5kC0 - 

s;-iv - 
5^::: - 
- 
- 

5:;:: - 
5-::: - 
i-::: - 
Ji::: - 



I/O iFACE 



r::.E}RD.N? sC^-EE^. 



5 i^. 
! •■ 

1" 

w 

i 

! I 

I 2-^ 

! : 
! I 

; i 
; ■ 



- /;- 

/I 



■i- 



KErj''(Ai. 



AFFL!C«TI^ iFrCE 




\ 



A 



2 

f 
o 
J 

a- 
-a. 



»N»:VT JS'jii^ 






NSJD3. 











030 





Z 'PAGE 



VDOO 




C'20:, 



6C500 



1)6 \!U5^ S 



D 3 



dcc<) 



I 



ceo 



^ ^^-X€>\ "Ro vJT 1 ^£5 (£000 - FPT=? 



<<< 

OCO 



UTiLi"r\,sS 



MAIM 



p£oo 




£&:>!} 

62,00 

t.Cac 

9^00 



'2/ o 

'2^ Eii: 



L0CA.i- 



IB \CoM^ 



I coo 



0&«5O 

020) 
OCcO 



TA3^£S -6<soo t\o)C) 



ceo 



•41 



M16C 




42® 



• 


i 


! 

1 
1 

1 


1 






















I>£oO 






F OMT3 

• 




<<< 

2 = 3 

ceo 






















sna : 
f» J-. -- • 












































« 

^— ^ 























< 








T 








E 

5 










• 


• - 







files ftppleSpriteGuide, page 0, tiae Thu Mar 24 IZsJl^U 1988 



Files flppleSpriteGuide (128sprtte6uide) 
Author: Jin OeFrisco 
Date: 14 January 1987 

Purpose: This file explains what needs to be done to convert 

the portions of C64 6E0S applications that deal uith 
sprites to run under Apple GEOS. 



Baci^ground Info: 



The C64 contains a chip to handle sprites in hardware. 
Unfortunately, this chip is not available on the Apple, 
so the functions of that chip have been sinulated in 
software that is included in the kernal. Host of 
the capabilities of the VIC chip haue been taken care 
of, and if you are not doing exotic things uith sprites 
your code nay work uith one or tuo changes. 

The aaior changes include: sprite (the cursor) is 
treated differently than any other sprite. The code 
for this beast has been optiaized to get reasonably 
fast nouse response, uith a resulting loss in 
functionality. You cannot double the cursor's size in 
either x or y. You cannot change the color of the 
cursor. The size of the cursor is liiited to 16-pixel5 
uide and 8 lines high. One added feature is the ability 
to add a uhite outline to the picture that is used for 
the cursor. This allows it to be seen while nouing 
ouer a black background. 

For the other 7 sprites, all the capabilities have been 
emulated except for color and collision detection. In 
addition, the <4th byte of the sprite picture definition 
(previously unused] is now used to provide soae size 
info about the sprite. This is used to optiaize the 
drawing code. 

To change your code over, look over the following list 
of possible problen areas. This list will be updated 
as Bore probiens are found, and you should add an entry 
when you cone up with a new one. 



Q 



file: flppIeSpriteGuide, page 1, tine Thu flar 24 12:51:16 1988 



Sprite Problen Areas: 

To make sure your sprite code «iH run under fippleGEOS, read ouer the 
following lisl. If you see a problen that applies to your application, 
take the appropriate corrective action. If you encounter a problen 
that is not listed belou, add a solution when you cose up wich one (or 
state that a solution is not possible). 

PROBLEM SOLUTION 



l/riting directly to the screen 



Change the cursor picture (sprite 0) 



Use a large picture for the cursor. 



All sprite picture data 



Since the old sprite were handled with 
hardware, writing to the screen uasn^t 
a problen. If you do it (systeiB calls 
NOT included), then call 'TenpHidedouse' 
before the write. This will erase the 
cursor and any sprites you haue enabled. 
You don^t haue to do anything to get 
then back, this is done autonatically 
during the next eain loop. 

This should be done with the new call 
■SettlousePicture'. The source for 
this routine is in /staff/jim/applegeos/ 
Sprite/softSprites. There is a liuit to 
the size of che cursor to 16 pixels wide 
and 8 lines high, and you cannot use 
■double in x or y'. 

You should discontinue using sprite 
for this. Uhen you need to change the 
arrow to something large, disable sprite 
and use another sprite that tracks the 
fBousePosition uariables. Right now, the 
only way to disable sprite is to giue 
it a null picture or clear the low bit 
of mobenble. , A "disable aouse" call 
should be added soon. 

All picture data should be adjusted to 
include the 64th byte. This byte has 
size inforoation that is read by the 
software sprite routines, euen if they 
are garbage ualues. The foraat of this 
byte is: nigh bit set iieans that the 
sprite is no sore that 8 pixels wide 
(this neans it can be shifted 7 tines 
and still be contained in 2 bytes). The 
rest of the byte is a count of the scan 
lines in the sprite. You can either 
include this info as part of the picture 
definition, or stuff it into the right 
place with sone special code. 



file: AppleSpriteGuide, page 2, tiae Thu Har 24 12:51:16 1768 



PROBLEfl 



SOLUTION 



Uriting directly to the VIC chip 



Reading ualues froo the VIC chip 



This is generally ok, since the sprite 
enulation routines take the position 
and doubling info froa the registers on 
the VIC chip,. with the exception of the 
X position. The VIC chip allows 9 bits 
for X positions, uhich is not enough 
for a 560-wide screen. You should write 
the X position to the qlobal variables 
•reqXposO, regXposl...' (request x pos). 
These are full words, in consecutive 
locations. Better yet, use the 
■PosSprite' call in the kernel. 

This is also ok for the status ualues 
and for the y position. The x oosition 
should be read froa the reqXposO regs. 



Using VIC chip collision detection There is none. 



Uriting to the VIC chip for calling 
PosSpnte, EnablSorite, DisablSprire) 
at interrupt level 



Turning the nouse On/Off 



Don't do it. Since the sprites are 
drawn at aain loop, this causes subtle, 
irreproducable tiainq bugs that are 
impossible to oet out. It is all right 
to change the House's position here, 
since the aouse is drawn at interrupt 
level also. 

The aouse cursor is the only ■sprite' 
that is drawn at interrupt level. 
There is now a byte (called offFlag) 
that is used to tell the interrupt code 
what the status of the nouse currently 
is. Uhen TeapHidetlouse (or any graphics 
routine) is called, the nouse is erased 
fron the screen. The value $80 is stored 
in offFlag tq. tell the interrupt code 
not to draw the aouse. Uhile the value 
in offFlag is $80, the aouse will NOT be 
redrawn or erased. Uhen we wish to have 
the aouse redrawn, we store the value 
^40 in offFlag, which tells the 
interrupt code to resuae drawing the 
aouse. nain Loop stores this value in 
offFlag when the application returns to 
it. A value of $00 In offFlag allows the 
interrupt code to function noraally 
(erase and redraw the aouse whenever 
necessary) and is stored there by the 
interrupt code. 



file! changes, fonts, page 0, time Thu Har 24 12j52!02 1988 



Font changes' 

Now the systet font is located in auxilliary aeiiory. There is plenty of 
space on the aux side, so the apolications uill probably want to use it for 
holding the font data. Certain flags need to be set to tell the font routines 
that the fonts are in auxilliary aenory. If the font is in nain nefBory, the 
application should call LoadCharSet as usual. But, if the font is in auxilliary 
nenory, it should call LoadAuxCharSet, uhich sets a bunch of flags and uars for 
the font routined. 

Most of the font uariables still exist in flppleGEOS. Three variables 
lie in sain nenory where the application can easily access then: 
baselineOffset 
currentSetliidth 
currentHeight 

Tuo of the uariables lie in the alternate zero page: 
currentlndexTable 
cardDataPo inter 

If the application needs to access these. It nust first do a 'sta ALTZP ON' and 
then access then, and then do a "sta flLTzPJFFV Remember that ALL of tHe aain 
(application) zero page and stack is swapped out here, so it cannot be accessed 
until the 'sta ftLTZPJFF' is executed. 



file: changes. db, page 0, tine Thu Har 24 12:51:40 1988 



This file contains the lany changes iade in the dialog box routines: 

DBUSRROUTIHE: He nou assune that only ONE DBUSRROUTINE call is lade 
per dialog box. This call is nou nade AFTER the icons are displayed. This nakes 
It possible to use DBUSRROUTINE to put stuff up ouer the icons... 

DBGETFILES: Holding the button doun on the scroll icon aakes the 
scrolling continue. Ho Hui... Also, the buffer that holds the filenanes is in 
auxilliary tenory, and uill hold 32 filenanes. 

DBGETNflriES: This is exactly like DBGETFILES except that the user 
passes the address of a routine to load a buffer with the nanes to be displayed. 
This routine should: 

Clear out the buffer in auxilliary aienory froa $7B00 - $7B50 

Clear the hiqh bit of r7H and decrenent r7H for each nane stuck in 
the Duffer. 

Put up to 32 file naaes in the buffer (starting at $7600 in aux nen) 

The names nay be up to 15 characters long, ^ a null terninator. 

fl buffer can be cleared in auxilliary nenory by doing a 'sta RflHilRT ON' 
before the call to ClearRan and a 'sta RfirtllRtJFF' afterwarls. 

The Dialog Box table entry for this routine is as follows: 

.byte DBGETNfinES 

.uord Address of routine to get names 

•byte xpos.offset of file box from corner of DB 

.byte yposloffset of file box froa corner of DB 



NEUDBGETFILES: This routine has a whole slew of fun new features... 
You can see the spec file for a description. Here is what you need to know to 
use it: 

The NEUDBGETFILES dialog box puts up its own OPEN icon. But the 
application can treat it as if it were its own OPEN icon. 

The NEUDBGETFILES box returns the selected file naae in the same Banner 
as DBGETFILES does... It also returns the directory block in 
which the file lies in the global variable curKBlkno. 

The NEUDBGETFILES table entry is of the following format: 

.byte NEUDBGETFILES 

.byte file box x offset 

.byte file box y offset 

.byte open icon x offset (bytes) 

.byte open icon y offset 

.byte directory icon/pathnaae text x offset 

.byte directory icon/pathnaae text y offset 



ICONS: There were aany new system icons added also. The complete list 
is now: 

CANCEL,flK,YES,NO,OPEN,DISK,ORIVE,QUIT,CREATE and IGNORE 

These can be used by applications outside of the dialog boxes. 
They lie in auxilliary aemory, and their addresses are equated 
to the constants: CANCELJCNJDDRESS.OKJCNJDDRESS, etc... 

Also, the dialog boxes nou allow 16 icons to be displayed! 



file? changes, string, page 0, tiae Thu Har 24 IZ^SJOO 1?88 



For PutString! 



ft change has been aade in PutString to fix a snail •bug". In M4 GEOS, 
?[1^S?C!59 ^loes not handle any yarqin faults (i.e. If ue attewpf to print out 
•»Byni;, and only fits, PutString uill keep trying to output characters 
until the end of the string is reached). Now, PutString uill test to see if 
there is a user specified StringFauItVector. If not (StrinqFaultUector « SOOOO), 
then It uill put its oun StringFauItVector in, uhich uill aerely exit the 
PutString routine when the aargin is reached. 

ft change has been aade in GetString. SystenStringSeruice nou always 
null-terninates the string in the buffer (i.e. even while the user is inputtinq 
the string, it is null-terainated). 



files changes. icons, page 0, tine Thu tlar 24 12:53:28 1788 



This file contains the changes »ade in the icon and senu routines. 
Icons: 

The icon pictures can nou be 'double uidth' and can also lie in 
aux nenory. Also, the icon routines currently noue the nouse 
when they are run. This option can be disabled. Uithin the 
table, flags are set to show that these options are active. 
These flags ares 

.word XPositionOf House $Set high bit to disable eouse 

; Boue 

.byte XJOSJCON 5Set high bit to signify that 

Uhe icon picture lies in 
I'auxilliary Beaory 

.byte BytellidthOflcon ;Set hiqh bit to signify that 

;ue uant the icon data to be 
I'double-uidth 



Menus: 

DoHenu currently places the nouse ouer the nenu iten passed 
in the accunulator... Nou, if the ualue in the accunuiator is 
negative, the Doftenu routine does not noue the louse. 



file! changes. grapp 



ccs 0, tiw Thu Har 24 12:53:25 1988 



For bitnaps: 

There are nr-r :yo entry points to the bitmap routines. The old ones 
still work (BitnapCi BitnapOp. etc). There are now also new routines with 
a new format (Neubit:>:-::DCnp, HeuBitoapUp). This fornat allows routines to 
place bitmaps on a pixel boundary and to let a bitnap haue a pixel width. 
The pixel width convention is as follows: 

flssuning a bitmap with a pixel width of 11, the first line is represented by 
X's and the second line is represented by Ts; The bitmaps must lie in memory 
as follows: 

byte 10: XXXXXXXX 

byte «1: XXXUUUUU ;The pixel boundary lies within a byte 

byte 12: YYYYYm ? so the remainder of the byte will be 

byte t3: YYYUUUUU ; ignored (U stands for unused bits) 

Also, the BitmapUp routines allow the icons to be doubled in width. To 
use this option, set the high bit (bit 7) in the high byte of the pixel width 
(for NewBitmapUp) or the high bit in the byte width (for BitmapUp). The 
routine will double the width of the bitmap, but not the x coordinate of the 
bitmap .Also, the routines allow the bitmap to be in auxilliary ram. To enable 
this option, set the high bit in the x coordinate. 

The parameters that are passed to the routines have changed. These 
changes are described here: 

ffff««fi»«ililiifliifiliiiilili«iii«iii««il««i«ilii«««««»«ii«iiliiilifi««li««ii* 

Parameters for BitmapUp: 
Pass: 

rO - pointer to the bit mapped data 

rlL - x byte position for the bit mapped data (0-69) 

NOTE: if bit 7 is set in rlL, the bitmap is in aux. ram 
rlH - y pixel position for the bit mapped data (0-191) 
r2L - wUth in bytes of the bit mapped data (0-/0) 

NOTE: if bit 7 is set in rzL, the icon is doubled in X 
(bitmap width is doubled) 
r2H - height in pixels of the bit mapped data (1-192) 

Pass: (inline) 

.word dataPointer 

.byte xCoord 

.byte yCoord 

.byte width 

.byte height 

Parameters for NewBitmapUp: 
Pass: 

rO - pointer to the bit mapped data 
rlL - height in pixels of the bit mapped data (1-192) 
rlH - y pixel position for the bit mapped data (0-191) 
r2 - width in pixels of the bit mapped data (0-560) 

NOTE: if bit 7 is set in r2H, the icon is doubled in X 
(bitmap width is doubled) 
r3 - x pixel position tor the bit mapped data (0-559) 

NOTE: if bit 7 is set in r3H, the bitmap is in aux. ran 

Pass: (inline) 

.word dataPointer 
.word xCoord 
.byte yGoord 
.word width 
.byte height 



...c- uiioiii^ca.ijrdpnics, page 1, time Thu flar 24 12S53525 1988 



li«liilltl«fii«iilililfffliliif|ffffilf|«||iiliiifiiiiltli«iii|f|«t|«s||«f|||tsi||«t 

Paraneters for BitBapCMp: 
Passs 

rO - pointer to the bit Mapped data 

rlL - X byte position for the bit tapped data (0-691 

, , NOTEj if bit 7 is set in rlL, the bitnap is in aux. ran 
rlH - y pixel position for the bit napped data (0-192) 
r2L - width in bytes of the bit lapped data (to print) (0-70) 

NOTE* if bit T is set in r2L, the icon is doubled in X 
(bitnap width is doubted) 
r2H - height in pixels of the bit napped data (to print) (1-192) 

rllL - nunber of bytes to skip each row 

rllH - number of bytes to sliip after printing each row 

rl2 - nunber of lines to skip before printing 

Parameters for NeuBitnapClip-' 

Pass! 

rO - pointer to the bit napped data 

rlL - height in pixels of the bit napped data (to print) (1-192) 

rlH - y pixel position for the bit napped data (0-192) 

r2 - width in pixels of the bit napped data (to print) (0-560) 

NOTE: if bit 7 is set in r2H, the icon is doubled in X 
(bitnap width is doubled) 
r3 - X pixel position for the bit napped data (0-559) 

NOTE: if bit 7 is set in rJH, the bitnap is in aux. ran 

rllL - nunber of bytes to skip each row 

rllH - nunber of bytes to skip after printing each row 

rl2 - nunber of lines to skip before printing 

»ifiiiiii«iiiiii»iiiiiiiiitiii§i«iiiiiiiiiiiifiiiii«iiif fiifiii«itt«m)iiiiii,iim 



file: RUblock, page 0, ti»e Thu flar 24 12:06:27 1988 



•iilifilfiiffiiifilillllllfifiliilfililillffflfiff lifffillXliillfiliiilliiS 

ReadBlock 

synopsis 

prouides the Apple equiualent of the Coo»odcre's lotf level 
routine 

Authors 

Brian Chin February 1988 

Called by: ^ 
Pass: 

rl — block nuaber 
r4 — buffer address 
RVbank — bank to use 
Accesses: 

curDriue — drive to read block from 

Returns: 

X — disk error 

Alters: 

y 

Calls: 

GetBlock 

«iiififffi«ifffiiii«iifiiiiiiif«fiiffiiiii«ii«ifffffiif«iiiiiiitiiiii«iifiii 

ReadBlock: 

jmp GetBlock ithese are equaivalent routines 



file: RUblock, page 1, tine Thu flar 24 12:06:29 1988 



;iiiiifiiiiiifi<iiifffi«iiffffiiiiiifffiiiiiiffiiiiiiiiifiiii«iiiiiiiii«s«ifis 

s UriteBIock 
$ synopsis 

; provides the Apple equivalent of the Comodore's lou level 

I routine 
; Author: 

; Brian Chin February 198B 

; Called by: ^ 
; Pass: • 

I rl — block nuttber 

; r4 — buffer address 

; Rybank — bank to use 

f Accesses: 

\ curOrive — drive to read block frou 

f Returns: 
; X — disk error 

; Alters: 
; a, y 

Calls: 

PutBIock 

iififfiifff<iiii«fffif«i«ii«iiiiffiiiiiiftiififiiiiiiiffifi«iiiii««iftf liiitii 

VriteBlock: 

PushB nunDiskRetries ;save global retry count 

LoadB nuBjOiskRetries.lO Jset to zero for no retries 
isr PutBIock ;put block to disk u/o retries 

PopB nunDiskRetries ;restore nuaber of retries 

rts ;return with error fron PutBIock 



file: Ryblock, page 2, tioe Thu Har 24 12!0i!29 1988 



;«ffiiiiiiiififiiffffiiiiffiiiiiiffifiiiiiiiiiiiffiiiiii«iiii«iifi««iifiiiii««f 

; l/erUriteBlock 
$ synopsis 

I provides the equivalent of the Connodore GEOS Kerna] 

; routine 
Authors 

Brian Chin February 1988 

Called by: ^ 
Passs 

rl — blocli number 
r4 — buffer address 
RUbank — bank to use 
flccessess 

curDriue — drive to urite 
nuffiOiskRetries — global retry count 
Returns: 

X — disk error status 

filters! 

a, y 

Calls: 

ReadBlock (Kernal routine) 
IfriteBlock (routine above) 

lffiffffffil«ff««illf«iiiil«||f|«ili««iff||fiSiiii||iii|f|fiiliifilfiliiflfif 



generalBuf 



VerVriteBlock: 



{address of KernaTs internal diks buffer in 
; AUXILIflRY aeaory 



10$: 



90$: 



PushB 
Idx 

Ida 
beq 

PushU 
PushB 
Loady 
LoadB 

PopB 
PopV 
txa 
beq 

dec 

jsr 

txa 
beq 



PopB 
rts 



nunDiskRetries ;save global retry count 

to ;assuoe no error in case of no retries 

nunDiskRetries ijet global retry count 

90$ tif no retries, do nothing 

r4 isave buffer address 

RUbank ;save bank status 

r4.SgeneralBuf ;use Kernal internal block buffer 
RUbank, tflUX 

ReadBlock ;read block to verify it 

RUbank , irestore bank status 

r4 irestore buffer address 

90$ 5if no error, exit 

nunDiskRetries iadjust retry count to indicate upcoiing attenpt 

UriteBlock icall our urite block routine (above) that 
I does no retries 

10$ ;if no error, Iood back to verify it 
tif error, exit ioiBediately 



nunDiskRetries 



files print0ut2.agl, page 0, tin Thu Har 24 11M4--J4 1?88 



CEOS Variable docuDentation 
Preliainary release 3/23/88 



file-' printGut2.ng], page 1, tine Thu Har 24 11:46:54 1988 



iiauic * 


alarnSetFlao 


PnrMor 1 ii S 

roiRcr ly* 




nuurcds * 




w 1 fcC 


Byte 


Default: 


FALSE 


javcu! * 


No 


Oacr r 1 nf 1 nn S 

Uc9cr ipw luii* 


TPIir if thp fllArn <pf! fnr npn< fn nnnitnr p1<(p FOI 


Note: 




Name: 


a larnTtttUector 


Ffirtt^r lui 

1 U 1 Mw 1 » y 




AdHr^s^: 

nuui 


C64: §84ad C128: $84ad Aoole: $0212 


Size: 


Vord 


Default: 





Saued?: 


Yes 


uescr ipv lon* 


dUQic?? or d scrviwC iDUbinc lur wne aidrni wiuCR biRic ouv 

(ringing, graphic etc.) that the application can use if 

nprp<cAru 

tlwbk^^Ql y » 


Note: 

liU Ww * 




Nane: 


alphaFlag 


Formerly: 


• 


Address: 


C64: $84b4 C128: $84b4 Apple: $0225 


Size: 


Byte 


Default: 


if not gettinq text input 

llxxxxxx if getting text input, where xxxxx are counter bits 


Saued?: 


Yes 


uescr ipc lon* 


n^n fnr ;i1nhAniimpr ir ^trinfl infiut 
r idQ lUi a ipndnuoici lu ^wi in^ mpuv 

bit 0-5 - Counter before pronpt flashes 

bit 6 ' Flag indicating prompt is visible 

bit 7 - Flag indicating alphanuiseric input is on 


Note: 




liuulC ■ 


rinnfldin 

r r 


Fflrn^r 1u: 

1 u 1 Hci • y 


addI icdtiontlain 


nuui C^T> * 


C64: S849b C128: S849b Apple: $0200 


Size: 


Hord 


uerauii* 




Saued?: 


No 


Description: 


Vector that allows applications to include their own sain loop 
code. The code pointed to by appftain will run at the end of 
every EEOS lainloop. 



Note: 



files print0ut2.agl, page 2, ti»e Thu Har 24 ll!46s34 1?88 



Nane: 


backBufPtr 


Foraerlys 




flddresss 


C64: NA Ci28: $131b Apple: $9d7c 


Q 1 70 ■ 
W 1 4C* 


16 bytes 


Default: 


None 


Saved?: 


No 


Description: 


Screen pointer where the back buffer cane from. 
Resides in back ran of C128 and Apple. 


Note: 




Name: 


bakclrO. bakclrl, bakclr2, bakclr3 


For»erIy: 




Address: 


C<4: $do21 - 4do24 respectiuely 
C12a: ^do2l - sdo24 resoectiuelu 
Apple: NA 


Size: 


1 Byte each 


Uetau It* 




davcuf * 


No 

nu 


ucscr ip V lun* 


RArknrniinrl colors 0*3 


nu wc* 




Name: 


backXBufNuR 


Foraerly: 




Address: 


C64: NA C128: n32b Apple: $d98c 


Size: 


8 bytes 


Default: 


Hone 


ddueof * 


no 


vcscr ip V 1 on* 


For fiArh ^nritp thpr# W nnp hutp h^rp for hou Bdnu hutffS 

rUI cavil l*Ct WIICIC I9 UIIC uyvc IICI C i ui nwv waiiy wywb7 

wide the corresponding sprite is.^ Used by C128 and Apple 

9ulW VC iVIU*illC9 QIIU iC9l III VOWR I BUi • 


nu wc • 




Naae: 


backYBufHuB 


Formerly: 




Address: 


C64: Hfl C128S $1333 Apples $d994 


Size: 


8 bytes 


Default: 


None 


Saved?: 


Ho 



Description: For each sprite, there is one byte here for hou nany scanlines 
high the corresponding sprite. Used by C128 and Apple soft 
sprite routines and resides in back raa. 

Note: 



Nane: bootNaeie 



file: printOutZ.ngl, page 3, tine Thu flar 24 11:46:34 1988 



rorBicr ly* 




nuui 


c^4: scoo^ C17A: ^roo/( Onnip: <rnn? 




9 But?^ 


Default: 


6E0S BOOT 


Saued?: 


Ho 


Description: 


This is the start of the 'GEOS BOOT' string. 


Note: 




naUK * 




Foraerly: 




Address: 


C64: $84af C128: $84af Apple: $0214 


Size: 


Uord 


Default: 


Coraroodore - SCf85 
Apple - $FEF} 


Saved?: 


Yes 


Descr iot ion: 


Vector to the routine that is called uhen a RRK in^t:riirf inn i< 
encountered. The default is to the operating systeia 

'^u^tpii Prrnr' Hitilnfi hnv rniitinp 
wy^wcii bi 1 UI uiaiuu uua iuuviiic* 


no vc* 




naioc * 


hif iipr 
UK vcu 


Forner tu* 




Address: 

iiu w 1 www 


C64: $0916 C128: i316 Aoole: NA 

WW* Y"^*** W4fcW y^*W IllrlrlW lilt 


Size: 


Uord 


Default: 


???????? 


Saued?: 


No 


Description: 


BRK instruction uector for uhen ROfls ar? switched in. 


Note: 




Nafoe: 


basel ineOffset 


rnrnpr 1 ii s 
1 ui ifici 1 y * 




nuui * 


C^d: C128: £76 floole: §0218 


Size: 


Byte 


Default: 


$06 - for BSy 9 font 


daUcUf* 


ICS 


UC^bl 1 U V lull * 


Offset frnn tnn line to hA<p1inp in character <pt i p \t 

U i 1 9C« 1 I UHI WUU 1 1 liw WU Ua^C llllw lit wtiuiow 9C b* ItCt IV 

changes as fonts change. 


Note: 




Nane: 


CPUJATA 


For»er1y: 




Address: 


C64: $0001 C128: NA Apple: NA 



file! printOutZ.agl, page 4, tiae Thu Mar 24 11j4<!34 1988 



Size5 
Default: 
Saved?! 
Description! 



Uord 

RAnj4K ($30) 
No 

Address of 6510 data register that controls the hardware nenoru 
nap of the C64. The following constants are used with CPU.DfiTA. 



Value 

10 IH 
RAH 64K 

KRNU BAS 10 IN 
KRNnO TN " 



dapping 

<0K RAH, 4K I/O space 
64K RAH 

both Kernal and basic ROtIs napped into s^ory 
Kernal ROM and I/O space napped into menory 



Note! 



Name! 

Foraerly! 

Address! 

Size! 

Default! 

Saved?! 

Description! 

Note! 



CPUJOR 

C64! $0000 C128! NA Apple: NA 

Byte 



No 



address of 6510 data direction register 



Nane: 

Foriaerly! 

Address: 

Size: 

Default! 

Saved?: 
Description: 

Note: 



cardDataPntr 
cardOataPointer 

C64: $2c C128: $2c Apple: $60 

Uord 

Coottodore: $D2DC - for BSil 9 font 
Apple: $0150 - for BSU 9 font 

Yes 

This is a pointer to the actual card graphics data for the 
current font in use 



Naote: 
Fornerly: 
Address: 
Size: 

Default: 

Saved?: 

Description: 

Note: 
Nane: 



curDirHead 



C64: $8200 C128! $8200 Apple: $FA80 

Conaodore - 256 bytes 
Apple - 39 bytes 

$00 

No 

For Coflttodore, it is the buffer containing header infomation 
for the disk in currently selected drive. 
On the Apple, curOirHead contains the header of the current 
directory. Initialized to all zeros. 



curDevice 



file! print0ut2.ngl, page 5, tine Thu tiar 24 ll!46!34 1?B8 



Formerly! 




Address! 


C64: m C128: $ba Apple: NA 


Size! 


Byte 


Default! 


Comaodore « $08 


Saved?! 


No 


Description! 


This holds the current serial deuice number. See curDrive 
for Bore information 


Note! 




Nane: 


curDriue 


For«erly! 




Address! 


Ci4! $8489 C128: $8489 Apple: $F<Od 


Size! 


Byte 


Default! 


Commodore - $08 
Apple = $00 


Saued?! 


No 


Description! 


Holds the deuice number of the currently actiue disk drive. 
For Commodore, allowed values are 8 - 11. For Apple, drives 
are numbered 0-3. 


Note! 




Name! 


curEnable 


Fornerly! 




Address! 


C64! NA C128: $1300 Apple: $0951 


Size! 


Byte 


Default! 


None 


Saued?! 


No 


Description! 


This is an image of the C<4 mobenble register. Used for C128 
and Apple soft sprites. 


Note: 




Hairie! 


curHeight 


Foroerly! 


currentHeight 


Address! 


C64: $29 C128: $29 Apple: $021B 


Size! 


Byte 


Default: 


$09 for BSB 9 font 


Saued?! 


Yes 


Description: 


Used to. hold the card height in pixels of the current font in 
use. 


Note! 




Nane! 


curlndexTable 


Formerly! 


currentlndexTable 


Address! 


C64: $2a C128: $2a Apple: $005E 



file: print0ut2.figl, page 6, tiK Thu liar 24 11:4604 1988 
Sizes Word 

Default: CoBuiodore: $D218 for BSU 9 font 

Apple: $0C08 for BSy 9 font 

Saved?: Yes 

Description: curlndexTable points to the table of sizes, in bytes, of each 
card in of the current font. On the Apple, this variable only 
exists in the back ran zero page. Aponcations nust switch 
zero pages before accessing it directly. 



Hote: 


Nafoe: 


curnobx2 


Fomerly: 




Address: 


C64: HA C128: $1302 Apple: $D953 


Size: 


Byte 


Default: 


None 


Saued?: 


No 


Description: 


Imaoe of the C64 Bobx2 register. Used for C128 and Apple 
soft sprites. Resides in back ran. 


Note: 




Narne: 


curnoby2 


Foroerly: 




Address: 


C<4: NA C128: $1301 Apple: $0952 


Size: 


Byte 


Default: 


None 


Saued?: 


No 


Description: 


Inaqe of of C64 Roby2 register. Used for C128 and Apple 
soft sprites. Resides in back ran. 


Note: 




Nane: 


curPattern 


Foraerly: 


currentPattern 


Address: 


W4: $22 C128: $22 Apple: $022c 


Size: 


yord 


Default: 


$0010 


Saved?: 


Yes 


Description: 


curPattern points to the first byte of the graphics data for the 
current pattern in use. 


Note: 


Each pattern is 1 byte wide and 8 bytes bytes high, to give an 
8 by 8 bit pattern. 

Apple: The location of patterns pointed t/ bu cLrPattern is in 
back raiB and should not be accessed directTyr^See SetPattern 
and GetPattern. 



Hai&e: curRecord 
Formerly: 



files printOutZ.ngl, page 7, tiae Thu flar 24 ll!4i!34 1988 



flddresss C<4: $849i C128: $8496 Apple: $f<18 

Sizes Byte 

Default: $00 

Saued?: No 

Descriptions Holds the current record number for an open ULIR file. 

Note: Uhen a VLIR file is opened, using OpenRecordFile, curRecord is 

set to if there is at least 1 record in the file, or -1 if 
their are no records. 



HaiBes 

Former lys 

fiddresss 

Size: 

Default: 

Saued?: 

Descriptions 



currentHode 

C64s $2e C128: $2e Apple: $021C 

Byte 

$00 

Yes 

Holds the current text drawing node. Each bit is a flag for a 
drawing style. If set, that style is actiue, if clear it is 
inactiue. The bit usage and constants for naninuplating these 
bits are as follows. 

Bit Style Constant 

b7: Underline flag SET UNDERLINE - XIOOOOOOO 

b6: Bold flag SETlOLO « XOIOOOOOO 

b5: Reuerse flag SETlEUERSE « XOOIOOOOO 

b4s Italics flag SETlTflLIC = MOOIOOOO 

b3s Outline flag SEFOJITLINE « XOOOOIOOO 

b2s Superscript flag SET"SUPERSCRIPT=J:00000100 

bis Subscript flag SET SUBSCRIPT - XOOOOOOIO 

bO: Unused 

Clears all flags (plain text) SETJLAINTEXT = WOOOOOOO 

Any combination of flags can be set or clear. If current 
node is plaintext, all flags are clear. 

Constants that can be used within text strings themselues that 
affect currentflode ares 

UNDERLINEON, UNDERLINEOFF, REUERSEON, REVERSEOFF, BOLDON, 
ITflLICON, OUTLINEON, PLAINTEXT 



Note: 



Natte: curSetVidth 

Formerly: currentSetllidth 

Address: C64: $27 C128s $27 Apples $219 

Sizes llord 

Defaults Coonodores $005c 
Apples $0051 

Saued? s Yes 

Descriptions Holds the card width in pixels for the current font 
Notes 



Na»es curType 
Formerly: 



file: printOutZ.agl, page 8, tine Thu flar 24 11:46:34 19B8 



Address: C64: $88ci C128: $88c6 Apple: Nfl 

^Size: Byte 
Default: Disk type of driue 8 for Comnodore 

Saued?: Ho 

Description: Holds the current disk type. This ualge is copied fron 
driueType for quicker access to the current drive 
b7: Set if the disk is a RAH disk 
b6: Set if using disk shadouing 

Only one of bit 6 or 7 nay be set. Other constants used with 
curlype are 

DRUjULL "0 No driue present at this device address 
DRU 1541 > 1 Driue type Conmodore 1541 
DRU 1571 « 2 Drive type Connodore 1571 
DRVJ581 « 3 Drive type Comaodore 1581 



Note: 



Naoe: curXposO I q \^^f[f^ 
Forserly: 

Address: C64: NA C128: /<1303/ Apple: $0954 

Size: 16 bytes ^ 7 

Default: None 

Saved?: No 

Description: The current X positions of the C128 and Apple soft sprites. 
Resides in back ran. 

Note: 



Nane: 
Formerly: 


curYposO I ^ \r^(£Ky>^ 


Address: 


C<4: NA C128:/il313y Apple: $0964 


Size: 
Default: 


None 


Saved?: 


No 


Description: 


The current Y positions for the C128 and Apple soft sprites. 
Resides in back ran. 


Note: 




Nai&e: 


devUnitTab 


Fornerly: 




Address: 


C64: NA C128: NA Apple: $FAEF 


Size: 


4 Bytes 


Default: 


$60 in each byte 


Saved?: 


No 


Description: 


The ProDos unit nuabers of the four possible devices are kept 
here. Used for conaunicating with the device drivers. 



Note: 



deuTabHi 



file: printOutZ.ag], page ?, tine Thu Har 24 11:46:34 1988 



Fornerly: 




fiddress: 


Cj4: NA C128: NA 

Apple: deuTabHi - $FA£7, devTabLo - $FAEB 


Size! 


4 Bytes each 


Default: 


deuTabHi - $D0 in each byte, devTabLo - $00 in each byte 


Saved?: 


No • 


Description: 


For the Apple, these are the high and lou bytes of the four 
possible device drivers. 


Note: 




Naoe: 


dirBUno 


Foraerly: 




Address: 


C64: NA C128: NA Apple: $F620 


Size: 


Uord 


Default: 


$02 


Saved?: 


No 


Description: 


Block number of the key block of the directory containing 
this file's entry. 


Note: 




Name: 


dirPtr 


Formerly: 




Address: 


C64: NA C128: NA Apple: $F622 


Size: 


Uord 


Default: 


$00 


Saved?: 


No 


Description: 


Pointer into diskBlkBuf for this file's entry. 


Note: 




Haiae: 


diskBlkBuf 


Fornerly: 




Address: 


C64: $8000 C128: $8000 Apple: $F659 


Size: 


Comaodore - 256 bytes 
Apple - 512 bytes 


Default: 


$00 


Saved?: 


No 


Description: 


Eeneral disk block buffer. Initialized to all zeros. 


Note: 




Nai&e: 


doRestFlag 


Formerly: 




Address: 


C64: NA C128: $lb54 Apple: $DBld 


Size: 


Byte 



files print0ut2.Bgl, page 10, tine Thu tlar 24 11546J34 1988 



Defaults 

Saued?s 

Description* 

Note! 



FALSE » 
No 

Flag needed because of overlapping soft sprite problens on C128 
and Apple. Set to TRUE if ue see a sprite that needs to be 
redrawn and therefore all higher numbered sprites need to be 
redrawn as well. Resides in back Raa. 



Naoie: 

Fornerly! 

Address: 

Size! 

Default! 

Saved?! 

Description! 



Note! 



driueType 

C64! $848e C128! $848e Apple: $FAF3 
4 bytes. 

Set to type of drive 8 on Connodore or drive on Apple. 
No 

There are 4 bytes at location driveType, one for each of four 
possible drives. 

For CofWBodore, each byte has the following for»at! 

b7: Set if drive is RAH DISK 

h6' Set if Shadowed disk 

Only 1 of bit 7 or bit 6 aay be set 

Constants and values used for drive types are 

Constant Value Type 

DRV NULL No drive present at this device address 

DRU'"1541 1 Drive type Commodore 1541 

DRri571 2 Drive type Commodore 1571 

DRVJ^Bl 3 Drive type Commodore 1581 

For Apple, the only differences between drive types is whether 
the drive media is removable (e.g. floppy) or non-removable 
(e.g. hard drive). The bit usage is as follows: 

b7! set if disk medium is removable 

b6! set if device is interruptable 

b5,4! number of drives on the device (0-3) 

b3! device driver supports format 

b2! device driver supports write 

bl: device driver supports read 

bO: device driver supports status call 



Th 
d 



his bit usage conforms to the information ProDos keeps about 
isk drives. 6E0S, however, only makes use of bits 7 and 3. 



Name! drSizeLo, drSizeHi 

Formerly! driveSizeLo, driveSizeHI 

Address: C<4! NA C128! NA 

Apple: drSizelo - $ FAF7, driveSizeHi - $FAFB 

Size: 4 Bytes each 

Defaults Hone 

Saved?! Ho 

Descriptions The low and high bytes of the sizes of the four possible 
device sizes. 



Note: 



file! print0ut2.ac' 



, tine Thu tlar 24 11:4^:34 1788 



Kane: 


disi^^ j 


Forftcrlys 




Address^ 


C44: ^^43a Ci28: $848a Apple: $F617 


Sizes 


Byte 


Default: 


TRUE (§FF) 


Saved? 5 


No 


Description: 


Set to TRUE or FALSE to indicate ubether a disi is currently 
open . 


Note* 




Name: 


DrflCurOliNa 


Forsier lys 




Address! 


Cj4< $841e C128s $841e AddIc: i?M7 


Size* 


Commodore • 18 bvtes 
Apple - 14 bytes 


Default: 


None 


Saved?: 


No 


Descr iot ion: 


This is the disk name of the current disk in drive A. 

Illl^ 1^ vllW II WUIW wl «IIW WWIIWIlV Ul^n III Wl IVW 111 

Commodore - padded uith $A0 

Annlp *- nAHHpri uitK ADO 
nuu ic pauucu m i vii yvv 


Note: 




Na»e: 


DrBCurDkN« 


Fo(»erIy: 




Address: 


C44: $8430 C128: $8430 Apple: $FAB7 




Commodore " 18 butes 
Apple - 14 bytes 


Default: 


None 


Saved?: 


No 


np<rr 1 inn ■ 


Thi< 1^ thp di^k nAfhP flf the current di^k in drive B. 

11119 19 Vllu U 1 9K llQUtC U 1 VllW WUIIwllV UI9I^ III Ul IVw U* 

Commodore - padded yith $A0 
Anole " oadded uith SOO 

nupiw VHUucu w 1 VII 


Nntp: 




Nase: 


dataFileName 


Foraer ly: 




Address: 


C44: $8442 C128: $8442 Apple: $02A4 


Size: 


Cnnnndore * 17 bvtes 

bUIWiiWUUI C *• 

Apple - 14 bytes 


Aof All If! 

uerau IV* 


Mil AM 

none 


Saved?: 


Hp 


Description: 


This is the naee of a data to open. The name is passed to the 
parent application so the file can be openned. 



Note: 



file: printOutZ.sgl, page 12, tine Thu Har 24 11:46:34 1788 



Hane: 
) For»erly: 
Address: 
Size: 

Default: 
Saved?: 
Description: 
Note: 



dataDiskNane 



C64: $8453 C128: $8453 Apple: $02B4 

Com&odore - 18 bytes 
Apple - li bytes 

Hone 

Ho 

Holds the disk nane that an application's data file is on. 



Name: 

Foraerly: 

Address: 

Size: 

Default: 

Sayed?: 

Description: 



Naiie: 

Formerly: 

Address: 

Size: 

Default: 

Saved?: 

Description: 

Hote: 



dispBufferOn 
displayBufferOn 

C64: $002f C128: $002f Apple: $021d 
byte 

(STJRJORE I STJRJACK) « $cO 
yes 

Routes graphic and text operations to either the foreground 
screen, background buffer, or both simultaneously. 

b?: 
bi: 
b5: 



1 « draw to foreground screen buffer 
1 draw to background buffer 
1 « limit GetStnng text entry to foreground screen. 
" GetString text entry will use b7,bi 
b4-bO: reserved for future usei should always be 

Use ST HRJORE (write to foreground) and STJRJACK (write 
to background) to access these bits. 

Note: !(OOxxxxxxxx is an undefined state and will result in sending 

most graphic operations to the center of the dtspaly area. 



day 

C64: $8518 C128: $8518 Apple: $F202 

Byte 

20 

Ho 

Holds the value for current day. 



Name: 
Formerly: 
Address: 
Size: 

Default: 

Saved?: 

Descriptions 



dIgBoxRamBuf 



C64: $851f C128: $851f Apple: $F381 

Commodore - 417 Bytes 
Apple - 64? Bytes 

Hone 

Yes 

This is the buffer for variables that are saved when desk 
accessories or dialog boxes are run. 



file: printOutZ.ngl, page 13, tine Thu liar 24 ll:4j:}4 1988 



Note: 



nai8C * 


UI ivcuava 


PflrikPr 1 11 * 
1 ui ■ici 1 y " 




Address' 


C64: $88bf C128: $88bf Apple: NA 


Size: 


4 bytes 


UCI uU 1 b * 


None 


gdvcQ! * 


No 

liU 


Dp^cr lot ion* 

UC9Wi 1 U W 1 Uli 


One bute is rss^rupd for each disk dr iup. to bp us^d hu th^ 
the disk driver. Each driver nay use it differently. 


Note: 




nanic * 


dbiriirkCniin^ 

UU lb 1 IwKbUUIIW 


r oriBcr ly • 




Address: 


C64: $8515 C128: $8515 Apple: $0258 


Size: 


Byte 


Default: 


$00 


Saued?: 


No 


Description: 


Used to deteraine uhen an icon is double clicked on. Vhen an 
icon is selected, dblClickCount is loaded with a value of 
LLXLN^tuuni i/V|. OD it 1 iCRLounw IS vnen oecreDcnieQ eacn 
interrupt. If the value is non-zero uhen the icon is again 

ep1orfp<4 fhpn fhp Wmihlo rlirk flan frOUl i< nAft<o<4 fn fko 

service routine with a value of TRUE. If the dblClickCount 
variable is zero uhen the icon is clicked on, then the flag is 
passed uith a value of FALSE. 


Note: 




Nase: 


DrCCurDkNn 


Foriaerly: 




Address: 


C<4: $88dc C128: $88dc Apple: $FAC7 


Size: . 


CorDinodore - 18 bytes 
AddIc " 16 bvtes 


UCI au 1 w * 


Nonp 

nunc 


wOVCU ! * 


No 


Dp^rr \ nt. \ nn S 

Vw3Wi iUblUII* 


Thi^ i^ the disk n^ftp nf thp current disk in driup T 
Commodore - padded uith $A0 

Onnip - n^ddpd uith ^nO 

nUU IC uaUUCU 9 1 Wll y VV 


Note: 




Haoe: 


OrOCurOkHi 


Forwrlys 




Address: 


C64: $88ee C128: $88ee Apple: $FflD7 


Size: 


Comodore - 18 bytes 
Apple - U bytes 


Default: 


None 


Saued?: 


No 



file: printOutZ.agl, page 14, tiM Thu liar 24 11:46:34 1988 



Dp^rr intionS 


Thi^ 1^ thp fii^k rififiP nf thp nirrpnt rfi<ir in ilrfiip 

11119 19 WIIC UI9ft lianC Ul VIIC bUIICIIW Ul9ft III Ul IVC w* 

Cottttodore - padded with $A0 
Aoole ~ oadded uith SOO 


Nntp: 




Name: 


dirEfltryBuf 


FoFBGr ]y* 




Address: 


C<4s $8400 C128S $8400 Apoles $FA59 


Size* 


CoQtnodore ~ 25^ 
Apple - 39 bytes 




$00 


Saued?: 


Ho 


Descriptions 


Buffer used to build a file's directory entry. Initialized to 

a}] zpro^ 

all fcCi wjt 


Note: 




Name-* 


dir2Head 


ForaerlyJ 




Address: 


C<4: $8900 C128: $8900 Apple: Nfl 


Sizes 


Conaodore - 256 bytes 


Defaults 


None 


Saued?! 


No 


Descriptions 


This is the 2nd directory header block used for larger capacity 
disli driues (e.g. Coounodore 1571) 


Notes 


« 


Nanes 


dateCopy 


Fornerlys 




Addresss 


C64S $C018 C128S $C018 Apples NA 


Sizes 


3 bytes 


Defaults 


Sane as variables year, lonth, day 


wU vwu : 


No 

liU 


Dp^cr i ot ion! 


Thi< i< A cfiQU of thff ^u^tpfi udr iahl#^ for uesr annth AnA Aau 

11119 19 a biiwy Ul viiw 9y9irwM vul iauic9 i wi ywai | hiuiiwiI| qiiu uoyi 


Notes 




Nanes 


extclr 


Forterlys 




Addresss 


C64: $0020 Ci28: $0020 Apple: NA 


Sizes 


Byte 


Defaults 


$FB 


Saued? s 


No 


Descriptions 


Holds ualue for exterior (border) color. 


Notes 





file: printOutZ.agl, page 15, tiae Thu flar 24 11j4<:54 1988 



Nane: 

former ly! 

Address^ 

Sizes 

Defaults 

Saved?: 

Description-* 



fauitOata 

C64: $84b6 C128: $84b6 Apple: $0227 

Byte 

$00 

Yes 

Holds information about mouse faults. House faults occur when 
the mouse attempts to aoue outside the bounds set by mouseLeft, 
aouseRight, mouselop, and mouseBotton. fl fault is also 
signalled when the mouse is outside the current menu area. The 
bits for signalling are used as follouss 



Bit Fault 

b/s mouse fault up 

h6' mouse fault down 

b5: mouse fault, left 

b4: mouse fault right 

b5: menu fault 



Constant for bit access 

OFFTOP BIT 
OFFBOTlOn BIT 
OFFLEFT BIT 
OFFRIGHT BIT 
OFFtlENU BIT 



Notes 



Names 
Formerly: 
Addresss 
Sizes 

Defaults 
Saued?s 
Descriptions 
Notes 



f ileHeader 



Cj4s $8100 C128S $8100 Apples $F857 

Commodore - 256 bytes 
Apple - 512 bytes 

$00 

No 

Buffer used to hold the header block for a 6E0S file. 



Names 

Formerlys 

Address: 

Sizes 

Defaults 

Saved?: 

Description: 

Note: 



f ileSize 

C64: $8499 C128: $8499 Apple: $F<1B 

Uord 

None 

No 

This is the current size (in blocks) of a file. It is pulled 
in from and written to the file's directory entry. 



Name: 

Formerlys 

Addresss 

Sizes 

Defaults 

Saved? s 

Descriptions 



fileTrScTab 

C64s $8300 C128S $8300 Apples NA 

25< Bytes 

$00 

No 

For Commodore, it is the buffer used to hold the track and 



file: printOutZ.tgl, page li, tine Thu Flar 24 lls46:54 1?88 



Hote: 



sector chain for a file of ■axinue size of 32258 bytes. 



Nai&e: 

Fomerlys 

ftddresss 

Size* 

Default: 

Saved?: 

Description: 

Notes 



C128: $8498 Apple: $F£1A 



fileyritten 

C£4: $8498 
Byte 
None 
No 

Flag indicating if a if the currently open file has been uritten 
to since the last update of its index table and the Bfttl. 



Nai&e: 

Foraerlys 

Address: 

Size: 

Default: 

Saued?: 

Description: 

Note: 



firstBoot 

C64: $88c5 C128: $88c5 Apple: $0281 
Byte 

See below 
Ho 

This flag is changed fron to $FF uhen the desklop coaes up 
after booting. 




f^ntOata 
saueFontTab 

rrl850C C128: $850c Appl 
9 bytes 
None 
No 

Description: Buffer for sauing the user active font table uhen going into 
nenus. 

Note: 




"JntTable ^ 
cardDat| 

4: $26 C128: $26 

8 bytes 

Default font information 
Yes 



Appl 



<™2 



Saued?: 

Description: fontTable is a label for the beginning of variables for the 
current font in use. These variables are baselineOffset, 
curSetllidth. curHeight, curlndexTable, and cardOataPntr. 
For more inroraation, see docusentation on these variables. 



Note: 



file: print0ut2.ig], page 17, tine Thu Har 24 11:46:34 1988 



Nane: 


grcntrll 


Foraerlys 




Address: 


C64: $0011 C128: $0011 Apple: NA 


Size: 


Byte 


Default: 


$55 


Saued?: 


Ho 


Hacr p 1 nf 1 nn S 
UC^Ci ip V lUit* 


ijiapiiius buiiwiui icijoicr ffi| ic bpu raster/ ctii/oiut/ucn/ngCL/y 
scroll bits defined for use with above reg. 
st^eca « S40 

<f KmM s 470 

St Jen « 510 
st 25rou « 508 


Note: 




Nane: 


grcntrl2 


Formerly: 




Address: 


C64: $0016 C128: $0016 Apple: NA 


Size: 


Byte 


Default: 


$AA 


Saued?: 


no 


Description: 


graphics control register 12, ie: RES/flCfl/CSEL/x scroll bits 

t nt%A 91%^ Ilea iii^K AnAiia 

QcrineQ ror use uicn aoove reg. 
St.BCBI = 510 


Note: 




Name: 


grirq 


Formerly: 




Address: 


C64: $0019 C12B: $001? Apple: NA 


Size: 


Byte 


Default: 


$42 . 


jovcu : * 


Nn 
no 


Hpcrr {nt inn* 


nrdohic^ chin intprriini! fpti\^tpr 


ilU wc* 




Nane: 


grirqen 


ForBerly: 




Address: 


C64> $d01a C128: $d01a Apple: NA 


Size: 


Byte 


Default: 


$24 


Saved?: 


No 


Description: 


graphics chip interrupt enable register 

bit to enable raster interrupt in grirqen is bit 

St rasen » $01 


Note: 





files printOutZ.ng), page 18, tine Thu Mar 24 11:46:54 1988 



Name: 

Fornierlys 

Address: 

Size: 

Default: 

Saued?: 

Description: 

Note: 



grnenptr 

C64: $d018^ C128: $d018 Apple: NA 
Byte 

No 

graphics nenory pointer Vni3-UniO|CB13-CBll. ie video satrix 
and character base. 



Name: 

Fornerly: 

Address: 

Size: 

Default: 

Saved?: 

Description: 

Note: 



hour 

C64: $8519 C128: $8519 Apple: $F203 

Byte 

12 

Ho 

Variable for hour 



Name: 

Formerly: 

Address: 

Size: 

Default: 

Saved?: 

Description: 



C128: $84b5 Apple: $0226 



iconSelFlag 

C64: $84b5 
Byte 
$00 
Yes 

This RAH variable contains flag bits in b7 and b6 to specify 
how the systes should indicate icon selection to the user, if 
no bits are set, then the systett toes nothing to indicate icon 
selection, and the service routine is sinply called. 
The possible flags are: 

ST FLASH « $80 \ flash the icon 
STiINVERT « $40 ; invert the selected icon 

If ST FLASH is set, the ST INVERT flag is ignored and the icon 
flashes but is not inverted when the prograttner's routine is 
called. If ST INVERT is set, and STJLASR is CLEAR, then the 
icon uill be Inverted uhen the prograiMier's routine is called. 



Note: 



Name: 

Formerly: 

Address: 

Size: 

Default: 

Saved?: 

Description: 



indexBlkno 



Apple: $F624 



C64: NA C128: NA 

Uord 
$00 
No 

Block number of the VLIR index table (ProDos master index 



file* print0ut2.«gl, page 19, tiae Thu flar 24 11J44SJ4 1988 





block). 


Note« 




Name: 


inputData 


FortterlyJ 




Address: 


C64: $8506 C128: $8506 Apple: $0247 


Size: 


4 bytes 


Default: 


None 


Saued?: 


No 


Description: 


This is where input driuers pass deuice specific inforaation to 
applications that want it. 


Note: 




Nane: 


inputDeuNarse 


forwerly: 




Address: 


C64: $88cb C128: $88cb Apple: $08CC 


Size: 


Comnodore - 17 bytes 
Apple - 16 Bytes 


Default: 


None 


Saued?: 


No 


Description: 


String that holds the name of the current input deuice. 
e.g. Conn nOUSE for coflinodore mouse. 


Note: 




Name: 


inputVector 


Foriaerly: 




Address: 


C64: $84a5 C128: $84a5 Apple< $020A 


Size: 


Uord 


Default: 


$00 


Saued?: 


No 


Description: 


Pointer to routine to call on input deuice change. 


Note: 




Haine: 


intfiotVector 


Forfterly: 


interruptBottoaVector 


Address: 


C64: $849f C128: $849f Apple: $0204 


Size: 


Hord 


Default: 


$00 


Saued?: 


No 


Description: 


Vector to routine to call after the operating systea interrupt 
code has run. This allows applications to haue interrupt leuel 
routines. 


Hote: 





file: print0ut2.ag1, page 20, tine Thu flar 24 li:4i:34 1788 



Watae'' intlopVector 
Fornerlys interruptTopVector 



Address! 


Ci4: $849d C128: $849d Apple: ^0202 


Size: 


Uord 


uciau 1 V * 


Y V V 


wQVCU : * 


No 


Dp^cr iotion* 


Vector to routine to call before operating systen interrupt 
code is run. It allous applications to interrupt leuel 
routines. 


llU bC* 




Name: 


intSource 


Foraerly! 


interruptSource 


Address: 


C64: NA C128: NA Apple: $02C6 




Rut? 


Default: 


None 


Saued?: 


No 


Description: 


Byte to indicate where interrupts are coning fron on the Apple. 

$oO indicates nouse card 

^40 indicates interrupt nanagenent card 

$00 indicates software interrupts 


Note: 




Nane: 


interleaue 


Forierly: 




nuui ww9* 


C64: i848c C128: $848c Aoole: NA 


Size: 


Byte 


Defaults 


$08 


Saued?: 


No 


Description: 


Vartabje used by BIkAlloc routine as the desired interleaue uhen 

ocicwwiitM 1 1 cc uiuwiks 1 III a ui3i^ Liiaiii* 


liU * 




Nane: 


inuertBuffer 


Fornerly: 






CM: NA ri7A: ^Irpd Annlp: Nfl 
but" iin wi4D* yiucu nupic* nn 


Size: 


80 Bytes 


Default: 


None 


Saued?: 


No 


Description: 


Buffer area used to speed up the 80 colunn InuertLine routine. 
Resides in back Ran. 


Hote: 




Naoie: 


irquec 



Fornerly: 



file: printOutZ.sgl, page 21, tisie Thu Har 24 11:46:54 1?88 



Address: 


C64: $0314 C128: $514 Apple: HA 


Size: 


Uord 


Default: 


$?5fd 


Saued?: 


No 


Description: 


irq uector. 


Hote: 




Haiae: 


isGEOS 


Fornerly: 




Address: 


C64: $848b C128: $849b Apple: HA 


Size: 


Byte 


Default: 


Disk dependent 


Saued?: 


No 


Description: 


Flag to indicate whether the current disk is a GEOS disk. 


Note: 




Haine: 


keyData 


Fornerly: 




Address: 


C64: $8504 C128: $8504 Apple: $0245 


Size: 


Byte 


Default: 


$00 


Saued?: 


No 


Description: 


Holds the ASCII ualue of the current last key that uas pressed. 
Used by keyboard seruice routines. 


Note: 




Nane: 


keyUector 


Foraerly: 




Address: 


C64: $84a5 C128: $84a5 Apple: $0208 


Size: 


Uord 


Default: 


Comnodore - $26A1 
Apple - $416D 


Saued?: 


Yes 


Description: 


Uector to routine to call on keypress 


Note: 




Natae: 


leftHargin 


Fornerly: 




nUUl * 


C'64: $0055 C128: $0055 Apple: $0220 


Size: 


yord 


Default: 


$00 


Saued?: 


Yes 



file: printOutZ.figl, page 22, tine Thu liar 24 11:46:34 1988 



Description: 


Leftmost point for writing characters. Doing a carriage 
return uiil return to this point. 


Note: 




Nane: 


BachineType 


Foraerly: 




Address: 


C64: NA C128: NA Apple: $02C4 


Size: 


Byte 


Default: 


None 


Saved?: 


No 


Description: 


Type of Apple nachine. Values are: 
^00: He 

$80: lie or something else 


Note: 




Nane: 


eaxflouseSpeed 


Fornerly: 


saxifiuiDnouseSpeed 


(Iddress: 


C64: $8$01 C128: $8501 Apple: $027D 


Size: 


Byte 


Default: 


$7f (127) 


Saved?: 


No 


Description: 


llaxiiDUtt speed for nouse cursor. 


Note: 




Nai&e: 


BcnclrO, BCDctrl 


Formerly: 




Address: 


C64: $d025, $d026 
C128: $d025, $d026 
Apple: NA 


Size: 


1 Byte each 


Default: 


None 


Saved?: 


No 


Description: 


These are the variables for Bulti-color node colors 
and 1 respectively on the Connodore. 


Note: 




Hane: 


nenuNuttber 


Foraerly: 




Address: 


C64: $84b7 C128: $84b7 Apple: $0228 


Size: 


Bvte 


Default: 


$00 


Saved?: 


No 


Description: 


Nunber of currently uorking aenu 



file! print0ut2.»gl, page 23, tiiae Thu Mar 24 lUUi3A 1988 



Notes 



Ha»es 


ttinflouseSpeed 


foraerlys 


niniKunflouseSpeed 


flddress-' 


Ci4! $8502 C128! $8502 Apple: $027E 


Size! 


Byte 


Default! 


He (30) 


OdUCU! * 


Nn 

no 


np<rr intionS 


nininuii ^nppH fnr nnii<sP nircnr 


Note! 




Name! 


ninutes 


Foroerly! 




Address! 


C«! $851a C128! $85Ia Apple: $F204 


Size! 


Byte 


Default! 


$00 


Saued?! 


No 


Description! 


Variable for ainutes for tine of day clock. 


Note! 




llaiUC * 


(nnhOrlr nnhlrlr nnhJrlr nnK^rlr itnhArlr- mnK^rlr 




0)ob6clr, Bob7clr 


Foriaerlyi 




Address! 


C64i $d027 - $d02e 








Apple: NA 


Size! 


1 Byte each 


ucrdu 1 w * 


none 


Sdupd?! 

Uwvcu : * 


No 

liU 


uescr ipwion* 


inese are ine colors or vne o oojecws ^spriiesj on LoiD&oooret 


Note! 




Nai&e! 


nobOxpos, nobOypos, noblxpos, noblypos, Aob7xpos, Bob7ypos 


Fornerly! 




Address! 


C64: $0000 - $DOOF 








Apple: Nfl~ r/t(A 


W i bC * 


1 Rutp pArh 
* uy vc cavil 


Default! 


None 


Saved?: 


Ho 


Description! 


These are the x any y positions of sprites 10 to 17 


respectively. 


Note: 





ttobbakcQl 



file: printOut2.ngl, page 24, tine Thu flar 24 11:46:54 1988 



For»erly: 



Address: 


C64: $d01f C128: $d01f Apple: NA 


Size: 


Byte 


Default: 


None 


Saued?: 


No 


Description: 


sprite to baciiground collision register for Connodore. 


Note: 




ndiDC * 




pArnor In • 

r ur mci ly • 




nuui * 


Ci4: idol$ C128: id015 Apple: $0818 


Size: 


Byte 


Default: 


$01 


Saued?: 


No 


Description: 


sprite enable bits 


Note: 




NafDe: 


Biobncm 


r ornpr 1u* 




Address: 

n M v« 1 www 


C64: $d01c C128: $d01c Apple: NA 


Size: 


Byte 


Default: 


$00 


Saued?: 


No 


Description: 


sprite nulti-color node select 


Note: 




Nane: 


Bobnobcol 


Forn^r 1u* 




Address: 


C64: $d01e C128: $d01e Apple: NA 


Size: 


Byte 


Default: 


§00 


Saued?: 


No 


Description: 


object to object collision register 


Note: 




Nai&e: 


nnhor lor 


Fornerly: 




Address: 


C64: $d01b C128S $d01b Apple: HA 


Size: 


Byte 


Default: 


$00 


Saued?: 


No 



file: printOutZ.agl, page 25, tiae Thu flar 24 11:46:34 1?88 



Description: 


object to background priority 


Note: 




Naitte: 


Bobx2, BobyZ 


Forierly: 




Address: 


C64: $d01d, d017 respectively 
LlZo* $dOId, dOu respectively 
Apple: $0819, $081A 


Size: 


1 Byte each 


Default: 


$00 


Saved?: 


No 


Description: 


Double object size in x and y respectively 


Note: 




Haoe: 


Bonth 


Foraerly: 




Address: 


Ci4: $8517 C128: $8517 Apple: $F201 


Size: 


Byte 


Default: 


$09 


Saued?: 


No 


Description: 


Holds Bonth for time of day clock 


Note: 





Name: 


BouseAccel 


Foraerly: 


BOuseAcceleration 


Address: 


C64: $8503 C128: $8503 


Size: 


Byte 


Default: 


$75 (127) 


Saved?: 


No 


Description: 


Acceleration of aouse cursor 


Note: 





Nane: BOuseBottoa 
Foraerly: 

Address: C64: $84b9 C128: $84b9 Apple: $0058 

Size: Byte 

Default: C64 - 199 

Apple - 191 

Saved?: Yes 

Description: Bottoa Bost position for aouse cursor. Noraally set to bottoa 
of the screen. 

Note: 



flies print0ut2.igt, page 26, tiae Thu Har 24 Ui46s34 1988 





BOUseFaultUec 


Foroerlys 


BOUseFaultUector 


Address! 


C64: ^84a7 0128: $84a7 Apple: $020C 


Size! 


Uord 


Default! 


Systen handling routine 


Saved?! 


Yes 


Description! 


Vector to routine to call uhen laouse goes outside region 
defined for nouse position or when louse goes off of a aenu. 


Note! 




Naine! 


wouseLeft 


.ForiBerly! 




Address! 


C64! $84ba C128i $84ba Apple: $0059 


Size! 


Vord 


Default! 


$00 


jdvCU : * 


Yes 


Descr iotion! 


Left Bost position for Bouse 


Note! 




Name! 


nouseOn 


Foroerly! 




Address! 


C64! $30 C128: $30 Apple: $0050 


Size! 


Byte 


Default: 


$E0 


Saued?! 


Yes 


Description! 


Flag indicating that the Bouse is Bode is on. Bit usage and 
constants for accessing theB are as follows 

Bit flode Constant 

b?! Bouse on if set SET HOUSEOH » UOOOOOOO 
b6! nenus on if set SErriENUON » XOIOOOOOO 
b5! icons on if set SETlICONSOH « ZOOIOOOOO 
b4 " bO not used 


Note! 




Nane! 


BOUsePicData 


FortDerly! 




Address! 


W4: $84cl C128! $84cl Apple: NA 


Size! 


64 bytes 


Default! 


BOUse pointer picture 


Saued?! 


No 


Description! 


64 byte array for the Bouse sprite picture on CoBBodore 


Note: 





Naae: 



BouseRight 



files print0ut2.BgU page 27, tiae Thu flar 24 11:4<:34 1988 



ForaerlyJ 




ftddressJ 


C64: $84bc C128: $84bc Apple« $005B 


Size* 


Uord 


Default: 


C<4 - 319 

ClZo - 65/ 
Apple - 559 


2)auedf • 


les 


Description! 


Right Bost position for Bouse. 


note- 




Nantes 


BiouseSaue 


fornerlys 




Address'' 


Ci4s NA C128S $1655 Apples $EE53 


Sizes 


24 Bytes 


Defaults 


None 


Saued?s 


No 


Descriptions 


Screen data for what is beneath nouse soft sprite. Resides in 
Dacx Kan. 


notes 




Names 


BouseTop 


Foroerlys 




flddresss 


C64S $84b8 C128S $84b8 Apples $0057 


Sizes 


Byte 


Defaults 


$00 


SauedfS 


Yes 


Descriptions 


Top Bost position for aouse 


Notes 




Nases 


BouseUector 


Foraerlys 




flddresss 


C64: $84al C128s $84al Apples $020i 


Sizes 


Uord 


Defaults 


Systen routine for icons, nenus, etc. 


Saued?s 


Yes 


Descriptions 


Routine to call on a Bouse key press 


Note: 




Nane* 


BOUseXPos 


Foraerlys 


BOUseXPosition 


Address: 


Ci4s $3a C128: $5a Apples $0241 


Size: 


Uord 



files printOutZ.agl, page 28, tine Thu Har 24 11:46:34 1988 



Default: 


None 


Saved?: 


No 


Description: 


House X position 


Note: 




Name: 


■ouseYPos 


Foraerly: 


RouseYPosition 


Address: 


C64: $3c C128: $3c Apple: $0243 


Size: 


Byte — ' 


Default: 


None 


Saved?: 


No 


Description: 


House Y position 


Note: 




Nane: 


BOUseXOffset 


Formerly: 




Address: 


C64: NA C128: NA Apple: $0229 


Size: 


yord 


Default: 


$00 


Saved?: 


No 


Description: 


Offset froB nouseXPos to draw BOuse sprite. Froa -$8000 
to $7fff 


Note: 




Nafie: 


BouseYOffset 


Foraerly: 




Address: 


C64: $ C128: $ Apple: $022B 


Size: 


Byte 


Default: 


$00 


Saved?: 


No 


Description: 


Offset froB BouseYPos to draw the souse sprite. FroB -128 to 
127 


Note: 




Nane: 


Bsbxpos 


Fornerly: 




Address: 


C64S $d010 C12B: $d010 Apple: NA 


Size: 


Byte 



^^.y Default: 
Saved?: 
Description: 
Note: 



file: print0ut2.»gl, page 29, tine Thu liar 24 11:46:34 1988 



Naoe: 


BsePicPtr 


for»erIy: 


BousePicture 


Address: 


C<4: $31 C12B: $31 Apple: HA 


Size: 


Uord 


Default: 


$84cl 


Saued?: 


Yes 


Description: 


pointer to the nouse graphics data 


Note: 





Naise: 

Formerly: 

Address: 

Size: 

Default: 

Saved?: 

Description: 



Note: 



C128: $c010 Apple: $EOOD 



nationality. 

C64: $c010 
Byte 

- American 
No 



Byte to hold nationality of Kernal. Values are: 

American 

1 German 

2 French (France S Belqiun) 

3 Dutch 

4 Italian 

5 Swiss (Switzerland) 

6 Spanish 

7 Portugese 

8 Finnish (Finland) 

9 UK 

Norwegian (Norway) 

11 Danish (Denmark) 

12 for Swedish 



Name: 


nmiuec 


Formerly: 




Address: 


Ci4: $0318 C128: $318 Apple: NA 


Size: 


Uord 


Default: 


$90c9 


Saued?: 


Ho 


Description: 


NUI vector 


Note: 




Name: 


noEraseSprites 


Formerly: 




Address: 


C64: HA C128: HA Apple: $0240 


Size: 


Byte 


Default: 


FALSE » $00 


Saued?: 


Ho 


Description: 


Flag to stop routine TempHideftouse from erasing sprites 12 - 



file: print0ut2.ng1g page 30, tine Thu Mar 24 11:46:34 1788 



17. Set bit V (set to $80) to signal not to erase sprites. 



Note: 



Nane: 

Forwerly: 

Address: 

Size: 

Default: 

Saued?: 

Description: 

Note: 



nunDriues 

C64: $848d C128: $848d Apple: '$F60E 
Byte 

Drive dependent 
Ho 

Set to nunber of drives on the syste« 



Name: 

Formerly: 
Address: 

Size: 

Default: 

Saued?: 

Description: 

Note: 



objOPointer, objlPointer, obj2Pointer, obj3Pointer, obj4Pointer, 
objSPointer, obj6Pointer, obj7Pointer 



Ci4: $8ff8 - $8fff 
C128: $8ff8 - $8fff 
Apple: NA 

1 Byte each 

objOPointer is set to louse cursor picture 
Ho 

Pointers to the picture data for sprites 



Hafse: 

Formerly: 

Address: 

Size: 

Default: 

Saued?: 

Description: 



Hote: 
^^^^ Hame: 



C128: HA Apple: $027C 



offFlag 

C64: NA 
Byte 

FALSE » $00 
Ho 

Flag telling uhether the louse needs to be redraun. It is used 
as follows: 

Value 

$80 iouse is erased; do not redraw it during interrupt 
aouse is erased; OK to redrau it next interrupt 



$40 
$00 



nornal: iouse is displayed. (Rust be erased before 
draun at a new position.) 



$ff (negatiue/set to TRUE anytiae TettpHidedouse is called) 

otherPressVec 
Fomerly: otherPressVector 

Address: C64: $84a7 C128: $e4a7 Apple: $020E 

Size: Uord 



file! printOutZ.agl, page 31, tiie Thu Har 24 ll!4i:34 1988 



Default t 


$00 


Saved? s 


Yes 


Descriptions 


Vector to routine that is called uhen the louse button is 
pressed and it is not on either a aenu or an icon. 


Note: 




Hane: 


pressFlag 


Forwrlys 




Address! 


C64s $39 C128! $39 Apple! $08FE 


Size! 


Byte 


Default: 


$00 


Saved?! 


No 


Descriptions 


Flag to indicate that a neu key has been pressed. Bit usage! 

b7: key data is neu ^ 
b<! disk data is neu f ■ - 
b5! Bouse data is neu 


Note! 




Naoe! 


PrntFilenaiae 


Forierly! 




Address! 


C64! $8465 C128! $8465 Apples $08AC 


Size? 


Cownodore - 17 bytes 


Default! 


None 


Saved?.! 


« 

No 


Description! 


Name of the current printer driver 


Note! 
• 




Naie! 


PrntOiskNane 


Fornerly! 




Address! 


C64S $847i C128S $8476 Apples NA 


Size! 


Conmodore - 18 bytes 


Default! 


None 


Saved?! 


No 


Description! 


Disk na»e that current printer driver is on 


Note! 




Nane! 


ranBase 


Formerly! 




Addr^^s! 

nuui 


C64s i88c7 C128! $88c7 flpples NA 


Size! 


4 bytes 


Default! 


None 


Saved?! 


No 



file: printOutZ.igl, page 32, tine Thu Har 24 11:46:34 1?88 



Description: 


RAH bank for each disk drive to use if the driue type is either 
» RAH Di^k or Shadoued Driue 


note* 




Name: 


ranExpSize 


Foraerly: 




Address: 


Ci4: $88c3 C128: $88c3 Apple: NA 


Size: 


Byte 


Default: 


RAH driue dependent 


saueo: • 


no 


uescr ipt lon* 


Dyvc lor nuoiuci or laii uoiik? avaiiauic iii nan CApaii^ioii uiiiv* 






Naoe: 


randon 


Foraerly: 




Address: 


Ci4: $850a C128: $850a Apple: $024C 


Size: 


Vord 


Default: 


None 


oauedf • 


no 


vC3l#l 1 U W 1 Ull * 


UArifihlp incrpfipntpd PAch intprruot to o^n^ratp a rArtAnin niifshpr 

vol lOUiw lllwi wWCII WwU wQwII III vwl 1 UU w « U UwllCI BWC O iOIIUUH IIUIhUCI 


note' 




Name: 


rasreg 


Foraerly: 




Address: 


C64: $d012 C128: $d012 Apple: NA 


Size: 


Byte 


Default: 


None 


^avcu: * 


Nn 
no 


uescr ipx ion* 


raster register 






Naae: 


RecouerVector 


Foraerly: 




Address: 


C64: $84bl C128: $84bl Apple: $0216 


Size: 


Hord 


Default: 


Points to RecouerRectangle routine 


Saued?: 


Yes 


Description: 


Pointer to routine that is called to recouer the background 
behind nenus and dialogue boxes. Noraally this routine is 
RecouerRectangle, but the user can supply his oun routine. 


Note: 





Name: returnAddress 



file! print0ut2.agl, page 33, tiae Thu Har 24 11:46:34 1988 



Forierlys 



Address: 


C64: $3d ' C128: $3d Apple: $0064 


Size: 


Vord • 


Default: 


None 


Saved?: 


Ho 


Description: 


Address to return to from in-line call 


Note: 




iiaiuc * 


Ttin)ll\n<(\ rDAVnnel paiiVnne? »csaVam«7 •M^V»j%«it 

reqAposy, reqAposi, reqAposz, reqApos^, reqXpo54, 
reqXposS, reqXpos6, reqXpos? 


Formerly: 




Address: 


C64: NA C128: NA Apple: See below 


Size: 


Tuo Bytes each 


Default: 


None 


Saved?: 


No 


Description: 


These variables correspond to the Coaaodore VIC chip registers 
for sprite X positions. They reside at: 
reoXna^O ^0800 
reqXposl ^0802 
reqXpos2 i0804 

1 cuAuu^y ovuvo 

reqXpos4 f0808 

1 w«^opu9y 9vUVCl 

reqXpos6 i080c 

1 CUApUPr yVOVC 


Note: 




Name: 


rightHargin 


Foriierly: 




Address: 


C64: $37 C128: $37 Apple: $0222 


Size: 


Hord 


Default: 


C64 - 31? 
C128 - 639 
Apple - 559 


waveor * 


Yp< 

ICS 


i/csur ipw ion* 


Thp rinhtnn^t Doint for uritino characters. If an Attpmnt i< 
Bade to urite past riqhtHargin, the routine pointed to by 

Qf r innrAiilfUpr i< PftliPd. 
3 wi inur du 1 bVCw i^ waiicut 


noic* 




Naoe: 


saveFontTab 


rnrnpr luS 
r ui nci 1 y " 






C64: $850c C128: ^A^Oc Aoole: $024E 


Size: 


Cowodore - 9 bytes 
Apple - 10 Bytes 


Default: 


None 


Saved?: 


Ho 


Description: 


Uhen a aenu is selected, the users active font table is saved 
in this buffer. 



file: print0ut2.Bg1, page 34, tiK Thu Har 24 ll:4i:34 1988 



Note: 

Nane: 

forwrlys 

Address! 

Size« 

Defaults 

Saved? 8 

Description' 

Note: 



sauedaobyZ 

C64: $88bb C128: $88bb Apple; NA 

Byte 

None 

Yes 

Saued ualue of Boby2 for context sauing done when dialogue boxes 
and desli accessories run. Because this was left out of the 
original 6E0S saue code, it uas put here so it remains 
conpatible with desk accessories, etc. that use the size of 
TOTJRAtlJAVED for how what gets saued. 



Nai&e: 

foraerlys 

Address*' 

Size: 

Default: 

Saued?: 

Description: 

Note: 



scrSOcolors 



C64: NA 
Byte 
None 
No 



C128: $88bd Apple: NA 



Screen colors for 80 coluan node on the C128. It is a copy of 
reg 26 in the UDC. ^ 



Naiae: 

Foroerly: 

Address: 

Size: 

Default: 

Saved?: 

Description: 

Note: 



scrBOpolar 



C128: $88bc Apple: NA 



C64: NA 
Byte 

None ?? 
No 

Copy of reg 24 in the UDC for the C128 



Naae: 

Fomerly: 

Address: 

Size: 

Default: 

Saued?: 

Description: 

Note: 



screencolors 

C64: $851e C128: $851e Apple: NA 
Byte 

$BF (1?1) 
No 

Default screen colors 



Naae: 



seconds 



file: printOutZ.ngl, page 35, tiie Thu Kdr 24 11:46:34 1?88 



For»erly: 



Address: 


Ci4: $851b C128: $851b Apple' $F205 


Size: 


Byte 


Default: 


$00 


Saued?: 


Ho 


Description: 


Seconds variable for the tine of day clock. 


Note: 




Nane: 


selectionFlash 


Forwerly: 




Address: 


C64: $84b3 C128: $84b3 Apple: $0224 


Size: 


Bute 


Default: 


SLECTIONJELAY « $0A (10) 


Saved?: 


Yes 


Description: 


Variable for the speed at uhich nenu iteas and icons are 
flashed. 


Note: 




Kane: 


shiftBuf 


Foraerly: 




Address: 


C64: NA C128: $lb45 Apple: $0070 


Size: 


7 bytes 


Default: 


None 


Saued?: 


No 


Description: 


Buffer for shifting/doubling sprites. Located in back Raa. 


Note: 




Nar&e: 


shiftOutBuf 


Formerly: 




Address: 


C64: NA C128: $lb4c Apple: $0078 


Size: 


7 Bytes 


Default: 


None 


Saued?: 


No 


Description: 


Buffer for shifting/doubling/oring sprites. Located in back 
Raa. 


Note: 




HaiBe: 


sizeFlags 


Foraerly: 




Address: 


C64: NA C128: $lb53 Apple: $DB1C 


Size: 


Byte 


Default: 


None 



file: printOutZ.igl, page 36, tiM Thu Har 24 11:46:34 1788 



Sdued?s 
Descriptions 

Note* 



No 

height of sprite | 9-pixel flag this is grabbed froi the 64th 
byte of the sprite definition. The high bit is set if the 
sprite is only 9 pixels wide. The rest of the byte is a 
count of scan lines. 



Nanes 

Foraerly* 

Address*' 

Size: 

Default! 

Saved?! 

Description! 

Note! 



softZeros 

C64! Nft 
192 Bytes 
None 
No 



C128! $lb6d Apple! $DOEO 



Buffer used for putting sprite bitmaps uo on screen without 
disturbing background. Resides in back RaM. 



NaiDe! 

fori&erly! 

Address! 

Size! 

Default! 

Saued?! 

Description! 

Note! • 



softOnes 

C64! NA 
192 Bytes 
None 
No 



C128! $lc2d Apple! $D0OO 



Buffer used for putting sprite bitnaps uo on 
disturbing background. Resides in back Ran. 



on screen without 



Naae! 

Foraerly! 
Address! 

Size! 
Default! 
Saued?! 
Description! 

Note! 



sprOpic, sprlpic, spr2pic, spr3pic, spr4pic, spr5pic, 
spr6pic, sprZpic 



C64! $8a00 - 8bc0 respectively 
C128! ^8a00 - 8bc0 respectively 
Apple! NA 

64 bytes each 

sprOpic is used for souse picture 
No 

This is uhere the graphics data for sprites - 7 are kept on 
the C64. 



Name! 

Foroerly! 

Address! 

Size: 

Default! 



ssprlback, sspr2back, sspr3back, sspr4back, ssprSback, 
sspr6back, sspr7back 



C64: NA 



C128: See belou 



Apple: $5600 



Commodore - 294 bytes each 
Apple - 336 bytes each 

None 



file: printOutZ.ig], page 37, tioe Thu Har 24 11:46:34 1988 



Saued?: 
Descriptions 



Ho 

For each of the soft sprites tl - 17, there is a buffer in the 
back Raci for sauinq the screen behind the sprites. The 
nouse (sprite 10) is handled seperately. Locations for the 
buffers are* 



Comodore: 

ssprlback* 
ssprZback> 
sspr3back> 
sspr4backs 
sspr5back: 
sspr6back: 
S5pr7back: 



Apple: 



ssprlbackx 
sspr2back: 
S5pr3back: 
sspr4back: 
ssprSback: 
S5pr6back: 
sspr7backs 



5133b 
1461 
1587 
16ad 
17d3 

hif? 

half 



S56d0 
15820 
S5970 
§5ac0 
^5cl0 
I5d60 
bebO 



Each buffer is 7 butes wide by 42 scanlines high (292 bytes) on 
the Contfflodore and 8 bytes vide by 42 scanlines high for Apple 
soft sprites. The extra byte is needed because of the App 
7 bit screen bytes. These buffers are large enough to hol_ 
largest possible sprite size (doubled in both x and y) and 
include an extra byte in width to save stuff on byte boundar 



es 

d the 



Haoe: 


string 


Forrerly: 




Address: 


C64: $24 C128: $24 Apple: $0053 


Size: 


Word 


Default: 


None 


Saved?: 


Yes 


Description: 


Used by GEOS as a pointer to string destinations for routines 
such as GetString. 


Note: 




Haoe: 


StringFaultVec 


Foraerly: 


StringFaultVector 


Address: 


C64: $84ab C128: $84db Apple: $0210 


Size: 


Uord 


Default: 


$00 


Saved?: 


Yes 


Description: 


Vector called when an attenpt is aade to write a character 
past rightflargin. 


Note: 




Haf&e: 


stringX 


Fornerly: 




Address: 


C64: $84be C128: $84be Apple: $022E 


Size: 


Uord 


Default: 


None 



file; printOutZ.ngl, page 36, tiie Thu liar 24 11:46:34 1788 



Sailed?! 


Yes 


Descriptions 


The X position for string input 


Note: 




Nane: 


stringY 


Fomerly: 




Address: 


C64: $84c0 C12B: $84c0 Apple: $0230 


Size: 


Byte 


Default: 


None 


Saued?: 


Yes 


Description: 


The Y position for string input 


Note: 




Natr«: 


sysDBData 


Fortter 1y: 




Address: 


C64: i851d C128: i851d Aoole: i0259. 


Size: 


Byte 


Default: 


None 


Saued?: 


NA 


Description: 


Variable that is used internally to indicate which icon caused 
a return to the application (froi a dialogue box). The actual 
data is returned to the user in rOL. 


Note: 




Nane: 


sysFIqCopy 


Forier ]y: 




Address: 


C<4: ic012 C128: $c012 ' AoDle: NA 


Size: 


Byte 


Default: 


None 


Saued?: 


No 


Description: 


This is a copy of the sysRAMFlg that is saued here when going 
into basic on Conaodore. See sysRAIIFlg for lore infornation. 


Note: 




Nane: 


sysRAHFlg 


F ori^r lus 




Address: 


C64: $88c4 C128: i88c4 Aoole: NA 


Size: 


Byte 


Default: 


None 


Saued?: 


No 


Description: 


If RAtI expansion in. Bank is reserued for the kernaTs use. 
This byte contains flags designating its usage: 

Bit 7: if 1, $0000-$78FF used by lloueData routine 



file: printOutZ.agI, page 39, tine Thu Har 24 11:46:34 1988 



Bit 6i \f 1, $8300-$B8FF holds disk driuers for drives A 
throuoh C 

Bit 5^ if 1. V'OH^DFF is loaded uith GEOS raa area 

i8400-$88FF by ToBasic routine when going to BASIC. 

Bit 4: if 1, i7E00-$82FF is loaded uith reboot code by a 

setup AUTO-EXEC file, which is loaded by the restart 
code in GEOS at $C000 if this flag is set, at $6000, 
instead of loading GEOS BOOT. Also, the area 
$B900-$FC3F is saued for the kernal for fast re-boot 
without sustea disk (depending on setup file). This 
area should be updated uhe^ input deuices are changed 
(inpleaented in 1/1.3 deskTop). 



Note: 


Coinfliodore only 


nasic* 


tntNiinRIk^ 


rorBicr ly • 




Address: 


riA» NO ri7Q2 NO Onnlo! drXflR 

104* iiH tiiO" iiH nppie* ^rouo 


Size: 


UnrA 

■oro 


Default: 


$llo 


p ..... • 
Saued?: 


no 


uescr ipc ion* 


lOvai nuiiDcr or diucks in currenb voiuibc. 


Note: 




Nai&e: 


bUroor lags 


r orBier ly • 




Address: 




Si7p: 


4 bytes 


npf Atlit: 


Nnrtp 

llllllC 


« 

oavcQ: ■ 


Nn 

nu 


UCdwi ipw lull* 


Thp turbo state flaos for driues 8 throuoh 11 on Coaaodore 


Note: 




nacie* 


iicoHPemrnc 


r orBier ly • 




HOflress- 


rXAs 6flA97 ri7fl: ^ftA97 finnlp: 

LOH* 90**7r Ul&O* 90H7r npplc* 9rOi/ 


3 1 Zc* 


oy wc 


uefault: 


AAA 

$U0 


Saued?: 


No 


Description: 


Holds the nunber of records in an open ULIR file 


Note: 




Haote: 


udcClrflode 


Forserly: 




Address: 


C64: NA C128: $88be Apple: NA 


Size: 


Byte 


Default: 


Hone ?? 


Saued?: 


No 



file: printout!. ng], page 40, tioie Thu flar 24 11:46:34 198B 



Description: Holds the current color sode for C128 color routines. 
) Note: ' ;.: 



nafDe- 


version . » 


tn^MA^ lit! 

roriier ly' 




ftddress: 


C<4: $cOOf C12B: $cOOf Apple: '$EoW ' 


Size: 


Byte 


Default: 


Hone 


Saved?: 


No 


Description: 


Holds byte indicating uhat version of EEOS is running. 


Note: 




na/Be« 


uindouTop 


L #1 ^ Aft A ^ 1 1 1 9 

r orioer ly • 




Address: 


U^'' $33 C128: $33 Apple' $021E 


Size: 


Byte 


Default: 


$00 


Saued?: 


Yes 


Description: 


Top line of uindou for text clipping 


Note: 




naioe* 


year 


rorBer ly • 




Address: 


Ci4: $B5U C128: $8516 Apple' $F200 


Size: 


Byte 


Default: 


86 


Saued?: 


No 


Description: 


Holds the year for the tine of day clock. 


Note: