; IN - HL - pointer to menu menu_init: ld bc, MENU_T ; copy menu descriptor from (hl) to (var_menu) ld de, var_menu ; ... ldir ; ... xor a ld (var_menu_current_item), a ld (var_menu_animate_cnt), a ld ix, var_menu ld b, (ix+MENU_T.y_row) ld c, (ix+MENU_T.x) ld d, (ix+MENU_T.height) ld e, (ix+MENU_T.width) call draw_box ld ix, var_menu ld hl, str_sizif ld b, (ix+MENU_T.y_pixel) ld c, (ix+MENU_T.x) call print_string ld ix, var_menu ld b, (ix+MENU_T.y_pixel) ld c, (ix+MENU_T.x_logo) ld e, 0 call draw_logo call menu_draw_menu xor a ld d, MENU_SELECT_ATTR call menu_draw_selected_item ret menu_process: ;call menu_animate_logo ;call menu_handle_updown ;call menu_handle_action_left_right menu_animate_logo: ld a, (var_menu_animate_cnt) ; inc a ; cnt++ (only cnt[7:5] used as color offset) cp #a0 ; if (cnt[7:5] == 5) cnt = 0 - because valid offsets 0..4 jr nz, .animate ; ... xor a ; ... .animate: ; ld (var_menu_animate_cnt), a ; and a, #1F ; if (cnt[7:5] was not changed) - exit jr nz, .return ; ... ld a, (var_menu_animate_cnt) ; srl a ; cnt[7:5] -> cnt[2:0] srl a ; ... srl a ; ... srl a ; ... srl a ; ... ld e, a ; reverse animation direction (from left to right) ld a, 4 ; ... sub e ; ... ld e, a ; ... ld ix, var_menu ; ld b, (ix+MENU_T.y_pixel) ; draw logo ld c, (ix+MENU_T.x_logo) ; ... call draw_logo ; ... .return: ; ret ; pass to menu_handle_updown ; OUT - A - pressed key ; OUT - BC - garbage ; OUT - DE - garbage ; OUT - HL - garbage ; OUT - IX - garbage menu_handle_updown: ld ix, var_menu call input_key_get ; A = current_pressed_key .down: ; bit 2, a ; down? jr z, .up ; ... ld a, (var_menu_current_item) ; ld d, MENU_BODY_ATTR ; fill selected item with background color call menu_draw_selected_item ; ... inc a ; current_item++ cp a, (ix+MENU_T.items) ; if (current_item == max) current_item = 0 jr nz, .return_save ; ... ld a, 0 ; ... jr .return_save ; .up: ; bit 3, a ; up? jr z, .return ; ... ld a, (var_menu_current_item) ; ld d, MENU_BODY_ATTR ; fill selected item with background color call menu_draw_selected_item ; ... or a ; if (current_item == 0) current_item = max jr nz, .up_decrement ; ... ld a, (ix+MENU_T.items) .up_decrement ; ... dec a ; current_item-- .return_save: ; ld (var_menu_current_item), a ; ... ld d, MENU_SELECT_ATTR ; highlight selected item call menu_draw_selected_item ; ... xor a .return: ;ret ; pass to menu_handle_action_left_right ; IN - A - pressed key ; OUT - D - pressed key ; OUT - AF - garbage ; OUT - BC - garbage ; OUT - HL - garbage ; OUT - IX - garbage menu_handle_action_left_right: ld d, a and #13 ; action/left/right? jr z, .return ld ix, var_menu ; IX = &menu ld c, (ix+MENU_T.addr+0) ; IX = &menu_entry ld b, (ix+MENU_T.addr+1) ; ... ld ixl, c ; ... ld ixh, b ; ... ld a, (var_menu_current_item) ; A = selected item index sla a ; A*8 (one menu entry - 8 bytes) sla a ; ... sla a ; ... ld c, a ; IX = &menu_entry[index].callback ld b, 0 ; ... add ix, bc ; ... ld l, (ix+MENUENTRY_T.callback+0) ; HL = menu_entry[index].callback ld h, (ix+MENUENTRY_T.callback+1) ; ... ld a, h ; if (HL == 0) - exit or l ; ... jr z, .return ; ... call .callback ; call menu[index].callback(), D is pressed key call menu_draw_menu ; update menu if something changed .return: ret .callback: jp (hl) ; AF, BC, HL, IX may be changed ; IN - A - selected menu item number ; IN - D - attribute ; OUT - BC - garbage ; OUT - E - garbage ; OUT - HL - garbage ; OUT - IX - garbage menu_draw_selected_item: push af ld ix, var_menu ld b, (ix+MENU_T.y_row) inc b add b ld b, a ld c, (ix+MENU_T.x) ld e, (ix+MENU_T.width) call draw_attribute_line pop af ret menu_draw_menu: ld ix, var_menu ld a, (ix+MENU_T.y_pixel) add a, 8 ld b, a ld c, (ix+MENU_T.x) inc c ld e, (ix+MENU_T.width) ld l, (ix+MENU_T.addr+0) ld h, (ix+MENU_T.addr+1) call draw_menu ret ;var_menu_current_item: DB 0 ;var_menu_animate_cnt: DB 0