menu.z80 7.3 KB

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