// MIT License // Copyright (c) 2017 Vadim Grigoruk @nesbox // grigoruk@gmail.com // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // The above copyright notice and this permission notice shall be included in all // copies or substantial portions of the Software. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE // SOFTWARE. #pragma once #include "tic80.h" #include "defines.h" #define TIC_VRAM_SIZE (16*1024) //16K #define TIC_RAM_SIZE (TIC_VRAM_SIZE+80*1024) //16K+80K #define TIC_WASM_PAGE_COUNT 4 // 256K #define TIC_FONT_WIDTH 6 #define TIC_FONT_HEIGHT 6 #define TIC_ALTFONT_WIDTH 4 #define TIC_PALETTE_BPP 4 #define TIC_PALETTE_SIZE (1 << TIC_PALETTE_BPP) #define TIC_PALETTES 2 #define TIC_SPRITESIZE 8 #define TIC_DEFAULT_BIT_DEPTH 4 #define TIC_DEFAULT_BLIT_MODE 2 #define TIC80_OFFSET_LEFT ((TIC80_FULLWIDTH-TIC80_WIDTH)/2) #define TIC80_OFFSET_TOP ((TIC80_FULLHEIGHT-TIC80_HEIGHT)/2) #define BITS_IN_BYTE 8 #define TIC_BANK_SPRITES (1 << BITS_IN_BYTE) #define TIC_SPRITE_BANKS 2 #define TIC_FLAGS (TIC_BANK_SPRITES * TIC_SPRITE_BANKS) #define TIC_SPRITES (TIC_BANK_SPRITES * TIC_SPRITE_BANKS) #define TIC_SPRITESHEET_SIZE 128 #define TIC_SPRITESHEET_COLS (TIC_SPRITESHEET_SIZE / TIC_SPRITESIZE) #define TIC_MAP_ROWS (TIC_SPRITESIZE) #define TIC_MAP_COLS (TIC_SPRITESIZE) #define TIC_MAP_SCREEN_WIDTH (TIC80_WIDTH / TIC_SPRITESIZE) #define TIC_MAP_SCREEN_HEIGHT (TIC80_HEIGHT / TIC_SPRITESIZE) #define TIC_MAP_WIDTH (TIC_MAP_SCREEN_WIDTH * TIC_MAP_ROWS) #define TIC_MAP_HEIGHT (TIC_MAP_SCREEN_HEIGHT * TIC_MAP_COLS) #define TIC_PERSISTENT_SIZE (1024/sizeof(s32)) // 1K #define TIC_SAVEID_SIZE 64 #define TIC_SOUND_CHANNELS 4 #define SFX_TICKS 30 #define SFX_COUNT_BITS 6 #define SFX_COUNT (1 << SFX_COUNT_BITS) #define SFX_SPEED_BITS 3 #define SFX_DEF_SPEED (1 << SFX_SPEED_BITS) #define NOTES 12 #define OCTAVES 8 #define MAX_VOLUME 15 #define MUSIC_PATTERN_ROWS 64 #define MUSIC_PATTERNS 60 #define MUSIC_CMD_BITS 3 #define TRACK_PATTERN_BITS 6 #define TRACK_PATTERN_MASK ((1 << TRACK_PATTERN_BITS) - 1) #define TRACK_PATTERNS_SIZE (TRACK_PATTERN_BITS * TIC_SOUND_CHANNELS / BITS_IN_BYTE) #define MUSIC_FRAMES 16 #define MUSIC_TRACKS 8 #define DEFAULT_TEMPO 150 #define DEFAULT_SPEED 6 #define PITCH_DELTA 128 #define NOTES_PER_BEAT 4 #define PATTERN_START 1 #define MUSIC_SFXID_LOW_BITS 5 #define WAVES_COUNT 16 #define WAVE_VALUES 32 #define WAVE_VALUE_BITS 4 #define WAVE_MAX_VALUE ((1 << WAVE_VALUE_BITS) - 1) #define WAVE_SIZE (WAVE_VALUES * WAVE_VALUE_BITS / BITS_IN_BYTE) #define TIC_BANKSIZE_BITS 16 #define TIC_BANK_SIZE (1 << TIC_BANKSIZE_BITS) // 64K #define TIC_BANK_BITS 3 #define TIC_BANKS (1 << TIC_BANK_BITS) #define TIC_CODE_SIZE (TIC_BANK_SIZE * TIC_BANKS) #define TIC_BINARY_BANKS 4 #define TIC_BINARY_SIZE (TIC_BINARY_BANKS * TIC_BANK_SIZE) // 4 * 64k = 256K #define TIC_BUTTONS 8 #define TIC_GAMEPADS (sizeof(tic80_gamepads) / sizeof(tic80_gamepad)) #define SFX_NOTES {"C-", "C#", "D-", "D#", "E-", "F-", "F#", "G-", "G#", "A-", "A#", "B-"} #define TIC_FONT_CHARS 128 #define TIC_UNUSED(x) (void)x enum { NoteNone = 0, NoteStop, NoteNone2, NoteNone3, NoteStart, }; typedef enum { tic_color_black, tic_color_purple, tic_color_red, tic_color_orange, tic_color_yellow, tic_color_light_green, tic_color_green, tic_color_dark_green, tic_color_dark_blue, tic_color_blue, tic_color_light_blue, tic_color_cyan, tic_color_white, tic_color_light_grey, tic_color_grey, tic_color_dark_grey, } tic_color; typedef enum { tic_no_flip = 0b00, tic_horz_flip = 0b01, tic_vert_flip = 0b10, } tic_flip; typedef enum { tic_no_rotate, tic_90_rotate, tic_180_rotate, tic_270_rotate, } tic_rotate; typedef enum { tic_bpp_4 = 4, tic_bpp_2 = 2, tic_bpp_1 = 1, } tic_bpp; typedef struct { u8 start:4; u8 size:4; } tic_sound_loop; typedef struct { struct { u8 volume:4; u8 wave:4; u8 chord:4; s8 pitch:4; } data[SFX_TICKS]; struct { u8 octave:3; u8 pitch16x:1; // pitch factor s8 speed:SFX_SPEED_BITS; u8 reverse:1; // chord reverse u8 note:4; u8 stereo_left:1; u8 stereo_right:1; u8 temp:2; }; union { struct { tic_sound_loop wave; tic_sound_loop volume; tic_sound_loop chord; tic_sound_loop pitch; }; tic_sound_loop loops[4]; }; } tic_sample; typedef struct { union { struct { s8 wave; s8 volume; s8 chord; s8 pitch; }; s8 data[4]; }; } tic_sfx_pos; typedef struct { u8 data[WAVE_SIZE]; }tic_waveform; typedef struct { tic_waveform items[WAVES_COUNT]; } tic_waveforms; #define MUSIC_CMD_LIST(macro) \ macro(empty, 0, "") \ macro(volume, M, "master volume for LEFT=X / RIGHT=Y channel") \ macro(chord, C, "play chord, X=3 Y=7 plays +0,+3,+7 notes") \ macro(jump, J, "jump to FRAME=X / BEAT=Y") \ macro(slide, S, "slide to note (legato) with TICKS=XY") \ macro(pitch, P, "finepitch UP/DOWN=XY-" DEF2STR(PITCH_DELTA)) \ macro(vibrato, V, "vibrato with PERIOD=X and DEPTH=Y") \ macro(delay, D, "delay triggering a note with TICKS=XY") typedef enum { #define ENUM_ITEM(name, ...) tic_music_cmd_##name, MUSIC_CMD_LIST(ENUM_ITEM) #undef ENUM_ITEM tic_music_cmd_count } tic_music_command; typedef struct { u8 note :4; u8 param1 :4; u8 param2 :4; u8 command :MUSIC_CMD_BITS; // tic_music_command u8 sfxhi :1; u8 sfxlow :MUSIC_SFXID_LOW_BITS; u8 octave :3; } tic_track_row; typedef struct { tic_track_row rows[MUSIC_PATTERN_ROWS]; } tic_track_pattern; typedef struct { u8 data[MUSIC_FRAMES * TRACK_PATTERNS_SIZE]; // sfx - 6bits per channel = 24 bit s8 tempo; // delta value, rel to 120 bpm * 10 [32-255] u8 rows; // delta value, rel to 64 rows, can be [1-64] s8 speed; // delta value, rel to 6 [1-31] } tic_track; typedef struct { tic_track_pattern data[MUSIC_PATTERNS]; } tic_patterns; typedef struct { tic_track data[MUSIC_TRACKS]; } tic_tracks; typedef struct { tic_sample data[SFX_COUNT]; } tic_samples; typedef struct { tic_waveforms waveforms; tic_samples samples; }tic_sfx; typedef struct { tic_patterns patterns; tic_tracks tracks; }tic_music; typedef enum { tic_music_stop, tic_music_play_frame, tic_music_play, } tic_music_status; typedef struct { struct { s8 track; s8 frame; s8 row; } music; struct { u8 music_loop:1; u8 music_status:2; // enum tic_music_status u8 music_sustain:1; u8 unknown:4; } flag; } tic_music_state; typedef union { struct { u8 left1:4; u8 right1:4; u8 left2:4; u8 right2:4; u8 left3:4; u8 right3:4; u8 left4:4; u8 right4:4; }; u32 data; } tic_stereo_volume; typedef struct { struct { u16 freq:12; u16 volume:4; }; tic_waveform waveform; } tic_sound_register; typedef struct { u8 data[TIC_MAP_WIDTH * TIC_MAP_HEIGHT]; } tic_map; typedef struct { u8 data[TIC_SPRITESIZE * TIC_SPRITESIZE * TIC_PALETTE_BPP / BITS_IN_BYTE]; } tic_tile; typedef struct { char data[TIC_CODE_SIZE]; } tic_code; typedef struct { char data[TIC_BINARY_SIZE]; u32 size; } tic_binary; typedef struct { u8 r; u8 g; u8 b; } tic_rgb; typedef union { tic_rgb colors[TIC_PALETTE_SIZE]; u8 data[TIC_PALETTE_SIZE * sizeof(tic_rgb)]; } tic_palette; typedef struct { u32 data[TIC_PALETTE_SIZE]; } tic_blitpal; typedef struct { tic_tile data[TIC_BANK_SPRITES]; } tic_tiles, tic_sprites; typedef struct { u8 data[TIC_FLAGS]; } tic_flags; typedef struct { tic_palette vbank0; tic_palette vbank1; } tic_palettes; typedef struct { u8 data[TIC80_WIDTH * TIC80_HEIGHT * TIC_PALETTE_BPP / BITS_IN_BYTE]; } tic_screen; typedef struct { tic_screen screen; tic_tiles tiles; tic_sprites sprites; tic_map map; tic_sfx sfx; tic_music music; tic_flags flags; tic_palettes palette; } tic_bank; typedef struct { union { tic_bank bank0; tic_bank banks[TIC_BANKS]; }; tic_code code; tic_binary binary; u8 lang; } tic_cartridge; typedef struct { u8 data[(TIC_FONT_CHARS - 1) * BITS_IN_BYTE]; union { struct { u8 width; u8 height; }; u8 params[BITS_IN_BYTE]; }; } tic_font_data; typedef struct { tic_font_data regular; tic_font_data alt; } tic_font; typedef union { struct { tic_screen screen; tic_palette palette; u8 mapping[TIC_PALETTE_SIZE * TIC_PALETTE_BPP / BITS_IN_BYTE]; struct { union { u8 border:TIC_PALETTE_BPP; // clear color for the BANK1 u8 clear:TIC_PALETTE_BPP; }; struct { s8 x; s8 y; } offset; struct { u8 sprite:7; bool system:1; } cursor; } vars; struct { u8 segment:4; u8 reserved:4; } blit; u8 reserved[3]; }; u8 data[TIC_VRAM_SIZE]; } tic_vram; typedef struct { u32 data[TIC_PERSISTENT_SIZE]; } tic_persistent; typedef struct { u8 data[TIC_GAMEPADS * TIC_BUTTONS]; } tic_mapping; typedef union { struct { tic_vram vram; tic_tiles tiles; tic_sprites sprites; tic_map map; tic80_input input; tic_sfx_pos sfxpos[TIC_SOUND_CHANNELS]; tic_sound_register registers[TIC_SOUND_CHANNELS]; tic_sfx sfx; tic_music music; tic_music_state music_state; tic_stereo_volume stereo; tic_persistent persistent; tic_flags flags; tic_font font; tic_mapping mapping; u8 free; }; u8 data[TIC_RAM_SIZE]; } tic_ram; typedef enum { tic_key_unknown, tic_key_a, tic_key_b, tic_key_c, tic_key_d, tic_key_e, tic_key_f, tic_key_g, tic_key_h, tic_key_i, tic_key_j, tic_key_k, tic_key_l, tic_key_m, tic_key_n, tic_key_o, tic_key_p, tic_key_q, tic_key_r, tic_key_s, tic_key_t, tic_key_u, tic_key_v, tic_key_w, tic_key_x, tic_key_y, tic_key_z, tic_key_0, tic_key_1, tic_key_2, tic_key_3, tic_key_4, tic_key_5, tic_key_6, tic_key_7, tic_key_8, tic_key_9, tic_key_minus, tic_key_equals, tic_key_leftbracket, tic_key_rightbracket, tic_key_backslash, tic_key_semicolon, tic_key_apostrophe, tic_key_grave, tic_key_comma, tic_key_period, tic_key_slash, tic_key_space, tic_key_tab, tic_key_return, tic_key_backspace, tic_key_delete, tic_key_insert, tic_key_pageup, tic_key_pagedown, tic_key_home, tic_key_end, tic_key_up, tic_key_down, tic_key_left, tic_key_right, tic_key_capslock, tic_key_ctrl, tic_key_shift, tic_key_alt, tic_key_escape, tic_key_f1, tic_key_f2, tic_key_f3, tic_key_f4, tic_key_f5, tic_key_f6, tic_key_f7, tic_key_f8, tic_key_f9, tic_key_f10, tic_key_f11, tic_key_f12, //////////////// tic_keys_count } tic_keycode; typedef enum { tic_mouse_left, tic_mouse_middle, tic_mouse_right, } tic_mouse_btn; typedef enum { tic_cursor_arrow, tic_cursor_hand, tic_cursor_ibeam, } tic_cursor;