Files
mazegame/projects/samples/s_sm1.c
T

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);
}