| 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 | |