mirror of
https://github.com/mi57730/a2d.git
synced 2024-11-25 10:30:50 +00:00
690 lines
17 KiB
ArmAsm
690 lines
17 KiB
ArmAsm
.setcpu "6502"
|
|
|
|
.include "apple2.inc"
|
|
.include "../inc/apple2.inc"
|
|
.include "../mgtk.inc"
|
|
.include "../desktop.inc"
|
|
.include "../macros.inc"
|
|
.include "../inc/fp_macros.inc"
|
|
|
|
;;; ============================================================
|
|
|
|
.org $800
|
|
|
|
entry:
|
|
|
|
;;; Copy the DA to AUX for easy bank switching
|
|
.scope
|
|
lda ROMIN2
|
|
copy16 #$0800, STARTLO
|
|
copy16 #da_end, ENDLO
|
|
copy16 #$0800, DESTINATIONLO
|
|
sec ; main>aux
|
|
jsr AUXMOVE
|
|
lda LCBANK1
|
|
lda LCBANK1
|
|
.endscope
|
|
|
|
.scope
|
|
;; run the DA
|
|
sta RAMRDON
|
|
sta RAMWRTON
|
|
jsr init
|
|
|
|
;; tear down/exit
|
|
sta ALTZPON
|
|
lda LCBANK1
|
|
lda LCBANK1
|
|
|
|
;; back to main for exit
|
|
sta RAMRDOFF
|
|
sta RAMWRTOFF
|
|
rts
|
|
.endscope
|
|
|
|
;;; ============================================================
|
|
|
|
da_window_id = 60
|
|
da_width = screen_width / 3
|
|
da_height = screen_height / 3
|
|
da_left = (screen_width - da_width)/2
|
|
da_top = 50
|
|
|
|
str_title:
|
|
PASCAL_STRING "Eyes"
|
|
|
|
;;; TODO: Allow resizing
|
|
|
|
.proc winfo
|
|
window_id: .byte da_window_id
|
|
options: .byte MGTK::Option::go_away_box
|
|
title: .addr str_title
|
|
hscroll: .byte MGTK::Scroll::option_none
|
|
vscroll: .byte MGTK::Scroll::option_none
|
|
hthumbmax: .byte 32
|
|
hthumbpos: .byte 0
|
|
vthumbmax: .byte 32
|
|
vthumbpos: .byte 0
|
|
status: .byte 0
|
|
reserved: .byte 0
|
|
mincontwidth: .word screen_width / 5
|
|
mincontlength: .word screen_height / 5
|
|
maxcontwidth: .word screen_width
|
|
maxcontlength: .word screen_height
|
|
port:
|
|
viewloc: DEFINE_POINT da_left, da_top
|
|
mapbits: .addr MGTK::screen_mapbits
|
|
mapwidth: .word MGTK::screen_mapwidth
|
|
maprect: DEFINE_RECT 0, 0, da_width, da_height, maprect
|
|
pattern: .res 8, $FF
|
|
colormasks: .byte MGTK::colormask_and, MGTK::colormask_or
|
|
penloc: DEFINE_POINT 0, 0
|
|
penwidth: .byte 1
|
|
penheight: .byte 1
|
|
penmode: .byte 0
|
|
textback: .byte $7F
|
|
textfont: .addr DEFAULT_FONT
|
|
nextwinfo: .addr 0
|
|
.endproc
|
|
|
|
;;; ============================================================
|
|
|
|
|
|
.proc event_params
|
|
kind: .byte 0
|
|
;;; EventKind::key_down
|
|
key := *
|
|
modifiers := * + 1
|
|
;;; EventKind::update
|
|
window_id := *
|
|
;;; otherwise
|
|
xcoord := *
|
|
ycoord := * + 2
|
|
.res 4
|
|
.endproc
|
|
|
|
.proc findwindow_params
|
|
mousex: .word 0
|
|
mousey: .word 0
|
|
which_area: .byte 0
|
|
window_id: .byte 0
|
|
.endproc
|
|
|
|
.proc trackgoaway_params
|
|
clicked: .byte 0
|
|
.endproc
|
|
|
|
.proc dragwindow_params
|
|
window_id: .byte 0
|
|
dragx: .word 0
|
|
dragy: .word 0
|
|
moved: .byte 0
|
|
.endproc
|
|
|
|
.proc winport_params
|
|
window_id: .byte da_window_id
|
|
port: .addr grafport
|
|
.endproc
|
|
|
|
|
|
.proc preserve_zp_params
|
|
flag: .byte MGTK::zp_preserve
|
|
.endproc
|
|
|
|
.proc overwrite_zp_params
|
|
flag: .byte MGTK::zp_overwrite
|
|
.endproc
|
|
|
|
.proc screentowindow_params
|
|
window_id: .byte da_window_id
|
|
DEFINE_POINT 0, 0, screen
|
|
DEFINE_POINT 0, 0, window
|
|
.endproc
|
|
mx := screentowindow_params::window::xcoord
|
|
my := screentowindow_params::window::ycoord
|
|
|
|
.proc grafport
|
|
viewloc: DEFINE_POINT 0, 0
|
|
mapbits: .word 0
|
|
mapwidth: .word 0
|
|
cliprect: DEFINE_RECT 0, 0, 0, 0
|
|
pattern: .res 8, 0
|
|
colormasks: .byte 0, 0
|
|
penloc: DEFINE_POINT 0, 0
|
|
penwidth: .byte 0
|
|
penheight: .byte 0
|
|
penmode: .byte 0
|
|
textback: .byte 0
|
|
textfont: .addr 0
|
|
.endproc
|
|
|
|
grow_box_width = 17
|
|
grow_box_height = 7
|
|
|
|
.proc grow_box_params
|
|
viewloc: DEFINE_POINT 0, 0, viewloc
|
|
mapbits: .addr grow_box_bitmap
|
|
mapwidth: .byte 3
|
|
reserved: .byte 0
|
|
cliprect: DEFINE_RECT 2, 2, 19, 9
|
|
.endproc
|
|
|
|
grow_box_bitmap:
|
|
.byte px(%1111111),px(%1111111),px(%1111111)
|
|
.byte px(%1000000),px(%0000000),px(%0000001)
|
|
.byte px(%1001111),px(%1111110),px(%0000001)
|
|
.byte px(%1001100),px(%0000111),px(%1111001)
|
|
.byte px(%1001100),px(%0000110),px(%0011001)
|
|
.byte px(%1001100),px(%0000110),px(%0011001)
|
|
.byte px(%1001111),px(%1111110),px(%0011001)
|
|
.byte px(%1000011),px(%0000000),px(%0011001)
|
|
.byte px(%1000011),px(%1111111),px(%1111001)
|
|
.byte px(%1000000),px(%0000000),px(%0000001)
|
|
.byte px(%1111111),px(%1111111),px(%1111111)
|
|
|
|
;;; ============================================================
|
|
|
|
.proc init
|
|
sta ALTZPON
|
|
lda LCBANK1
|
|
lda LCBANK1
|
|
|
|
;; Don't let MGTK smash zero page
|
|
MGTK_CALL MGTK::SetZP1, preserve_zp_params
|
|
lda #0
|
|
sta SHIFT_SIGN_EXT ; Must zero before using FP ops
|
|
|
|
MGTK_CALL MGTK::OpenWindow, winfo
|
|
jsr draw_window
|
|
MGTK_CALL MGTK::FlushEvents
|
|
;; fall through
|
|
.endproc
|
|
|
|
.proc input_loop
|
|
MGTK_CALL MGTK::GetEvent, event_params
|
|
bne exit
|
|
lda event_params::kind
|
|
cmp #MGTK::EventKind::button_down
|
|
beq handle_down
|
|
cmp #MGTK::EventKind::key_down
|
|
beq handle_key
|
|
cmp #MGTK::EventKind::no_event
|
|
beq handle_no_event
|
|
jmp input_loop
|
|
.endproc
|
|
|
|
.proc exit
|
|
MGTK_CALL MGTK::CloseWindow, winfo
|
|
DESKTOP_CALL DT_REDRAW_ICONS
|
|
MGTK_CALL MGTK::SetZP1, overwrite_zp_params
|
|
rts
|
|
.endproc
|
|
|
|
;;; ============================================================
|
|
|
|
.proc handle_key
|
|
lda event_params::key
|
|
cmp #CHAR_ESCAPE
|
|
beq exit
|
|
bne input_loop
|
|
.endproc
|
|
|
|
;;; ============================================================
|
|
|
|
.proc handle_down
|
|
copy16 event_params::xcoord, findwindow_params::mousex
|
|
copy16 event_params::ycoord, findwindow_params::mousey
|
|
MGTK_CALL MGTK::FindWindow, findwindow_params
|
|
bne exit
|
|
lda findwindow_params::window_id
|
|
cmp winfo::window_id
|
|
bne input_loop
|
|
lda findwindow_params::which_area
|
|
cmp #MGTK::Area::close_box
|
|
beq handle_close
|
|
cmp #MGTK::Area::dragbar
|
|
beq handle_drag
|
|
cmp #MGTK::Area::content
|
|
bne :+
|
|
jmp handle_grow
|
|
: jmp input_loop
|
|
.endproc
|
|
|
|
;;; ============================================================
|
|
|
|
.proc handle_close
|
|
MGTK_CALL MGTK::TrackGoAway, trackgoaway_params
|
|
lda trackgoaway_params::clicked
|
|
beq input_loop
|
|
bne exit
|
|
.endproc
|
|
|
|
;;; ============================================================
|
|
|
|
.proc handle_no_event
|
|
;; First time? Need to store last coords
|
|
lda has_last_coords
|
|
bne test
|
|
inc has_last_coords
|
|
bne moved
|
|
|
|
;; Moved?
|
|
test:
|
|
lda event_params::xcoord
|
|
cmp screentowindow_params::screen::xcoord
|
|
bne moved
|
|
lda event_params::xcoord+1
|
|
cmp screentowindow_params::screen::xcoord+1
|
|
bne moved
|
|
lda event_params::ycoord
|
|
cmp screentowindow_params::screen::ycoord
|
|
bne moved
|
|
lda event_params::ycoord+1
|
|
cmp screentowindow_params::screen::ycoord+1
|
|
beq done
|
|
|
|
moved: copy16 event_params::xcoord, screentowindow_params::screen::xcoord
|
|
copy16 event_params::ycoord, screentowindow_params::screen::ycoord
|
|
MGTK_CALL MGTK::ScreenToWindow, screentowindow_params
|
|
jsr draw_window
|
|
|
|
done: jmp input_loop
|
|
|
|
.endproc
|
|
|
|
;;; ============================================================
|
|
|
|
.proc handle_drag
|
|
copy winfo::window_id, dragwindow_params::window_id
|
|
copy16 event_params::xcoord, dragwindow_params::dragx
|
|
copy16 event_params::ycoord, dragwindow_params::dragy
|
|
MGTK_CALL MGTK::DragWindow, dragwindow_params
|
|
common: lda dragwindow_params::moved
|
|
bpl :+
|
|
|
|
;; Draw DeskTop's windows
|
|
sta RAMRDOFF
|
|
sta RAMWRTOFF
|
|
jsr JUMP_TABLE_REDRAW_ALL
|
|
sta RAMRDON
|
|
sta RAMWRTON
|
|
|
|
;; Draw DA's window
|
|
lda #0
|
|
sta has_last_coords
|
|
sta has_drawn_outline
|
|
jsr draw_window
|
|
|
|
;; Draw DeskTop icons
|
|
DESKTOP_CALL DT_REDRAW_ICONS
|
|
|
|
: jmp input_loop
|
|
|
|
.endproc
|
|
|
|
;;; ============================================================
|
|
|
|
.proc handle_grow
|
|
;; Is the hit within the grow box area?
|
|
copy16 event_params::xcoord, screentowindow_params::screen::xcoord
|
|
copy16 event_params::ycoord, screentowindow_params::screen::ycoord
|
|
MGTK_CALL MGTK::ScreenToWindow, screentowindow_params
|
|
sub16 winfo::maprect::x2, mx, tmpw
|
|
cmp16 #grow_box_width, tmpw
|
|
bcc nope
|
|
sub16 winfo::maprect::y2, my, tmpw
|
|
cmp16 #grow_box_height, tmpw
|
|
bcc nope
|
|
|
|
;; Initiate the grow... re-using the drag logic
|
|
copy winfo::window_id, dragwindow_params::window_id
|
|
copy16 event_params::xcoord, dragwindow_params::dragx
|
|
copy16 event_params::ycoord, dragwindow_params::dragy
|
|
MGTK_CALL MGTK::GrowWindow, dragwindow_params
|
|
jmp handle_drag::common
|
|
|
|
nope: jmp input_loop
|
|
|
|
tmpw: .word 0
|
|
.endproc
|
|
|
|
;;; ============================================================
|
|
|
|
penxor: .byte MGTK::penXOR
|
|
notpencopy: .byte MGTK::notpencopy
|
|
|
|
penw = 8
|
|
penh = 4
|
|
pupilw = penw * 2
|
|
pupilh = penh * 2
|
|
|
|
.proc outline_pensize
|
|
penwidth: .byte penw
|
|
penheight: .byte penh
|
|
.endproc
|
|
|
|
.proc pupil_pensize
|
|
penwidth: .byte pupilw
|
|
penheight: .byte pupilh
|
|
.endproc
|
|
|
|
;;; Flag set once we have coords from a move event
|
|
has_last_coords:
|
|
.byte 0
|
|
|
|
;;; Flag set once outline is drawn (cleared on window move)
|
|
has_drawn_outline:
|
|
.byte 0
|
|
|
|
;;; Saved coords
|
|
pos_l: DEFINE_POINT 0, 0, pos_l
|
|
pos_r: DEFINE_POINT 0, 0, pos_r
|
|
|
|
;;; ============================================================
|
|
|
|
.proc draw_window
|
|
;; Defer if content area is not visible
|
|
MGTK_CALL MGTK::GetWinPort, winport_params
|
|
cmp #MGTK::Error::window_obscured
|
|
bne :+
|
|
rts
|
|
:
|
|
;; Defer until we have mouse coords
|
|
lda has_last_coords
|
|
bne :+
|
|
rts
|
|
:
|
|
|
|
MGTK_CALL MGTK::SetPort, grafport
|
|
MGTK_CALL MGTK::HideCursor
|
|
|
|
copy16 winfo::maprect::x2, rx ; width / 4
|
|
inc16 rx
|
|
inc16 rx
|
|
lsr16 rx
|
|
lsr16 rx
|
|
copy16 winfo::maprect::y2, ry ; height / 2
|
|
inc16 ry
|
|
inc16 ry
|
|
lsr16 ry
|
|
|
|
lda has_drawn_outline
|
|
beq :+
|
|
jmp erase_pupils
|
|
: inc has_drawn_outline
|
|
|
|
;; Draw resize box
|
|
MGTK_CALL MGTK::SetPenMode, notpencopy
|
|
sub16 winfo::maprect::x2, #grow_box_width, grow_box_params::viewloc::xcoord
|
|
sub16 winfo::maprect::y2, #grow_box_height, grow_box_params::viewloc::ycoord
|
|
MGTK_CALL MGTK::PaintBits, grow_box_params
|
|
|
|
;; Draw outline
|
|
MGTK_CALL MGTK::SetPenMode, notpencopy
|
|
MGTK_CALL MGTK::SetPenSize, outline_pensize
|
|
|
|
copy16 rx, cx
|
|
copy16 ry, cy
|
|
jsr draw_outline
|
|
|
|
add16 rx, cx, cx
|
|
add16 rx, cx, cx
|
|
jsr draw_outline
|
|
|
|
;; Skip erasing pupils if we're redrawing
|
|
jmp draw_pupils
|
|
|
|
erase_pupils:
|
|
MGTK_CALL MGTK::SetPenMode, penxor
|
|
MGTK_CALL MGTK::SetPenSize, pupil_pensize
|
|
|
|
MGTK_CALL MGTK::MoveTo, pos_l
|
|
MGTK_CALL MGTK::LineTo, pos_l
|
|
MGTK_CALL MGTK::MoveTo, pos_r
|
|
MGTK_CALL MGTK::LineTo, pos_r
|
|
|
|
draw_pupils:
|
|
MGTK_CALL MGTK::SetPenMode, penxor
|
|
MGTK_CALL MGTK::SetPenSize, pupil_pensize
|
|
|
|
copy16 rx, cx
|
|
copy16 ry, cy
|
|
jsr compute_pupil_pos
|
|
sub16 ppx, #pupilw/2, pos_l::xcoord
|
|
sub16 ppy, #pupilh/2, pos_l::ycoord
|
|
MGTK_CALL MGTK::MoveTo, pos_l
|
|
MGTK_CALL MGTK::LineTo, pos_l
|
|
|
|
add16 rx, cx, cx
|
|
add16 rx, cx, cx
|
|
jsr compute_pupil_pos
|
|
sub16 ppx, #pupilw/2, pos_r::xcoord
|
|
sub16 ppy, #pupilh/2, pos_r::ycoord
|
|
MGTK_CALL MGTK::MoveTo, pos_r
|
|
MGTK_CALL MGTK::LineTo, pos_r
|
|
|
|
MGTK_CALL MGTK::ShowCursor
|
|
done: rts
|
|
|
|
tmpw: .word 0
|
|
.endproc
|
|
|
|
;;; ============================================================
|
|
;;; Common input params
|
|
|
|
rx: .word 0
|
|
ry: .word 0
|
|
|
|
cx: .word 0
|
|
cy: .word 0
|
|
|
|
;;; ============================================================
|
|
;;; Compute pupil location
|
|
;;;
|
|
;;; Inputs: mx, my, cx, cy, rx, ry
|
|
;;; Outputs: ppx, ppy
|
|
|
|
ppx: .word 0
|
|
ppy: .word 0
|
|
|
|
.proc compute_pupil_pos
|
|
lda ROMIN2
|
|
|
|
fac_load_int cx
|
|
fac_store cxf
|
|
|
|
fac_load_int cy
|
|
fac_store cyf
|
|
|
|
;; pupil shouldn't overlap border
|
|
sub16 rx, #penw, tmpw
|
|
sub16 tmpw, #pupilw, tmpw
|
|
fac_load_int tmpw
|
|
fac_store prx
|
|
|
|
sub16 ry, #penh, tmpw
|
|
sub16 tmpw, #pupilh, tmpw
|
|
fac_load_int tmpw
|
|
fac_store pry
|
|
|
|
;; x scale, so math is circular
|
|
;; xs = pry / prx
|
|
|
|
fac_load prx
|
|
fac_div pry
|
|
fac_store scale
|
|
|
|
;; mouse delta, in transformed space
|
|
;; dx = (mx - cx) * xs
|
|
;; dy = mx - cy
|
|
|
|
fac_load_int mx ; dx = (mx - cx) * xs
|
|
fac_store tmpf
|
|
fac_load cxf
|
|
fac_sub tmpf
|
|
fac_mul scale
|
|
fac_store dx
|
|
|
|
fac_load_int my ; dy = mx - cy
|
|
fac_store tmpf
|
|
fac_load cyf
|
|
fac_sub tmpf
|
|
fac_store dy
|
|
|
|
;; d = SQR(dx * dx + dy * dy)
|
|
|
|
fac_load dx
|
|
fac_mul dx
|
|
fac_store tmpf
|
|
fac_load dy
|
|
fac_mul dy
|
|
fac_add tmpf
|
|
|
|
jsr SQR ; ??? Crashes here after window drag
|
|
|
|
;; if d > pry:
|
|
;; f = pry / d
|
|
;; dx = f * dx
|
|
;; dy = f * dy
|
|
|
|
fac_comp pry
|
|
bmi skip
|
|
|
|
fac_div pry ; f = pry / d
|
|
fac_store tmpf
|
|
|
|
fac_mul dx ; dx = f * dx
|
|
fac_store dx
|
|
|
|
fac_load tmpf ; dy = f * dy
|
|
fac_mul dy
|
|
fac_store dy
|
|
skip:
|
|
|
|
;; plot coords
|
|
;; ppx = (dx / xs) + cx
|
|
;; ppy = dy + cy
|
|
|
|
fac_load scale ; ppx = (dx / xs) + cx
|
|
fac_div dx
|
|
fac_add cxf
|
|
fac_store_int ppx
|
|
|
|
fac_load dy ; ppy = dy + cy
|
|
fac_add cyf
|
|
fac_store_int ppy
|
|
|
|
lda LCBANK1
|
|
lda LCBANK1
|
|
|
|
rts
|
|
|
|
tmpw: .word 0
|
|
tmpf: DEFINE_FLOAT
|
|
|
|
scale: DEFINE_FLOAT
|
|
dx: DEFINE_FLOAT
|
|
dy: DEFINE_FLOAT
|
|
pry: DEFINE_FLOAT
|
|
prx: DEFINE_FLOAT
|
|
cxf: DEFINE_FLOAT
|
|
cyf: DEFINE_FLOAT
|
|
.endproc
|
|
|
|
;;; ============================================================
|
|
;;; Draw eye outlines as a 36-sided polygon
|
|
;;; Inputs: cx, cy, rx, ry
|
|
|
|
.proc draw_outline
|
|
segments = 36
|
|
|
|
lda ROMIN2
|
|
|
|
fac_load_int segw
|
|
fac_div CON_TWO_PI
|
|
fac_store step
|
|
|
|
sub16 cx, #penw/2, tmpw
|
|
fac_load_int tmpw
|
|
fac_store cxf
|
|
|
|
sub16 cy, #penh/2, tmpw
|
|
fac_load_int tmpw
|
|
fac_store cyf
|
|
|
|
sub16 rx, #penw/2, tmpw
|
|
fac_load_int tmpw
|
|
fac_store rxf
|
|
|
|
sub16 ry, #penh/2, tmpw
|
|
fac_load_int tmpw
|
|
fac_store ryf
|
|
|
|
lda #segments
|
|
sta count
|
|
|
|
jsr ZERO_FAC
|
|
fac_store theta
|
|
|
|
fac_load rxf
|
|
fac_add cxf
|
|
fac_store_int ptx
|
|
|
|
fac_load cyf
|
|
fac_store_int pty
|
|
|
|
lda LCBANK1
|
|
lda LCBANK1
|
|
|
|
MGTK_CALL MGTK::MoveTo, drawpos
|
|
|
|
loop:
|
|
lda ROMIN2
|
|
|
|
fac_load theta
|
|
fac_add step
|
|
fac_store theta
|
|
|
|
jsr COS
|
|
fac_mul rxf
|
|
fac_add cxf
|
|
fac_store_int ptx
|
|
|
|
fac_load theta
|
|
jsr SIN
|
|
fac_mul ryf
|
|
fac_add cyf
|
|
fac_store_int pty
|
|
|
|
lda LCBANK1
|
|
lda LCBANK1
|
|
|
|
MGTK_CALL MGTK::LineTo, drawpos
|
|
|
|
dec count
|
|
bpl loop
|
|
rts
|
|
|
|
count: .byte 0
|
|
segw: .word segments
|
|
tmpw: .word 0
|
|
step: DEFINE_FLOAT
|
|
theta: DEFINE_FLOAT
|
|
rxf: DEFINE_FLOAT
|
|
ryf: DEFINE_FLOAT
|
|
cxf: DEFINE_FLOAT
|
|
cyf: DEFINE_FLOAT
|
|
|
|
drawpos: DEFINE_POINT 0, 0, drawpos
|
|
ptx := drawpos::xcoord
|
|
pty := drawpos::ycoord
|
|
.endproc
|
|
|
|
|
|
;;; ============================================================
|
|
|
|
da_end = *
|
|
.assert * < $1B00, error, "DA too big"
|
|
;; I/O Buffer starts at MAIN $1C00
|
|
;; ... but icon tables start at AUX $1B00
|