The next series of posts will document a windowing system I built for the Atari 8 bit computer using Action!. In this first post I’ll show you the windowing system is designed, and show you the first few functions to get started.
To keep the windowing system somewhat simple, I chose not to include any Z ordering, and instead put window order management on the programmers shoulders. Programs are small enough on the Atari that this isn’t really a problem as far as I am concerned.
The Window system needs a few basic things. The first two:
- Window handles which hold the information about each window (top and left cursor position, width, height, etc)
- Memory to store the screen contents the window replaces when drawn.
I chose a simple stack based ordering system. This means windows are added to a stack as they are created. The last one added, should be the first one removed. There are a number of reason I chose this. First and foremost was simplicity. This approach brings with it less management of window screen buffer memory. It also helps keep the code size down.
I gave each window handle 8 attributes:
- Status (bS)
- X position / column (bX)
- Y position / row (bY)
- Width (bW)
- Height (bH)
- Inverse flag (bI)
- Window Buffer Memory Location (cM)
- Window Buffer Memory Size (cZ)
To make the windowing system easy to use in programs I broke it into library modules that fit in with the other library routines I’ve posted about before. These are, and should be included in this order in any program:
Next I’ll break down whats in each one.
To make storage, almost straight forward, I created a record:
; Window handle type definition
TYPE WnREC=[BYTE bS,bX,bY,bW,bH,bI
The BYTE parameters each take 1 byte of memory to store. The CARD parameters each take 2 bytes of memory to store. This brings the total record size to 10 bytes. There is a definition for the window handle record size. While setting up definitions, I also setup the maximum size for the window screen buffer memory size. Just under 3K. You can make this bigger or smaller as needed:
; Record and memory alloc sizes
Next comes the system-wide pointers used for accessing the window handles and window screen buffer memory:
; Pointers for window handle and mem
WnREC POINTER pWn
CARD POINTER cpWM
Then the memory is allocated for both the window handles and the window screen buffer memory. I set aside enough window handle memory for 11 handles – 10 for general usage, and 1 as a system handle (for dedicated functions that will come later). You can shrink the size of the window handle memory to fit your needs. It just needs to be a multiple of the WRECSZ defined previously:
; Window handle and memory storage
; 10 handles + 1 system handle
BYTE ARRAY baW(110),baWM(WBUFSZ)
I also define the vector to screen memory, which is locations 88 and 89. Created in this way, the computation of the actual address in memory is done for you by Action!:
; Screen memory vector
The window system also keeps track of where the cursor is, virtually. To do so I used a two byte record to hold the virtual X and Y positions. Then assign it as a variable for use system wide:
; Virtual cursor type definition
TYPE WnPOS=[BYTE vX,vY]
; Virtual cursor var
There are some other defines in the file which are use to make program source code easier to read. These are:
; Inverse Flags
; Window Status
; Error Status
The Inverse flags are WINVON and WINVOFF. They represent the values used to set a window to be drawn in inverse video or not.
The Window Status flags are WSFREE and WSUSED. They represent the values assigned to the window handles status byte. 0, the window handle is free (available). 1, the window handle is in use.
The Error Status flags are:
- WERNONE – Window ERror NONE – No window handles available
- WERNOPN – Window ERror Not OPeN – Window handle not open
- WERUSED – Window ERror USED – Window handle in use
The other definitions will be discussed when the time comes.
This contains all the window routines. For this post, I will cover the initialization routine and the open routine. Future posts will cover other routines.
First the init routine. The window system needs to be initialized before use. The initialization routine is described here.
- First, it turns the cursor off, sets the left margin to 0, moves the physical cursor to top left corner, then sends clear screen to CIO.
- Then it zeros out the window screen buffer memory, and sets the initial index to the memory which will be at byte 0 of the window memory address.
- Then for each of the 10 general window handles and 1 system window handle, it sets the window handle attributes to status of free, inverse off, base memory address of window screen buffer memory, and 0 for all other attributes.
- Last it sets the virtual cursor coordinates.
; Proc..: WInit()
; Desc..: Initializes windowing system.
; Setup cursor and screen
; Clear window memory
; Set index into window memory
; Work on 10 window+system handles
for bL=0 to 10
; Find windows handle location
; Clear handle record vars
pWn.cM=baWM ; point at base storage
; Set virtual cursor coords
Now for the window open routine. To open a window, WOpen is called 5 parameters:
- x position / column
- y position / row
- width (inclusive of border)
- height (inclusive of border)
- inverse flag
The routine will return either the window handle number assigned, or an error code. The window handle number is chosen based on the first free handle. What the routine does:
- Sets the default return code to no window handles available (WERNONE).
- It cycles through each general window handle starting at the first, looking for the first one that is not used. To do this, it finds the window handle in memory, and checks the status byte.
- If the window handle is free, the window handle status byte is set to used.
- It sets the window handle memory location pointer to the same value as the systems window screen buffer memory pointer. The system one gets updated as the window is drawn and underlying screen elements are saved to it. It also sets the size of the memory needed to store the underlying screen elements, which is the width times height of the window.
- It sets the other window handle attributes to match those passed in to the function.
- It then computes the location in screen memory where the top left of the window location should be.
- It draws the window. To do this, it creates each row of the window from top to bottom. This is done by creating an in-memory image of each row, then copying that memory block into screen memory at the correct location. It will also inverse the in-memory image of the row if the inverse flag was set.
- Then it sets the return value of the function to the window handle that was used.
- Last, the routine exits passing back the return value which is the window handle that was used.
; Func..: BYTE WOpen(BYTE x,y,w,h,i)
; Desc..: Opens new window
; Params: x = column
; y = row
; w = width
; h = height
; i = inverse
; Return: Window handle number
; >100 on error
BYTE FUNC WOpen(BYTE x,y,w,h,i)
CHAR ARRAY cL(40)
CARD POINTER cS
; Set default return code
; Cycle through handles (excl system)
for bL=0 to 9
; Find window handle record
; If handle record not in use
if pWn.bS=WSFREE then
; Set handle record in use
; Set storage address and size
; Set other handle record vars
; Find top left corner of window
; in screen memory
; Draw window
for bD=0 to h-1
; Build window line as string
; Top or bottom line "+-+"
if bD=0 or bD=h-1 then
; Top line corners
if bD=0 then
; Bottom line corners
; Middle line "| |"
; If inverse flag, flip line
if i=WINVON then
; Save underlying scrn to win mem
; Inc mem ptr index by width
; Move line to screen
; Inc scr by 40 to next line start
; Set return to handle number
; Exit loop
The following program demonstrates the usage. This program will be built upon as the posts progress. You’ll notice LIBSTR.ACT is included as well. It has the StrInv function which is used to inverse a window.
; Program: WINDOW.ACT
; Author.: Wade Ripkowski
; Date...: 2016.04
; Desc...: Test Windowing Library
; License: Creative Commons
; 4.0 International
; Include library
; Window handles
; Init Window System
; Open window 1
; Open window 2
; Open window 3
That’s it. The next post will cover window closing and background. Other posts will include window titles, printing to windows, putting characters to windows, and eventually some widgets.