menu.z80 7.6 KB

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