diff --git a/src/console.c b/src/console.c index ab86fcf..79867af 100644 --- a/src/console.c +++ b/src/console.c @@ -811,6 +811,7 @@ static const BinarySection BinarySections[] = {"SFX", SFX_COUNT, offsetof(tic_bank, sfx.samples), sizeof(tic_sample), true}, {"PATTERNS", MUSIC_PATTERNS, offsetof(tic_bank, music.patterns), sizeof(tic_track_pattern), true}, {"TRACKS", MUSIC_TRACKS, offsetof(tic_bank, music.tracks), sizeof(tic_track), true}, + {"FLAGS", TIC_SPRITE_BANKS, offsetof(tic_bank, flags), TIC_BANK_SPRITES, true}, {"PALETTE", 1, offsetof(tic_bank, palette), sizeof(tic_palette), false}, }; @@ -2339,6 +2340,7 @@ static void onConsoleRamCommand(Console* console, const char* param) {offsetof(tic_ram, music.patterns.data), "MUSIC PATTERNS"}, {offsetof(tic_ram, music.tracks.data), "MUSIC TRACKS"}, {offsetof(tic_ram, sound_state), "SOUND STATE"}, + {offsetof(tic_ram, flags), "SPRITE FLAGS"}, {offsetof(tic_ram, free), "..."}, {TIC_RAM_SIZE, ""}, }; diff --git a/src/sprite.c b/src/sprite.c index 6b5afa4..7694f3d 100644 --- a/src/sprite.c +++ b/src/sprite.c @@ -572,6 +572,83 @@ static void flipCanvasVert(Sprite* sprite) copySelection(sprite); } +static s32* getSpriteIndexes(Sprite* sprite) +{ + static s32 indexes[TIC_SPRITESIZE*TIC_SPRITESIZE+1]; + memset(indexes, -1, sizeof indexes); + + { + tic_rect r = {sprite->index % SHEET_COLS, sprite->index / SHEET_COLS + , sprite->size / TIC_SPRITESIZE, sprite->size / TIC_SPRITESIZE}; + + s32 c = 0; + for(s32 j = r.y; j < r.h + r.y; j++) + for(s32 i = r.x; i < r.w + r.x; i++) + indexes[c++] = i + j * SHEET_COLS; + + } + + return indexes; +} + +static void drawFlags(Sprite* sprite, s32 x, s32 y) +{ + if(hasCanvasSelection(sprite)) return; + + enum {Flags = 8, Size = 5}; + + u8* flags = getBankFlags()->data; + u8 or = 0; + u8 and = 0xff; + + s32* indexes = getSpriteIndexes(sprite); + + { + s32* i = indexes; + while(*i >= 0) + { + or |= flags[*i]; + and &= flags[*i]; + i++; + } + } + + for(s32 i = 0; i < Flags; i++) + { + const u8 mask = 1 << i; + tic_rect rect = {x, y + (Size+1)*i, Size, Size}; + + bool over = false; + if(checkMousePos(&rect)) + { + setCursor(tic_cursor_hand); + over = true; + + if(checkMouseClick(&rect, tic_mouse_left)) + { + s32* i = indexes; + + if(or & mask) + while(*i >= 0) + flags[*i++] &= ~mask; + else + while(*i >= 0) + flags[*i++] |= mask; + } + } + + sprite->tic->api.rect(sprite->tic, rect.x, rect.y, Size, Size, tic_color_black); + + if(or & mask) + sprite->tic->api.pixel(sprite->tic, rect.x+2, rect.y+2, over ? tic_color_white : tic_color_gray); + + if(and & mask) + sprite->tic->api.rect(sprite->tic, rect.x+1, rect.y+1, Size-2, Size-2, over ? tic_color_white : tic_color_gray); + + sprite->tic->api.draw_char(sprite->tic, '0' + i, rect.x + (Size+2), rect.y, tic_color_dark_gray, true); + } +} + static void drawMoveButtons(Sprite* sprite) { if(hasCanvasSelection(sprite)) @@ -1599,6 +1676,7 @@ static void tick(Sprite* sprite) drawCanvas(sprite, 24, 20); drawMoveButtons(sprite); + drawFlags(sprite, 24+64+7, 20+8); sprite->editPalette ? drawRGBSliders(sprite, 24, 91) diff --git a/src/studio.c b/src/studio.c index c4fdfd0..a93152d 100644 --- a/src/studio.c +++ b/src/studio.c @@ -297,6 +297,11 @@ tic_palette* getBankPalette() return &impl.studio.tic->cart.banks[impl.bank.index.sprites].palette; } +tic_flags* getBankFlags() +{ + return &impl.studio.tic->cart.banks[impl.bank.index.sprites].flags; +} + void playSystemSfx(s32 id) { const tic_sample* effect = &impl.config->cart.bank0.sfx.samples.data[id]; diff --git a/src/studio.h b/src/studio.h index 9a06f05..1ca40d2 100644 --- a/src/studio.h +++ b/src/studio.h @@ -157,6 +157,7 @@ void runProject(); tic_tiles* getBankTiles(); tic_palette* getBankPalette(); +tic_flags* getBankFlags(); tic_map* getBankMap(); char getKeyboardText(); diff --git a/src/tic.c b/src/tic.c index 2c746c2..84819c6 100644 --- a/src/tic.c +++ b/src/tic.c @@ -52,7 +52,7 @@ typedef enum CHUNK_COVER, // 3 CHUNK_MAP, // 4 CHUNK_CODE, // 5 - CHUNK_TEMP, // 6 + CHUNK_FLAGS, // 6 CHUNK_TEMP2, // 7 CHUNK_TEMP3, // 8 CHUNK_SAMPLES, // 9 @@ -775,6 +775,28 @@ static void api_sprite_ex(tic_mem* memory, const tic_tiles* src, s32 index, s32 } } +static inline u8* getFlag(tic_mem* memory, s32 index, u8 flag) +{ + static u8 stub; + if(index >= TIC_FLAGS || flag >= BITS_IN_BYTE) + return &stub; + + return memory->ram.flags.data + index; +} + +static bool api_get_flag(tic_mem* memory, s32 index, u8 flag) +{ + return *getFlag(memory, index, flag) & (1 << flag); +} + +static void api_set_flag(tic_mem* memory, s32 index, u8 flag, bool value) +{ + if(value) + *getFlag(memory, index, flag) |= (1 << flag); + else + *getFlag(memory, index, flag) &= ~(1 << flag); +} + s32 drawSpriteFont(tic_mem* memory, u8 symbol, s32 x, s32 y, s32 width, s32 height, u8 chromakey, s32 scale, bool alt) { api_sprite_ex(memory, &memory->ram.sprites, symbol, x, y, 1, 1, &chromakey, 1, scale, tic_no_flip, tic_no_rotate); @@ -1512,6 +1534,7 @@ static void api_sync(tic_mem* tic, u32 mask, s32 bank, bool toCart) {offsetof(tic_bank, sfx), offsetof(tic_ram, sfx), sizeof(tic_sfx) }, {offsetof(tic_bank, music), offsetof(tic_ram, music), sizeof(tic_music) }, {offsetof(tic_bank, palette), offsetof(tic_ram, vram.palette), sizeof(tic_palette) }, + {offsetof(tic_bank, flags), offsetof(tic_ram, flags), sizeof(tic_flags) }, }; enum{Count = COUNT_OF(Sections), Mask = (1 << Count) - 1}; @@ -1842,6 +1865,7 @@ static void api_load(tic_cartridge* cart, const u8* buffer, s32 size, bool palet case CHUNK_MUSIC: LOAD_CHUNK(cart->banks[chunk.bank].music.tracks); break; case CHUNK_PATTERNS: LOAD_CHUNK(cart->banks[chunk.bank].music.patterns); break; case CHUNK_PALETTE: LOAD_CHUNK(cart->banks[chunk.bank].palette); break; + case CHUNK_FLAGS: LOAD_CHUNK(cart->banks[chunk.bank].flags); break; case CHUNK_CODE: if(chunk.bank == 0) LOAD_CHUNK(cart->code); @@ -1913,6 +1937,7 @@ static s32 api_save(const tic_cartridge* cart, u8* buffer) buffer = SAVE_CHUNK(CHUNK_PATTERNS, cart->banks[i].music.patterns, i); buffer = SAVE_CHUNK(CHUNK_MUSIC, cart->banks[i].music.tracks, i); buffer = SAVE_CHUNK(CHUNK_PALETTE, cart->banks[i].palette, i); + buffer = SAVE_CHUNK(CHUNK_FLAGS, cart->banks[i].flags, i); } buffer = SAVE_CHUNK(CHUNK_CODE, cart->code, 0); @@ -2021,6 +2046,8 @@ static void initApi(tic_api* api) INIT_API(rect_border); INIT_API(sprite); INIT_API(sprite_ex); + INIT_API(get_flag); + INIT_API(set_flag); INIT_API(map); INIT_API(remap); INIT_API(map_set); diff --git a/src/tic.h b/src/tic.h index 6d91e1f..86f08f8 100644 --- a/src/tic.h +++ b/src/tic.h @@ -64,6 +64,7 @@ #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 @@ -364,6 +365,11 @@ typedef struct tic_tile data[TIC_BANK_SPRITES]; } tic_tiles; +typedef struct +{ + u8 data[TIC_FLAGS]; +} tic_flags; + typedef struct { tic_tiles tiles; @@ -372,6 +378,7 @@ typedef struct tic_sfx sfx; tic_music music; tic_palette palette; + tic_flags flags; } tic_bank; typedef struct @@ -457,7 +464,8 @@ typedef union tic_sfx sfx; tic_music music; tic_sound_state sound_state; - u8 free[16*1024]; + tic_flags flags; + u8 free[16*1024 - sizeof(tic_flags)]; }; u8 data[TIC_RAM_SIZE]; diff --git a/src/ticapi.h b/src/ticapi.h index 66f21f0..ddd3772 100644 --- a/src/ticapi.h +++ b/src/ticapi.h @@ -132,6 +132,8 @@ typedef struct void (*rect) (tic_mem* memory, s32 x, s32 y, s32 width, s32 height, u8 color); void (*rect_border) (tic_mem* memory, s32 x, s32 y, s32 width, s32 height, u8 color); void (*sprite) (tic_mem* memory, const tic_tiles* src, s32 index, s32 x, s32 y, u8* colors, s32 count); + bool (*get_flag) (tic_mem* memory, s32 index, u8 flag); + void (*set_flag) (tic_mem* memory, s32 index, u8 flag, bool value); void (*sprite_ex) (tic_mem* memory, const tic_tiles* src, s32 index, s32 x, s32 y, s32 w, s32 h, u8* colors, s32 count, s32 scale, tic_flip flip, tic_rotate rotate); void (*map) (tic_mem* memory, const tic_map* src, const tic_tiles* tiles, s32 x, s32 y, s32 width, s32 height, s32 sx, s32 sy, u8 chromakey, s32 scale); void (*remap) (tic_mem* memory, const tic_map* src, const tic_tiles* tiles, s32 x, s32 y, s32 width, s32 height, s32 sx, s32 sy, u8 chromakey, s32 scale, RemapFunc remap, void* data);