Compare commits

...

6 Commits

9 changed files with 536 additions and 2110 deletions

View File

@ -3,7 +3,12 @@
%GTH0 { }
%GTH0* { ORA }
%GTH0k* { DUP* ORA }
%ADD2* { INC* INC* }
%ADD2r* { INCr* INCr* }
%ADD3* { INC* INC* INC* }
%CALL { JSR* }
%GOTO { JMP* }
%RETURN { JMPr* }
@ -65,13 +70,14 @@
%MOD16 { #0f AND } %MOD16* { #000f AND* }
%DIVMOD { DIVk MULk STH ROT STHr SUB ROT POP } ( val mod -- quotient remainder )
%DIVMOD* { DIVk* MULk* STH* ROT* STHr* SUB* ROT* POP* } ( val* mod* -- quotient* remainder* )
%DIVMOD { DIVk MULk STH ROT STHr SUB ROT POP } ( val mod -- quotient remainder )
%DIVMOD* { DIVk* MULk* STH* ROT* STHr* SUB* ROT* POP* } ( val* mod* -- quotient* remainder* )
%DEC { #01 SUB } %DEC* { #0001 SUB* }
%DECr { LITr 01 SUBr } %DECr* { LITr* 0001 SUBr* }
%DECk { DUP #01 SUB } %DECk* { DUP* #0001 SUB* }
%DECkr { DUPr LITr 01 SUBr } %DECkr* { DUPr* LITr* 0001 SUBr* }
%DEC { #01 SUB } %DEC* { #0001 SUB* }
%DECr { LITr 01 SUBr } %DECr* { LITr* 0001 SUBr* }
%DECk { DUP #01 SUB } %DECk* { DUP* #0001 SUB* }
%DECkr { DUPr LITr 01 SUBr } %DECkr* { DUPr* LITr* 0001 SUBr* }
%MOVE_LEFT { /SCREEN.X? SWP* SUB* /SCREEN.X! }
%MOVE_RIGHT { /SCREEN.X? ADD* /SCREEN.X! }
@ -89,9 +95,6 @@
%PANIC { BREAKPOINT }
%TO_SHORT { #00 SWP }
%DIGIT_TO_ASCII { #30 ADD }
%INDEX_TO_ASCII { #20 ADD }
%ASCII_TO_INDEX { #20 SUB }
%AND_FLIPX { #10 ORA }
%AND_FLIPY { #20 ORA }
@ -144,13 +147,18 @@
%CHOOSE { ROT JMP SWP NIP } ( flag value0 value1 -- value )
%CHOOSE* { STH* ROT STHr* ROT JMP SWP* NIP* } ( flag value0* value1* -- value* )
%IS_POSITIVE { #80 LTH }
%IS_POSITIVE* { #8000 LTH* }
%IS_NEGATIVE { #7f GTH }
%IS_NEGATIVE* { #7fff GTH* }
%ABS* { DUP* #8000 LTH* #05 JCN #0000 SWP* SUB* }
%IS_POSITIVE { #80 LTH }
%IS_POSITIVE* { #8000 LTH* }
%IS_NEGATIVE { #7f GTH }
%IS_NEGATIVE* { #7fff GTH* }
%ABS* { DUP* #8000 LTH* #05 JCN #0000 SWP* SUB* }
%NEG { LIT 00 SWP SUB }
%NEGr { LITr 00 SWPr SUBr }
%NEG* { LIT* 0000 SWP* SUB* }
%NEGr* { LITr* 0000 SWPr* SUBr* }
( Convert a positive number to a negative number )
%NEG { LIT 00 SWP SUB }
%NEGr { LITr 00 SWPr SUBr }
%NEG* { LIT* 0000 SWP* SUB* }
%NEGr* { LITr* 0000 SWPr* SUBr* }
( Invert all the bits in a number )
%INVERT { #ff EOR }
%INVERT* { #ffff EOR* }

View File

@ -1,3 +1,5 @@
%ASCII_TO_INDEX { #20 SUB }
( Draw proportional text )
@draw_text ( colour text_addr* -- )
ROT ,&colour STR ( t_addr* )

View File

@ -1,14 +1,31 @@
( Convert an integer to a null-terminated string )
@convert_byte_to_decimal_string ( byte -- text_addr* )
( Convert an integer to a null-terminated decimal string )
@convert_byte_to_hexadecimal_string ( value -- text_addr* )
TO_SHORT
@convert_short_to_hexadecimal_string ( value* -- text_addr* )
#10 ,_convert_short_to_string JMP
@convert_byte_to_decimal_string ( value -- text_addr* )
TO_SHORT
@convert_short_to_decimal_string ( value* -- text_addr* )
;&array_end SWP*
&loop ( addr* value* )
#000a DIVMOD* ( addr* value/10* digit* )
DIGIT_TO_ASCII ( addr* value* junk ascii )
#0a ,_convert_short_to_string JMP
@convert_byte_to_binary_string ( value -- text_addr* )
TO_SHORT
@convert_short_to_binary_string ( value* -- text_addr* )
#02 ( ... jump elided ... )
@_convert_short_to_string ( value* base -- text_addr* )
,&base STR ;&array_end SWP* ( addr* value* )
( Fill the output array with "zero" characters )
;&array_end INC* ;&array &clear
LIT "0 ROT ROT STAk ROT POP
INC* GTHk* ,&clear JCN
POP* POP*
&loop
[ LIT* 00 &base $1 ] DIVMOD* ( addr* value/base* digit* )
DUP #09 GTH #30 #37 CHOOSE ADD ( addr* value* junk ascii )
ROT* STAk NIP* DEC* SWP* ( addr-1* value* )
DUP* ADD ,&loop JCN ( addr* value* )
GTH0k* ,&loop JCN ( addr* value* )
&end
POP* INC* RETURN ( text_addr* )
&array $4 &array_end $1 <NULL>
&array $0f &array_end $1 <NULL>

43
_print_macros.tal Normal file
View File

@ -0,0 +1,43 @@
( Print characters )
%PRINTF(\s) { ;print_space CALL }
%PRINTF(\n) { ;print_newline CALL }
( Print strings )
%PRINTF(%s) { ;print_string CALL }
%PRINTF(%s\s) { PRINTF(%s) PRINTF(\s) }
%PRINTF(%s\n) { PRINTF(%s) PRINTF(\n) }
( Print decimal numbers )
%PRINTF(%d) { ;print_byte_decimal CALL }
%PRINTF(%d\s) { PRINTF(%d) PRINTF(\s) }
%PRINTF(%d\n) { PRINTF(%d) PRINTF(\n) }
%PRINTF(%d*) { ;print_short_decimal CALL }
%PRINTF(%d*\s) { PRINTF(%d*) PRINTF(\s) }
%PRINTF(%d*\n) { PRINTF(%d*) PRINTF(\n) }
%PRINTF(%-d*) { ;print_short_decimal_signed CALL }
%PRINTF(%-d*\s) { PRINTF(%-d*) PRINTF(\s) }
%PRINTF(%-d*\n) { PRINTF(%-d*) PRINTF(\n) }
( Print hexadecimal numbers )
%PRINTF(%x) { ;print_byte_hexadecimal CALL }
%PRINTF(%x\s) { PRINTF(%x) PRINTF(\s) }
%PRINTF(%x\n) { PRINTF(%x) PRINTF(\n) }
%PRINTF(%x*) { ;print_short_hexadecimal CALL }
%PRINTF(%x*\s) { PRINTF(%x*) PRINTF(\s) }
%PRINTF(%x*\n) { PRINTF(%x*) PRINTF(\n) }
( Print binary numbers )
%PRINTF(%b) { ;print_byte_binary CALL }
%PRINTF(%b\s) { PRINTF(%b) PRINTF(\s) }
%PRINTF(%b\n) { PRINTF(%b) PRINTF(\n) }
%PRINTF(%b*) { ;print_short_binary CALL }
%PRINTF(%b*\s) { PRINTF(%b*) PRINTF(\s) }
%PRINTF(%b*\n) { PRINTF(%b*) PRINTF(\n) }
( Print boolean values )
%PRINTF(%?) { ;print_bool CALL }
%PRINTF(%?\s) { PRINTF(%?) PRINTF(\s) }
%PRINTF(%?\n) { PRINTF(%?) PRINTF(\n) }
%PRINTF(%?*) { ;print_bool_short CALL }
%PRINTF(%?*\s) { PRINTF(%?*) PRINTF(\s) }
%PRINTF(%?*\n) { PRINTF(%?*) PRINTF(\n) }

View File

@ -1,58 +1,39 @@
%PRINTF(\s) { ;print_space CALL }
%PRINTF(\n) { ;print_newline CALL }
%PRINTF(%s) { ;print_string CALL }
%PRINTF(%s\s) { PRINTF(%s) PRINTF(\s) }
%PRINTF(%s\n) { PRINTF(%s) PRINTF(\n) }
%PRINTF(%d) { ;print_byte_decimal CALL }
%PRINTF(%d\s) { PRINTF(%d) PRINTF(\s) }
%PRINTF(%d\n) { PRINTF(%d) PRINTF(\n) }
%PRINTF(%d*) { ;print_short_decimal CALL }
%PRINTF(%d*\s) { PRINTF(%d*) PRINTF(\s) }
%PRINTF(%d*\n) { PRINTF(%d*) PRINTF(\n) }
%PRINTF(%-d*) { ;print_short_decimal_signed CALL }
%PRINTF(%-d*\s) { PRINTF(%-d*) PRINTF(\s) }
%PRINTF(%-d*\n) { PRINTF(%-d*) PRINTF(\n) }
%PRINTF(%b) { ;print_byte_binary CALL }
%PRINTF(%b\s) { PRINTF(%b) PRINTF(\s) }
%PRINTF(%b\n) { PRINTF(%b) PRINTF(\n) }
%PRINTF(%?) { ;print_bool CALL }
%PRINTF(%?\s) { PRINTF(%?) PRINTF(\s) }
%PRINTF(%?\n) { PRINTF(%?) PRINTF(\n) }
%PRINTF(%?*) { ;print_bool_short CALL }
%PRINTF(%?*\s) { PRINTF(%?) PRINTF(\s) }
%PRINTF(%?*\n) { PRINTF(%?) PRINTF(\n) }
@print_newline LIT <LINEFEED> /CONSOLE.WRITE! RETURN
@print_space LIT <SPACE> /CONSOLE.WRITE! RETURN
( Print a byte to the console in binary )
@print_byte_binary ( byte -- )
#80
&loop ( byte mask )
ANDk TO_BOOL LIT* "01 CHOOSE ( byte mask ascii )
/CONSOLE.WRITE! SHR1 DUP ,&loop JCN ( byte mask )
&end POP* RETURN
( Print a single byte to the console in decimal )
@print_byte_decimal_signed ( byte -- )
DUP* IS_POSITIVE ,print_byte_decimal JCN
LIT "- /CONSOLE.WRITE! NEGATE
@print_byte_decimal ( byte -- )
;convert_byte_to_decimal_string CALL
( Binary padded )
@print_byte_binary ( value -- )
#0002 ROT SWP
;_convert_short_to_string CALL POP*
;_convert_short_to_string/array #0008 ADD*
PRINTF(%s) RETURN
( Print a single short to the console in decimal )
@print_short_decimal_signed ( short* -- )
@print_short_binary ( value* -- )
#02 ;_convert_short_to_string CALL POP*
;_convert_short_to_string/array
PRINTF(%s) RETURN
( Hexadecimal padded )
@print_byte_hexadecimal ( value -- )
#0010 ROT SWP
;_convert_short_to_string CALL POP*
;_convert_short_to_string/array #000e ADD*
PRINTF(%s) RETURN
@print_short_hexadecimal ( value* -- )
#10 ;_convert_short_to_string CALL POP*
;_convert_short_to_string/array #000c ADD*
PRINTF(%s) RETURN
( Decimal )
@print_byte_decimal_signed ( value -- )
TO_SHORT
@print_short_decimal_signed ( value* -- )
DUP* IS_POSITIVE* ,print_short_decimal JCN
LIT "- /CONSOLE.WRITE! NEGATE*
@print_short_decimal ( short* -- )
;convert_short_to_decimal_string CALL
LIT "- /CONSOLE.WRITE! NEG*
@print_short_decimal ( value* -- )
#0a ;_convert_short_to_string CALL
PRINTF(%s) RETURN
@print_byte_decimal ( value -- )
TO_SHORT ,print_short_decimal JMP
( Print a null-terminated string to the console )
@print_string ( text_addr* -- )
@ -68,10 +49,18 @@
( Print a region of memory to the console as shorts, excluding the end address )
@print_memory_region_shorts ( start* end* -- )
SWP*
@print_memory_region_shorts ( start* end* -- )
SWP* EQUk* ,&end JCN ( end* start* )
&loop
EQUk* ,&end JCN
LDAk* PRINTF(%d*\s)
INC* INC* ,&loop JMP
LDAk* PRINTF(%x*\s)
ADD2* GTHk* ,&loop JCN
&end POP* POP* PRINTF(\n) RETURN
( Print a region of memory to the console as bytes, excluding the end address )
@print_memory_region_bytes ( start* end* -- )
SWP* EQUk* ,&end JCN ( end* start* )
&loop
LDAk PRINTF(%x\s)
INC* GTHk* ,&loop JCN
&end POP* POP* PRINTF(\n) RETURN

View File

@ -4,12 +4,14 @@
( Callbacks are two-byte addresses )
@ui__callbacks
( TODO: Do something with this callback, or remove it )
( TODO: Do something with this callback, or remove it
Also consider a 'fire-after-the-next-screen-update' callback feature. )
&on_screen $2
( One callback per UI element, signature [ -- ] )
( UI action callbacks, one per UI element, signature [ -- ] )
&go $32
( One callback per controller button, signature [ -- ] )
&click $32
( Raw input callbacks, one per controller button, signature [ -- ] )
&left $2
&right $2
&up $2
@ -18,16 +20,22 @@
&B $2
&start $2
&select $2
( One callback per UI element, signature [ active? -- ] )
( UI render callbacks, one per UI element, signature [ active? -- ] )
&draw $32
( One callback per UI element, signature [ delta -- ] )
( UI action callbacks, one per UI element, signature [ delta -- ]. -1: left/dec, 1: right/inc )
&change $32
( One callback per mouse action, signature [ state -- ]. 0: held, 1: released )
( Raw input callbacks, one per mouse button, signature [ state -- ]. -1: pressed, 0: held, 1: released )
&mouse1 $2
&mouse2 $2
&mouse3 $2
&end
( TODO: Add byte to each of the 16 zones )
( Zones are groups of left* right* top* bottom* inclusive bounds for each control )
@ui__zones $128
( Each zone slot consists of left*, right*, top*, bottom* coordinates, plus an action defining byte.
The action defining byte contains three numbers.
The first/greatest two bits are unused.
The next two bits contain the on-click action, where 0: go, 1: dec 2: inc, 3: click-callback.
The final/lowest four bits contains the index of the UI element that this zone corresponds to.
Hovering a zone will always make active the UI element that's registered to that zone.
)
@ui__zones $144 ( 16 slots * 9 bytes each )
&end

View File

@ -49,9 +49,10 @@
( Draw all UI elements )
@ui__draw_all /I.NUM_ELEMENTS? #00 ( -- )
&loop EQUk ,&end JCN ( total index )
EQUk ,&end JCN
&loop ( total index )
DUP ;ui__draw_single CALL ( total index )
INC ,&loop JMP ( total index )
INC GTHk ,&loop JCN ( total index )
&end POP* RETURN ( -- )
( Draw a single UI element by index )
@ -61,49 +62,56 @@
LDA* CALLRETURN ( active? )
( Call the callback for a single UI element by index, [ index -- ] )
@ui__press_go ;ui__callbacks/go ,__ui__call_callback JMP
@ui__press_inc #01 SWP ;ui__callbacks/change ,__ui__call_callback JMP
@ui__press_go ;ui__callbacks/go ,_ui__call_callback JMP
@ui__press_click ;ui__callbacks/click ,_ui__call_callback JMP
@ui__press_inc #01 SWP ;ui__callbacks/change ,_ui__call_callback JMP
@ui__press_dec #ff SWP ;ui__callbacks/change ( ... jump elided ... )
( Calculate the real address of a callback and call )
@__ui__call_callback ( index callback_block_start_addr* )
@_ui__call_callback ( index callback_block_start_addr* )
ROT TO_SHORT DOUBLE ADD* LDA* CALL ( real_callback_addr* )
;ui__redraw_controls CALLRETURN ( -- )
( Register a separate callback for each user interface element.
Each of the following subroutines accepts a list of pairs of a control index
Each of the following subroutines accepts a list of pairs of a UI element index
and a callback address, followed by the number of pairs that were provided.
For example: [ #00 ;func0 #01 ;func1 #04 ;func4 #03 ]
Draw callbacks MUST consume the 1-byte 'active?' bool that is passed to them.
Change callbacks MUST consume the 1-byte 'delta' that is passed to them (is either -1 or 1).
Change callbacks MUST consume the 1-byte 'delta' that is passed to them, is either -1 or 1.
Go callbacks do not receive any data.
Callbacks SHOULD consume the return address on the return stack by calling
either RETURN or NORETURN.
Signature for each 'register' subroutine is: [index callback*]+ count -- )
@ui__register_draw_callbacks ;ui__callbacks/draw ,__ui__register_callbacks JMP
@ui__register_change_callbacks ;ui__callbacks/change ,__ui__register_callbacks JMP
@ui__register_draw_callbacks ;ui__callbacks/draw ,_ui__register_callbacks JMP
@ui__register_change_callbacks ;ui__callbacks/change ,_ui__register_callbacks JMP
@ui__register_click_callbacks ;ui__callbacks/click ,_ui__register_callbacks JMP
@ui__register_go_callbacks ;ui__callbacks/go ( ... jump elided ... )
@__ui__register_callbacks ( [index callback*]+ count block_addr* -- )
,&block_addr STR* ( [index callback*]+ count )
&loop ( [index callback*]+ count )
STH ROT DOUBLE TO_SHORT ( ... callback* offset* | count )
[ LIT* &block_addr $2 ] ADD* STA* ( ... | count )
STHr DEC DUP ,&loop JCN ( ... count )
POP RETURN ( -- )
@_ui__register_callbacks ( [index callback*]+ count block_addr* -- )
,&block_addr STR* #00 ( [index callback*]+ total i )
&loop
STH* ROT DOUBLE TO_SHORT ( ... callback* offset* | total i )
[ LIT* &block_addr $2 ] ADD* STA* ( ... | total i )
STHr* INC GTHk ,&loop JCN ( ... total i | )
POP* RETURN ( -- )
( Register a single screen zone for each of multiple UI elements )
@ui__register_zones ( [index left* top* width* height*]+ count -- )
( Note: We decrement right* and bottom* because the bounds of the zone are inclusive )
&loop ( ... index left* top* width* height* count )
STH STH* STH* STH* STH* ( ... index | count height* width* top* left* )
TO_SHORT MUL8* ;ui__zones ADD* ( ... zone_left_addr* | count height* width* top* left* )
STHkr* ROTr* ADDr* DECr* STHr* ( ... zone_left_addr* left* right* | count height* top* )
STHkr* ADDr* DECr* STH* STH* ( ... zone_left_addr* left* | count bottom* top* right* )
OVR* STA* ADD2* ( ... zone_right_addr* | count bottom* top* right* )
STHr* OVR* STA* ADD2* ( ... zone_top_addr* | count bottom* top* )
STHr* OVR* STA* ADD2* ( ... zone_bottom_addr* | count bottom* )
STHr* SWP* STA* STHr ( ... count )
DEC DUP ,&loop JCN
POP RETURN
( Register a single screen zone for each of multiple UI elements. Zones are
registered in reverse order to how they're declared in code, so the last
zone in the declaration list will be the first to be checked. )
@ui__register_zones ( [action left* top* width* height*]+ count -- )
( Initialise start and end addresses )
;ui__zones DUP* ,&addr STR* ( ... count start_addr* )
ROT #09 MUL TO_SHORT ADD* ,&end STR* ( ... )
&loop ( ... action left* top* width* height* )
ROT* ADDk* STH* STH* POP* ( ... action left* width* | bottom* top* )
ADDk* STH* POP* STH* ( ... action | bottom* top* right* left* )
( Note: We decrement right* and bottom* because the bounds of the zone are inclusive )
#ffff [ LIT* &addr $2 ] ( ... action -1* addr* | bottom* top* right* left* )
STHr* OVR* STA* ADD2* ( ... action -1* addr+2* | bottom* top* right* )
OVR* STHr* ADD* OVR* STA* ADD2* ( ... action -1* addr+2* | bottom* top* )
STHr* OVR* STA* ADD2* ( ... action -1* addr+2* | bottom* )
SWP* STHr* ADD* OVR* STA* ADD2* ( ... action addr+2* | )
STAk ROT POP INC* ( ... addr+1* )
DUP* ,&addr STR* ( ... addr* )
[ LIT* &end $2 ] LTH* ,&loop JCN ( ... )
RETURN
( Call to activate the declared user interface )
@ui__run_blank ( -- )
@ -122,28 +130,29 @@
subroutine before declaring the UI for a new screen. )
@ui__initialise
@ui__clear
( Clear mouse button state, to prevent weird clicks when the new UI comes up )
#0000 DUP /I.MOUSE.PRESSED! /I.MOUSE.HELD! /I.MOUSE.RELEASED!
( Clear mouse button state, to prevent weird clicks when the new UI comes up )
#00 DUPk /I.MOUSE.PRESSED! /I.MOUSE.HELD! /I.MOUSE.RELEASED!
( Recalculate the center of the screen )
/SCREEN.WIDTH? HALVE* /I.CENTER.X! /SCREEN.HEIGHT? HALVE* /I.CENTER.Y!
/SCREEN.WIDTH? HALVE* /I.CENTER.X! /SCREEN.HEIGHT? HALVE* /I.CENTER.Y!
;clear_foreground CALL
;ui__callbacks ;ui__callbacks/end ;&null_callback ,__ui__clear_memory_region JSR
;ui__callbacks/draw ;ui__callbacks/end ;&pop_null_callback ,__ui__clear_memory_region JSR
;ui__zones ;ui__zones/end #0000 ,__ui__clear_memory_region JMP
&pop_null_callback POP &null_callback RETURN
( Fill a region of memory with a repeated value. Address includes `start_addr`, but excludes `end_addr`. )
@__ui__clear_memory_region ( start_addr* end_addr* value* -- )
STH* SWP* ( end* addr* | val* )
&loop ( end* addr* | val* )
EQUk* ,&end JCN ( end* addr* | val* )
STHkr* OVR* STA* ( addr* )
ADD2* ,&loop JMP ( end* addr* | val* )
( Clear all callbacks )
;ui__callbacks ;ui__callbacks/draw ;null_callback ,_ui__clear_memory_region JSR
;ui__callbacks/draw ;ui__callbacks/end ;pop_null_callback ,_ui__clear_memory_region JSR
;ui__zones ;ui__zones/end #ffff ( ... jump elided ... )
( Fill a region of memory with a repeated value. Address range includes start but excludes end. )
@_ui__clear_memory_region ( start_addr* end_addr* value* -- )
STH* SWP* EQUk ,&end JCN ( end* addr* | val* )
&loop
STHkr* OVR* STA* ( end* addr* | val* )
ADD2* GTHk* ,&loop JCN ( end* addr* | val* )
&end POP* POP* POPr* RETURN
@pop_null_callback POP
@null_callback RETURN
( Mouse vector )
@ui__on_mouse ( -- )
( TODO: Add back in the mouse2 stuff )
( Update the mouse button state variables )
/MOUSE.STATE? DUP /I.MOUSE.HELD? DUPk* ( held now prev now prev now prev )
EOR AND SWP SWP* EOR AND ( held released pressed )
@ -151,6 +160,7 @@
;ui__callbacks/mouse1 LDA* ,&mouse_callback STR* BITMASK_1 ,&mouse_mask STR
;ui__start_mouse1_drag ,&start_drag_callback STR*
,&click_element JSR
,&mouse_pressed JSR
,&mouse_held JSR
,&mouse_released JSR
@ -173,20 +183,22 @@
[ LIT &mouse_mask $1 ] IF_NOT_MASK NORETURN RETURN
&mouse_callback $2
&click_element
/I.MOUSE.PRESSED? ,&return_if_not JSR
;ui__click_hovered_element CALLRETURN
&mouse_pressed
/I.MOUSE.PRESSED? ,&return_if_not JSR
;ui__press_go ;ui__call_on_hovered_element CALL
[ LIT* &start_drag_callback $2 ] CALL
#ff ;&mouse_callback LDA* CALLRETURN
#ff ,&mouse_callback LDR* CALLRETURN
&mouse_held
/I.MOUSE.HELD? ,&return_if_not JSR
,&return_if_cursor_not_moved JSR
#00 ;&mouse_callback LDA* CALLRETURN
#00 ,&mouse_callback LDR* CALLRETURN
&mouse_released
/I.MOUSE.RELEASED? ,&return_if_not JSR
#01 ;&mouse_callback LDA* CALLRETURN
#01 ,&mouse_callback LDR* CALLRETURN
&return_if_cursor_not_moved ( -- )
&return_if_cursor_not_moved ( -- )
/I.CURSOR.X? /MOUSE.X? NEQ* ( diff_x? )
/I.CURSOR.Y? /MOUSE.Y? NEQ* ( diff_x? diff_y? )
ORA IF_FALSE NORETURN RETURN ( -- )
@ -204,7 +216,7 @@
COL_00_FG /SCREEN.SPRITE!
( Draw the mouse cursor under the current mouse position )
/MOUSE.X? /SCREEN.X! /MOUSE.Y? /SCREEN.Y!
COL_T1_FG /SCREEN.SPRITE!
COL_T2_FG /SCREEN.SPRITE!
RETURN
@ui__start_mouse1_drag ( -- )
@ -214,7 +226,7 @@
@ui__start_mouse3_drag ( -- )
/I.MOUSE3.X /I.MOUSE3.Y ,_ui__store_cursor_position JMP
@ui__update_cursor_position ( -- )
/I.CURSOR.X /I.CURSOR.Y ( ,_ui__store_cursor_position JMP )
/I.CURSOR.X /I.CURSOR.Y ( ... jump elided ... )
@_ui__store_cursor_position ( x_variable y_variable )
/MOUSE.Y? ROT STZ* /MOUSE.X? ROT STZ* RETURN
@ -265,31 +277,55 @@
DUP /I.ACTIVE_ELEMENT? NEQ ,&cont JCN POP RETURN &cont
/I.ACTIVE_ELEMENT! ;ui__redraw_controls CALLRETURN
( If there is a control under the mouse cursor, push the index of that
control to the stack and call the given routine. The index must be
consumed by the routine. )
@ui__call_on_hovered_element #00 ( func_addr* -- )
&loop ( f_addr* i )
/I.NUM_ELEMENTS? OVR GTH ,&cont JCN ( f_addr* i )
POP POP* RETURN ( // -- )
&cont ( f_addr* i )
DUP TO_SHORT MUL8* ( f_addr* i ix8* )
;ui__zones ADD* ( f_addr* i zone_left_addr* )
( Test horizontal bounds )
/I.CURSOR.X? OVR* LDA* LTH* STH ( f_addr* i zone_left_addr* | lth_left? )
#0002 ADD* ( f_addr* i zone_right_addr* | lth_left? )
/I.CURSOR.X? OVR* LDA* GTH* STHr ( f_addr* i zone_right_addr* gth_right? lth_left? )
ADD ,&no_match JCN #0002 ADD* ( f_addr* i zone_top_addr* )
( Test vertical bounds )
/I.CURSOR.Y? OVR* LDA* LTH* STH ( f_addr* i zone_top_addr* | lth_top? )
#0002 ADD* ( f_addr* i zone_bot_addr* )
/I.CURSOR.Y? OVR* LDA* GTH* STHr ( f_addr* i zone_top_addr* gth_bot? lth_top? )
ADD ,&no_match JCN POP* ,&match JMP ( // varies )
&no_match ( f_addr* i junk_addr* )
POP* INC ,&loop JMP ( f_addr* i )
&match ( f_addr* i )
ROT ROT GOTO ( i )
( If there is an element under the mouse cursor, push the index of the
associated control to the stack and call the given routine. The
index must be consumed by the routine. )
@ui__call_on_hovered_element ( func_addr* -- )
,ui__get_action_for_hovered_element JSR ( func_addr* action )
INCk ,&matched JCN ( func_addr* action )
POP POP* RETURN ( -- )
&matched ( func_addr* action )
#0f AND ROT ROT CALLRETURN ( action )
( Call the click action of the hovered element )
@ui__click_hovered_element ( -- )
,ui__get_action_for_hovered_element JSR ( action )
INCk ,&matched JCN ( action )
POP RETURN ( -- )
&matched
DUP #0f AND SWP SHR4 ( index clickmode )
MUL4 JMP
( 0 ) ;ui__press_go CALLRETURN
( 1 ) ;ui__press_dec CALLRETURN
( 2 ) ;ui__press_inc CALLRETURN
( 3 ) ;ui__press_click CALLRETURN
( Returns 0xff if no element is under the mouse )
@ui__get_action_for_hovered_element ( -- action )
;ui__zones ( addr* )
&loop ( left_addr* )
DUP* ;ui__zones/end EQU* ,&end JCN ( left_addr* )
( Test if out of bounds horizontally )
LDAk* SWP* ADD2* LDAk* ROT* ( right_addr* right* left* )
/MOUSE.X? GTH* STH ( right_addr* right* | l? )
/MOUSE.X? LTH* STH ADD2* ( top_addr* | l? r? )
( Test if out of bounds vertically )
LDAk* SWP* ADD2* LDAk* ROT* ( bot_addr* bot* top* | l? r? )
/MOUSE.Y? GTH* STH ( bot_addr* bot* | l? r? t? )
/MOUSE.Y? LTH* STH ADD2* ( action_addr* | l? r? t? b? )
( If all `l? r? t? b?` are 0, jump to &match )
ORAr* ORAr STHr NOT ,&match JCN ( action_addr* )
&no_match ( action_addr* )
( Fall through to &end if next left-coord is uninitialised, is #ffff )
INC* LDAk* INC* ORA ,&loop JCN
&end ( addr* )
POP* #ff RETURN
&match ( action_addr* )
LDA RETURN
@ui__on_screen ( -- )
;&counter LDAk* INC* SWP* STA* BRK &counter $2 ( // increment the frame counter )

File diff suppressed because it is too large Load Diff

View File

@ -14,34 +14,41 @@
%/V.CANVAS.HEIGHT { #06 } %/V.CANVAS.HEIGHT? { #06 LDZ* } %/V.CANVAS.HEIGHT! { #06 STZ* }
( Canvas colour palette )
( Default screen background is colour 0x02 )
|0008 @canvas_colour_palette
|0008 @canvas_palette
%/V.CANVAS.RED { #08 } %/V.CANVAS.RED? { #08 LDZ* } %/V.CANVAS.RED! { #08 STZ* }
%/V.CANVAS.GREEN { #0a } %/V.CANVAS.GREEN? { #0a LDZ* } %/V.CANVAS.GREEN! { #0a STZ* }
%/V.CANVAS.BLUE { #0c } %/V.CANVAS.BLUE? { #0c LDZ* } %/V.CANVAS.BLUE! { #0c STZ* }
( UI colour palette )
|000e @ui_colour_palette
|000e @ui_palette
%/V.UI.RED { #0e } %/V.UI.RED? { #0e LDZ* } %/V.UI.RED! { #0e STZ* }
%/V.UI.GREEN { #10 } %/V.UI.GREEN? { #10 LDZ* } %/V.UI.GREEN! { #10 STZ* }
%/V.UI.BLUE { #12 } %/V.UI.BLUE? { #12 LDZ* } %/V.UI.BLUE! { #12 STZ* }
( Scratch colour palette )
( The channels of the colour that's currently being edited in the colour palette editor )
( These are used individually as bytes, but stored here as a palette )
|0014 @scratch_palette
%/V.SCRATCH.RED { #15 } %/V.SCRATCH.RED? { #15 LDZ } %/V.SCRATCH.RED! { #15 STZ }
%/V.SCRATCH.GREEN { #17 } %/V.SCRATCH.GREEN? { #17 LDZ } %/V.SCRATCH.GREEN! { #17 STZ }
%/V.SCRATCH.BLUE { #19 } %/V.SCRATCH.BLUE? { #19 LDZ } %/V.SCRATCH.BLUE! { #19 STZ }
( The currently active and previously active drawing tools. )
%/V.ACTIVE_TOOL { #14 } %/V.ACTIVE_TOOL? { #14 LDZ } %/V.ACTIVE_TOOL! { #14 STZ }
%/V.PREV_TOOL { #15 } %/V.PREV_TOOL? { #15 LDZ } %/V.PREV_TOOL! { #15 STZ }
%/V.ACTIVE_TOOL { #20 } %/V.ACTIVE_TOOL? { #20 LDZ } %/V.ACTIVE_TOOL! { #20 STZ }
%/V.PREV_TOOL { #21 } %/V.PREV_TOOL? { #21 LDZ } %/V.PREV_TOOL! { #21 STZ }
%/V.BRUSH1.COLOUR { #16 } %/V.BRUSH1.COLOUR? { #16 LDZ } %/V.BRUSH1.COLOUR! { #16 STZ }
%/V.BRUSH2.COLOUR { #17 } %/V.BRUSH2.COLOUR? { #17 LDZ } %/V.BRUSH2.COLOUR! { #17 STZ }
%/V.BRUSH3.COLOUR { #18 } %/V.BRUSH3.COLOUR? { #18 LDZ } %/V.BRUSH3.COLOUR! { #18 STZ }
%/V.BRUSH1.COLOUR { #22 } %/V.BRUSH1.COLOUR? { #22 LDZ } %/V.BRUSH1.COLOUR! { #22 STZ }
%/V.BRUSH2.COLOUR { #23 } %/V.BRUSH2.COLOUR? { #23 LDZ } %/V.BRUSH2.COLOUR! { #23 STZ }
%/V.BRUSH3.COLOUR { #24 } %/V.BRUSH3.COLOUR? { #24 LDZ } %/V.BRUSH3.COLOUR! { #24 STZ }
%/V.BRUSH1.SHAPE { #19 } %/V.BRUSH1.SHAPE? { #19 LDZ } %/V.BRUSH1.SHAPE! { #19 STZ }
%/V.BRUSH2.SHAPE { #1a } %/V.BRUSH2.SHAPE? { #1a LDZ } %/V.BRUSH2.SHAPE! { #1a STZ }
%/V.BRUSH3.SHAPE { #1b } %/V.BRUSH3.SHAPE? { #1b LDZ } %/V.BRUSH3.SHAPE! { #1b STZ }
%/V.BRUSH1.SHAPE { #25 } %/V.BRUSH1.SHAPE? { #25 LDZ } %/V.BRUSH1.SHAPE! { #25 STZ }
%/V.BRUSH2.SHAPE { #26 } %/V.BRUSH2.SHAPE? { #26 LDZ } %/V.BRUSH2.SHAPE! { #26 STZ }
%/V.BRUSH3.SHAPE { #27 } %/V.BRUSH3.SHAPE? { #27 LDZ } %/V.BRUSH3.SHAPE! { #27 STZ }
%/V.BRUSH1.PATTERN { #1c } %/V.BRUSH1.PATTERN? { #1c LDZ } %/V.BRUSH1.PATTERN! { #1c STZ }
%/V.BRUSH2.PATTERN { #1d } %/V.BRUSH2.PATTERN? { #1d LDZ } %/V.BRUSH2.PATTERN! { #1d STZ }
%/V.BRUSH3.PATTERN { #1e } %/V.BRUSH3.PATTERN? { #1e LDZ } %/V.BRUSH3.PATTERN! { #1e STZ }
%/V.BRUSH1.PATTERN { #28 } %/V.BRUSH1.PATTERN? { #28 LDZ } %/V.BRUSH1.PATTERN! { #28 STZ }
%/V.BRUSH2.PATTERN { #29 } %/V.BRUSH2.PATTERN? { #29 LDZ } %/V.BRUSH2.PATTERN! { #29 STZ }
%/V.BRUSH3.PATTERN { #2a } %/V.BRUSH3.PATTERN? { #2a LDZ } %/V.BRUSH3.PATTERN! { #2a STZ }
( The index of the colour that's currently selected in the colour palette editor )
%/V.ACTIVE_COLOUR { #1f } %/V.ACTIVE_COLOUR? { #1f LDZ } %/V.ACTIVE_COLOUR! { #1f STZ }
%/V.ACTIVE_COLOUR { #2b } %/V.ACTIVE_COLOUR? { #2b LDZ } %/V.ACTIVE_COLOUR! { #2b STZ }
%TOOL_COUNT? { #07 }
@ -49,17 +56,20 @@
( ---------------------------------------------------------------------------- )
( P R O G R A M S T A R T )
|0100
;ui__initialise CALL
#0080 /V.CANVAS.WIDTH! #0060 /V.CANVAS.HEIGHT! #01 /V.ACTIVE_TOOL!
( Seed default palettes for canvas and UI )
( Populate default palettes for canvas and UI )
#1c8d /V.CANVAS.RED! #1619 /V.CANVAS.GREEN! #1010 /V.CANVAS.BLUE!
( TODO: Remove this line )
#1d44 /V.UI.RED! #2d68 /V.UI.GREEN! #397a /V.UI.BLUE!
#1d24 /V.UI.RED! #2d8a /V.UI.GREEN! #3946 /V.UI.BLUE!
;recenter_canvas CALL
;colour_screen GOTO
;tool_screen GOTO
( TODO: Remove print macros )
~_print_macros.tal
~_print_routines.tal
~_user_interface_framework.tal
@ -68,78 +78,119 @@
@colour_screen
( TODO: Set /V.ACTIVE_COLOUR to be the active brush colour on entry, if there is one, else don't change it )
;ui__clear CALL
( Draw static elements )
COL_30 ;fill_screen_with_colour CALL
#0000 DUP* /SCREEN.X! /SCREEN.Y!
COL_0 #0080 /SCREEN.HEIGHT? ;draw_rect_filled CALL
#0080 /SCREEN.X! COL_1 /SCREEN.HEIGHT? ;draw_vertical_line CALL
#0018 /SCREEN.X! #0008 /SCREEN.Y!
COL_T1 ;&title_text ;draw_text CALL
#0019 /SCREEN.X! #0048 /SCREEN.Y!
COL_T1 ;&red_text ;draw_text CALL
#0058 /SCREEN.Y!
COL_T1 ;&green_text ;draw_text CALL
#0068 /SCREEN.Y!
COL_T1 ;&blue_text ;draw_text CALL
( Populate slider values )
#00 ;colour_screen__change__colour CALL
( Draw background )
COL_30 ;fill_screen_with_colour CALL
#0000 DUP* /SCREEN.X! /SCREEN.Y!
COL_0 #0080 /SCREEN.HEIGHT? ;draw_rect_filled CALL
#0080 /SCREEN.X! COL_1 /SCREEN.HEIGHT? ;draw_vertical_line CALL
( Draw title )
#0018 /SCREEN.X! #0022 CENTER_UP!
COL_T1 ;&title_text ;draw_text CALL
( Draw R G B labels )
#0019 /SCREEN.X!
#0000 CENTER_DOWN!
COL_T1 ;&red_text ;draw_text CALL
#000b CENTER_DOWN!
COL_T1 ;&green_text ;draw_text CALL
#0016 CENTER_DOWN!
COL_T1 ;&blue_text ;draw_text CALL
( Register change callbacks )
#00 ;colour_screen__change__colour
#01 ;ui__register_change_callbacks CALL
#01 ;colour_screen__change__colour
#02 ;colour_screen__change__red
#03 ;colour_screen__change__green
#04 ;colour_screen__change__blue
#04 ;ui__register_change_callbacks CALL
( Register draw callbacks )
#00 ;colour_screen__draw__colours
#01 ;colour_screen__draw__red
#02 ;colour_screen__draw__green
#03 ;colour_screen__draw__blue
#04 ;ui__register_draw_callbacks CALL
#0004 ;ui__run GOTO
#00 ;colour_screen__draw__back
#01 ;colour_screen__draw__colours
#02 ;colour_screen__draw__red
#03 ;colour_screen__draw__green
#04 ;colour_screen__draw__blue
#05 ;ui__register_draw_callbacks CALL
( Register go callbacks )
#00 ;tool_screen
#01 ;ui__register_go_callbacks CALL
( Register raw input callbacks )
;tool_screen /I.CALLBACK.B!
#01 #05 ;ui__run GOTO
&title_text "CHANGE <SPACE> "COLOURS <NULL>
&red_text "R <NULL>
&green_text "G <NULL>
&blue_text "B <NULL>
@colour_screen__change__colour ( delta )
/V.ACTIVE_COLOUR #04 ;change_variable CALLRETURN
@colour_screen__draw__back ( active? )
#0006 /SCREEN.X! #0023 CENTER_UP!
COL_21 COL_31 CHOOSE ;sprite/back ( colour )
;draw_icon_button CALL
;ui_palette ;ui__load_colour_palette
CALLRETURN
@colour_screen__draw__colours ( active? )
#0013 /SCREEN.X! #0020 /SCREEN.Y!
/V.ACTIVE_COLOUR? DUP ROT
;draw_colour_swatch CALL
;load_merged_palette CALLRETURN
@colour_screen__draw__red ( active? )
#0024 /SCREEN.X! #0060 /SCREEN.Y!
#04 SWP ;draw_slider CALLRETURN
@colour_screen__draw__green ( active? )
#0024 /SCREEN.X! #006a /SCREEN.Y!
#04 SWP ;draw_slider CALLRETURN
@colour_screen__draw__blue ( active? )
#0024 /SCREEN.X! #0075 /SCREEN.Y!
#04 SWP ;draw_slider CALLRETURN
#0013 /SCREEN.X! #0012 CENTER_UP!
/V.ACTIVE_COLOUR? DUP ROT ( n n active? )
;draw_colour_swatch CALL ( n )
;load_merged_ui_palette CALLRETURN ( -- )
@colour_screen__draw__red /V.SCRATCH.RED? #0000 ,colour_screen__draw__slider JMP
@colour_screen__draw__green /V.SCRATCH.GREEN? #000b ,colour_screen__draw__slider JMP
@colour_screen__draw__blue /V.SCRATCH.BLUE? #0016 ( ... jump elided ... )
@colour_screen__draw__slider ( active? value y_offset* )
CENTER_DOWN! #0024 /SCREEN.X!
SWP ;draw_slider CALL
/V.ACTIVE_COLOUR?
;load_merged_ui_palette CALLRETURN
@colour_screen__draw__sliders ( -- )
#00 DUPk
,colour_screen__draw__red JSR
,colour_screen__draw__green JSR
,colour_screen__draw__blue JMP
@colour_screen__change__colour ( delta )
/V.ACTIVE_COLOUR #04 ;change_variable CALL
( Extract the channels of the current canvas colour into scratch variables )
#03 /V.ACTIVE_COLOUR? SUB MUL4 STH ( | sft )
#0300 ( total i | sft )
&loop
DUPk ADD STHk ( total i 2i | sft 2i )
.canvas_palette ADD LDZ* ( total i channel* | sft 2i )
OVRr STHr SFT* #000f AND* ( total i scratch* | sft 2i )
.scratch_palette STHr ADD STZ* ( total i | sft )
INC GTHk ,&loop JCN ( total i | sft )
POP* POPr ( -- )
( Redraw all the sliders )
;colour_screen__draw__sliders CALLRETURN
@colour_screen__change__red
/V.SCRATCH.RED #10 ;change_variable CALL ,commit_scratch_colours JMP
@colour_screen__change__green
/V.SCRATCH.GREEN #10 ;change_variable CALL ,commit_scratch_colours JMP
@colour_screen__change__blue
/V.SCRATCH.BLUE #10 ;change_variable CALL ( .. jump elided ... )
@commit_scratch_colours ( -- )
#03 /V.ACTIVE_COLOUR? SUB MUL4 SHL4 STH ( | sft )
#0300 ( total i | sft )
&loop
DUPk ADD STHk ( total i 2i | sft 2i )
.scratch_palette ADD LDZ* ( total i scratch* | sft 2i )
OVRr STHr SFT* ( total i col* | sft 2i )
.canvas_palette STHkr ADD LDZ* ( total i col* chan* | sft 2i )
( Zero out the active colour by using a mask )
#000f OVRr STHr SFT* INVERT* AND* ( total i col* maskd* | sft 2i )
ORA* ( total i merged* | sft 2i )
.canvas_palette STHr ADD STZ* ( total i | sft )
INC GTHk ,&loop JCN ( total i | sft )
POP* POPr RETURN
@canvas_screen
;ui__clear CALL
;canvas_colour_palette ;ui__load_colour_palette CALL
;canvas_palette ;ui__load_colour_palette CALL
;draw_canvas CALL
;canvas_screen__A /I.CALLBACK.A!
;canvas_screen__B /I.CALLBACK.B!
@ -166,8 +217,8 @@
/V.PREV_TOOL? /V.ACTIVE_TOOL!
&return RETURN
@canvas_screen__chtool #01 IF_NOT_EQUAL RETURN
@canvas_screen__B NORETURN ;tool_screen GOTO
@canvas_screen__chtool #ff IF_NOT_EQUAL RETURN
@canvas_screen__B ;tool_screen GOTO
@canvas_screen__use_tool
( Dispatch control to the routine of the active tool )
@ -232,11 +283,11 @@
COL_0 ;fill_screen_with_colour CALL
( Labels )
#0043 CENTER_LEFT? /SCREEN.X! #0005 CENTER_DOWN? /SCREEN.Y!
#0043 CENTER_LEFT! #0005 CENTER_DOWN!
COL_1 ;&colour_text ;draw_text CALL
#003e CENTER_LEFT? /SCREEN.X! #0013 CENTER_DOWN? /SCREEN.Y!
#003e CENTER_LEFT! #0013 CENTER_DOWN!
COL_1 ;&shape_text ;draw_text CALL
#004a CENTER_LEFT? /SCREEN.X! #0021 CENTER_DOWN? /SCREEN.Y!
#004a CENTER_LEFT! #0021 CENTER_DOWN!
COL_1 ;&pattern_text ;draw_text CALL
( Draw shape and pattern backgrounds )
@ -245,7 +296,7 @@
#001f CENTER_DOWN!
COL_1 #005a #000c ;draw_capsule CALL
( Register inc/dec callbacks )
( Register change callbacks )
#00 ;tool_screen__change__tool
#01 ;tool_screen__change__colour
#02 ;tool_screen__change__shape
@ -260,20 +311,107 @@
( Register raw input callbacks )
;tool_screen__B /I.CALLBACK.B!
;tool_screen__canvas /I.CALLBACK.MOUSE3!
( Register go callbacks )
#00 ;canvas_screen
#01 ;colour_screen
#02 ;ui__register_go_callbacks CALL
( Register click callbacks )
#00 ;tool_screen__click__tool
#01 ;tool_screen__click__colour
#02 ;tool_screen__click__shape
#03 ;tool_screen__click__pattern
#04 ;ui__register_click_callbacks CALL
( Register mouse zones )
#30 ;get_tool_palette_coords CALL
#31 #0013 CENTER_LEFT? #0005 CENTER_DOWN? #005a #0008
#32 #0013 CENTER_LEFT? #0011 CENTER_DOWN? #005a #000b
#33 #0013 CENTER_LEFT? #001f CENTER_DOWN? #005a #000c
#04 ;ui__register_zones CALL
( Finish callback registration )
#0004 ;ui__run GOTO
&colour_text "Colour: <NULL>
&shape_text "Shape: <NULL>
&pattern_text "Pattern: <NULL>
@tool_screen__canvas #01 IF_NOT_EQUAL RETURN
@tool_screen__B NORETURN ;canvas_screen GOTO
@tool_screen__canvas #ff IF_NOT_EQUAL RETURN
@tool_screen__B ;canvas_screen GOTO
@tool_screen__click__tool
;get_tool_palette_coords CALL ( x* y* width* height* )
POP* POP* POP* ADD2* ( x* )
#0017 #0003 TOOL_COUNT? ( x* e_width* gap* total )
;get_index_of_element_in_line CALL ( index )
INCk ,&matched JCN
POP RETURN
&matched
( If clicking active tool, go to canvas screen )
DUP /V.ACTIVE_TOOL? EQU ;canvas_screen JCN*
( Set new tool and return )
/V.ACTIVE_TOOL! RETURN
@tool_screen__click__colour
#0013 CENTER_LEFT? ( x* )
#0015 #0002 #08 ( x* e_width* gap* total )
;get_index_of_element_in_line CALL ( index )
DEBUG
INCk ,&matched JCN
POP RETURN
&matched
DUP /V.ACTIVE_COLOUR!
( If clicking active colour, go to colour screen )
DUP /V.BRUSH1.COLOUR? EQU ;colour_screen JCN*
( Set new tool and return )
/V.BRUSH1.COLOUR! RETURN
@tool_screen__click__shape
#0012 CENTER_LEFT? ( x* )
#000b #0000 #08 ( x* e_width* gap* total )
;get_index_of_element_in_line CALL ( index )
INCk ,&matched JCN
POP RETURN
&matched
( Set new tool and return )
/V.BRUSH1.SHAPE! RETURN
@tool_screen__click__pattern
#0011 CENTER_LEFT? ( x* )
#000a #0001 #08 ( x* e_width* gap* total )
;get_index_of_element_in_line CALL ( index )
INCk ,&matched JCN
POP RETURN
&matched
( Set new tool and return )
/V.BRUSH1.PATTERN! RETURN
( Takes the x-coordinate of the left-most element, the individual element
width, the size of the gaps between elements, and the total number of
elements. Returns 0xff if nothing was clicked. )
@get_index_of_element_in_line ( x* width* gap* total -- index )
,&total STR ( x* width* gap* )
OVR* ADD* ,&fullwidth STR* ( x* width* )
,&width STR* ( x* )
( Calculate distance of cursor along line )
/MOUSE.X? SWP* SUB* ( distance* )
( Return 0xff if cursor is left of x* )
DUP* IS_NEGATIVE* ,&err JCN ( distance* )
[ LIT* &fullwidth $2 ] DIVMOD* ( quotient* remainder* )
( Return 0xff if cursor is on a gap )
[ LIT* &width $2 ] LTH* NOT ,&err JCN ( quotient* )
( Return 0xff if cursor is past end of line )
DUP [ LIT &total $1 ] LTH NOT ,&err JCN ( quotient* )
NIP RETURN ( index )
&err POP* #ff RETURN ( ff )
@tool_screen__change__tool ( delta -- )
/V.ACTIVE_TOOL TOOL_COUNT? ,change_variable JMP
@tool_screen__change__colour ( delta -- )
/V.BRUSH1.COLOUR #04 ,change_variable JMP
/V.BRUSH1.COLOUR #04 ,change_variable JSR
/V.BRUSH1.COLOUR? /V.ACTIVE_COLOUR! RETURN
@tool_screen__change__shape ( delta -- )
/V.BRUSH1.SHAPE #08 ,change_variable JMP
@tool_screen__change__pattern ( delta -- )
@ -287,8 +425,8 @@
/V.BRUSH1.COLOUR? SWP DUP*
;draw_colour_swatch CALL
( Either load regular UI palette, or replace colour 0x03 )
;load_merged_palette JCN* POP
;ui_colour_palette ;ui__load_colour_palette GOTO
;load_merged_ui_palette JCN* POP
;ui_palette ;ui__load_colour_palette GOTO
@ -349,10 +487,9 @@
#0040 CENTER_LEFT! #002f CENTER_UP!
COL_01 #0080 /V.ACTIVE_TOOL? ;get_tool_name CALL ;draw_button CALL
( Draw a large capsule to use as a background for the tool icons )
#001f CENTER_UP! COL_1 ( colour -- )
;get_tool_palette_width CALL ( colour width* )
/SCREEN.WIDTH? OVR* SUB* HALVE* ( colour width* bg_x* )
/SCREEN.X! #001b ;draw_capsule CALL ( -- )
COL_1 ;get_tool_palette_coords CALL ( colour x* y* width* height* )
ROT* /SCREEN.Y! ROT* /SCREEN.X! ( colour width* height* )
;draw_capsule CALL ( -- )
( Draw each of the large tool icons )
TOOL_COUNT? #00 ( total i )
&loop
@ -361,6 +498,33 @@
INC GTHk ,&loop JCN
POP* RETURN
@get_tool_palette_coords ( -- x* y* width* height* )
#00 TOOL_COUNT? #001a MUL* INC* ( width* )
/SCREEN.WIDTH? OVR* SUB* HALVE* ( width* x* )
#001f CENTER_UP? ( width* x* y* )
ROT* #001b RETURN ( x* y* width* height* )
( Draw a single tool icon )
@draw_tool_palette_icon ( index active? )
OVR TO_SHORT #001a MUL* ADD2* ( index active? x_offset* )
;get_tool_palette_coords CALL POP* POP* ( index active? x_offset* x* y* )
ADD2* /SCREEN.Y! ADD* /SCREEN.X! ( index active? )
#00 ROT STHk ( active? index* | index )
#0048 MUL* ;tool_icon ADD* /SCREEN.ADDR! ( active? | index )
( Choose colour: unchosen - inactive - active )
/V.ACTIVE_TOOL? STHr EQU ( active? chosen? )
COL_0 COL_2 CHOOSE COL_3 CHOOSE ( colour )
( Draw background )
#0017 DUP* ;draw_capsule_smooth CALL ( -- )
( Draw 1-bit 3x3 sprite )
#26 /SCREEN.AUTO! ( -- )
COL_T1 /SCREEN.SPRITE DEOk DEOk DEO ( -- )
#00 /SCREEN.AUTO! RETURN ( -- )
@get_tool_name ( index -- text_addr* )
MUL4 JMP
@ -379,32 +543,7 @@
&rect "Rectangle <SPACE> "tool <NULL>
&fill "Bucket <SPACE> "fill <NULL>
( Calculates the width of the tool palette from the number of icons )
@get_tool_palette_width ( -- width* )
#00 TOOL_COUNT? #001a MUL* INC* RETURN ( width* )
( Draw a single tool icon )
@draw_tool_palette_icon ( index active? )
LITr 00 STHk* POP LITr 00 STH ( | index* active index* )
#001d CENTER_UP! /SCREEN.WIDTH? ( s_width* | index* active index* )
,get_tool_palette_width JSR ( s_width* width* | index* active index* )
SUB* HALVE* ADD2* ( zone_0_x* | index* active index* )
STHr* #001a MUL* ADD* /SCREEN.X! ( | index* active )
STHr STHkr /V.ACTIVE_TOOL? EQU ( active? current_tool? | index* )
( unchosen - inactive - active )
COL_0 COL_2 CHOOSE COL_3 CHOOSE ( colour | index* )
#0017 DUP* ;draw_capsule_smooth CALL ( | index* )
COL_T1 ;tool_icon STHr* #0048 MUL* ADD* ( colour 3x3_sprite_addr* )
( Draw the 1-bit 3x3 sprite ) ( colour sprite_addr* )
/SCREEN.ADDR! #26 /SCREEN.AUTO!
/SCREEN.SPRITE DEOk DEOk DEO
#00 /SCREEN.AUTO! #0018 MOVE_UP
RETURN
( Erase a foreground pixel, draw a background pixel, and set a canvas pixel )
@get_callback_to_commit_pixel ( colour -- callback* )
DUP ,&colour STR ,get_callback_to_set_pixel/colour STR ;&callback RETURN
@ -503,9 +642,9 @@
( Draw four boxes, with the nth box filled with colour #3 )
@draw_colour_swatch ( n active? -- )
STH* #0400 ( total i | n active? )
STH* #0400 ( total i | n active? )
&loop
DUP OVRr STHr EQU ( total i nth? | n active? )
DUP OVRr STHr EQU ( total i nth? | n active? )
STHkr COL_2 COL_3 CHOOSE ( total i nth? col | n active? )
COL_1 SWP CHOOSE ( total i col | n active? )
#0015 #0008 ;draw_capsule CALL ( total i | n active? )
@ -516,16 +655,16 @@
INC NEQk ,&loop JCN
POP* POPr* RETURN
@load_merged_palette ( ui_colour )
@load_merged_ui_palette ( ui_colour )
#03 SWP SUB MUL4 STH #0300 ( total i | sft )
&loop_colour
DUPk ADD STHk ( total i i*2 | sft i*2 )
.canvas_colour_palette ADD LDZ* ( total i channel* | sft i*2 )
OVRr STHr SFT* #000f AND* ( total i col3* | sft i*2 )
.ui_colour_palette STHkr ADD LDZ* ( total i col3* chan* | sft i*2 )
#fff0 AND* ORA* ( total i channel* | sft i*2 )
&loop
DUPk ADD STHk ( total i 2i | sft 2i )
.canvas_palette ADD LDZ* ( total i channel* | sft 2i )
OVRr STHr SFT* #000f AND* ( total i col3* | sft 2i )
.ui_palette STHkr ADD LDZ* ( total i col3* chan* | sft 2i )
#fff0 AND* ORA* ( total i channel* | sft 2i )
/SYSTEM.RED STHr ADD DEO* ( total i | sft )
INC GTHk ,&loop_colour JCN
INC GTHk ,&loop JCN
POP* POPr RETURN
@ -585,6 +724,7 @@
&8 40a0 4000 0000 0000 ( 1/16 clumps )
@sprite
&back 1830 60ff ff60 3018
&left_chevron 1030 70f0 7030 1000
&cursor 80c0 e0f0 f8e0 1000
&halftone aa55 aa55 aa55 aa55