1 | // MIT License |
2 | |
3 | // Copyright (c) 2017 Vadim Grigoruk @nesbox // grigoruk@gmail.com |
4 | |
5 | // Permission is hereby granted, free of charge, to any person obtaining a copy |
6 | // of this software and associated documentation files (the "Software"), to deal |
7 | // in the Software without restriction, including without limitation the rights |
8 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
9 | // copies of the Software, and to permit persons to whom the Software is |
10 | // furnished to do so, subject to the following conditions: |
11 | |
12 | // The above copyright notice and this permission notice shall be included in all |
13 | // copies or substantial portions of the Software. |
14 | |
15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
16 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
17 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
18 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
19 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
20 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE |
21 | // SOFTWARE. |
22 | |
23 | #pragma once |
24 | |
25 | #include "retro_endianness.h" |
26 | #include "tic.h" |
27 | #include "time.h" |
28 | |
29 | // convenience macros to loop languages |
30 | #define FOR_EACH_LANG(ln) for (tic_script_config** conf = Languages ; *conf != NULL; conf++ ) { tic_script_config* ln = *conf; |
31 | #define FOR_EACH_LANG_END } |
32 | |
33 | |
34 | typedef struct { u8 index; tic_flip flip; tic_rotate rotate; } RemapResult; |
35 | typedef void(*RemapFunc)(void*, s32 x, s32 y, RemapResult* result); |
36 | |
37 | typedef void(*TraceOutput)(void*, const char*, u8 color); |
38 | typedef void(*ErrorOutput)(void*, const char*); |
39 | typedef void(*ExitCallback)(void*); |
40 | |
41 | typedef struct |
42 | { |
43 | TraceOutput trace; |
44 | ErrorOutput error; |
45 | ExitCallback exit; |
46 | |
47 | clock_t start; |
48 | |
49 | void* data; |
50 | } tic_tick_data; |
51 | |
52 | typedef struct tic_mem tic_mem; |
53 | typedef void(*tic_tick)(tic_mem* memory); |
54 | typedef void(*tic_boot)(tic_mem* memory); |
55 | typedef void(*tic_scanline)(tic_mem* memory, s32 row, void* data); |
56 | typedef void(*tic_border)(tic_mem* memory, s32 row, void* data); |
57 | typedef void(*)(tic_mem* memory, s32 index, void* data); |
58 | |
59 | typedef struct |
60 | { |
61 | const char* pos; |
62 | s32 size; |
63 | } tic_outline_item; |
64 | |
65 | typedef struct |
66 | { |
67 | tic_scanline scanline; |
68 | tic_border border; |
69 | tic_gamemenu ; |
70 | void* data; |
71 | } tic_blit_callback; |
72 | |
73 | typedef struct |
74 | { |
75 | u8 id; |
76 | const char* name; |
77 | const char* fileExtension; |
78 | const char* ; |
79 | struct |
80 | { |
81 | bool(*init)(tic_mem* memory, const char* code); |
82 | void(*close)(tic_mem* memory); |
83 | |
84 | tic_tick tick; |
85 | tic_boot boot; |
86 | tic_blit_callback callback; |
87 | }; |
88 | |
89 | const tic_outline_item* (*getOutline)(const char* code, s32* size); |
90 | void (*eval)(tic_mem* tic, const char* code); |
91 | |
92 | const char* ; |
93 | const char* ; |
94 | const char* ; |
95 | const char* ; |
96 | const char* blockStringStart; |
97 | const char* blockStringEnd; |
98 | const char* ; |
99 | const char* blockEnd; |
100 | |
101 | const char* const * keywords; |
102 | s32 keywordsCount; |
103 | } tic_script_config; |
104 | |
105 | extern tic_script_config* Languages[]; |
106 | |
107 | typedef enum |
108 | { |
109 | tic_tiles_texture, |
110 | tic_map_texture, |
111 | tic_vbank_texture, |
112 | } tic_texture_src; |
113 | |
114 | typedef struct |
115 | { |
116 | s32 x, y; |
117 | } tic_point; |
118 | |
119 | typedef struct |
120 | { |
121 | s32 x, y, w, h; |
122 | } tic_rect; |
123 | |
124 | // SYNC DEFINITION TABLE |
125 | // .--------------------------------- - - - |
126 | // | CART | RAM | INDEX |
127 | // |---------+---------------+------- - - - |
128 | // | | | |
129 | #define TIC_SYNC_LIST(macro) \ |
130 | macro(tiles, tiles, 0) \ |
131 | macro(sprites, sprites, 1) \ |
132 | macro(map, map, 2) \ |
133 | macro(sfx, sfx, 3) \ |
134 | macro(music, music, 4) \ |
135 | macro(palette, vram.palette, 5) \ |
136 | macro(flags, flags, 6) \ |
137 | macro(screen, vram.screen, 7) |
138 | |
139 | enum |
140 | { |
141 | #define TIC_SYNC_DEF(NAME, _, INDEX) tic_sync_##NAME = 1 << INDEX, |
142 | TIC_SYNC_LIST(TIC_SYNC_DEF) |
143 | #undef TIC_SYNC_DEF |
144 | }; |
145 | |
146 | #define TIC_FN "TIC" |
147 | #define BOOT_FN "BOOT" |
148 | #define SCN_FN "SCN" |
149 | #define OVR_FN "OVR" // deprecated since v1.0 |
150 | #define BDR_FN "BDR" |
151 | #define "MENU" |
152 | |
153 | #define TIC_CALLBACK_LIST(macro) \ |
154 | macro(TIC, TIC_FN "()", "Main function. It's called at " DEF2STR(TIC80_FRAMERATE) \ |
155 | "fps (" DEF2STR(TIC80_FRAMERATE) " times every second).") \ |
156 | macro(BOOT, BOOT_FN, "Startup function.") \ |
157 | macro(MENU, MENU_FN "(index)", "Game Menu handler.") \ |
158 | macro(SCN, SCN_FN "(row)", "Allows you to execute code between the drawing of each scanline, " \ |
159 | "for example, to manipulate the palette.") \ |
160 | macro(BDR, BDR_FN "(row)", "Allows you to execute code between the drawing of each fullscreen scanline, " \ |
161 | "for example, to manipulate the palette.") |
162 | |
163 | // API DEFINITION TABLE |
164 | // macro |
165 | // ( |
166 | // definition |
167 | // help |
168 | // parameters count |
169 | // required parameters count |
170 | // callback? |
171 | // return type |
172 | // function parameters |
173 | // ) |
174 | |
175 | #define TIC_API_LIST(macro) \ |
176 | macro(print, \ |
177 | "print(text x=0 y=0 color=15 fixed=false scale=1 smallfont=false) -> width", \ |
178 | \ |
179 | "This will simply print text to the screen using the font defined in config.\n" \ |
180 | "When set to true, the fixed width option ensures that each character " \ |
181 | "will be printed in a `box` of the same size, " \ |
182 | "so the character `i` will occupy the same width as the character `w` for example.\n" \ |
183 | "When fixed width is false, there will be a single space between each character.\n" \ |
184 | "\nTips:\n" \ |
185 | "- To use a custom rastered font, check out `font()`.\n" \ |
186 | "- To print to the console, check out `trace()`.", \ |
187 | 7, \ |
188 | 1, \ |
189 | 0, \ |
190 | s32, \ |
191 | tic_mem*, const char* text, s32 x, s32 y, u8 color, bool fixed, s32 scale, bool alt) \ |
192 | \ |
193 | \ |
194 | macro(cls, \ |
195 | "cls(color=0)", \ |
196 | \ |
197 | "Clear the screen.\n" \ |
198 | "When called this function clear all the screen using the color passed as argument.\n" \ |
199 | "If no parameter is passed first color (0) is used.", \ |
200 | 1, \ |
201 | 0, \ |
202 | 0, \ |
203 | void, \ |
204 | tic_mem*, u8 color) \ |
205 | \ |
206 | \ |
207 | macro(pix, \ |
208 | "pix(x y color)\npix(x y) -> color", \ |
209 | \ |
210 | "This function can read or write pixel color values.\n" \ |
211 | "When called with a color parameter, the pixel at the specified coordinates is set to that color.\n" \ |
212 | "Calling the function without a color parameter returns the color of the pixel at the specified position.", \ |
213 | 3, \ |
214 | 2, \ |
215 | 0, \ |
216 | u8, \ |
217 | tic_mem*, s32 x, s32 y, u8 color, bool get) \ |
218 | \ |
219 | \ |
220 | macro(line, \ |
221 | "line(x0 y0 x1 y1 color)", \ |
222 | \ |
223 | "Draws a straight line from point (x0,y0) to point (x1,y1) in the specified color.", \ |
224 | 5, \ |
225 | 5, \ |
226 | 0, \ |
227 | void, \ |
228 | tic_mem*, float x1, float y1, float x2, float y2, u8 color) \ |
229 | \ |
230 | \ |
231 | macro(rect, \ |
232 | "rect(x y w h color)", \ |
233 | \ |
234 | "This function draws a filled rectangle of the desired size and color at the specified position.\n" \ |
235 | "If you only need to draw the the border or outline of a rectangle (ie not filled) see `rectb()`.", \ |
236 | 5, \ |
237 | 5, \ |
238 | 0, \ |
239 | void, \ |
240 | tic_mem*, s32 x, s32 y, s32 width, s32 height, u8 color) \ |
241 | \ |
242 | \ |
243 | macro(rectb, \ |
244 | "rectb(x y w h color)", \ |
245 | \ |
246 | "This function draws a one pixel thick rectangle border at the position requested.\n" \ |
247 | "If you need to fill the rectangle with a color, see `rect()` instead.", \ |
248 | 5, \ |
249 | 5, \ |
250 | 0, \ |
251 | void, \ |
252 | tic_mem*, s32 x, s32 y, s32 width, s32 height, u8 color) \ |
253 | \ |
254 | \ |
255 | macro(spr, \ |
256 | "spr(id x y colorkey=-1 scale=1 flip=0 rotate=0 w=1 h=1)", \ |
257 | \ |
258 | "Draws the sprite number index at the x and y coordinate.\n" \ |
259 | "You can specify a colorkey in the palette which will be used as the transparent color " \ |
260 | "or use a value of -1 for an opaque sprite.\n" \ |
261 | "The sprite can be scaled up by a desired factor. For example, " \ |
262 | "a scale factor of 2 means an 8x8 pixel sprite is drawn to a 16x16 area of the screen.\n" \ |
263 | "You can flip the sprite where:\n" \ |
264 | "- 0 = No Flip\n" \ |
265 | "- 1 = Flip horizontally\n" \ |
266 | "- 2 = Flip vertically\n" \ |
267 | "- 3 = Flip both vertically and horizontally\n" \ |
268 | "When you rotate the sprite, it's rotated clockwise in 90 steps:\n" \ |
269 | "- 0 = No rotation\n" \ |
270 | "- 1 = 90 rotation\n" \ |
271 | "- 2 = 180 rotation\n" \ |
272 | "- 3 = 270 rotation\n" \ |
273 | "You can draw a composite sprite (consisting of a rectangular region of sprites from the sprite sheet) " \ |
274 | "by specifying the `w` and `h` parameters (which default to 1).", \ |
275 | 9, \ |
276 | 3, \ |
277 | 0, \ |
278 | void, \ |
279 | tic_mem*, s32 index, s32 x, s32 y, s32 w, s32 h, \ |
280 | u8* trans_colors, u8 trans_count, s32 scale, tic_flip flip, tic_rotate rotate) \ |
281 | \ |
282 | \ |
283 | macro(btn, \ |
284 | "btn(id) -> pressed", \ |
285 | \ |
286 | "This function allows you to read the status of one of the buttons attached to TIC.\n" \ |
287 | "The function returns true if the key with the supplied id is currently in the pressed state.\n" \ |
288 | "It remains true for as long as the key is held down.\n" \ |
289 | "If you want to test if a key was just pressed, use `btnp()` instead.", \ |
290 | 1, \ |
291 | 1, \ |
292 | 0, \ |
293 | u32, \ |
294 | tic_mem*, s32 id) \ |
295 | \ |
296 | \ |
297 | macro(btnp, \ |
298 | "btnp(id hold=-1 period=-1) -> pressed", \ |
299 | \ |
300 | "This function allows you to read the status of one of TIC's buttons.\n" \ |
301 | "It returns true only if the key has been pressed since the last frame.\n" \ |
302 | "You can also use the optional hold and period parameters " \ |
303 | "which allow you to check if a button is being held down.\n" \ |
304 | "After the time specified by hold has elapsed, " \ |
305 | "btnp will return true each time period is passed if the key is still down.\n" \ |
306 | "For example, to re-examine the state of button `0` after 2 seconds " \ |
307 | "and continue to check its state every 1/10th of a second, you would use btnp(0, 120, 6).\n" \ |
308 | "Since time is expressed in ticks and TIC runs at 60 frames per second, " \ |
309 | "we use the value of 120 to wait 2 seconds and 6 ticks (ie 60/10) as the interval for re-checking.", \ |
310 | 3, \ |
311 | 1, \ |
312 | 0, \ |
313 | u32, \ |
314 | tic_mem*, s32 id, s32 hold, s32 period) \ |
315 | \ |
316 | \ |
317 | macro(sfx, \ |
318 | "sfx(id note=-1 duration=-1 channel=0 volume=15 speed=0)", \ |
319 | \ |
320 | "This function will play the sound with `id` created in the sfx editor.\n" \ |
321 | "Calling the function with id set to -1 will stop playing the channel.\n" \ |
322 | "The note can be supplied as an integer between 0 and 95 (representing 8 octaves of 12 notes each) " \ |
323 | "or as a string giving the note name and octave.\n" \ |
324 | "For example, a note value of `14` will play the note `D` in the second octave.\n" \ |
325 | "The same note could be specified by the string `D-2`.\n" \ |
326 | "Note names consist of two characters, " \ |
327 | "the note itself (in upper case) followed by `-` to represent the natural note or `#` to represent a sharp.\n" \ |
328 | "There is no option to indicate flat values.\n" \ |
329 | "The available note names are therefore: C-, C#, D-, D#, E-, F-, F#, G-, G#, A-, A#, B-.\n" \ |
330 | "The `octave` is specified using a single digit in the range 0 to 8.\n" \ |
331 | "The `duration` specifies how many ticks to play the sound for since TIC-80 runs at 60 frames per second, " \ |
332 | "a value of 30 represents half a second.\n" \ |
333 | "A value of -1 will play the sound continuously.\n" \ |
334 | "The `channel` parameter indicates which of the four channels to use. Allowed values are 0 to 3.\n" \ |
335 | "The `volume` can be between 0 and 15.\n" \ |
336 | "The `speed` in the range -4 to 3 can be specified and means how many `ticks+1` to play each step, " \ |
337 | "so speed==0 means 1 tick per step.", \ |
338 | 6, \ |
339 | 1, \ |
340 | 0, \ |
341 | void, \ |
342 | tic_mem*, s32 index, s32 note, s32 octave, \ |
343 | s32 duration, s32 channel, s32 left, s32 right, s32 speed) \ |
344 | \ |
345 | \ |
346 | macro(map, \ |
347 | "map(x=0 y=0 w=30 h=17 sx=0 sy=0 colorkey=-1 scale=1 remap=nil)", \ |
348 | \ |
349 | "The map consists of cells of 8x8 pixels, each of which can be filled with a sprite using the map editor.\n" \ |
350 | "The map can be up to 240 cells wide by 136 deep.\n" \ |
351 | "This function will draw the desired area of the map to a specified screen position.\n" \ |
352 | "For example, map(5,5,12,10,0,0) will draw a 12x10 section of the map, " \ |
353 | "starting from map co-ordinates (5,5) to screen position (0,0).\n" \ |
354 | "The map function's last parameter is a powerful callback function " \ |
355 | "for changing how map cells (sprites) are drawn when map is called.\n" \ |
356 | "It can be used to rotate, flip and replace sprites while the game is running.\n" \ |
357 | "Unlike mset, which saves changes to the map, this special function can be used to create " \ |
358 | "animated tiles or replace them completely.\n" \ |
359 | "Some examples include changing sprites to open doorways, " \ |
360 | "hiding sprites used to spawn objects in your game and even to emit the objects themselves.\n" \ |
361 | "The tilemap is laid out sequentially in RAM - writing 1 to 0x08000 " \ |
362 | "will cause tile(sprite) #1 to appear at top left when map() is called.\n" \ |
363 | "To set the tile immediately below this we need to write to 0x08000 + 240, ie 0x080F0.", \ |
364 | 9, \ |
365 | 0, \ |
366 | 1, \ |
367 | void, \ |
368 | tic_mem*, s32 x, s32 y, s32 width, s32 height, s32 sx, s32 sy, \ |
369 | u8* trans_colors, u8 trans_count, s32 scale, RemapFunc remap, void* data) \ |
370 | \ |
371 | \ |
372 | macro(mget, \ |
373 | "mget(x y) -> tile_id", \ |
374 | \ |
375 | "Gets the sprite id at the given x and y map coordinate.", \ |
376 | 2, \ |
377 | 2, \ |
378 | 0, \ |
379 | u8, \ |
380 | tic_mem*, s32 x, s32 y) \ |
381 | \ |
382 | \ |
383 | macro(mset, \ |
384 | "mset(x y tile_id)", \ |
385 | \ |
386 | "This function will change the tile at the specified map coordinates.\n" \ |
387 | "By default, changes made are only kept while the current game is running.\n" \ |
388 | "To make permanent changes to the map, see `sync()`.\n" \ |
389 | "Related: `map()` `mget()` `sync()`.", \ |
390 | 3, \ |
391 | 3, \ |
392 | 0, \ |
393 | void, \ |
394 | tic_mem*, s32 x, s32 y, u8 value) \ |
395 | \ |
396 | \ |
397 | macro(peek, \ |
398 | "peek(addr bits=8) -> value", \ |
399 | \ |
400 | "This function allows to read the memory from TIC.\n" \ |
401 | "It's useful to access resources created with the integrated tools like sprite, maps, sounds, " \ |
402 | "cartridges data?\n" \ |
403 | "Never dream to sound a sprite?\n" \ |
404 | "Address are in hexadecimal format but values are decimal.\n" \ |
405 | "To write to a memory address, use `poke()`.\n" \ |
406 | "`bits` allowed to be 1,2,4,8.", \ |
407 | 2, \ |
408 | 1, \ |
409 | 0, \ |
410 | u8, \ |
411 | tic_mem*, s32 address, s32 bits) \ |
412 | \ |
413 | \ |
414 | macro(poke, \ |
415 | "poke(addr value bits=8)", \ |
416 | \ |
417 | "This function allows you to write a single byte to any address in TIC's RAM.\n" \ |
418 | "The address should be specified in hexadecimal format, the value in decimal.\n" \ |
419 | "`bits` allowed to be 1,2,4,8.", \ |
420 | 3, \ |
421 | 2, \ |
422 | 0, \ |
423 | void, \ |
424 | tic_mem*, s32 address, u8 value, s32 bits) \ |
425 | \ |
426 | \ |
427 | macro(peek1, \ |
428 | "peek1(addr) -> value", \ |
429 | \ |
430 | "This function enables you to read single bit values from TIC's RAM.\n" \ |
431 | "The address is often specified in hexadecimal format.", \ |
432 | 1, \ |
433 | 1, \ |
434 | 0, \ |
435 | u8, \ |
436 | tic_mem*, s32 address) \ |
437 | \ |
438 | \ |
439 | macro(poke1, \ |
440 | "poke1(addr value)", \ |
441 | \ |
442 | "This function allows you to write single bit values directly to RAM.\n" \ |
443 | "The address is often specified in hexadecimal format.", \ |
444 | 2, \ |
445 | 2, \ |
446 | 0, \ |
447 | void, \ |
448 | tic_mem*, s32 address, u8 value) \ |
449 | \ |
450 | \ |
451 | macro(peek2, \ |
452 | "peek2(addr) -> value", \ |
453 | \ |
454 | "This function enables you to read two bits values from TIC's RAM.\n" \ |
455 | "The address is often specified in hexadecimal format.", \ |
456 | 1, \ |
457 | 1, \ |
458 | 0, \ |
459 | u8, \ |
460 | tic_mem*, s32 address) \ |
461 | \ |
462 | \ |
463 | macro(poke2, \ |
464 | "poke2(addr value)", \ |
465 | \ |
466 | "This function allows you to write two bits values directly to RAM.\n" \ |
467 | "The address is often specified in hexadecimal format.", \ |
468 | 2, \ |
469 | 2, \ |
470 | 0, \ |
471 | void, \ |
472 | tic_mem*, s32 address, u8 value) \ |
473 | \ |
474 | \ |
475 | macro(peek4, \ |
476 | "peek4(addr) -> value", \ |
477 | \ |
478 | "This function enables you to read values from TIC's RAM.\n" \ |
479 | "The address is often specified in hexadecimal format.\n" \ |
480 | "See 'poke4()' for detailed information on how nibble addressing compares with byte addressing.", \ |
481 | 1, \ |
482 | 1, \ |
483 | 0, \ |
484 | u8, \ |
485 | tic_mem*, s32 address) \ |
486 | \ |
487 | \ |
488 | macro(poke4, \ |
489 | "poke4(addr value)", \ |
490 | \ |
491 | "This function allows you to write directly to RAM.\n" \ |
492 | "The address is often specified in hexadecimal format.\n" \ |
493 | "For both peek4 and poke4 RAM is addressed in 4 bit segments (nibbles).\n" \ |
494 | "Therefore, to access the the RAM at byte address 0x4000\n" \ |
495 | "you would need to access both the 0x8000 and 0x8001 nibble addresses.", \ |
496 | 2, \ |
497 | 2, \ |
498 | 0, \ |
499 | void, \ |
500 | tic_mem*, s32 address, u8 value) \ |
501 | \ |
502 | \ |
503 | macro(memcpy, \ |
504 | "memcpy(dest source size)", \ |
505 | \ |
506 | "This function allows you to copy a continuous block of TIC's 96K RAM from one address to another.\n" \ |
507 | "Addresses are specified are in hexadecimal format, values are decimal.", \ |
508 | 3, \ |
509 | 3, \ |
510 | 0, \ |
511 | void, \ |
512 | tic_mem*, s32 dst, s32 src, s32 size) \ |
513 | \ |
514 | \ |
515 | macro(memset, \ |
516 | "memset(dest value size)", \ |
517 | \ |
518 | "This function allows you to set a continuous block of any part of TIC's RAM to the same value.\n" \ |
519 | "The address is specified in hexadecimal format, the value in decimal.", \ |
520 | 3, \ |
521 | 3, \ |
522 | 0, \ |
523 | void, \ |
524 | tic_mem*, s32 dst, u8 val, s32 size) \ |
525 | \ |
526 | \ |
527 | macro(trace, \ |
528 | "trace(message color=15)", \ |
529 | \ |
530 | "This is a service function, useful for debugging your code.\n" \ |
531 | "It prints the message parameter to the console in the (optional) color specified.\n" \ |
532 | "\nTips:\n" \ |
533 | "- The Lua concatenator for strings is .. (two points).\n" \ |
534 | "- Use console cls command to clear the output from trace.", \ |
535 | 2, \ |
536 | 1, \ |
537 | 0, \ |
538 | void, \ |
539 | tic_mem*, const char* text, u8 color) \ |
540 | \ |
541 | \ |
542 | macro(pmem, \ |
543 | "pmem(index value)\npmem(index) -> value", \ |
544 | \ |
545 | "This function allows you to save and retrieve data in one of the 256 individual 32-bit slots " \ |
546 | "available in the cartridge's persistent memory.\n" \ |
547 | "This is useful for saving high-scores, level advancement or achievements.\n" \ |
548 | "The data is stored as unsigned 32-bit integers (from 0 to 4294967295).\n" \ |
549 | "\nTips:\n" \ |
550 | "- pmem depends on the cartridge hash (md5), so don't change your lua script if you want to keep the data.\n" \ |
551 | "- Use `saveid:` with a personalized string in the header metadata to override the default MD5 calculation.\n" \ |
552 | "This allows the user to update a cart without losing their saved data.", \ |
553 | 2, \ |
554 | 1, \ |
555 | 0, \ |
556 | u32, \ |
557 | tic_mem*, s32 index, u32 value, bool get) \ |
558 | \ |
559 | \ |
560 | macro(time, \ |
561 | "time() -> ticks", \ |
562 | \ |
563 | "This function returns the number of milliseconds elapsed since the cartridge began execution.\n" \ |
564 | "Useful for keeping track of time, animating items and triggering events.", \ |
565 | 0, \ |
566 | 0, \ |
567 | 0, \ |
568 | double, \ |
569 | tic_mem*) \ |
570 | \ |
571 | \ |
572 | macro(tstamp, \ |
573 | "tstamp() -> timestamp", \ |
574 | \ |
575 | "This function returns the number of seconds elapsed since January 1st, 1970.\n" \ |
576 | "Useful for creating persistent games which evolve over time between plays.", \ |
577 | 0, \ |
578 | 0, \ |
579 | 0, \ |
580 | s32, \ |
581 | tic_mem*) \ |
582 | \ |
583 | \ |
584 | macro(exit, \ |
585 | "exit()", \ |
586 | \ |
587 | "Interrupts program execution and returns to the console when the TIC function ends.", \ |
588 | 0, \ |
589 | 0, \ |
590 | 0, \ |
591 | void, \ |
592 | tic_mem*) \ |
593 | \ |
594 | \ |
595 | macro(font, \ |
596 | "font(text x y chromakey char_width char_height fixed=false scale=1) -> width", \ |
597 | \ |
598 | "Print string with font defined in foreground sprites.\n" \ |
599 | "To simply print to the screen, check out `print()`.\n" \ |
600 | "To print to the console, check out `trace()`.", \ |
601 | 8, \ |
602 | 6, \ |
603 | 0, \ |
604 | s32, \ |
605 | tic_mem*, const char* text, s32 x, s32 y, \ |
606 | u8* trans_colors, u8 trans_count, s32 w, s32 h, bool fixed, s32 scale, bool alt) \ |
607 | \ |
608 | \ |
609 | macro(mouse, \ |
610 | "mouse() -> x y left middle right scrollx scrolly", \ |
611 | \ |
612 | "This function returns the mouse coordinates and a boolean value for the state of each mouse button," \ |
613 | "with true indicating that a button is pressed.", \ |
614 | 0, \ |
615 | 0, \ |
616 | 0, \ |
617 | tic_point, \ |
618 | tic_mem*) \ |
619 | \ |
620 | \ |
621 | macro(circ, \ |
622 | "circ(x y radius color)", \ |
623 | \ |
624 | "This function draws a filled circle of the desired radius and color with its center at x, y.\n" \ |
625 | "It uses the Bresenham algorithm.", \ |
626 | 4, \ |
627 | 4, \ |
628 | 0, \ |
629 | void, \ |
630 | tic_mem*, s32 x, s32 y, s32 radius, u8 color) \ |
631 | \ |
632 | \ |
633 | macro(circb, \ |
634 | "circb(x y radius color)", \ |
635 | \ |
636 | "Draws the circumference of a circle with its center at x, y using the radius and color requested.\n" \ |
637 | "It uses the Bresenham algorithm.", \ |
638 | 4, \ |
639 | 4, \ |
640 | 0, \ |
641 | void, \ |
642 | tic_mem*, s32 x, s32 y, s32 radius, u8 color) \ |
643 | \ |
644 | \ |
645 | macro(elli, \ |
646 | "elli(x y a b color)", \ |
647 | \ |
648 | "This function draws a filled ellipse of the desired a, b radiuses and color with its center at x, y.\n" \ |
649 | "It uses the Bresenham algorithm.", \ |
650 | 5, \ |
651 | 5, \ |
652 | 0, \ |
653 | void, \ |
654 | tic_mem*, s32 x, s32 y, s32 a, s32 b, u8 color) \ |
655 | \ |
656 | \ |
657 | macro(ellib, \ |
658 | "ellib(x y a b color)", \ |
659 | \ |
660 | "This function draws an ellipse border with the desired radiuses a b and color with its center at x, y.\n" \ |
661 | "It uses the Bresenham algorithm.", \ |
662 | 5, \ |
663 | 5, \ |
664 | 0, \ |
665 | void, \ |
666 | tic_mem*, s32 x, s32 y, s32 a, s32 b, u8 color) \ |
667 | \ |
668 | \ |
669 | macro(tri, \ |
670 | "tri(x1 y1 x2 y2 x3 y3 color)", \ |
671 | \ |
672 | "This function draws a triangle filled with color, using the supplied vertices.", \ |
673 | 7, \ |
674 | 7, \ |
675 | 0, \ |
676 | void, \ |
677 | tic_mem*, float x1, float y1, float x2, float y2, float x3, float y3, u8 color) \ |
678 | \ |
679 | macro(trib, \ |
680 | "trib(x1 y1 x2 y2 x3 y3 color)", \ |
681 | \ |
682 | "This function draws a triangle border with color, using the supplied vertices.", \ |
683 | 7, \ |
684 | 7, \ |
685 | 0, \ |
686 | void, \ |
687 | tic_mem*, float x1, float y1, float x2, float y2, float x3, float y3, u8 color) \ |
688 | \ |
689 | \ |
690 | macro(ttri, \ |
691 | "ttri(x1 y1 x2 y2 x3 y3 u1 v1 u2 v2 u3 v3 texsrc=0 chromakey=-1 z1=0 z2=0 z3=0)", \ |
692 | \ |
693 | "It renders a triangle filled with texture from image ram, map ram or vbank.\n" \ |
694 | "Use in 3D graphics.\n" \ |
695 | "In particular, if the vertices in the triangle have different 3D depth, you may see some distortion.\n" \ |
696 | "These can be thought of as the window inside image ram (sprite sheet), map ram or another vbank.\n" \ |
697 | "Note that the sprite sheet or map in this case is treated as a single large image, " \ |
698 | "with U and V addressing its pixels directly, rather than by sprite ID.\n" \ |
699 | "So for example the top left corner of sprite #2 would be located at u=16, v=0.", \ |
700 | 17, \ |
701 | 12, \ |
702 | 0, \ |
703 | void, \ |
704 | tic_mem*, float x1, float y1, float x2, float y2, float x3, float y3, \ |
705 | float u1, float v1, float u2, float v2, float u3, float v3, tic_texture_src texsrc, u8* colors, s32 count, \ |
706 | float z1, float z2, float z3, bool depth) \ |
707 | \ |
708 | \ |
709 | macro(clip, \ |
710 | "clip(x y width height)\nclip()", \ |
711 | \ |
712 | "This function limits drawing to a clipping region or `viewport` defined by x,y,w,h.\n" \ |
713 | "Things drawn outside of this area will not be visible.\n" \ |
714 | "Calling clip() with no parameters will reset the drawing area to the entire screen.", \ |
715 | 4, \ |
716 | 4, \ |
717 | 0, \ |
718 | void, \ |
719 | tic_mem*, s32 x, s32 y, s32 width, s32 height) \ |
720 | \ |
721 | \ |
722 | macro(music, \ |
723 | "music(track=-1 frame=-1 row=-1 loop=true sustain=false tempo=-1 speed=-1)", \ |
724 | \ |
725 | "This function starts playing a track created in the Music Editor.\n" \ |
726 | "Call without arguments to stop the music.", \ |
727 | 7, \ |
728 | 0, \ |
729 | 0, \ |
730 | void, \ |
731 | tic_mem*, s32 track, s32 frame, s32 row, bool loop, bool sustain, s32 tempo, s32 speed) \ |
732 | \ |
733 | \ |
734 | macro(sync, \ |
735 | "sync(mask=0 bank=0 tocart=false)", \ |
736 | \ |
737 | "The pro version of TIC-80 contains 8 memory banks.\n" \ |
738 | "To switch between these banks, sync can be used to either load contents from a memory bank to runtime, " \ |
739 | "or save contents from the active runtime to a bank.\n" \ |
740 | "The function can only be called once per frame." \ |
741 | "If you have manipulated the runtime memory (e.g. by using mset), " \ |
742 | "you can reset the active state by calling sync(0,0,false).\n" \ |
743 | "This resets the whole runtime memory to the contents of bank 0." \ |
744 | "Note that sync is not used to load code from banks; this is done automatically.", \ |
745 | 3, \ |
746 | 0, \ |
747 | 0, \ |
748 | void, \ |
749 | tic_mem*, u32 mask, s32 bank, bool toCart) \ |
750 | \ |
751 | \ |
752 | macro(vbank, \ |
753 | "vbank(bank) -> prev\nvbank() -> prev", \ |
754 | \ |
755 | "VRAM contains 2x16K memory chips, use vbank(0) or vbank(1) to switch between them.", \ |
756 | 1, \ |
757 | 1, \ |
758 | 0, \ |
759 | s32, \ |
760 | tic_mem*, s32 bank) \ |
761 | \ |
762 | \ |
763 | macro(reset, \ |
764 | "reset()", \ |
765 | \ |
766 | "Resets the cartridge. To return to the console, see the `exit()`.", \ |
767 | 0, \ |
768 | 0, \ |
769 | 0, \ |
770 | void, \ |
771 | tic_mem*) \ |
772 | \ |
773 | \ |
774 | macro(key, \ |
775 | "key(code=-1) -> pressed", \ |
776 | \ |
777 | "The function returns true if the key denoted by keycode is pressed.", \ |
778 | 1, \ |
779 | 0, \ |
780 | 0, \ |
781 | bool, \ |
782 | tic_mem*, tic_key key) \ |
783 | \ |
784 | \ |
785 | macro(keyp, \ |
786 | "keyp(code=-1 hold=-1 period=-1) -> pressed", \ |
787 | \ |
788 | "This function returns true if the given key is pressed but wasn't pressed in the previous frame.\n" \ |
789 | "Refer to `btnp()` for an explanation of the optional hold and period parameters.", \ |
790 | 3, \ |
791 | 0, \ |
792 | 0, \ |
793 | bool, \ |
794 | tic_mem*, tic_key key, s32 hold, s32 period) \ |
795 | \ |
796 | \ |
797 | macro(fget, \ |
798 | "fget(sprite_id flag) -> bool", \ |
799 | \ |
800 | "Returns true if the specified flag of the sprite is set. See `fset()` for more details.", \ |
801 | 2, \ |
802 | 2, \ |
803 | 0, \ |
804 | bool, \ |
805 | tic_mem*, s32 index, u8 flag) \ |
806 | \ |
807 | \ |
808 | macro(fset, \ |
809 | "fset(sprite_id flag bool)", \ |
810 | \ |
811 | "Each sprite has eight flags which can be used to store information or signal different conditions.\n" \ |
812 | "For example, flag 0 might be used to indicate that the sprite is invisible, " \ |
813 | "flag 6 might indicate that the flag should be draw scaled etc.\n" \ |
814 | "See algo `fget()`.", \ |
815 | 3, \ |
816 | 3, \ |
817 | 0, \ |
818 | void, \ |
819 | tic_mem*, s32 index, u8 flag, bool value) |
820 | |
821 | #define TIC_API_DEF(name, _, __, ___, ____, _____, ret, ...) ret tic_api_##name(__VA_ARGS__); |
822 | TIC_API_LIST(TIC_API_DEF) |
823 | #undef TIC_API_DEF |
824 | |
825 | struct tic_mem |
826 | { |
827 | tic80 product; |
828 | tic_ram* ram; |
829 | tic_cartridge cart; |
830 | |
831 | tic_ram* base_ram; |
832 | |
833 | char saveid[TIC_SAVEID_SIZE]; |
834 | |
835 | union |
836 | { |
837 | struct |
838 | { |
839 | #if RETRO_IS_BIG_ENDIAN |
840 | u8 padded:5; |
841 | u8 keyboard:1; |
842 | u8 mouse:1; |
843 | u8 gamepad:1; |
844 | #else |
845 | u8 gamepad:1; |
846 | u8 mouse:1; |
847 | u8 keyboard:1; |
848 | u8 padded:5; |
849 | #endif |
850 | }; |
851 | |
852 | u8 data; |
853 | } input; |
854 | }; |
855 | |
856 | tic_mem* tic_core_create(s32 samplerate, tic80_pixel_color_format format); |
857 | void tic_core_close(tic_mem* memory); |
858 | void tic_core_pause(tic_mem* memory); |
859 | void tic_core_resume(tic_mem* memory); |
860 | void tic_core_tick_start(tic_mem* memory); |
861 | void tic_core_tick(tic_mem* memory, tic_tick_data* data); |
862 | void tic_core_tick_end(tic_mem* memory); |
863 | void tic_core_synth_sound(tic_mem* tic); |
864 | void tic_core_blit(tic_mem* tic); |
865 | void tic_core_blit_ex(tic_mem* tic, tic_blit_callback clb); |
866 | const tic_script_config* tic_core_script_config(tic_mem* memory); |
867 | |
868 | #define VBANK(tic, bank) \ |
869 | bool MACROVAR(_bank_) = tic_api_vbank(tic, bank); \ |
870 | SCOPE(tic_api_vbank(tic, MACROVAR(_bank_))) |
871 | |