menu.z80 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476
  1. #define Text() call p1_PutTokenText
  2. font_height = tempword5
  3. ;#define TEXT_PAD_TOP ;comment if there is not a row of padding above the text
  4. ;#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)
  5. textcoord = textRow
  6. #macro LCD_Update()
  7. di
  8. call p1_GraphToLCD
  9. #endmacro
  10. #macro rect_OR()
  11. ;Draw a black rectangle
  12. ld a,b
  13. ld b,e
  14. ld e,a
  15. ld a,1
  16. call drawrect
  17. #endmacro
  18. #macro rect_XOR()
  19. ;Draw an inverted rectangle
  20. ld a,b
  21. ld b,e
  22. ld e,a
  23. ld a,2
  24. call drawrect
  25. #endmacro
  26. #macro rect_Erase()
  27. ;Draw a white rectangle
  28. ld a,b
  29. ld b,e
  30. ld e,a
  31. xor a
  32. call drawrect
  33. #endmacro
  34. menuroutine:
  35. ;Input:
  36. ; (B,C) = (x,y)
  37. ; (D,E) = (width,height)
  38. ; HL points to the header
  39. ; IX points to the get/select code
  40. ; If you are using the TI-OS VPutS routine, you'll need to have the textWrite flag set in sGrFlags
  41. ; (font_height) is the height of the font
  42. ; (menu_header_get) points to a routine that fetches the menu header.
  43. ;Notes:
  44. ; The header is set up as follows:
  45. ; .db number_of_titles
  46. ; .db "title 0",0
  47. ; .db "title 1",0
  48. ; .db "title 2",0
  49. ; ...
  50. ;
  51. ; The get/select code is passed the following information:
  52. ; A is the index of the current title (0 is the first, 1 is the second, etc.)
  53. ; BC is the index of the currently highlighted item
  54. ; carry flag is reset if it needs to return a pointer to the string for the element
  55. ; Return carry flag as set if the element is out-of-bounds.
  56. ; carry flag is set if it needs to return a pointer to the data for the element
  57. ld (menucallptr),ix
  58. ;save box dimensions
  59. push bc
  60. ;Save the pointer to the menu headers field
  61. ld (menuheader_ptr),hl
  62. ;Set the menu header to header 0
  63. xor a
  64. ld (menuheader_cur),a
  65. ;establish the bottom and right edges of the textbox
  66. ld a,c
  67. add a,e
  68. ld (textbox_bottom),a
  69. ld a,b
  70. add a,d
  71. ld (textbox_right),a
  72. ; Draw the rectangle for the menu. Black border, white fill.
  73. rect_OR()
  74. ; Display the header
  75. ; get coords
  76. pop hl
  77. inc h
  78. inc h
  79. inc l
  80. push hl
  81. #ifdef TEXTCOORD_YX
  82. ;need to swap the coords order
  83. ld a,h
  84. ld h,l
  85. ld l,a
  86. #endif
  87. ld (menuheader_coord),hl
  88. call draw_header
  89. pop bc
  90. ;Before we do too much, let's establish the top-left textbox boundaries.
  91. ld a,(font_height)
  92. add a,2
  93. add a,c
  94. ld c,a
  95. ld (textbox_top),bc
  96. ld hl,(menutopinit)
  97. ld (menutop),hl
  98. ex de,hl
  99. ld hl,(menudefault)
  100. ld (menucur),hl
  101. ;need to set menu selection to:
  102. ; (textbox_top-1)+(menucur-menutop)*fontheight
  103. ; =(textbox_top-1)+(HL-DE)*fontheight
  104. ; or a
  105. sbc hl,de
  106. ld a,l
  107. add a,a
  108. add a,l
  109. add a,a
  110. ld hl,(textbox_top)
  111. dec h
  112. add a,l
  113. ld l,a
  114. ld (menuselection),hl
  115. ;===============================================================================
  116. ; Now we have drawn the menu box, we have to populate it.
  117. ; We'll call a routine to get the n-th string to be displayed.
  118. ; Stop fetching once the next item would go at or past textbox_bottom.
  119. ; Draw at least one item.
  120. menu_render:
  121. ;Restore the text coordinates top
  122. ld hl,(textbox_top)
  123. #ifndef TEXT_PAD_TOP
  124. inc l
  125. #endif
  126. #ifdef TEXTCOORD_YX
  127. ;need to swap the coords order
  128. ld a,h
  129. ld h,l
  130. ld l,a
  131. #endif
  132. ld (textcoord),hl
  133. ;rerender the items
  134. call menu_render_sub
  135. menu_render_0:
  136. ;highlight the current option
  137. ld bc,(menuselection)
  138. ld hl,(textbox_bottom)
  139. ld a,h
  140. sub b
  141. ld d,a
  142. ld a,(font_height)
  143. ld e,a
  144. inc e
  145. dec d
  146. push de
  147. push bc
  148. rect_XOR()
  149. LCD_Update()
  150. pop bc
  151. pop de
  152. rect_XOR()
  153. ;wait for a keypress
  154. _:
  155. in a,(4)
  156. and 8
  157. jr z,menu_get_select_err
  158. call p1_getKeyDebounce
  159. or a
  160. jr z,-_
  161. cp 9
  162. scf
  163. jr z,menu_get_select
  164. cp 15
  165. jr z,menu_get_select_err
  166. call menu_arrow
  167. jr c,menu_render_0
  168. jr menu_render
  169. menu_get_select:
  170. ld hl,(menucallptr)
  171. ld a,(menuheader_cur)
  172. jp (hl)
  173. menu_render_sub:
  174. ; need to clear out the textbox
  175. ld bc,(textbox_top)
  176. ld hl,(textbox_bottom)
  177. ld a,h
  178. sub b
  179. ld d,a
  180. ld a,l
  181. sub c
  182. ld e,a
  183. dec e
  184. dec b
  185. rect_Erase()
  186. xor a
  187. ld bc,(menutop)
  188. menu_render_sub_loop:
  189. push bc
  190. call menu_get_select
  191. pop bc
  192. ret c
  193. ld de,(textcoord)
  194. push bc
  195. push de
  196. Text()
  197. pop de
  198. ld a,(font_height)
  199. ld c,a
  200. #ifdef TEXTCOORD_YX
  201. add a,d
  202. ld d,a
  203. ld a,(textbox_bottom)
  204. sub c
  205. #ifdef TEXT_PAD_TOP
  206. sub 2
  207. #else
  208. dec a
  209. #endif
  210. cp d
  211. #else
  212. add a,e
  213. ld e,a
  214. ld a,(textbox_bottom)
  215. sub c
  216. #ifdef TEXT_PAD_TOP
  217. sub d
  218. #else
  219. dec a
  220. #endif
  221. cp e
  222. #endif
  223. ld (textcoord),de
  224. pop bc
  225. inc bc
  226. jr nc,menu_render_sub_loop
  227. ret
  228. menu_get_select_err:
  229. ;return a null pointer.
  230. ;A=0, HL=0
  231. xor a
  232. ld b,a
  233. ld c,a
  234. ret
  235. menu_arrow:
  236. ;check arrow keys
  237. dec a
  238. jr z,menu_down
  239. dec a
  240. jp z,menu_left
  241. dec a
  242. jp z,menu_right
  243. add a,-1 ;sets the carry flag if it is not a keypress
  244. ret nz
  245. ;if would select oob
  246. ; if next element exists
  247. ; increment the menutop and rerender the menu
  248. ;else
  249. ; move menuselection
  250. menu_up:
  251. or a
  252. ld bc,(menucur)
  253. dec bc
  254. push bc
  255. call menu_get_select
  256. ld (menu_temp),hl
  257. pop hl
  258. ret c
  259. ld (menucur),hl
  260. ld a,(menuselection)
  261. ld hl,(textbox_top)
  262. cp l
  263. jr z,+_
  264. ld e,a
  265. ld a,(font_height)
  266. ld d,a
  267. ld a,e
  268. sub d
  269. ld (menuselection),a
  270. scf
  271. ret
  272. _:
  273. ;now we need to scroll the textbox down FONT_HEIGHT pixels, then draw the top element
  274. ld a,11
  275. ;decrement the menutop
  276. ld hl,(menutop)
  277. dec hl
  278. jr menu_scroll
  279. menu_down:
  280. or a
  281. ld bc,(menucur)
  282. inc bc
  283. push bc
  284. call menu_get_select
  285. ld (menu_temp),hl
  286. pop hl
  287. ret c
  288. ld (menucur),hl
  289. ld a,(font_height)
  290. ld e,a
  291. ld a,(menuselection)
  292. add a,e
  293. add a,e
  294. inc a
  295. ld hl,(textbox_bottom)
  296. cp l
  297. jr nc,+_
  298. sub e
  299. dec a
  300. ld (menuselection),a
  301. scf
  302. ret
  303. _:
  304. ;now we need to scroll the textbox up FONT_HEIGHT pixels, then draw the top element
  305. ld a,10
  306. ;decrement the menutop
  307. ld hl,(menutop)
  308. inc hl
  309. menu_scroll:
  310. ld (menutop),hl
  311. push af
  312. call gettextbox
  313. ld hl,(font_height-1)
  314. pop af
  315. _:
  316. push af
  317. push bc
  318. push de
  319. push hl
  320. call drawrect
  321. pop hl
  322. pop de
  323. pop bc
  324. pop af
  325. dec h
  326. jr nz,-_
  327. ;Set the textcoord
  328. ld hl,(menuselection)
  329. inc h
  330. inc l
  331. #ifdef TEXTCOORD_YX
  332. ;need to swap the coords order
  333. ld b,l
  334. ld c,h
  335. ld (textcoord),bc
  336. #else
  337. ld (textcoord),hl
  338. #endif
  339. ld hl,(menu_temp)
  340. Text()
  341. scf
  342. ret
  343. gettextbox:
  344. ld bc,(textbox_top)
  345. ld e,b
  346. ld hl,(textbox_bottom)
  347. ld a,h
  348. sub b
  349. ld d,a
  350. ld a,l
  351. sub c
  352. ld b,a
  353. dec d
  354. dec b
  355. ret
  356. ;These change to the next menu header
  357. menu_left:
  358. ld a,(menuheader_cur)
  359. dec a
  360. ld hl,(menu_header_get)
  361. call p1_call_hl
  362. ret z
  363. ld a,(menuheader_cur)
  364. dec a
  365. jr +_
  366. menu_right:
  367. ld a,(menuheader_cur)
  368. inc a
  369. ld hl,(menu_header_get)
  370. call p1_call_hl
  371. ret z
  372. ld a,(menuheader_cur)
  373. inc a
  374. _:
  375. ld (menuheader_cur),a
  376. call reset_menu_cursor
  377. draw_header:
  378. ;Set up textcoord
  379. ld hl,(menuheader_coord)
  380. #ifndef TEXT_PAD_TOP
  381. #ifdef TEXTCOORD_YX
  382. inc h
  383. #else
  384. inc l
  385. #endif
  386. #endif
  387. ld (textcoord),hl
  388. ;Need to erase the current header area
  389. #ifdef TEXTCOORD_YX
  390. ;need to swap the coords order
  391. ld b,l
  392. ld c,h
  393. #else
  394. ld b,h
  395. ld c,l
  396. #endif
  397. #ifndef TEXT_PAD_TOP
  398. dec c
  399. #endif
  400. ld de,(textbox_bottom)
  401. ld a,d
  402. sub b
  403. ld d,a
  404. dec b
  405. ld a,(font_height)
  406. ld e,a
  407. inc e
  408. rect_Erase()
  409. ;Verify that the header element is valid, wrap if needed
  410. ld a,(menuheader_cur)
  411. ld hl,(menu_header_get)
  412. call p1_call_hl
  413. ;now draw the header
  414. Text()
  415. or a
  416. ret
  417. menu_header_getter:
  418. ld hl,(menuheader_ptr)
  419. xor a
  420. ret
  421. reset_menu_cursor:
  422. ld hl,0
  423. ld (menutop),hl
  424. ld (menucur),hl
  425. ld hl,(textbox_top)
  426. dec h
  427. ld (menuselection),hl
  428. ret