a2d/mgtk.inc
2018-04-10 16:26:36 -07:00

790 lines
24 KiB
PHP

;;; ============================================================
;;; MouseGraphics ToolKit (w/ Graphics Primitives)
;;; ============================================================
.scope MGTK
MLI := $4000
;; MLI-style call (jsr MLI ; .byte call ; .addr params)
;; Call from AUX (RAMRDON/RAMWRTON)
;;; ============================================================
;;; Graphics Primitives
;;; ============================================================
;;; Point record:
;;;
;;; .word xcoord
;;; .word ycoord
;;; Rect record:
;;;
;;; .word x1
;;; .word y1
;;; .word x2
;;; .word y2
;;; MapInfo record:
;;;
;;; Point viewloc
;;; .addr mapbits screen_mapbits
;;; .byte mapwidth screen_mapwidth
;;; .byte reserved
;;; Rect maprect a.k.a. cliprect
;;; GrafPort record:
;;;
;;; MapInfo portmap
;;; .res 8 penpattern
;;; .byte colormask_and
;;; .byte colormask_or
;;; Point penloc
;;; .byte penwidth horizontal pen thickness
;;; .byte penheight vertical pen thickness
;;; .byte penmode
;;; .byte textback text background
;;; .addr textfont
;;; PolyList record:
;;; .byte count number of vertices in this polygon
;;; .byte last high bit set if there are more polygons
;;; Point vertex1
;;; Point vertex2
;;; ...
;;; Font record:
;;;
;;; .byte fonttype 0=regular, $80=double-width
;;; .byte lastchar char code of last character (usually $7F)
;;; .byte height pixels (1-16)
;;; .res N charwidth pixels, for each char
;;; .res N row0 bits
;;; .res N row0right bits (double-width only)
;;; ...
NoOp := $00 ; No-op
;;; (no parameters)
;;; --------------------------------------------------
;;; Initialization Commands
InitGraf := $01
;;; (no parameters)
SetSwitches := $02 ; Configure display switches
;;; .byte flags bit 0=hires, 1=page2, 2=mixed, 3=text
;;; --------------------------------------------------
;;; GrafPort Commands
InitPort := $03 ; Initialize GrafPort to standard values
;;; (input is address of GrafPort record)
SetPort := $04 ; Set current port as specified
;;; (input is address of GrafPort record)
GetPort := $05 ; Get pointer to current port
;;; .addr port (out)
SetPortBits := $06 ; Set just the mapinfo (viewloc, mapbits)
;;; (input is address of MapInfo record)
SetPenMode := $07 ; Set the current pen mode
;;; .byte mode pen*/notpen*
SetPattern := $08 ; Set the current pattern
;;; .res 8 pattern 8x8 pixel pattern for PaintRect calls
SetColorMasks := $09 ; Set the current color masks
;;; .byte and_mask
;;; .byte or_mask
SetPenSize := $0A ; Set the current pen size
;;; .byte penwidth horizontal pen thickness
;;; .byte penheight vertical pen thickness
SetFont := $0B ; Set the current font
;;; .addr textfont font definition
SetTextBG := $0C ; Set the current text background
;;; .byte backcolor 0=black, $7F=white
;;; --------------------------------------------------
;;; Drawing Commands
Move := $0D ; Set current pen location (relative)
;;; .word xdelta
;;; .word ydelta
MoveTo := $0E ; Set current pen location (absolute)
;;; Point pos
Line := $0F ; Draw line from current pen location (relative)
;;; .word xdelta
;;; .word ydelta
LineTo := $10 ; Draw line from current pen location (absolute)
;;; Point pos
PaintRect := $11 ; Fill rectangle with selected simple pattern/thickness
;;; Rect rect
FrameRect := $12 ; Draw rectangle with selected simple pattern/thickness
;;; Rect rect
InRect := $13 ; Is current position in bounds? A=$80 true, 0 false
;;; Rect rect
PaintBits := $14 ; Draw pattern
;;; (input is address of MapInfo record)
PaintPoly := $15
;;; (input is address of PolyList record)
FramePoly := $16 ; Draw multiple closed polygons
;;; (input is address of PolyList record)
InPoly := $17 ; Is current position in bounds? A=$80 true, 0 false
;;; (input is address of PolyList record)
;;; --------------------------------------------------
;;; Text Commands
TextWidth := $18 ; Measure the width of a string in pixels
;;; .addr data
;;; .byte length
;;; .word width (out) result in pixels
DrawText := $19 ; Drawn at penpos as left, baseline
;;; .addr data
;;; .byte length
;;; --------------------------------------------------
;;; Utility Commands
SetZP1 := $1A ; Configure lower half of ZP usage by API (speed vs. convenience)
SetZP2 := $1B ; Configure upper half ZP usage by API (speed vs. convenience)
;;; .byte preserve 0=stash/no auto restore; 1=restore now and onward
Version := $1C ; Get toolkit version
;;; .byte (out) major
;;; .byte (out) minor
;;; .byte (out) patch
;;; .byte (out) status
;;; .word (out) number
;;; ============================================================
;;; MouseGraphics ToolKit Calls
;;; ============================================================
;;; --------------------------------------------------
;;; Initialization Calls
StartDeskTop := $1D ; Inits state, registers interrupt handler, draws desktop
;;; .byte machine ROM FBB3 ($06 = IIe or later)
;;; .byte subid ROM FBC0 ($EA = IIe, $E0 = IIe enh/IIgs, $00 = IIc/IIc+)
;;; .byte op_sys 0=ProDOS, 1=Pascal
;;; .byte slot_num Mouse slot, 0 = search (will be filled in)
;;; .byte use_interrupts 0=passive, 1=interrupt
;;; .addr sysfontptr
;;; .addr savearea buffer for saving screen data (e.g. behind menus)
;;; .word savesize bytes
StopDeskTop := $1E ; Deallocates interrupt, hides cursor
;;; (no parameters)
SetUserHook := $1F
;;; .byte hook_id 0=before, 1=after event checking
;;; .addr routine_ptr 0=remove hook_id
AttachDriver := $20 ; Install pointer driver; A=0 on success, $95 if mouse disabled
;;; .addr hook Mouse hook routine to install
;;; .addr mouse_state (out) Address of mouse state (.word x, y; .byte status)
ScaleMouse := $21 ; Set mouse/screen scaling
;;; .byte x_exponent x-scale factor for mouse, 0...3
;;; .byte y_exponent y-scale factor for mouse, 0...3
KeyboardMouse := $22 ; Next operation will be performed by keyboard
;;; (no parameters)
GetIntHandler := $23 ; Get address of interrupt handler
;;; .addr handler (out) Address of interrupt handler (after cld)
;;; --------------------------------------------------
;;; Cursor Manager Calls
;;; Cursor record:
;;;
;;; .res 24 bitmap 2x12 byte bitmap (XOR'd after mask)
;;; .res 24 mask 2x12 byte mask (OR'd with screen)
;;; .byte hotx hotspot coords (pixels)
;;; .byte hoty
SetCursor := $24 ; Set cursor definition
;;; (input is address of Cursor record)
ShowCursor := $25 ; Return cursor to visibility
;;; (no parameters)
HideCursor := $26 ; Cursor hidden until ShowCursor call
;;; (no parameters)
ObscureCursor := $27 ; Cursor hidden until moved
;;; (no parameters)
GetCursorAddr := $28 ; Get cursor definition
;;; .addr definition (out) Address of cursor record
;;; --------------------------------------------------
;;; Event Manager Calls
;;; Event record:
;;;
;;; .byte kind event_kind_*
;;; if kind is event_kind_key_down:
;;; .byte key (ASCII code; high bit clear)
;;; .byte modifiers (0=none, 1=open-apple, 2=solid-apple, 3=both)
;;; if kind is event_kind_update:
;;; .byte window_id
;;; otherwise:
;;; .word xcoord
;;; .word ycoord
CheckEvents := $29 ; Process mouse/kbd if GetEvent will be delayed.
;;; (no parameters)
GetEvent := $2A
;;; (parameter is address of Event record)
FlushEvents := $2B
;;; (no parameters)
PeekEvent := $2C
;;; (parameter is address of Event record)
PostEvent := $2D ; Post event to queue
;;; (parameter is address of Event record)
SetKeyEvent := $2E ; If set, keypresses are ignored by Tool Kit
;;; .byte handle_keys high bit set = ignore keyboard, otherwise check
;;; --------------------------------------------------
;;; Menu Manager Calls
;;; Menu Bar record:
;;;
;;; .word count Number of menu bar items
;;; (array of...)
;;; .byte menu_id Menu identifier
;;; .byte disabled Flag
;;; .addr title Address of length-prefixed string
;;; .addr menu Address of Menu record
;;; .res 6 reserved Reserved
;;; ...
;;;
;;; Menu record:
;;;
;;; .byte count Number of items in menu
;;; .res 5 reserved Reserved
;;; (array of...)
;;; .byte options bit 0=OA, 1=SA, 2=mark, 5=check, 6=filler, 7=disabled
;;; .byte mark_char Custom mark character if mark option set
;;; .byte char1 ASCII code of shortcut #1 (e.g. uppercase B); or 0
;;; .byte char2 ASCII code of shortcut #2 (e.g. lowercase b, or same); or 0
;;; .addr name Address of length-prefixed string
;;; ...
InitMenu := $2F
;;; .byte solid_char char code to use for solid apple glyph
;;; .byte open_char char code to use for open apple glyph
;;; .byte check_char char code to use for checkmark glyph
;;; .byte control_char char code to use for control key glyph
SetMenu := $30 ; Configure (and draw) menu
;;; (input is address of Menu Bar record)
MenuSelect := $31 ; Enter modal loop for handling mouse-down on menu bar
;;; .byte menu_id (out) Top level menu identifier, or 0 if none
;;; .byte menu_item (out) Index (1-based) of item in menu, or 0 if none
MenuKey := $32 ; Find menu item corresponding to keypress
;;; .byte menu_id (out)
;;; .byte menu_item (out)
;;; .byte which_key
;;; .byte key_mods bit 0=OA, bit 1=SA
HiliteMenu := $33 ; Toggle highlight state of menu
;;; .byte menu_id
DisableMenu := $34
;;; .byte menu_id
;;; .byte disable 0=enable, 1=disable
DisableItem := $35
;;; .byte menu_id
;;; .byte menu_item
;;; .byte disable 0=enable, 1=disable
CheckItem := $36
;;; .byte menu_id
;;; .byte menu_item
;;; .byte check 0=unchecked, 1=checked
SetMark := $37
;;; .byte menu_id
;;; .byte menu_item
;;; .byte set_char 0=use checkmark, 1=use mark_char
;;; .byte mark_char char code to use for mark
;;; --------------------------------------------------
;;; Window Manager Calls
;;; WInfo record:
;;;
;;; .byte id
;;; .byte options option_*
;;; .addr title
;;; .byte hscroll scroll_option_*
;;; .byte vscroll scroll_option_*
;;; .byte hthumbmax
;;; .byte hthumbpos
;;; .byte vthumbmax
;;; .byte vthumbpos
;;; .byte status
;;; .byte reserved
;;; .word mincontwidth minimum content size (horizontal)
;;; .word mincontlength minimum content size (vertical)
;;; .word maxcontwidth maximum content size (horizontal)
;;; .word maxcontlength maximum content size (vertical)
;;; GrafPort windowport GrafPort record
;;; .addr nextwinfo address of next lower window in stack
OpenWindow := $38
;;; (input is address of WInfo record)
CloseWindow := $39
;;; .byte window_id
CloseAll := $3A
;;; (no parameters)
GetWinPtr := $3B ; Get pointer to window params by id; A=0 on success
;;; .byte window_id
;;; .addr window_ptr (out) winfo address
GetWinPort := $3C ; Get drawing state of window (possibly clipped)
;;; .byte window_id
;;; .addr port address of grafport to populate
SetWinPort := $3D ; Update port of window
;;; .byte window_id
;;; .addr port GrafPort to copy from
BeginUpdate := $3E ; Respond to update event for window
;;; .byte window_id
EndUpdate := $3F
;;; (no parameters)
FindWindow := $40
;;; .word mousex screen coordinates
;;; .word mousey
;;; .byte which_area (out) area_*
;;; .byte window_id (out) of window
FrontWindow := $41 ; Get id of top window
;;; .byte window_id (out) window, or 0 if none
SelectWindow := $42 ; Make window topmost
;;; .byte window_id
TrackGoAway := $43
;;; .byte clicked (out) 0 = cancelled, 1 = close
DragWindow := $44
;;; .byte window_id
;;; .word dragx mouse coords
;;; .word dragy
;;; .byte moved high bit set if moved, clear if not
GrowWindow := $45
;;; .byte window_id
;;; .word mousex
;;; .word mousey
;;; .byte itgrew (out) 0 = no change, 1 = moved
ScreenToWindow := $46 ; Map screen coords to content coords
;;; .byte window_id
;;; .word screenx
;;; .word screeny
;;; .word windowx (out)
;;; .word windowy (out)
WindowToScreen := $47 ; Map content coords to screen coords
;;; .byte window_id
;;; .word windowx
;;; .word windowy
;;; .word screenx (out)
;;; .word screeny (out)
;;; --------------------------------------------------
;;; Control Manager Calls
FindControl := $48
;;; .word mousex
;;; .word mousey
;;; .byte which_ctl ctl_*
;;; .byte which_part part_*
SetCtlMax := $49
;;; .byte which_ctl ctl_*_scroll_bar
;;; .byte ctlmax maximum value
TrackThumb := $4A
;;; .byte which_ctl ctl_*_scroll_bar
;;; .word mousex
;;; .word mousey
;;; .byte thumbpos (out) 0...255
;;; .byte thumbmoved (out) 0 = no change, 1 = moved
UpdateThumb := $4B
;;; .byte which_ctl ctl_*_scroll_bar
;;; .byte thumbpos new position 0...250
ActivateCtl := $4C ; Activate/deactivate scroll bar
;;; .byte which_ctl ctl_*_scroll_bar
;;; .byte activate 0=deactivate, 1=activate
;;; $4D ???
;;; (input length: 16 bytes)
;;; $4E ???
;;; (input length: 2 bytes)
;;; ============================================================
;;; Graphics Primitives Constants
;;; Used in GetWinPort / SetPortBits
screen_mapbits := $2000 ; Screen address
screen_mapwidth := $80 ; Stride in bytes
;;; Used in SetPenMode
pencopy := 0
penOR := 1
penXOR := 2
penBIC := 3
notpencopy := 4
notpenOR := 5
notpenXOR := 6
notpenBIC := 7
;;; Used in SetZP1
zp_overwrite := 0
zp_preserve := 1<<7
;;; Used in GrafPorts
colormask_and := $FF
colormask_or := $00
textbg_black := $00
textbg_white := $7F
;;; ============================================================
;;; MouseGraphics ToolKit Constants
;;; Used in GetEvent
event_kind_no_event := 0 ; No mouse or keypress
event_kind_button_down := 1 ; Mouse button was depressed
event_kind_button_up := 2 ; Mouse button was released
event_kind_key_down := 3 ; Key was pressed
event_kind_drag := 4 ; Mouse button still down
event_kind_apple_key := 5 ; Mouse button was depressed, modifier key down
event_kind_update := 6 ; Window update needed
event_modifier_open_apple := 1 << 0
event_modifier_solid_apple := 1 << 1
;;; Used in FindWindow
area_desktop := 0
area_menubar := 1
area_content := 2 ; Includes scroll bars
area_dragbar := 3
area_grow_box := 4
area_close_box := 5
;;; Used in FindControl, TrackThumb, UpdateThumb
ctl_not_a_control := 0
ctl_vertical_scroll_bar := 1
ctl_horizontal_scroll_bar := 2
ctl_dead_zone := 3
;;; Used in FindControl
part_up_arrow := 1
part_left_arrow := 1
part_down_arrow := 2
part_right_arrow := 2
part_page_up := 3
part_page_left := 3
part_page_down := 4
part_page_right := 4
part_thumb := 5
;;; Used in OpenWindow
option_dialog_box := 1 << 0
option_go_away_box := 1 << 1
option_grow_box := 1 << 2
scroll_option_none := 0
scroll_option_present := 1 << 7
scroll_option_thumb := 1 << 6
scroll_option_active := 1 << 0
scroll_option_normal := scroll_option_present | scroll_option_thumb | scroll_option_active
;;; Used in menu structs
menuopt_open_apple := 1 << 0
menuopt_solid_apple := 1 << 1
menuopt_item_has_mark := 1 << 2
menuopt_item_is_checked := 1 << 5
menuopt_item_is_filler := 1 << 6
menuopt_disable_flag := 1 << 7
disablemenu_enable := 0
disablemenu_disable := 1
disableitem_enable := 0
disableitem_disable := 1
checkitem_uncheck := 0
checkitem_check := 1
;;; Used in ActivateCtl
activatectl_deactivate := 0
activatectl_activate := 1
;;; Response from InRect/InPoly
inrect_inside := $80
inrect_outside := $00
inpoly_inside := $80
inpoly_outside := $00
;;; ============================================================
;;; Offsets
grafport_offset_viewloc := 0
grafport_offset_viewloc_xcoord := 0
grafport_offset_viewloc_ycoord := 2
grafport_offset_mapbits := 4
grafport_offset_mapwidth := 6
grafport_offset_maprect := 8
grafport_offset_pattern := 16
grafport_offset_colormasks := 24
grafport_offset_penloc := 26
grafport_offset_penwidth := 30
grafport_offset_penheight := 31
grafport_offset_penmode := 32
grafport_offset_textback := 33
grafport_offset_textfont := 34
grafport_size := 36
winfo_offset_window_id := 0
winfo_offset_options := 1
winfo_offset_title := 2
winfo_offset_hscroll := 4
winfo_offset_vscroll := 5
winfo_offset_hthumbmax := 6
winfo_offset_hthumbpos := 7
winfo_offset_vthumbmax := 8
winfo_offset_vthumbpos := 9
winfo_offset_status := 10
winfo_offset_mincontwidth := 12
winfo_offset_mincontheight := 14
winfo_offset_maxcontwidth := 16
winfo_offset_maxcontheight := 18
winfo_offset_port := 20
winfo_offset_nextwinfo := 56
winfo_size := 58
menu_size := 12
menu_item_size := 6
short_event_size := 4 ; events that don't have mouse coordinates
event_size := 5 ; any kind of event
cursor_height := 12
cursor_width := 2
cursor_offset_mask := cursor_width * cursor_height
cursor_offset_hotspot := 2 * cursor_width * cursor_height
cursor_size := cursor_offset_hotspot + 2
font_offset_fonttype := 0
font_offset_lastchar := 1
font_offset_height := 2
font_offset_charwidth := 3
;;; Errors
error_empty_object := $81
error_bad_object := $82
error_font_too_big := $83
error_invalid_op_sys := $90
error_no_mouse := $92
error_invalid_irq_setting := $93
error_invalid_hook := $94
error_desktop_already_initialized := $95
error_irq_in_use := $97
error_invalid_event := $98
error_event_queue_full := $99
error_menu_not_found := $9A
error_menu_item_not_found := $9B
error_insufficient_savebehind_area := $9C
error_window_already_exists := $9D
error_window_id_required := $9E
error_window_not_found := $9F
error_no_active_window := $A0
error_window_not_draggable := $A1
error_window_not_resizable := $A2
error_window_obscured := $A3
error_control_not_found := $A4
.endscope ; MGTK
;;; ============================================================
;;; Macros
;;; Call an MGTK entry point:
;;; MGTK_CALL n - params is $0000
;;; MGTK_CALL n, params_addr
;;; MGTK_CALL m, params_addr, label - params_addr is labeled for modifying
.macro MGTK_CALL op, addr, label
jsr MGTK::MLI
.byte op
.if .paramcount > 2
label := *
.endif
.if .paramcount > 1
.addr addr
.else
.addr 0
.endif
.endmacro
;;; ------------------------------------
;;; Rect definition. Option fifth param gives scope.
;;; DEFINE_RECT 0,0,20,30
;;; DEFINE_RECT 0,0,20,30,rect ; rect::x1, rect::y1, rect::x2, rect::y2
.macro DEFINE_RECT left, top, right, bottom, opt_scope
.if .paramcount > 4
.scope opt_scope
x1: .word left
y1: .word top
x2: .word right
y2: .word bottom
.endscope
.else
.word left
.word top
.word right
.word bottom
.endif
.endmacro
;;; Point definition. Option third param gives scope.
;;; DEFINE_POINT 10,20
;;; DEFINE_POINT 10,20,pt ; pt::xcoord, pt::ycoord
.macro DEFINE_POINT left, top, opt_scope
.if .paramcount > 2
.scope opt_scope
xcoord: .word left
ycoord: .word top
.endscope
.else
.word left
.word top
.endif
.endmacro
;;; String definition w/ inline data, for use with DrawText
;;; DEFINE_STRING "abc"
;;; DEFINE_STRING {"Ring a bell",$07,"!!!"} ; control characters
;;; Optional second param gives label to internal Pascal string
.macro DEFINE_STRING str, opt_label
.local data
.local end
.addr data ; textptr
.if .paramcount > 1
opt_label:
.endif
.byte end - data ; textlen
data: .byte str
end:
.endmacro
;;; Menus (common cases; other options are possible)
.macro DEFINE_MENU_BAR count
.byte count ; num menus
.byte 0 ; reserved
.endmacro
.macro DEFINE_MENU_BAR_ITEM id, label, menu
.byte id ; menu id
.byte 0 ; disable flag
.addr label ; title pointer
.addr menu ; pointer to menu
.res 6, 0 ; 6 reserved bytes
.endmacro
.macro DEFINE_MENU count
.byte count ; num items
.res 5, 0 ; 5 reserved bytes
.endmacro
.macro DEFINE_MENU_ITEM saddr, shortcut1, shortcut2
.if .paramcount > 1
.byte MGTK::menuopt_open_apple ; option byte
.byte 0 ; mark_char
.byte shortcut1 ; char1
.byte shortcut2 ; char2
.addr saddr ; item_str_pointer
.else
.byte 0 ; option byte
.byte 0 ; mark_char
.byte 0 ; char1
.byte 0 ; char2
.addr saddr ; item_str_pointer
.endif
.endmacro
.macro DEFINE_MENU_SEPARATOR
.byte MGTK::menuopt_item_is_filler ; option byte
.byte 0 ; mark_char
.byte 19 ; char1 - Ctrl+S for separator ???
.byte 0 ; char2
.addr 0 ; item_str_pointer
.endmacro
;;; ------------------------------------
;;; Define pattern for PaintBits - low 7 bits are reversed
;;; e.g. .byte px(%1000000)
;;; px() has high bit clear, PX() has high bit set
.define px(bits) (((bits&$40)>>6)|((bits&$20)>>4)|((bits&$10)>>2)|(bits&$8)|((bits&$4)<<2)|((bits&$2)<<4)|((bits&$1)<<6))
.define PX(bits) (((bits&$40)>>6)|((bits&$20)>>4)|((bits&$10)>>2)|(bits&$8)|((bits&$4)<<2)|((bits&$2)<<4)|((bits&$1)<<6)|$80)