Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
333 lines
8.1 KiB
C
333 lines
8.1 KiB
C
// ____________________________
|
|
// ██▀▀█▀▀██▀▀▀▀▀▀▀█▀▀█ │ ▄▄▄ ▄▄
|
|
// ██ ▀ █▄ ▀██▄ ▀ ▄█ ▄▀▀ █ │ ▀█▄ ▄▀██ ▄█▄█ ██▀▄ ██ ▄███
|
|
// █ █ █ ▀▀ ▄█ █ █ ▀▄█ █▄ │ ▄▄█▀ ▀▄██ ██ █ ██▀ ▀█▄ ▀█▄▄
|
|
// ▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀────────┘ ▀▀
|
|
// Sprite mode 1 sample
|
|
//─────────────────────────────────────────────────────────────────────────────
|
|
|
|
//=============================================================================
|
|
// INCLUDES
|
|
//=============================================================================
|
|
#include "msxgl.h"
|
|
|
|
//=============================================================================
|
|
// DEFINES
|
|
//=============================================================================
|
|
|
|
// VRAM Tables Address
|
|
#define VRAM_LAYOUT_TABLE 0x3800
|
|
#define VRAM_COLOR_TABLE 0x2000
|
|
#define VRAM_PATTERN_TABLE 0x0000
|
|
#define VRAM_SPRITE_ATTRIBUTE_0 0x3E00
|
|
#define VRAM_SPRITE_ATTRIBUTE_1 0x3F00
|
|
#define VRAM_SPRITE_PATTERN 0x1800
|
|
|
|
// Pattern enum
|
|
#define PATTERN_8_NUM (u8)32
|
|
#define SPRITE_8_NUM (u8)32
|
|
|
|
// SAT MODE
|
|
enum SAT_MODE
|
|
{
|
|
SAT_STATIC = 0,
|
|
SAT_FLIP,
|
|
SAT_DOUBLE,
|
|
};
|
|
|
|
// Vector structure
|
|
struct Vector
|
|
{
|
|
i8 x, y;
|
|
};
|
|
|
|
//=============================================================================
|
|
// READ-ONLY DATA
|
|
//=============================================================================
|
|
|
|
// Fonts
|
|
#include "font/font_mgl_sample8.h"
|
|
#include "font/font_mgl_symbol1.h"
|
|
|
|
// Sprite movement
|
|
const struct Vector s_DirMove[] =
|
|
{
|
|
{ (i8)1, (i8)1 },
|
|
{ (i8)1, (i8)0 },
|
|
{ (i8)1, (i8)-1 },
|
|
{ (i8)0, (i8)-1 },
|
|
{ (i8)-1, (i8)-1 },
|
|
{ (i8)-1, (i8)0 },
|
|
{ (i8)-1, (i8)1 },
|
|
{ (i8)0, (i8)1 },
|
|
};
|
|
|
|
// Sprite Attribute Table
|
|
const u16 s_AddrSAT[] = { VRAM_SPRITE_ATTRIBUTE_0, VRAM_SPRITE_ATTRIBUTE_1 };
|
|
|
|
//=============================================================================
|
|
// MEMORY DATA
|
|
//=============================================================================
|
|
|
|
// Screen mode setting index
|
|
u8 g_VBlank = 0;
|
|
u8 g_Frame = 0;
|
|
u8 g_Size = 0;
|
|
u8 g_Scale = 0;
|
|
u8 g_SATMode = SAT_STATIC;
|
|
u8 g_Move = 0;
|
|
u8 g_Count = SPRITE_8_NUM;
|
|
|
|
// Sprite data
|
|
struct VDP_Sprite g_Sprite[32];
|
|
|
|
//=============================================================================
|
|
// 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++;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
//
|
|
void UpdateSpriteFlag()
|
|
{
|
|
u8 flag = 0;
|
|
|
|
Print_SetPosition(10, 19);
|
|
if (g_Size)
|
|
{
|
|
flag |= VDP_SPRITE_SIZE_16;
|
|
Print_DrawText("16px");
|
|
}
|
|
else
|
|
Print_DrawText("8px ");
|
|
|
|
Print_SetPosition(10, 20);
|
|
if (g_Scale)
|
|
{
|
|
flag |= VDP_SPRITE_SCALE_2;
|
|
Print_DrawText("x2");
|
|
}
|
|
else
|
|
Print_DrawText("x1");
|
|
|
|
VDP_SetSpriteFlag(flag);
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
//
|
|
void UpdateFlipSAT(u8 mode)
|
|
{
|
|
g_SATMode = mode;
|
|
Print_SetPosition(10, 21);
|
|
switch (g_SATMode)
|
|
{
|
|
case SAT_STATIC: Print_DrawText("Static"); break;
|
|
case SAT_FLIP: Print_DrawText("Flip "); break;
|
|
case SAT_DOUBLE: Print_DrawText("Double"); break;
|
|
}
|
|
|
|
VDP_SetSpriteAttributeTable(VRAM_SPRITE_ATTRIBUTE_0);
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
//
|
|
void UpdateMove(u8 move)
|
|
{
|
|
g_Move = move;
|
|
Print_SetPosition(10, 22);
|
|
if (g_Move)
|
|
Print_DrawText("\xC");
|
|
else
|
|
Print_DrawText("\xB");
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
//
|
|
void UpdateCount(u8 count)
|
|
{
|
|
if (count < 1)
|
|
return;
|
|
if (count > SPRITE_8_NUM)
|
|
return;
|
|
g_Count = count;
|
|
Print_SetPosition(10, 23);
|
|
Print_DrawInt(count);
|
|
Print_DrawText(" ");
|
|
}
|
|
|
|
|
|
|
|
//=============================================================================
|
|
// MAIN LOOP
|
|
//=============================================================================
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Program entry point
|
|
void main()
|
|
{
|
|
// Setup screen
|
|
VDP_SetMode(VDP_MODE_GRAPHIC2);
|
|
VDP_SetColor(0x44);
|
|
// Setup VRAM layout
|
|
VDP_SetLayoutTable(VRAM_LAYOUT_TABLE);
|
|
VDP_SetColorTable(VRAM_COLOR_TABLE);
|
|
VDP_SetPatternTable(VRAM_PATTERN_TABLE);
|
|
VDP_SetSpritePatternTable(VRAM_SPRITE_PATTERN);
|
|
VDP_SetSpriteAttributeTable(VRAM_SPRITE_ATTRIBUTE_0);
|
|
|
|
VDP_FillVRAM_16K(0, 0x0000, 0x4000); // Clear 16 KB of VRAM
|
|
|
|
// Setup print
|
|
Print_SetTextFont(g_Font_MGL_Sample8, 0);
|
|
Print_SetColor(0xF, 0x4);
|
|
Print_SetPosition(0, 0);
|
|
Print_DrawText("\x2\x3\x4\x5 SPRITE MODE 1 (G2)\n");
|
|
Print_DrawLineH(0, 1, 32);
|
|
|
|
Print_DrawLineH(0, 18, 32);
|
|
Print_SetPosition(0, 19);
|
|
Print_DrawText("F1:Size\n");
|
|
Print_DrawText("F2:Scale\n");
|
|
Print_DrawText("F3:SAT\n");
|
|
Print_DrawText("F4:Move\n");
|
|
Print_DrawText("\x81\x80:Count\n");
|
|
|
|
// Load 8x8 sprites
|
|
VDP_LoadSpritePattern(g_Font_MGL_Symbol1 + 4 + (16 * 10 * 8), 0, PATTERN_8_NUM);
|
|
|
|
// Initialize 8x8 sprites
|
|
for (u8 i = 0; i < SPRITE_8_NUM; ++i)
|
|
{
|
|
u16 rnd = Math_GetRandom16();
|
|
struct VDP_Sprite* sprt = &g_Sprite[i];
|
|
sprt->Y = rnd & 0x7F;
|
|
sprt->X = (rnd >> 7) & 0xFF;
|
|
sprt->Pattern = (rnd >> 4) % PATTERN_8_NUM;
|
|
sprt->Color = ((rnd >> 12) % 11) + 5;
|
|
|
|
g_SpriteAttributeLow = VRAM_SPRITE_ATTRIBUTE_0;
|
|
VDP_SetSpriteSM1(i, sprt->X, sprt->Y, sprt->Pattern, sprt->Color);
|
|
|
|
g_SpriteAttributeLow = VRAM_SPRITE_ATTRIBUTE_1;
|
|
VDP_SetSpriteSM1(SPRITE_8_NUM - 1 - i, sprt->X, sprt->Y, sprt->Pattern, sprt->Color);
|
|
}
|
|
|
|
UpdateSpriteFlag();
|
|
UpdateFlipSAT(SAT_STATIC);
|
|
UpdateMove(1);
|
|
UpdateCount(SPRITE_8_NUM);
|
|
|
|
BIOS_SetHookCallback(H_TIMI, VBlankHook);
|
|
VDP_EnableVBlank(TRUE);
|
|
|
|
u8 prevRow6 = 0xFF, prevRow7 = 0xFF, prevRow8 = 0xFF;
|
|
bool bContinue = TRUE;
|
|
while (bContinue)
|
|
{
|
|
// VDP_SetColor(COLOR_LIGHT_BLUE);
|
|
WaitVBlank();
|
|
// VDP_SetColor(COLOR_DARK_BLUE);
|
|
|
|
// Set current SAT
|
|
u16 vram;
|
|
i8 offset;
|
|
if (g_SATMode == SAT_STATIC)
|
|
{
|
|
vram = VRAM_SPRITE_ATTRIBUTE_0;
|
|
offset = 4;
|
|
}
|
|
else // if (g_SATMode != SAT_STATIC)
|
|
{
|
|
if ((g_Frame & 1) == 0)
|
|
{
|
|
VDP_SetSpriteAttributeTable(VRAM_SPRITE_ATTRIBUTE_0);
|
|
vram = VRAM_SPRITE_ATTRIBUTE_0;
|
|
offset = 4;
|
|
}
|
|
else
|
|
{
|
|
VDP_SetSpriteAttributeTable(VRAM_SPRITE_ATTRIBUTE_1);
|
|
vram = VRAM_SPRITE_ATTRIBUTE_1 + ((SPRITE_8_NUM - 1) * 4);
|
|
offset = -4;
|
|
}
|
|
}
|
|
|
|
// Update sprites attribute
|
|
struct VDP_Sprite* sprt = &g_Sprite[0];
|
|
for (u8 i = 0; i < SPRITE_8_NUM; i++)
|
|
{
|
|
if (g_Move)
|
|
{
|
|
const struct Vector* mov = &s_DirMove[i & 0x7];
|
|
sprt->Y = (sprt->Y + mov->y) & 0x7F;
|
|
sprt->X = sprt->X + mov->x;
|
|
}
|
|
if (i < g_Count)
|
|
VDP_WriteVRAM_16K((const u8*)sprt, vram, 2);
|
|
else
|
|
VDP_FillVRAM_16K(213, vram, 2);
|
|
|
|
sprt++;
|
|
vram += offset;
|
|
}
|
|
|
|
// Handle user input
|
|
u8 row6 = Keyboard_Read(6);
|
|
if (!IS_KEY_PRESSED(prevRow6, KEY_F1) && IS_KEY_PRESSED(row6, KEY_F1))
|
|
{
|
|
g_Size = 1 - g_Size;
|
|
UpdateSpriteFlag();
|
|
}
|
|
if (!IS_KEY_PRESSED(prevRow6, KEY_F2) && IS_KEY_PRESSED(row6, KEY_F2))
|
|
{
|
|
g_Scale = 1 - g_Scale;
|
|
UpdateSpriteFlag();
|
|
}
|
|
if (!IS_KEY_PRESSED(prevRow6, KEY_F3) && IS_KEY_PRESSED(row6, KEY_F3))
|
|
{
|
|
UpdateFlipSAT((g_SATMode + 1) % 2);
|
|
}
|
|
prevRow6 = row6;
|
|
|
|
u8 row7 = Keyboard_Read(7);
|
|
if (!IS_KEY_PRESSED(prevRow7, KEY_F4) && IS_KEY_PRESSED(row7, KEY_F4))
|
|
{
|
|
UpdateMove(1 - g_Move);
|
|
}
|
|
if (IS_KEY_PRESSED(prevRow7, KEY_ESC))
|
|
bContinue = FALSE;
|
|
prevRow7 = row7;
|
|
|
|
u8 row8 = Keyboard_Read(8);
|
|
if (IS_KEY_PRESSED(row8, KEY_RIGHT))
|
|
{
|
|
UpdateCount(g_Count + 1);
|
|
}
|
|
if (IS_KEY_PRESSED(row8, KEY_LEFT))
|
|
{
|
|
UpdateCount(g_Count - 1);
|
|
}
|
|
prevRow8 = row8;
|
|
}
|
|
|
|
BIOS_ClearHook(H_TIMI);
|
|
BIOS_Exit(0);
|
|
}
|
|
|
|
|