syscalls.c 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474
  1. /*
  2. * Copyright (C) 2018 Tom Li <tomli at tomli.me>.
  3. *
  4. * This software is free software; you can redistribute it and/or modify it
  5. * under the terms of the GNU Lesser General Public License as published by
  6. * the Free Software Foundation; either version 3, or (at your option) any
  7. * later version.
  8. *
  9. * This software is distributed in the hope that it will be useful, but
  10. * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
  11. * or FITNESS FOR A PARTICULAR PURPOSE.
  12. *
  13. * See COPYING for terms and conditions.
  14. *
  15. * GPL or LGPL does __not__ require attribution beyond preserving and
  16. * following the license, but if you find my code is useful or inspirational
  17. * to your own project, I'd be thankful if you attribute my name.
  18. */
  19. #include <stdint.h>
  20. #include <stdbool.h>
  21. #include <string.h>
  22. #ifndef __SYSCALLS_H
  23. #include "syscalls.h"
  24. #define __SYSCALLS_H
  25. #endif
  26. uint16_t bank1_get(void)
  27. {
  28. __asm
  29. in a, (0x06)
  30. ld l, a
  31. in a, (0x0E)
  32. ld h, a
  33. __endasm;
  34. }
  35. void bank1_swap(const uint16_t page) __z88dk_fastcall __naked
  36. {
  37. USED_IN_ASM(page);
  38. __asm
  39. ld a, l
  40. out (0x06), a
  41. ld a, h
  42. out (0x0E), a
  43. ret
  44. __endasm;
  45. }
  46. void bank1_fastswap(const uint8_t page) __z88dk_fastcall __naked
  47. {
  48. USED_IN_ASM(page);
  49. __asm
  50. ld a, l
  51. out (0x06), a
  52. ret
  53. __endasm;
  54. }
  55. uint8_t cpuclk_get(void)
  56. {
  57. __asm
  58. in a, (0x20)
  59. ld l, a
  60. __endasm;
  61. }
  62. void cpuclk_set(const uint8_t speed)
  63. {
  64. USED_IN_ASM(speed);
  65. __asm
  66. ld a, 4 (ix)
  67. out (0x20), a
  68. __endasm;
  69. }
  70. void clear_screen(void)
  71. {
  72. __asm
  73. rst 0x28
  74. .dw 0x453D
  75. __endasm;
  76. }
  77. void getkey(void)
  78. {
  79. __asm
  80. rst 0x28
  81. .dw 0x495D
  82. __endasm;
  83. }
  84. int putchar(int c)
  85. {
  86. USED_IN_ASM(c);
  87. __asm
  88. ld a, 4 (ix)
  89. cp a, #10
  90. jr nz, putchr
  91. rst 0x28
  92. .dw 0x4525
  93. jp putchar_retn
  94. putchr:
  95. rst 0x28
  96. .dw 0x44FB
  97. putchar_retn:
  98. __endasm;
  99. return c;
  100. }
  101. void disphl(uint8_t row, uint8_t col, const uint16_t i)
  102. {
  103. cursor_row = row;
  104. cursor_col = col;
  105. USED_IN_ASM(i);
  106. __asm
  107. ld l, 6 (ix)
  108. ld h, 7 (ix)
  109. rst 0x28
  110. .dw 0x44FE
  111. __endasm;
  112. }
  113. void fillrect(uint16_t x1, uint16_t x2, uint8_t y1, uint8_t y2)
  114. {
  115. USED_IN_ASM(x1);
  116. USED_IN_ASM(x2);
  117. USED_IN_ASM(y1);
  118. USED_IN_ASM(y2);
  119. __asm
  120. ld l, 4 (ix)
  121. ld h, 5 (ix)
  122. ld e, 6 (ix)
  123. ld d, 7 (ix)
  124. ld b, 8 (ix)
  125. ld c, 9 (ix)
  126. rst 0x28
  127. .dw 0x4D4A
  128. __endasm;
  129. }
  130. const bool findsym(const uint8_t type, const unsigned char *name, uint16_t *page, uint16_t *addr)
  131. {
  132. unsigned char op[9];
  133. if (strlen(name) > 7) {
  134. goto not_found;
  135. }
  136. op[0] = type;
  137. strncpy(&op[1], name, 8);
  138. op[8] = '\0';
  139. USED_IN_ASM(page);
  140. USED_IN_ASM(addr);
  141. __asm
  142. ld hl, #0
  143. add hl, sp
  144. rst 0x28
  145. .dw 0x4177
  146. rst 0x28
  147. .dw 0x42E8
  148. jr c, 2$ /* not found */
  149. jp 1$ /* found */
  150. 1$: /* found */
  151. /* page */
  152. ld a, b
  153. ld c, 7 (ix)
  154. ld b, 8 (ix)
  155. ld (bc), a
  156. inc bc
  157. ld a, #0
  158. ld (bc), a
  159. /* addr */
  160. ld c, 9 (ix)
  161. ld b, 10 (ix)
  162. ld a, e
  163. ld (bc), a
  164. inc bc
  165. ld a, d
  166. ld (bc), a
  167. __endasm;
  168. *addr -= 0x4000; /* remove base addr */
  169. /* See "Variable Storage in the User Archive" @ WikiTI */
  170. *addr += 9; /* metadata */
  171. *addr += 8; /* variable name */
  172. *addr += 2; /* size word */
  173. __asm
  174. ld l, #0
  175. jp 3$ /* return */
  176. __endasm;
  177. not_found:
  178. __asm
  179. 2$: /* not_found */
  180. ld l, #1
  181. 3$: /* return */
  182. __endasm;
  183. }
  184. const bool findapp(const unsigned char *name, uint16_t *page, uint16_t *addr)
  185. {
  186. uint16_t current_page = 0xFF63;
  187. uint16_t orig_page = bank1_get();
  188. uint8_t len = strlen(name);
  189. while (current_page != 0x00) {
  190. bank1_swap(current_page);
  191. if (bank1[0] != 0x80) {
  192. current_page--;
  193. goto next;
  194. }
  195. uint8_t *app_pages = NULL;
  196. uint8_t *app_name = NULL;
  197. uint8_t app_begin = 0;
  198. for (uint8_t idx = 1; idx < 40; idx++) {
  199. if (bank1[idx] != 0x80) {
  200. continue;
  201. }
  202. if (bank1[idx + 1] == 0x81) {
  203. app_pages = &bank1[idx + 2];
  204. }
  205. if (bank1[idx + 1] == 0x40 + len) {
  206. app_name = &bank1[idx + 2];
  207. }
  208. if (bank1[idx + 1] == 0x70) {
  209. app_begin = idx + 2;
  210. }
  211. }
  212. if (app_pages == NULL || app_name == NULL || app_begin == 0) {
  213. current_page--;
  214. goto next;
  215. }
  216. if (memcmp(name, app_name, len) == 0) {
  217. *page = current_page;
  218. *addr = app_begin;
  219. bank1_swap(orig_page);
  220. return 0;
  221. }
  222. else {
  223. current_page -= *app_pages;
  224. }
  225. next:
  226. if (current_page == 0xFF00 - 1) {
  227. current_page = 0x007F;
  228. }
  229. }
  230. /* TODO: determine the last application page, and abort early. */
  231. bank1_swap(orig_page);
  232. return 1;
  233. }
  234. /*
  235. * DCSE routines
  236. */
  237. void clear_lcd(void)
  238. {
  239. __asm
  240. call 0x402A
  241. __endasm;
  242. }
  243. void drawsprite_1bit(uint16_t x, uint16_t y, uint8_t *palette, uint8_t *sprite)
  244. {
  245. USED_IN_ASM(x);
  246. USED_IN_ASM(y);
  247. USED_IN_ASM(sprite);
  248. uint16_t addr = (uint16_t) palette;
  249. sprite[0] = addr & 0xFFU;
  250. sprite[1] = (addr >> 8) & 0xFFU;
  251. __asm
  252. ld e, 4 (ix)
  253. ld d, 5 (ix)
  254. ld l, 6 (ix)
  255. ld h, 7 (ix)
  256. ld c, 10 (ix)
  257. ld b, 11 (ix)
  258. push bc
  259. pop ix
  260. call 0x4036
  261. __endasm;
  262. }
  263. void drawsprite_8bit(uint16_t x, uint16_t y, uint8_t *palette, uint8_t *sprite)
  264. {
  265. USED_IN_ASM(x);
  266. USED_IN_ASM(y);
  267. USED_IN_ASM(sprite);
  268. if (palette != NULL) {
  269. uint16_t addr = (uint16_t) palette;
  270. sprite[0] = addr & 0xFFU;
  271. sprite[1] = (addr >> 8) & 0xFFU;
  272. }
  273. else {
  274. sprite[0] = 0x00;
  275. sprite[1] = 0x00;
  276. }
  277. __asm
  278. ld e, 4 (ix)
  279. ld d, 5 (ix)
  280. ld l, 6 (ix)
  281. ld h, 7 (ix)
  282. ld c, 10 (ix)
  283. ld b, 11 (ix)
  284. push bc
  285. pop ix
  286. call 0x4042
  287. __endasm;
  288. }
  289. /*
  290. * The following code is obtained from
  291. * https://github.com/faithanalog/wiki/blob/master/ti84cse/HalfRes.md
  292. *
  293. * Thanks for Unknown Loner's detailed tutorial and documentation!
  294. *
  295. * The MIT License (MIT)
  296. *
  297. * Copyright (c) 2014 Unknown Loner
  298. *
  299. * Permission is hereby granted, free of charge, to any person obtaining a copy
  300. * of this software and associated documentation files (the "Software"), to deal
  301. * in the Software without restriction, including without limitation the rights
  302. * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  303. * copies of the Software, and to permit persons to whom the Software is
  304. * furnished to do so, subject to the following conditions:
  305. *
  306. * The above copyright notice and this permission notice shall be included in all
  307. * copies or substantial portions of the Software.
  308. */
  309. void lcd_halfres(void)
  310. {
  311. __asm
  312. ld a, #0x01
  313. out (0x10), a
  314. out (0x10), a
  315. ld a, #0x04
  316. out (0x11), a
  317. xor a
  318. out (0x11), a
  319. ld a, #0x07
  320. out (0x10), a
  321. out (0x10), a
  322. ld a, #0x30
  323. out (0x11), a
  324. ld a, #0x33
  325. out (0x11), a
  326. ld a, #0x80
  327. out (0x10), a
  328. out (0x10), a
  329. xor a
  330. out (0x11), a
  331. out (0x11), a
  332. ld a, #0x83
  333. out (0x10), a
  334. out (0x10), a
  335. xor a
  336. out (0x11), a
  337. ld a, #160
  338. out (0x11), a
  339. ld c, #0x11
  340. ld a, #0x81
  341. out (0x10), a
  342. out (0x10), a
  343. xor a
  344. out (0x11), a
  345. out (0x11), a
  346. ld a, #0x84
  347. out (0x10), a
  348. out (0x10), a
  349. xor a
  350. out (0x11), a
  351. out (0x11), a
  352. ld de, #159
  353. ld a, #0x82
  354. out (0x10), a
  355. out (0x10), a
  356. out (c), d
  357. out (c), e
  358. ld a, #0x85
  359. out (0x10), a
  360. out (0x10), a
  361. out (c), d
  362. out (c), e
  363. __endasm;
  364. }
  365. void lcd_fullres(void)
  366. {
  367. __asm
  368. ld a, #0x01
  369. out (0x10), a
  370. out (0x10), a
  371. xor a
  372. out (0x11), a
  373. out (0x11), a
  374. ld a, #0x07
  375. out (0x10), a
  376. out (0x10), a
  377. ld a, #0x01
  378. out (0x11), a
  379. ld a, #0x33
  380. out (0x11), a
  381. __endasm;
  382. }