kegs/src/INTERNALS.xdriver

149 lines
7.4 KiB
Plaintext

xdriver.c contains the routines for interfacing to X windows. The rest
of KEGS interacts with X windows only through xdriver.c routines.
Externally called routines are:
show_xcolor_array(): Debug routine, it does not need to do anything.
dev_video_init(): Called at startup, it should open up the
window and do other initialization.
update_physical_colormap(): Updates the X windows palette with the colors
from xcolor_a2vid_array[], which is maintained by
other xdriver routines.
update_status_line(): Call to update the internal array of chars
representing the status lines at the bottom of
the window. Does not draw the chars to the screen.
xdriver_end(): Shutdown routine
check_input_events(): Called up to 60 times a second (see video_update() in
video.c) to handle any X window events and get
keypresses.
On a mouse press, call update_mouse() with the
new x, y coordinates, and the status of the mouse
button.
If g_warp_pointer is set, constrain mouse within
the window.
On keypress, calls handle_keysym().
handle_keysym(): Takes X keysym, and converts to the appropriate
a2code using the a2_key_to_xsym[] lookup table.
The a2codes are the Apple // ADB keycodes.
Special work is done to handle shift and control
properly since Apple only has one keycode for both
shift and control keys. Then call
adb_physical_key_update() with the a2 keycode and
is_up = 1 if keyup, 0 = if key down.
In addition, this routine handles all the Function
keys doing special actions, which should be easy to
port.
x_refresh_ximage(): Redraws the window using the a2_line_* arrays.
Described in more detail below.
update_color_array(): Interface to the color map. Sets color[col_num]
of the internal colormap array to a2_color.
a2_color is the 12 bit apple color of the form:
(red << 8) + (green << 4) + (blue).
There are 16 palettes of 16 colors each, managed as
one 256-color colormap. See discussion of
g_a2vid_palette below.
x_auto_repeat_on(): The X routines turn off key repeat when the cursor
enters the graphics window automatically, and turn
it back on when the cursor leaves. But if the
debugger gets control due to a breakpoint, keyrepeat
would be left off. So the debugger calls this
routine to make sure key repeat is back on.
redraw_status_lines(): Draw the status lines from the g_status_buf[][] array
to the graphics window.
Externally referenced data:
g_use_shmem: Set by main() to enable/disable MIT-SHM for X.
Also used by sound routines to auto-turn-off sound
if not using MIT-SHM.
Bytes representing screen data:
byte *data_text[2]: Array of bytes for the lores and text pages 1 and 2.
Just 400*640 bytes.
byte *data_hires[2]: Array of bytes for the hires pages 1 and 2.
byte *data_superhires: Array of bytes for superhires screen.
byte *data_border_sides: Array of bytes representing the border sides.
Basically just A2_WINDOW_HEIGHT*EFF_BORDER_WIDTH bytes.
byte *data_border_special: Top and bottom border bytes.
(X_A2_WINDOW_HEIGHT - A2_WINDOW_HEIGHT + 2*8) *
(X_A2_WINDOW_WIDTH) bytes.
Handles used for X windows drawing:
XImage *ximage_hires[2]: Opaque handle to XImage object for hires page 1 and
page 2.
XImage *ximage_text[2]: Text pages 1 and 2.
XImage *ximage_superhires: Superhires graphics XImage
XImage *ximage_border_special: Top and bottom border XImage.
XImage *ximage_border_sides: Left and right sides (only one copy, it is
drawn at two different locations to be both sides).
Basic operation of xdriver:
--------------------------
X windows can push arrays of bytes to the screen through structures
called XImages. An XImage is a structure describing an offscreen bitmap.
For efficiency of page flipping, KEGS maintains separate bitmaps for the
two lores/text screens, the two hires screens, and the superhires screen.
It also maintains bitmaps for the border. For MIT-SHM to work, X
requires a unique XImage for each bitmap, and the bitmap must be allocated
within xdriver.c since it must be obtained through an shmat() call.
The X code also has non-MIT-SHM code which allocates the data_* buffers
just through malloc().
All bitmaps are 8-bits of Pseudo-color. The color arrays are managed
through the update_color_array() and update_physical_colormap() routines.
KEGS manages all 256 colors in the colormap as 16 palettes of 16 colors.
One of the palettes is reserved for the 16 lores colors, and is
indicated by the variable g_a2vid_palette. It defaults to 0xe.
Update_color_array() is called to update superhires colormap entries.
Update_color_array must not update colors corresponding to g_a2vid_palette.
Update_physical_colormap() pushes the color array managed by
update_color_array() to the screen, but first forces the lores colors into
the g_a2vid_palette palette. g_installed_full_superhires_colormap is
always false in KEGS for now. video.c calls update_color_array and changes
g_a2vid_palette. No xdriver routines gets notified when g_a2vid_palette
changes, so update_physical_colormap must handle the case where
g_a2vid_palette might have changed since it was last called.
x_redraw_ximage():
Routines in video.c are free to draw into the corresponding data_*
arrays to change any byte at any time. video.c manages remembering
which lines need to be redrawn and which parts of the screen are in
which video mode via the a2_line_* arrays.
KEGS divides the video screen up into 25 groups, corresponding to each
text line. Each of these groups consists of 16 sublines. 25*8 = 400 lines.
(video.c has already doubled the vertical resolution in all video modes).
KEGS can allow any group to be from any of the five screens it manages:
The two text/lores pages, the two hires pages, and the superhires screen.
For each group, KEGS keeps track of what part of it needs to be redrawn.
g_a2_screen_buffer_changed has a bit set for each group which has changed
since the last call to x_redraw_ximage(). The rightmost bit (bit 0)
corresponds to group 0. If g_a2_screen_buffer_changed == 0, no groups
need to be redrawn. x_redraw_ximage clears out g_a2_screen_buffer_changed
after drawing the screen.
For each group, a2_line_left_edge[] and a2_line_right_edge give the pixel
offsets of what should be redrawn. a2_line_xim[] gives the ximage handle
of what needs to be redrawn. KEGS always redraws 8 verticals of a group.
g_full_refresh_needed also has one bit set in it for each group, which
indicates overriding the a2_line_*_edge functions and redraw from 0 to
640 pixels of each group that needs to be redrawn. x_redraw_ximage()
interprets this information now using a simple algorithm: Skip over
groups which have not changed (using g_a2_screen_buffer_changed).
Save the ximage of this group, the left pixel and the right pixel.
Continue with the next group if it has changed. Widen the pixel region
and keep sucking up new groups to the same ximage. At group 25, or
when the ximage changes, call x_refresh_lines to redraw this large
rectangle from this ximage. x_refresh_lines() knows the ximage
corresponding to the border for the last group has to be handled
specially since the border group is not 640*400 pixels like the others.
Other porting info:
a2_key_to_xsym[][3] contains the mapping function from X keysyms to
a2 keycodes. The first element is the a2 keycode, the second element
is the unshifted X keysym, and the third element is the shifted keysym.
A port must make the conversion to a2 keycodes, and provide up and
down events.