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 "tic80.h"
27#include "defines.h"
28
29#define TIC_VRAM_SIZE (16*1024) //16K
30#define TIC_RAM_SIZE (TIC_VRAM_SIZE+80*1024) //16K+80K
31#define TIC_WASM_PAGE_COUNT 4 // 256K
32#define TIC_FONT_WIDTH 6
33#define TIC_FONT_HEIGHT 6
34#define TIC_ALTFONT_WIDTH 4
35#define TIC_PALETTE_BPP 4
36#define TIC_PALETTE_SIZE (1 << TIC_PALETTE_BPP)
37#define TIC_PALETTES 2
38#define TIC_SPRITESIZE 8
39
40#define TIC_DEFAULT_BIT_DEPTH 4
41#define TIC_DEFAULT_BLIT_MODE 2
42
43#define TIC80_OFFSET_LEFT ((TIC80_FULLWIDTH-TIC80_WIDTH)/2)
44#define TIC80_OFFSET_TOP ((TIC80_FULLHEIGHT-TIC80_HEIGHT)/2)
45
46#define BITS_IN_BYTE 8
47#define TIC_BANK_SPRITES (1 << BITS_IN_BYTE)
48#define TIC_SPRITE_BANKS 2
49#define TIC_FLAGS (TIC_BANK_SPRITES * TIC_SPRITE_BANKS)
50#define TIC_SPRITES (TIC_BANK_SPRITES * TIC_SPRITE_BANKS)
51
52#define TIC_SPRITESHEET_SIZE 128
53#define TIC_SPRITESHEET_COLS (TIC_SPRITESHEET_SIZE / TIC_SPRITESIZE)
54
55#define TIC_MAP_ROWS (TIC_SPRITESIZE)
56#define TIC_MAP_COLS (TIC_SPRITESIZE)
57#define TIC_MAP_SCREEN_WIDTH (TIC80_WIDTH / TIC_SPRITESIZE)
58#define TIC_MAP_SCREEN_HEIGHT (TIC80_HEIGHT / TIC_SPRITESIZE)
59#define TIC_MAP_WIDTH (TIC_MAP_SCREEN_WIDTH * TIC_MAP_ROWS)
60#define TIC_MAP_HEIGHT (TIC_MAP_SCREEN_HEIGHT * TIC_MAP_COLS)
61
62#define TIC_PERSISTENT_SIZE (1024/sizeof(s32)) // 1K
63#define TIC_SAVEID_SIZE 64
64
65#define TIC_SOUND_CHANNELS 4
66#define SFX_TICKS 30
67#define SFX_COUNT_BITS 6
68#define SFX_COUNT (1 << SFX_COUNT_BITS)
69#define SFX_SPEED_BITS 3
70#define SFX_DEF_SPEED (1 << SFX_SPEED_BITS)
71
72#define NOTES 12
73#define OCTAVES 8
74#define MAX_VOLUME 15
75#define MUSIC_PATTERN_ROWS 64
76#define MUSIC_PATTERNS 60
77#define MUSIC_CMD_BITS 3
78#define TRACK_PATTERN_BITS 6
79#define TRACK_PATTERN_MASK ((1 << TRACK_PATTERN_BITS) - 1)
80#define TRACK_PATTERNS_SIZE (TRACK_PATTERN_BITS * TIC_SOUND_CHANNELS / BITS_IN_BYTE)
81#define MUSIC_FRAMES 16
82#define MUSIC_TRACKS 8
83#define DEFAULT_TEMPO 150
84#define DEFAULT_SPEED 6
85#define PITCH_DELTA 128
86#define NOTES_PER_BEAT 4
87#define PATTERN_START 1
88#define MUSIC_SFXID_LOW_BITS 5
89#define WAVES_COUNT 16
90#define WAVE_VALUES 32
91#define WAVE_VALUE_BITS 4
92#define WAVE_MAX_VALUE ((1 << WAVE_VALUE_BITS) - 1)
93#define WAVE_SIZE (WAVE_VALUES * WAVE_VALUE_BITS / BITS_IN_BYTE)
94
95#define TIC_BANKSIZE_BITS 16
96#define TIC_BANK_SIZE (1 << TIC_BANKSIZE_BITS) // 64K
97#define TIC_BANK_BITS 3
98#define TIC_BANKS (1 << TIC_BANK_BITS)
99
100#define TIC_CODE_SIZE (TIC_BANK_SIZE * TIC_BANKS)
101#define TIC_BINARY_BANKS 4
102#define TIC_BINARY_SIZE (TIC_BINARY_BANKS * TIC_BANK_SIZE) // 4 * 64k = 256K
103
104
105#define TIC_BUTTONS 8
106#define TIC_GAMEPADS (sizeof(tic80_gamepads) / sizeof(tic80_gamepad))
107
108#define SFX_NOTES {"C-", "C#", "D-", "D#", "E-", "F-", "F#", "G-", "G#", "A-", "A#", "B-"}
109#define TIC_FONT_CHARS 128
110
111#define TIC_UNUSED(x) (void)x
112
113enum
114{
115 NoteNone = 0,
116 NoteStop,
117 NoteNone2,
118 NoteNone3,
119 NoteStart,
120};
121
122typedef enum
123{
124 tic_color_black,
125 tic_color_purple,
126 tic_color_red,
127 tic_color_orange,
128 tic_color_yellow,
129 tic_color_light_green,
130 tic_color_green,
131 tic_color_dark_green,
132 tic_color_dark_blue,
133 tic_color_blue,
134 tic_color_light_blue,
135 tic_color_cyan,
136 tic_color_white,
137 tic_color_light_grey,
138 tic_color_grey,
139 tic_color_dark_grey,
140} tic_color;
141
142typedef enum
143{
144 tic_no_flip = 0,
145 tic_horz_flip = 1,
146 tic_vert_flip = 2,
147} tic_flip;
148
149typedef enum
150{
151 tic_no_rotate,
152 tic_90_rotate,
153 tic_180_rotate,
154 tic_270_rotate,
155} tic_rotate;
156
157typedef enum
158{
159 tic_bpp_4 = 4,
160 tic_bpp_2 = 2,
161 tic_bpp_1 = 1,
162} tic_bpp;
163
164typedef struct
165{
166#if RETRO_IS_BIG_ENDIAN
167 u8 size:4;
168 u8 start:4;
169#else
170 u8 start:4;
171 u8 size:4;
172#endif
173} tic_sound_loop;
174
175typedef struct
176{
177
178 struct
179 {
180#if RETRO_IS_BIG_ENDIAN
181 u8 wave:4;
182 u8 volume:4;
183 s8 pitch:4;
184 u8 chord:4;
185#else
186 u8 volume:4;
187 u8 wave:4;
188 u8 chord:4;
189 s8 pitch:4;
190#endif
191 } data[SFX_TICKS];
192
193 struct
194 {
195#if RETRO_IS_BIG_ENDIAN
196 u8 reverse:1; // chord reverse
197 s8 speed:SFX_SPEED_BITS;
198 u8 pitch16x:1; // pitch factor
199 u8 octave:3;
200 u8 temp:2;
201 u8 stereo_right:1;
202 u8 stereo_left:1;
203 u8 note:4;
204#else
205 u8 octave:3;
206 u8 pitch16x:1; // pitch factor
207 s8 speed:SFX_SPEED_BITS;
208 u8 reverse:1; // chord reverse
209 u8 note:4;
210 u8 stereo_left:1;
211 u8 stereo_right:1;
212 u8 temp:2;
213#endif
214 };
215
216 union
217 {
218 struct
219 {
220 tic_sound_loop wave;
221 tic_sound_loop volume;
222 tic_sound_loop chord;
223 tic_sound_loop pitch;
224 };
225
226 tic_sound_loop loops[4];
227 };
228
229} tic_sample;
230
231typedef struct
232{
233 union
234 {
235 struct
236 {
237 s8 wave;
238 s8 volume;
239 s8 chord;
240 s8 pitch;
241 };
242
243 s8 data[4];
244 };
245} tic_sfx_pos;
246
247typedef struct
248{
249 u8 data[WAVE_SIZE];
250}tic_waveform;
251
252typedef struct
253{
254 tic_waveform items[WAVES_COUNT];
255} tic_waveforms;
256
257#define MUSIC_CMD_LIST(macro) \
258 macro(empty, 0, "") \
259 macro(volume, M, "master volume for LEFT=X / RIGHT=Y channel") \
260 macro(chord, C, "play chord, X=3 Y=7 plays +0,+3,+7 notes") \
261 macro(jump, J, "jump to FRAME=X / BEAT=Y") \
262 macro(slide, S, "slide to note (legato) with TICKS=XY") \
263 macro(pitch, P, "finepitch UP/DOWN=XY-" DEF2STR(PITCH_DELTA)) \
264 macro(vibrato, V, "vibrato with PERIOD=X and DEPTH=Y") \
265 macro(delay, D, "delay triggering a note with TICKS=XY")
266
267typedef enum
268{
269#define ENUM_ITEM(name, ...) tic_music_cmd_##name,
270 MUSIC_CMD_LIST(ENUM_ITEM)
271#undef ENUM_ITEM
272
273 tic_music_cmd_count
274} tic_music_command;
275
276typedef struct
277{
278#if RETRO_IS_BIG_ENDIAN
279 u8 param1 :4;
280 u8 note :4;
281 u8 sfxhi :1;
282 u8 command :MUSIC_CMD_BITS; // tic_music_command
283 u8 param2 :4;
284 u8 octave :3;
285 u8 sfxlow :MUSIC_SFXID_LOW_BITS;
286#else
287 u8 note :4;
288 u8 param1 :4;
289 u8 param2 :4;
290 u8 command :MUSIC_CMD_BITS; // tic_music_command
291 u8 sfxhi :1;
292 u8 sfxlow :MUSIC_SFXID_LOW_BITS;
293 u8 octave :3;
294#endif
295} tic_track_row;
296
297typedef struct
298{
299 tic_track_row rows[MUSIC_PATTERN_ROWS];
300
301} tic_track_pattern;
302
303typedef struct
304{
305 u8 data[MUSIC_FRAMES * TRACK_PATTERNS_SIZE]; // sfx - 6bits per channel = 24 bit
306
307 s8 tempo; // delta value, rel to 120 bpm * 10 [32-255]
308 u8 rows; // delta value, rel to 64 rows, can be [1-64]
309 s8 speed; // delta value, rel to 6 [1-31]
310
311} tic_track;
312
313typedef struct
314{
315 tic_track_pattern data[MUSIC_PATTERNS];
316} tic_patterns;
317
318typedef struct
319{
320 tic_track data[MUSIC_TRACKS];
321} tic_tracks;
322
323typedef struct
324{
325 tic_sample data[SFX_COUNT];
326} tic_samples;
327
328typedef struct
329{
330 tic_waveforms waveforms;
331 tic_samples samples;
332}tic_sfx;
333
334typedef struct
335{
336 tic_patterns patterns;
337 tic_tracks tracks;
338}tic_music;
339
340typedef enum
341{
342 tic_music_stop,
343 tic_music_play_frame,
344 tic_music_play,
345} tic_music_status;
346
347typedef struct
348{
349 struct
350 {
351 s8 track;
352 s8 frame;
353 s8 row;
354 } music;
355
356 struct
357 {
358#if RETRO_IS_BIG_ENDIAN
359 u8 unknown:4;
360 u8 music_sustain:1;
361 u8 music_status:2; // enum tic_music_status
362 u8 music_loop:1;
363#else
364 u8 music_loop:1;
365 u8 music_status:2; // enum tic_music_status
366 u8 music_sustain:1;
367 u8 unknown:4;
368#endif
369 } flag;
370
371} tic_music_state;
372
373typedef union
374{
375 struct
376 {
377#if RETRO_IS_BIG_ENDIAN
378 u8 right4:4;
379 u8 left4:4;
380
381 u8 right3:4;
382 u8 left3:4;
383
384 u8 right2:4;
385 u8 left2:4;
386
387 u8 right1:4;
388 u8 left1:4;
389#else
390 u8 left1:4;
391 u8 right1:4;
392
393 u8 left2:4;
394 u8 right2:4;
395
396 u8 left3:4;
397 u8 right3:4;
398
399 u8 left4:4;
400 u8 right4:4;
401#endif
402 };
403
404 u32 data;
405} tic_stereo_volume;
406
407typedef struct
408{
409 struct
410 {
411 u8 freq_low;
412#if RETRO_IS_BIG_ENDIAN
413 u8 volume:4;
414 u8 freq_high:4;
415#else
416 u8 freq_high:4;
417 u8 volume:4;
418#endif
419 };
420
421 tic_waveform waveform;
422} tic_sound_register;
423
424
425static INLINE u16 tic_sound_register_get_freq(const tic_sound_register* reg)
426{
427 return (reg->freq_high << 8) | reg->freq_low;
428}
429
430static INLINE void tic_sound_register_set_freq(tic_sound_register* reg, u16 val)
431{
432 reg->freq_low = val;
433 reg->freq_high = val >> 8;
434}
435
436typedef struct
437{
438 u8 data[TIC_MAP_WIDTH * TIC_MAP_HEIGHT];
439} tic_map;
440
441typedef struct
442{
443 u8 data[TIC_SPRITESIZE * TIC_SPRITESIZE * TIC_PALETTE_BPP / BITS_IN_BYTE];
444} tic_tile;
445
446typedef struct
447{
448 char data[TIC_CODE_SIZE];
449} tic_code;
450
451typedef struct
452{
453 char data[TIC_BINARY_SIZE];
454 u32 size;
455} tic_binary;
456
457typedef struct
458{
459 u8 r;
460 u8 g;
461 u8 b;
462} tic_rgb;
463
464typedef union
465{
466 tic_rgb colors[TIC_PALETTE_SIZE];
467
468 u8 data[TIC_PALETTE_SIZE * sizeof(tic_rgb)];
469} tic_palette;
470
471typedef struct
472{
473 u32 data[TIC_PALETTE_SIZE];
474} tic_blitpal;
475
476typedef struct
477{
478 tic_tile data[TIC_BANK_SPRITES];
479} tic_tiles, tic_sprites;
480
481typedef struct
482{
483 u8 data[TIC_FLAGS];
484} tic_flags;
485
486typedef struct
487{
488 tic_palette vbank0;
489 tic_palette vbank1;
490} tic_palettes;
491
492typedef struct
493{
494 u8 data[TIC80_WIDTH * TIC80_HEIGHT * TIC_PALETTE_BPP / BITS_IN_BYTE];
495} tic_screen;
496
497typedef struct
498{
499 tic_screen screen;
500 tic_tiles tiles;
501 tic_sprites sprites;
502 tic_map map;
503 tic_sfx sfx;
504 tic_music music;
505 tic_flags flags;
506 tic_palettes palette;
507} tic_bank;
508
509typedef struct
510{
511 union
512 {
513 tic_bank bank0;
514 tic_bank banks[TIC_BANKS];
515 };
516
517 tic_code code;
518 tic_binary binary;
519 u8 lang;
520
521} tic_cartridge;
522
523typedef struct
524{
525 u8 data[(TIC_FONT_CHARS - 1) * BITS_IN_BYTE];
526
527 union
528 {
529 struct
530 {
531 u8 width;
532 u8 height;
533 };
534
535 u8 params[BITS_IN_BYTE];
536 };
537} tic_font_data;
538
539typedef struct
540{
541 tic_font_data regular;
542 tic_font_data alt;
543} tic_font;
544
545typedef union
546{
547 struct
548 {
549 tic_screen screen;
550 tic_palette palette;
551 u8 mapping[TIC_PALETTE_SIZE * TIC_PALETTE_BPP / BITS_IN_BYTE];
552
553 struct
554 {
555 union
556 {
557 struct {
558#if RETRO_IS_BIG_ENDIAN
559 u8 padding_border:4;
560 u8 border:TIC_PALETTE_BPP;
561#else
562 u8 border:TIC_PALETTE_BPP;
563 u8 padding_border:4;
564#endif
565 };
566 // clear color for the BANK1
567 struct {
568#if RETRO_IS_BIG_ENDIAN
569 u8 padding_clear:4;
570 u8 clear:TIC_PALETTE_BPP;
571#else
572 u8 clear:TIC_PALETTE_BPP;
573 u8 padding_clear:4;
574#endif
575 };
576 };
577
578 struct
579 {
580 s8 x;
581 s8 y;
582 } offset;
583
584 struct
585 {
586#if RETRO_IS_BIG_ENDIAN
587 u8 system:1;
588 u8 sprite:7;
589#else
590 u8 sprite:7;
591 u8 system:1;
592#endif
593 } cursor;
594 } vars;
595
596 struct
597 {
598#if RETRO_IS_BIG_ENDIAN
599 u8 reserved:4;
600 u8 segment:4;
601#else
602 u8 segment:4;
603 u8 reserved:4;
604#endif
605 } blit;
606
607 u8 reserved[3];
608 };
609
610 u8 data[TIC_VRAM_SIZE];
611} tic_vram;
612
613typedef struct
614{
615 u32 data[TIC_PERSISTENT_SIZE];
616} tic_persistent;
617
618typedef struct
619{
620 u8 data[TIC_GAMEPADS * TIC_BUTTONS];
621} tic_mapping;
622
623typedef union
624{
625 struct
626 {
627 tic_vram vram;
628 tic_tiles tiles;
629 tic_sprites sprites;
630 tic_map map;
631 tic80_input input;
632 tic_sfx_pos sfxpos[TIC_SOUND_CHANNELS];
633 tic_sound_register registers[TIC_SOUND_CHANNELS];
634 tic_sfx sfx;
635 tic_music music;
636 tic_music_state music_state;
637 tic_stereo_volume stereo;
638 tic_persistent persistent;
639 tic_flags flags;
640 tic_font font;
641 tic_mapping mapping;
642
643 u8 free;
644 };
645
646 u8 data[TIC_RAM_SIZE];
647
648} tic_ram;
649
650typedef enum
651{
652 tic_key_unknown,
653
654 tic_key_a,
655 tic_key_b,
656 tic_key_c,
657 tic_key_d,
658 tic_key_e,
659 tic_key_f,
660 tic_key_g,
661 tic_key_h,
662 tic_key_i,
663 tic_key_j,
664 tic_key_k,
665 tic_key_l,
666 tic_key_m,
667 tic_key_n,
668 tic_key_o,
669 tic_key_p,
670 tic_key_q,
671 tic_key_r,
672 tic_key_s,
673 tic_key_t,
674 tic_key_u,
675 tic_key_v,
676 tic_key_w,
677 tic_key_x,
678 tic_key_y,
679 tic_key_z,
680
681 tic_key_0,
682 tic_key_1,
683 tic_key_2,
684 tic_key_3,
685 tic_key_4,
686 tic_key_5,
687 tic_key_6,
688 tic_key_7,
689 tic_key_8,
690 tic_key_9,
691
692 tic_key_minus,
693 tic_key_equals,
694 tic_key_leftbracket,
695 tic_key_rightbracket,
696 tic_key_backslash,
697 tic_key_semicolon,
698 tic_key_apostrophe,
699 tic_key_grave,
700 tic_key_comma,
701 tic_key_period,
702 tic_key_slash,
703
704 tic_key_space,
705 tic_key_tab,
706
707 tic_key_return,
708 tic_key_backspace,
709 tic_key_delete,
710 tic_key_insert,
711
712 tic_key_pageup,
713 tic_key_pagedown,
714 tic_key_home,
715 tic_key_end,
716 tic_key_up,
717 tic_key_down,
718 tic_key_left,
719 tic_key_right,
720
721 tic_key_capslock,
722 tic_key_ctrl,
723 tic_key_shift,
724 tic_key_alt,
725
726 tic_key_escape,
727 tic_key_f1,
728 tic_key_f2,
729 tic_key_f3,
730 tic_key_f4,
731 tic_key_f5,
732 tic_key_f6,
733 tic_key_f7,
734 tic_key_f8,
735 tic_key_f9,
736 tic_key_f10,
737 tic_key_f11,
738 tic_key_f12,
739
740 ////////////////
741
742 tic_keys_count
743} tic_keycode;
744
745typedef enum
746{
747 tic_mouse_left,
748 tic_mouse_middle,
749 tic_mouse_right,
750} tic_mouse_btn;
751
752typedef enum
753{
754 tic_cursor_arrow,
755 tic_cursor_hand,
756 tic_cursor_ibeam,
757} tic_cursor;
758