Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
738 lines
17 KiB
C
738 lines
17 KiB
C
// ____________________________
|
|
// ██▀▀█▀▀██▀▀▀▀▀▀▀█▀▀█ │ ▄▄▄ ▄▄
|
|
// ██ ▀ █▄ ▀██▄ ▀ ▄█ ▄▀▀ █ │ ▀█▄ ▄▀██ ▄█▄█ ██▀▄ ██ ▄███
|
|
// █ █ █ ▀▀ ▄█ █ █ ▀▄█ █▄ │ ▄▄█▀ ▀▄██ ██ █ ██▀ ▀█▄ ▀█▄▄
|
|
// ▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀────────┘ ▀▀
|
|
// Sprite tool sample
|
|
//─────────────────────────────────────────────────────────────────────────────
|
|
|
|
//=============================================================================
|
|
// INCLUDES
|
|
//=============================================================================
|
|
#include "msxgl.h"
|
|
#include "bios.h"
|
|
#include "memory.h"
|
|
#include "fsm.h"
|
|
#include "sprite_fx.h"
|
|
|
|
//=============================================================================
|
|
// DEFINES
|
|
//=============================================================================
|
|
|
|
// Pattern enums
|
|
#define PATTERN_16_NUM (u8)(6*2*4)
|
|
#define SPRITE_8_NUM 16
|
|
|
|
// Functions
|
|
typedef void (*fxFunc)(const u8*, u8*);
|
|
|
|
// 8-bits unsigned vector structure
|
|
typedef struct
|
|
{
|
|
const u8* Name;
|
|
fxFunc Func;
|
|
} EffectInfo;
|
|
|
|
// Function prototypes
|
|
void Init16();
|
|
void Update16();
|
|
void Init8();
|
|
void Update8();
|
|
|
|
void DoCropLeft8(const u8* src, u8* dest);
|
|
void DoCropRight8(const u8* src, u8* dest);
|
|
void DoCropTop8(const u8* src, u8* dest);
|
|
void DoCropBottom8(const u8* src, u8* dest);
|
|
void DoMask8(const u8* src, u8* dest);
|
|
void SpriteFX_FlipVertical8(const u8* src, u8* dest);
|
|
void SpriteFX_FlipHorizontal8(const u8* src, u8* dest);
|
|
void SpriteFX_RotateRight8(const u8* src, u8* dest);
|
|
void SpriteFX_RotateLeft8(const u8* src, u8* dest);
|
|
void SpriteFX_RotateHalfTurn8(const u8* src, u8* dest);
|
|
|
|
//=============================================================================
|
|
// READ-ONLY DATA
|
|
//=============================================================================
|
|
|
|
// Fonts
|
|
#include "font/font_mgl_sample8.h"
|
|
#include "font/font_mgl_symbol1.h"
|
|
|
|
// Sprite by GrafxKid (https://opengameart.org/content/super-random-sprites)
|
|
#include "content/data_sprt_16or.h"
|
|
|
|
// Character animation
|
|
const u8 g_CharAnim[] = { '|', '\\', '-', '/' };
|
|
|
|
//
|
|
const u8 g_Mask1[32] =
|
|
{
|
|
0b00000111,
|
|
0b00011111,
|
|
0b00111111,
|
|
0b01111111,
|
|
0b01111111,
|
|
0b11111111,
|
|
0b11111111,
|
|
0b11111111,
|
|
0b11111111,
|
|
0b11111111,
|
|
0b11111111,
|
|
0b01111111,
|
|
0b01111111,
|
|
0b00111111,
|
|
0b00011111,
|
|
0b00000111,
|
|
|
|
0b11100000,
|
|
0b11111000,
|
|
0b11111100,
|
|
0b11111110,
|
|
0b11111110,
|
|
0b11111111,
|
|
0b11111111,
|
|
0b11111111,
|
|
0b11111111,
|
|
0b11111111,
|
|
0b11111111,
|
|
0b11111110,
|
|
0b11111110,
|
|
0b11111100,
|
|
0b11111000,
|
|
0b11100000,
|
|
};
|
|
|
|
//
|
|
const u8 g_Mask2[32] =
|
|
{
|
|
0b00000000,
|
|
0b00000000,
|
|
0b00000011,
|
|
0b00001111,
|
|
0b00011111,
|
|
0b00011111,
|
|
0b00111111,
|
|
0b00111111,
|
|
0b00111111,
|
|
0b00111111,
|
|
0b00011111,
|
|
0b00011111,
|
|
0b00001111,
|
|
0b00000011,
|
|
0b00000000,
|
|
0b00000000,
|
|
|
|
0b00000000,
|
|
0b00000000,
|
|
0b11000000,
|
|
0b11110000,
|
|
0b11111000,
|
|
0b11111000,
|
|
0b11111100,
|
|
0b11111100,
|
|
0b11111100,
|
|
0b11111100,
|
|
0b11111000,
|
|
0b11111000,
|
|
0b11110000,
|
|
0b11000000,
|
|
0b00000000,
|
|
0b00000000,
|
|
};
|
|
|
|
//
|
|
const u8 g_Mask3[32] =
|
|
{
|
|
0b00000000,
|
|
0b00000000,
|
|
0b00000000,
|
|
0b00000000,
|
|
0b00000011,
|
|
0b00000111,
|
|
0b00001111,
|
|
0b00001111,
|
|
0b00001111,
|
|
0b00001111,
|
|
0b00000111,
|
|
0b00000011,
|
|
0b00000000,
|
|
0b00000000,
|
|
0b00000000,
|
|
0b00000000,
|
|
|
|
0b00000000,
|
|
0b00000000,
|
|
0b00000000,
|
|
0b00000000,
|
|
0b11000000,
|
|
0b11100000,
|
|
0b11110000,
|
|
0b11110000,
|
|
0b11110000,
|
|
0b11110000,
|
|
0b11100000,
|
|
0b11000000,
|
|
0b00000000,
|
|
0b00000000,
|
|
0b00000000,
|
|
0b00000000,
|
|
};
|
|
|
|
//
|
|
const u8 g_Mask4[32] =
|
|
{
|
|
0b00000000,
|
|
0b00000000,
|
|
0b00000000,
|
|
0b00000000,
|
|
0b00000000,
|
|
0b00000000,
|
|
0b00000001,
|
|
0b00000011,
|
|
0b00000011,
|
|
0b00000001,
|
|
0b00000000,
|
|
0b00000000,
|
|
0b00000000,
|
|
0b00000000,
|
|
0b00000000,
|
|
0b00000000,
|
|
|
|
0b00000000,
|
|
0b00000000,
|
|
0b00000000,
|
|
0b00000000,
|
|
0b00000000,
|
|
0b00000000,
|
|
0b10000000,
|
|
0b11000000,
|
|
0b11000000,
|
|
0b10000000,
|
|
0b00000000,
|
|
0b00000000,
|
|
0b00000000,
|
|
0b00000000,
|
|
0b00000000,
|
|
0b00000000,
|
|
};
|
|
|
|
//
|
|
const u8 g_Mask8[8][8] =
|
|
{
|
|
{
|
|
0b11111111,
|
|
0b11111111,
|
|
0b11111111,
|
|
0b11111111,
|
|
0b11111111,
|
|
0b11111111,
|
|
0b11111111,
|
|
0b11111111,
|
|
},
|
|
{
|
|
0b11111111,
|
|
0b11111111,
|
|
0b11111111,
|
|
0b11101111,
|
|
0b11111111,
|
|
0b11111111,
|
|
0b11111111,
|
|
0b11111111,
|
|
},
|
|
{
|
|
0b11111111,
|
|
0b11111111,
|
|
0b11111111,
|
|
0b11100111,
|
|
0b11100111,
|
|
0b11111111,
|
|
0b11111111,
|
|
0b11111111,
|
|
},
|
|
{
|
|
0b11111111,
|
|
0b11111111,
|
|
0b11100111,
|
|
0b11000011,
|
|
0b11000011,
|
|
0b11100111,
|
|
0b11111111,
|
|
0b11111111,
|
|
},
|
|
{
|
|
0b11111111,
|
|
0b11100111,
|
|
0b11000011,
|
|
0b10000001,
|
|
0b10000001,
|
|
0b11000011,
|
|
0b11100111,
|
|
0b11111111,
|
|
},
|
|
{
|
|
0b11111111,
|
|
0b11000011,
|
|
0b10000001,
|
|
0b10000001,
|
|
0b10000001,
|
|
0b10000001,
|
|
0b11100111,
|
|
0b11111111,
|
|
},
|
|
{
|
|
0b11000011,
|
|
0b10000001,
|
|
0b00000000,
|
|
0b00000000,
|
|
0b00000000,
|
|
0b00000000,
|
|
0b10000001,
|
|
0b11000011,
|
|
},
|
|
{
|
|
0b00000000,
|
|
0b00000000,
|
|
0b00000000,
|
|
0b00000000,
|
|
0b00000000,
|
|
0b00000000,
|
|
0b00000000,
|
|
0b00000000,
|
|
},
|
|
};
|
|
|
|
//
|
|
const u8* g_MaskAnim[] = { 1, g_Mask1, g_Mask2, g_Mask3, g_Mask4, 0, g_Mask4, g_Mask3, g_Mask2, g_Mask1 };
|
|
|
|
//
|
|
const u8* g_RotAnim[] = { g_PatternData, g_PatternDataRotLeft, g_PatternDataRotHalf, g_PatternDataRotRight };
|
|
|
|
//
|
|
const FSM_State g_State8 = { 0, Init8, Update8, NULL };
|
|
const FSM_State g_State16 = { 0, Init16, Update16, NULL };
|
|
|
|
//
|
|
const EffectInfo g_Effect[] =
|
|
{
|
|
{ "None", NULL },
|
|
{ "Crop Left", DoCropLeft8 },
|
|
{ "Crop Right", DoCropRight8 },
|
|
{ "Crop Top", DoCropTop8 },
|
|
{ "Crop Bottom", DoCropBottom8 },
|
|
{ "Mask", DoMask8 },
|
|
{ "Flip Vertical", SpriteFX_FlipVertical8 },
|
|
{ "Flip Horizontal", SpriteFX_FlipHorizontal8 },
|
|
{ "Rotate Right", SpriteFX_RotateRight8 },
|
|
{ "Rotate Left", SpriteFX_RotateLeft8 },
|
|
{ "Rotate 180", SpriteFX_RotateHalfTurn8 },
|
|
};
|
|
|
|
//=============================================================================
|
|
// MEMORY DATA
|
|
//=============================================================================
|
|
|
|
// Screen mode setting index
|
|
u8 g_VBlank = 0;
|
|
u8 g_Frame = 0;
|
|
|
|
// Sprite data
|
|
u8 g_PatternData[PATTERN_16_NUM * 8];
|
|
u8 g_PatternDataRotRight[PATTERN_16_NUM * 8];
|
|
u8 g_PatternDataRotLeft[PATTERN_16_NUM * 8];
|
|
u8 g_PatternDataRotHalf[PATTERN_16_NUM * 8];
|
|
|
|
// Sprite buffer
|
|
u8 g_Buffer1[32];
|
|
u8 g_Buffer2[32];
|
|
u8 g_Buffer3[32];
|
|
u8 g_Buffer4[32];
|
|
|
|
// Sprite X position
|
|
u8 g_PosX0;
|
|
u8 g_PosX1;
|
|
|
|
//
|
|
u8 g_FXIndex;
|
|
VectorU8 g_SpritePos[SPRITE_8_NUM];
|
|
|
|
//=============================================================================
|
|
// HELPER FUNCTIONS
|
|
//=============================================================================
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// H_TIMI interrupt hook
|
|
void VBlankHook()
|
|
{
|
|
g_VBlank = 1;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Wait for V-Blank period
|
|
void WaitVBlank()
|
|
{
|
|
while (g_VBlank == 0) {}
|
|
g_VBlank = 0;
|
|
g_Frame++;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Fill sprite pattern
|
|
void VDP_FillSpritePattern(u8 val, u8 index, u8 count)
|
|
{
|
|
u16 low = g_SpritePatternLow;
|
|
low += (index * 8);
|
|
VDP_FillVRAM(val, low, g_SpritePatternHigh, count * 8);
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
//
|
|
void DoCropLeft8(const u8* src, u8* dest) { SpriteFX_CropLeft8(src, dest, (g_Frame >> 3) % 8); }
|
|
|
|
//-----------------------------------------------------------------------------
|
|
//
|
|
void DoCropRight8(const u8* src, u8* dest) { SpriteFX_CropRight8(src, dest, (g_Frame >> 3) % 8); }
|
|
|
|
//-----------------------------------------------------------------------------
|
|
//
|
|
void DoCropTop8(const u8* src, u8* dest) { SpriteFX_CropTop8(src, dest, (g_Frame >> 3) % 8); }
|
|
|
|
//-----------------------------------------------------------------------------
|
|
//
|
|
void DoCropBottom8(const u8* src, u8* dest) { SpriteFX_CropBottom8(src, dest, (g_Frame >> 3) % 8); }
|
|
|
|
//-----------------------------------------------------------------------------
|
|
//
|
|
void DoMask8(const u8* src, u8* dest) { SpriteFX_Mask8(src, dest, g_Mask8[(g_Frame >> 3) % 8]); }
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Initialize 16x16
|
|
void Init16()
|
|
{
|
|
// Setup screen
|
|
VDP_SetMode(VDP_MODE_SCREEN4);
|
|
VDP_SetColor(COLOR_DARK_BLUE);
|
|
VDP_ClearVRAM();
|
|
|
|
// Setup sprite
|
|
VDP_EnableSprite(TRUE);
|
|
VDP_SetSpriteFlag(VDP_SPRITE_SIZE_16);
|
|
|
|
// Load 16x16 sprites (Pattern 96~143)
|
|
u8* ptr = g_PatternData;
|
|
for (u8 i5 = 0; i5 < 6; i5++)
|
|
{
|
|
Mem_Copy((u8*)g_DataSprt16or + (i5 * 2 + 0) * 8, ptr, 8); ptr += 8;
|
|
Mem_Copy((u8*)g_DataSprt16or + (i5 * 2 + 12) * 8, ptr, 8); ptr += 8;
|
|
Mem_Copy((u8*)g_DataSprt16or + (i5 * 2 + 1) * 8, ptr, 8); ptr += 8;
|
|
Mem_Copy((u8*)g_DataSprt16or + (i5 * 2 + 13) * 8, ptr, 8); ptr += 8;
|
|
}
|
|
for (u8 i6 = 0; i6 < 6; i6++)
|
|
{
|
|
Mem_Copy((u8*)g_DataSprt16or + (i6 * 2 + 24) * 8, ptr, 8); ptr += 8;
|
|
Mem_Copy((u8*)g_DataSprt16or + (i6 * 2 + 36) * 8, ptr, 8); ptr += 8;
|
|
Mem_Copy((u8*)g_DataSprt16or + (i6 * 2 + 25) * 8, ptr, 8); ptr += 8;
|
|
Mem_Copy((u8*)g_DataSprt16or + (i6 * 2 + 37) * 8, ptr, 8); ptr += 8;
|
|
}
|
|
|
|
// Initialize 16x16 OR sprites
|
|
VDP_SetPaletteEntry(2, RGB16(7, 7, 7));
|
|
VDP_SetPaletteEntry(3, RGB16(6, 4, 1));
|
|
VDP_SetSpriteExUniColor(0, 0, 32-1, 0, 0x02);
|
|
VDP_SetSpriteExUniColor(1, 0, 32-1, 4, VDP_SPRITE_CC + 0x01);
|
|
VDP_SetSpriteExUniColor(2, 0, 80-1, 8, 0x02);
|
|
VDP_SetSpriteExUniColor(3, 0, 80-1, 12, VDP_SPRITE_CC + 0x01);
|
|
VDP_SetSpriteExUniColor(4, 0, 128-1, 16, 0x02);
|
|
VDP_SetSpriteExUniColor(5, 0, 128-1, 20, VDP_SPRITE_CC + 0x01);
|
|
VDP_SetSpriteExUniColor(6, 64, (u8)(176-1), 24, 0x02);
|
|
VDP_SetSpriteExUniColor(7, 64, (u8)(176-1), 28, VDP_SPRITE_CC + 0x01);
|
|
VDP_DisableSpritesFrom(8);
|
|
g_PosX0 = 0;
|
|
g_PosX1 = 0;
|
|
|
|
// Compute transformed sprite data
|
|
loop (i, 6 * 2)
|
|
{
|
|
u16 idx = i * 4 * 8;
|
|
SpriteFX_RotateRight16(&g_PatternData[idx], &g_PatternDataRotRight[idx]);
|
|
SpriteFX_RotateLeft16(&g_PatternData[idx], &g_PatternDataRotLeft[idx]);
|
|
SpriteFX_RotateHalfTurn16(&g_PatternData[idx], &g_PatternDataRotHalf[idx]);
|
|
}
|
|
|
|
// Setup print
|
|
Print_SetTextFont(g_Font_MGL_Sample8, 0);
|
|
Print_SetColor(0xF, 0x4);
|
|
VDP_FillVRAM_16K(COLOR_MERGE(COLOR_LIGHT_BLUE, COLOR_DARK_BLUE), g_ScreenColorLow + (32*4*8) + (0*256*8), 32*4*8);
|
|
VDP_FillVRAM_16K(COLOR_MERGE(COLOR_LIGHT_BLUE, COLOR_DARK_BLUE), g_ScreenColorLow + (32*4*8) + (1*256*8), 32*4*8);
|
|
VDP_FillVRAM_16K(COLOR_MERGE(COLOR_LIGHT_BLUE, COLOR_DARK_BLUE), g_ScreenColorLow + (32*4*8) + (2*256*8), 32*4*8);
|
|
|
|
Print_DrawTextAt(0, 0, "\x2\x3\x4\x5 SPRITE FX SAMPLE (16x16)");
|
|
Print_DrawCharXAt(0, 1, '\x17', 32);
|
|
|
|
Print_DrawTextAt(1, 4, "Crop R/L");
|
|
Print_DrawTextAt(15, 3, "\x9F\x9F");
|
|
Print_DrawTextAt(15, 4, "\x9F\x9F");
|
|
Print_DrawTextAt(15, 5, "\x9F\x9F");
|
|
Print_DrawCharXAt(0, 6, '\x9F', 32);
|
|
|
|
Print_DrawTextAt(1, 10, "Flip H");
|
|
Print_DrawCharXAt(0, 12, '\x9F', 32);
|
|
|
|
Print_DrawTextAt(1, 16, "Mask");
|
|
Print_DrawCharXAt(0, 18, '\x9F', 32);
|
|
|
|
Print_DrawTextAt(1, 22, "Rotate");
|
|
|
|
Print_DrawTextAt(31-7, 22, "\x82:Flip V");
|
|
Print_DrawTextAt(31-7, 23, "\x83:8x8");
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Update 16x16
|
|
void Update16()
|
|
{
|
|
bool bToggle = Keyboard_IsKeyPressed(KEY_UP) || Keyboard_IsKeyPressed(KEY_DOWN);
|
|
|
|
u8 frame = (g_Frame >> 2) % 6;
|
|
u8 pat = (frame * 8 * 4);
|
|
|
|
// Crop right/left
|
|
g_PosX0++;
|
|
VDP_SetSpritePositionX(0, g_PosX0);
|
|
VDP_SetSpritePositionX(1, g_PosX0);
|
|
u8* pat1 = g_PatternData + pat;
|
|
u8* pat2 = g_PatternData + pat + 24 * 8;
|
|
if ((g_PosX0 > 104) && (g_PosX0 <= 120))
|
|
{
|
|
u8 offset = g_PosX0 - 105;
|
|
SpriteFX_CropRight16(pat1, g_Buffer1, offset);
|
|
SpriteFX_CropRight16(pat2, g_Buffer2, offset);
|
|
pat1 = g_Buffer1;
|
|
pat2 = g_Buffer2;
|
|
}
|
|
else if ((g_PosX0 >= 120) && (g_PosX0 < 136))
|
|
{
|
|
u8 offset = 15 - (g_PosX0 - 120);
|
|
SpriteFX_CropLeft16(pat1, g_Buffer1, offset);
|
|
SpriteFX_CropLeft16(pat2, g_Buffer2, offset);
|
|
pat1 = g_Buffer1;
|
|
pat2 = g_Buffer2;
|
|
}
|
|
if (bToggle)
|
|
{
|
|
SpriteFX_FlipVertical16(pat1, g_Buffer3);
|
|
SpriteFX_FlipVertical16(pat2, g_Buffer4);
|
|
pat1 = g_Buffer3;
|
|
pat2 = g_Buffer4;
|
|
}
|
|
VDP_LoadSpritePattern(pat1, 0, 4);
|
|
VDP_LoadSpritePattern(pat2, 4, 4);
|
|
|
|
// Flip horizontal
|
|
g_PosX1--;
|
|
VDP_SetSpritePositionX(2, g_PosX1);
|
|
VDP_SetSpritePositionX(3, g_PosX1);
|
|
pat1 = g_PatternData + pat;
|
|
pat2 = g_PatternData + pat + 24 * 8;
|
|
if (bToggle)
|
|
{
|
|
SpriteFX_Rotate180_16(pat1, g_Buffer1);
|
|
SpriteFX_Rotate180_16(pat2, g_Buffer2);
|
|
}
|
|
else
|
|
{
|
|
SpriteFX_FlipHorizontal16(pat1, g_Buffer1);
|
|
SpriteFX_FlipHorizontal16(pat2, g_Buffer2);
|
|
}
|
|
VDP_LoadSpritePattern(g_Buffer1, 8, 4);
|
|
VDP_LoadSpritePattern(g_Buffer2, 12, 4);
|
|
|
|
// Mask
|
|
VDP_SetSpritePositionX(4, g_PosX0);
|
|
VDP_SetSpritePositionX(5, g_PosX0);
|
|
frame = (g_Frame >> 3) % 10;
|
|
if (g_MaskAnim[frame] == 0)
|
|
{
|
|
VDP_FillSpritePattern(0, 16, 4);
|
|
VDP_FillSpritePattern(0, 20, 4);
|
|
}
|
|
else
|
|
{
|
|
pat1 = g_PatternData + pat;
|
|
pat2 = g_PatternData + pat + 24 * 8;
|
|
|
|
if (g_MaskAnim[frame] != (u8*)1)
|
|
{
|
|
SpriteFX_Mask16(pat1, g_Buffer1, g_MaskAnim[frame]);
|
|
SpriteFX_Mask16(pat2, g_Buffer2, g_MaskAnim[frame]);
|
|
pat1 = g_Buffer1;
|
|
pat2 = g_Buffer2;
|
|
}
|
|
if (bToggle)
|
|
{
|
|
SpriteFX_FlipVertical16(pat1, g_Buffer3);
|
|
SpriteFX_FlipVertical16(pat2, g_Buffer4);
|
|
pat1 = g_Buffer3;
|
|
pat2 = g_Buffer4;
|
|
}
|
|
VDP_LoadSpritePattern(pat1, 16, 4);
|
|
VDP_LoadSpritePattern(pat2, 20, 4);
|
|
}
|
|
|
|
// Rotate 90°
|
|
u8 rot = (g_Frame >> 4) % 4;
|
|
VDP_LoadSpritePattern(g_RotAnim[rot] + pat, 24, 4);
|
|
VDP_LoadSpritePattern(g_RotAnim[rot] + pat + (24 * 8), 28, 4);
|
|
|
|
if (Keyboard_IsKeyPressed(KEY_SPACE))
|
|
FSM_SetState(&g_State8);
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
//
|
|
void SetFX(u8 id)
|
|
{
|
|
g_FXIndex = id;
|
|
Print_DrawCharXAt(0, 3, '\0', 32);
|
|
Print_DrawTextAt(0, 3, "Effect: ");
|
|
Print_DrawText(g_Effect[g_FXIndex].Name);
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
//
|
|
void Init8()
|
|
{
|
|
// Setup screen
|
|
VDP_SetMode(VDP_MODE_SCREEN4);
|
|
VDP_SetColor(COLOR_DARK_BLUE);
|
|
VDP_ClearVRAM();
|
|
|
|
// Setup sprite
|
|
VDP_EnableSprite(TRUE);
|
|
VDP_SetSpriteFlag(VDP_SPRITE_SIZE_8);
|
|
|
|
// Loading sprite data
|
|
VDP_LoadSpritePattern(g_Font_MGL_Symbol1 + 4 + (16 * 10 * 8), 0, 32);
|
|
|
|
// Initialize sprite attribute
|
|
loop (i, SPRITE_8_NUM)
|
|
{
|
|
VectorU8* vec = &g_SpritePos[i];
|
|
vec->x = Math_GetRandom8();
|
|
vec->y = 32 + (Math_GetRandom8() % 128);
|
|
VDP_SetSpriteExUniColor(i, vec->x, vec->y, i, 7 + (i % 8));
|
|
}
|
|
|
|
// Setup print
|
|
Print_SetTextFont(g_Font_MGL_Sample8, 0);
|
|
Print_SetColor(0xF, 0x4);
|
|
VDP_FillVRAM_16K(COLOR_MERGE(COLOR_LIGHT_BLUE, COLOR_DARK_BLUE), g_ScreenColorLow + (32*4*8) + (0*256*8), 32*4*8);
|
|
VDP_FillVRAM_16K(COLOR_MERGE(COLOR_LIGHT_BLUE, COLOR_DARK_BLUE), g_ScreenColorLow + (32*4*8) + (1*256*8), 32*4*8);
|
|
VDP_FillVRAM_16K(COLOR_MERGE(COLOR_LIGHT_BLUE, COLOR_DARK_BLUE), g_ScreenColorLow + (32*4*8) + (2*256*8), 32*4*8);
|
|
|
|
Print_DrawTextAt(0, 0, "\x2\x3\x4\x5 SPRITE FX SAMPLE (8x8)");
|
|
Print_DrawCharXAt(0, 1, '\x17', 32);
|
|
|
|
Print_DrawTextAt(31-7, 20, "\x8D:FX");
|
|
Print_DrawTextAt(31-7, 21, "\x8E:None");
|
|
Print_DrawTextAt(31-7, 22, "\x8F:Stop");
|
|
Print_DrawTextAt(31-7, 23, "\x83:16x16");
|
|
|
|
SetFX(0);
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
//
|
|
void Update8()
|
|
{
|
|
bool bDefault = Keyboard_IsKeyPressed(KEY_UP);
|
|
bool bStop = Keyboard_IsKeyPressed(KEY_DOWN);
|
|
|
|
// Initialize sprite attribute
|
|
const u8* pat = g_Font_MGL_Symbol1 + 4 + (16 * 10 * 8);
|
|
u16 vram = g_SpritePatternLow;
|
|
loop (i, SPRITE_8_NUM)
|
|
{
|
|
if (!bStop && (g_Frame & 0x03) == 0)
|
|
{
|
|
VectorU8* vec = &g_SpritePos[i];
|
|
switch (i % 8)
|
|
{
|
|
case 0: vec->x++; vec->y++; break;
|
|
case 1: vec->x++; break;
|
|
case 2: vec->x++; vec->y--; break;
|
|
case 3: vec->y--; break;
|
|
case 4: vec->x--; vec->y--; break;
|
|
case 5: vec->x--; break;
|
|
case 6: vec->x--; vec->y++; break;
|
|
case 7: vec->y++; break;
|
|
}
|
|
if (vec->y < 32)
|
|
vec->y += 128;
|
|
if (vec->y > 128+32)
|
|
vec->y -= 128;
|
|
VDP_SetSpritePosition(i, vec->x, vec->y);
|
|
}
|
|
|
|
const EffectInfo* fx = &g_Effect[g_FXIndex];
|
|
const u8* ptr = pat;
|
|
if (!bDefault && fx->Func)
|
|
{
|
|
fx->Func(pat, g_Buffer1);
|
|
ptr = g_Buffer1;
|
|
}
|
|
VDP_WriteVRAM(ptr, vram, g_SpritePatternHigh, 8);
|
|
pat += 8;
|
|
vram += 8;
|
|
}
|
|
|
|
if (Keyboard_IsKeyPressed(KEY_RIGHT))
|
|
{
|
|
SetFX((g_FXIndex + 1) % numberof(g_Effect));
|
|
while (Keyboard_IsKeyPressed(KEY_RIGHT)) {}
|
|
}
|
|
else if (Keyboard_IsKeyPressed(KEY_LEFT))
|
|
{
|
|
SetFX((g_FXIndex + numberof(g_Effect) - 1) % numberof(g_Effect));
|
|
while (Keyboard_IsKeyPressed(KEY_LEFT)) {}
|
|
}
|
|
|
|
if (Keyboard_IsKeyPressed(KEY_SPACE))
|
|
FSM_SetState(&g_State16);
|
|
}
|
|
|
|
//=============================================================================
|
|
// MAIN LOOP
|
|
//=============================================================================
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Program entry point
|
|
void main()
|
|
{
|
|
// Setup system
|
|
BIOS_SetKeyClick(FALSE);
|
|
BIOS_SetHookCallback(H_TIMI, VBlankHook);
|
|
|
|
FSM_SetState(&g_State16);
|
|
|
|
bool bContinue = TRUE;
|
|
while (bContinue)
|
|
{
|
|
// VDP_SetColor(COLOR_DARK_BLUE);
|
|
WaitVBlank();
|
|
// VDP_SetColor(COLOR_LIGHT_BLUE);
|
|
|
|
FSM_Update();
|
|
|
|
// Sign-of-life
|
|
Print_DrawCharAt(31, 0, g_CharAnim[g_Frame & 0x03]);
|
|
|
|
if (Keyboard_IsKeyPressed(KEY_ESC))
|
|
bContinue = FALSE;
|
|
}
|
|
|
|
BIOS_ClearHook(H_TIMI);
|
|
BIOS_Exit(0);
|
|
}
|
|
|
|
|