#define Text() call p1_PutTokenText font_height = tempword5 ;#define TEXT_PAD_TOP ;comment if there is not a row of padding above the text ;#define TEXTCOORD_YX ;define if textcoord is Y then X (TI-OS is Y then X for small font, large font and some custom text routines use the opposite) textcoord = textRow #macro LCD_Update() di call p1_GraphToLCD #endmacro #macro rect_OR() ;Draw a black rectangle ld a,b ld b,e ld e,a ld a,1 call drawrect #endmacro #macro rect_XOR() ;Draw an inverted rectangle ld a,b ld b,e ld e,a ld a,2 call drawrect #endmacro #macro rect_Erase() ;Draw a white rectangle ld a,b ld b,e ld e,a xor a call drawrect #endmacro menuroutine: ;Input: ; (B,C) = (x,y) ; (D,E) = (width,height) ; HL points to the header ; IX points to the get/select code ; If you are using the TI-OS VPutS routine, you'll need to have the textWrite flag set in sGrFlags ;Notes: ; The header is set up as follows: ; .db number_of_titles ; .db "title 0",0 ; .db "title 1",0 ; .db "title 2",0 ; ... ; ; The get/select code is passed the following information: ; A is the index of the current title (0 is the first, 1 is the second, etc.) ; BC is the index of the currently highlighted item ; carry flag is reset if it needs to return a pointer to the string for the element ; Return carry flag as set if the element is out-of-bounds. ; carry flag is set if it needs to return a pointer to the data for the element ld (menucallptr),ix ;save box dimensions push bc ;Save the pointer to the menu headers field ld (menuheader_ptr),hl ;Set the menu header to header 0 xor a ld (menuheader_cur),a ;establish the bottom and right edges of the textbox ld a,c add a,e ld (textbox_bottom),a ld a,b add a,d ld (textbox_right),a ; Draw the rectangle for the menu. Black border, white fill. rect_OR() ; Display the header ; get coords pop hl inc h inc h inc l push hl #ifdef TEXTCOORD_YX ;need to swap the coords order ld a,h ld h,l ld l,a #endif ld (menuheader_coord),hl call draw_header pop bc ;Before we do too much, let's establish the top-left textbox boundaries. ld a,(font_height) add a,2 add a,c ld c,a ld (textbox_top),bc ld hl,(menutopinit) ld (menutop),hl ex de,hl ld hl,(menudefault) ld (menucur),hl ;need to set menu selection to: ; (textbox_top-1)+(menucur-menutop)*fontheight ; =(textbox_top-1)+(HL-DE)*fontheight ; or a sbc hl,de ld a,l add a,a add a,l add a,a ld hl,(textbox_top) dec h add a,l ld l,a ld (menuselection),hl ;=============================================================================== ; Now we have drawn the menu box, we have to populate it. ; We'll call a routine to get the n-th string to be displayed. ; Stop fetching once the next item would go at or past textbox_bottom. ; Draw at least one item. menu_render: ;Restore the text coordinates top ld hl,(textbox_top) #ifndef TEXT_PAD_TOP inc l #endif #ifdef TEXTCOORD_YX ;need to swap the coords order ld a,h ld h,l ld l,a #endif ld (textcoord),hl ;rerender the items call menu_render_sub menu_render_0: ;highlight the current option ld bc,(menuselection) ld hl,(textbox_bottom) ld a,h sub b ld d,a ld a,(font_height) ld e,a inc e dec d push de push bc rect_XOR() LCD_Update() pop bc pop de rect_XOR() ;wait for a keypress _: in a,(4) and 8 jr z,menu_get_select_err call p1_getKeyDebounce or a jr z,-_ cp 9 scf jr z,menu_get_select cp 15 jr z,menu_get_select_err call menu_arrow jr c,menu_render_0 jr menu_render menu_get_select: ld hl,(menucallptr) ld a,(menuheader_cur) jp (hl) menu_render_sub: ; need to clear out the textbox ld bc,(textbox_top) ld hl,(textbox_bottom) ld a,h sub b ld d,a ld a,l sub c ld e,a dec e dec b rect_Erase() xor a ld bc,(menutop) menu_render_sub_loop: push bc call menu_get_select pop bc ret c ld de,(textcoord) push bc push de Text() pop de ld a,(font_height) ld c,a #ifdef TEXTCOORD_YX add a,d ld d,a ld a,(textbox_bottom) sub c #ifdef TEXT_PAD_TOP sub 2 #else dec a #endif cp d #else add a,e ld e,a ld a,(textbox_bottom) sub c #ifdef TEXT_PAD_TOP sub d #else dec a #endif cp e #endif ld (textcoord),de pop bc inc bc jr nc,menu_render_sub_loop ret menu_get_select_err: ;return a null pointer. ;A=0, HL=0 xor a ld b,a ld c,a ret menu_arrow: ;check arrow keys dec a jr z,menu_down dec a jp z,menu_left dec a jp z,menu_right add a,-1 ;sets the carry flag if it is not a keypress ret nz ;if would select oob ; if next element exists ; increment the menutop and rerender the menu ;else ; move menuselection menu_up: or a ld bc,(menucur) dec bc push bc call menu_get_select ld (menu_temp),hl pop hl ret c ld (menucur),hl ld a,(menuselection) ld hl,(textbox_top) cp l jr z,+_ ld e,a ld a,(font_height) ld d,a ld a,e sub d ld (menuselection),a scf ret _: ;now we need to scroll the textbox down FONT_HEIGHT pixels, then draw the top element ld a,11 ;decrement the menutop ld hl,(menutop) dec hl jr menu_scroll menu_down: or a ld bc,(menucur) inc bc push bc call menu_get_select ld (menu_temp),hl pop hl ret c ld (menucur),hl ld a,(font_height) ld e,a ld a,(menuselection) add a,e add a,e inc a ld hl,(textbox_bottom) cp l jr nc,+_ sub e dec a ld (menuselection),a scf ret _: ;now we need to scroll the textbox up FONT_HEIGHT pixels, then draw the top element ld a,10 ;decrement the menutop ld hl,(menutop) inc hl menu_scroll: ld (menutop),hl push af call gettextbox ld hl,(font_height-1) pop af _: push af push bc push de push hl call drawrect pop hl pop de pop bc pop af dec h jr nz,-_ ;Set the textcoord ld hl,(menuselection) inc h inc l #ifdef TEXTCOORD_YX ;need to swap the coords order ld b,l ld c,h ld (textcoord),bc #else ld (textcoord),hl #endif ld hl,(menu_temp) Text() scf ret gettextbox: ld bc,(textbox_top) ld e,b ld hl,(textbox_bottom) ld a,h sub b ld d,a ld a,l sub c ld b,a dec d dec b ret ;These change to the next menu header menu_left: ld a,(menuheader_cur) dec a ld hl,(menu_header_get) call p1_call_hl ret z ld a,(menuheader_cur) dec a jr +_ menu_right: ld a,(menuheader_cur) inc a ld hl,(menu_header_get) call p1_call_hl ret z ld a,(menuheader_cur) inc a _: ld (menuheader_cur),a call reset_menu_cursor draw_header: ;Set up textcoord ld hl,(menuheader_coord) #ifndef TEXT_PAD_TOP #ifdef TEXTCOORD_YX inc h #else inc l #endif #endif ld (textcoord),hl ;Need to erase the current header area #ifdef TEXTCOORD_YX ;need to swap the coords order ld b,l ld c,h #else ld b,h ld c,l #endif #ifndef TEXT_PAD_TOP dec c #endif ld de,(textbox_bottom) ld a,d sub b ld d,a dec b ld a,(font_height) ld e,a inc e rect_Erase() ;Verify that the header element is valid, wrap if needed ld a,(menuheader_cur) ld hl,(menu_header_get) call p1_call_hl ;now draw the header Text() or a ret menu_header_getter: ld hl,(menuheader_ptr) xor a ret reset_menu_cursor: ld hl,0 ld (menutop),hl ld (menucur),hl ld hl,(textbox_top) dec h ld (menuselection),hl ret