menu.z80 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487
  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. sub 3
  238. scf
  239. ret nz
  240. ; dec a
  241. ; jr z,menu_left
  242. ; dec a
  243. ; jr z,menu_right
  244. ; add a,-1 ;sets the carry flag if it is not a keypress
  245. ; ret nz
  246. ;if would select oob
  247. ; if next element exists
  248. ; increment the menutop and rerender the menu
  249. ;else
  250. ; move menuselection
  251. menu_up:
  252. or a
  253. ld bc,(menucur)
  254. dec bc
  255. push bc
  256. call menu_get_select
  257. ld (menu_temp),hl
  258. pop hl
  259. ret c
  260. ld (menucur),hl
  261. ld a,(menuselection)
  262. ld hl,(textbox_top)
  263. cp l
  264. jr z,+_
  265. ld e,a
  266. ld a,(font_height)
  267. ld d,a
  268. ld a,e
  269. sub d
  270. ld (menuselection),a
  271. scf
  272. ret
  273. _:
  274. ;now we need to scroll the textbox down FONT_HEIGHT pixels, then draw the top element
  275. ld a,11
  276. ;decrement the menutop
  277. ld hl,(menutop)
  278. dec hl
  279. jr menu_scroll
  280. menu_down:
  281. or a
  282. ld bc,(menucur)
  283. inc bc
  284. push bc
  285. call menu_get_select
  286. ld (menu_temp),hl
  287. pop hl
  288. ret c
  289. ld (menucur),hl
  290. ld a,(font_height)
  291. ld e,a
  292. ld a,(menuselection)
  293. add a,e
  294. add a,e
  295. inc a
  296. ld hl,(textbox_bottom)
  297. cp l
  298. jr nc,+_
  299. sub e
  300. dec a
  301. ld (menuselection),a
  302. scf
  303. ret
  304. _:
  305. ;now we need to scroll the textbox up FONT_HEIGHT pixels, then draw the top element
  306. ld a,10
  307. ;decrement the menutop
  308. ld hl,(menutop)
  309. inc hl
  310. menu_scroll:
  311. ld (menutop),hl
  312. push af
  313. call gettextbox
  314. ld hl,(font_height-1)
  315. pop af
  316. _:
  317. push af
  318. push bc
  319. push de
  320. push hl
  321. call drawrect
  322. pop hl
  323. pop de
  324. pop bc
  325. pop af
  326. dec h
  327. jr nz,-_
  328. ;Set the textcoord
  329. ld hl,(menuselection)
  330. inc h
  331. inc l
  332. #ifdef TEXTCOORD_YX
  333. ;need to swap the coords order
  334. ld b,l
  335. ld c,h
  336. ld (textcoord),bc
  337. #else
  338. ld (textcoord),hl
  339. #endif
  340. ld hl,(menu_temp)
  341. Text()
  342. scf
  343. ret
  344. gettextbox:
  345. ld bc,(textbox_top)
  346. ld e,b
  347. ld hl,(textbox_bottom)
  348. ld a,h
  349. sub b
  350. ld d,a
  351. ld a,l
  352. sub c
  353. ld b,a
  354. dec d
  355. dec b
  356. ret
  357. ;These change to the next menu header
  358. ; menu_left:
  359. ; ld a,(menuheader_cur)
  360. ; dec a
  361. ; jr +_
  362. ; menu_right:
  363. ; ld a,(menuheader_cur)
  364. ; inc a
  365. ; _:
  366. ; ld (menuheader_cur),a
  367. ; call reset_menu_cursor
  368. draw_header:
  369. ;Set up textcoord
  370. ld hl,(menuheader_coord)
  371. #ifndef TEXT_PAD_TOP
  372. #ifdef TEXTCOORD_YX
  373. inc h
  374. #else
  375. inc l
  376. #endif
  377. #endif
  378. ld (textcoord),hl
  379. ;Need to erase the current header area
  380. #ifdef TEXTCOORD_YX
  381. ;need to swap the coords order
  382. ld b,l
  383. ld c,h
  384. #else
  385. ld b,h
  386. ld c,l
  387. #endif
  388. #ifndef TEXT_PAD_TOP
  389. dec c
  390. #endif
  391. ld de,(textbox_bottom)
  392. ld a,d
  393. sub b
  394. ld d,a
  395. dec b
  396. ld a,(font_height)
  397. ld e,a
  398. inc e
  399. rect_Erase()
  400. ;Verify that the header element is valid, wrap if needed
  401. ld hl,(menuheader_ptr)
  402. ; ld a,(menuheader_cur)
  403. ; cp (hl)
  404. ; jr c,+_
  405. ; inc a
  406. ; jr nz,$+5
  407. ; ;cycle to the last header
  408. ; ld a,(hl)
  409. ; dec a
  410. ; .db $FE
  411. ; ;cycle to the first header
  412. ; xor a
  413. ; ld (menuheader_cur),a
  414. ; _:
  415. ;
  416. ; ;A is the header to seek
  417. ; ld bc,0 ;using CPIR, want to make sure it doesn't exit too soon!
  418. ; inc hl ;point to the first header
  419. ; or a
  420. ; jr draw_header_loopend
  421. ; draw_header_loop:
  422. ; push af
  423. ; xor a
  424. ; cpir
  425. ; pop af
  426. ; dec a
  427. ; draw_header_loopend:
  428. ; jr nz,draw_header_loop
  429. ;now draw the header
  430. Text()
  431. or a
  432. ret
  433. reset_menu_cursor:
  434. ld hl,0
  435. ld (menutop),hl
  436. ld (menucur),hl
  437. ld hl,(textbox_top)
  438. dec h
  439. ld (menuselection),hl
  440. ret