Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
242 lines
7.0 KiB
C
242 lines
7.0 KiB
C
// ____________________________
|
|
// ██▀▀█▀▀██▀▀▀▀▀▀▀█▀▀█ │ ▄▄▄ ▄▄
|
|
// ██ ▀ █▄ ▀██▄ ▀ ▄█ ▄▀▀ █ │ ▀█▄ ▄▀██ ▄█▄█ ██▀▄ ██ ▄███
|
|
// █ █ █ ▀▀ ▄█ █ █ ▀▄█ █▄ │ ▄▄█▀ ▀▄██ ██ █ ██▀ ▀█▄ ▀█▄▄
|
|
// ▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀────────┘ ▀▀
|
|
// Multi-directionnal scrolling sample
|
|
//
|
|
// Scrolling parameters (source data format, output window and used fetaures)
|
|
// are defined in msxgl_config.h for optimization purpose (the 'scroll' module
|
|
// is optimized at compile time to useonly necessary features).
|
|
//─────────────────────────────────────────────────────────────────────────────
|
|
#include "msxgl.h"
|
|
#include "scroll.h"
|
|
|
|
//=============================================================================
|
|
// DEFINES
|
|
//=============================================================================
|
|
|
|
// Library's logo
|
|
#define MSX_GL "\x02\x03\x04\x05"
|
|
|
|
#if (MSX_VERSION & MSX_1)
|
|
#define SET_SPRITE VDP_SetSpriteSM1
|
|
#else
|
|
#define SET_SPRITE VDP_SetSpriteExUniColor
|
|
#endif
|
|
|
|
//=============================================================================
|
|
// READ-ONLY DATA
|
|
//=============================================================================
|
|
|
|
// Fonts
|
|
#include "font/font_mgl_sample8.h"
|
|
// Tiles
|
|
#include "content/tile/data_tile_gm2.h"
|
|
#include "content/tile/data_map_gm2.h"
|
|
// Sprites by GrafxKid (https://opengameart.org/content/super-random-sprites)
|
|
#include "content/data_sprt_layer.h"
|
|
|
|
//=============================================================================
|
|
// MEMORY DATA
|
|
//=============================================================================
|
|
|
|
// Scrolling speed
|
|
i8 g_ScrollSpeed = 1;
|
|
|
|
// V-blank synchronization flag
|
|
u8 g_VBlank = 0;
|
|
|
|
// H-blank phase
|
|
u8 g_HBlank = 0;
|
|
|
|
//=============================================================================
|
|
// HELPER FUNCTIONS
|
|
//=============================================================================
|
|
|
|
#if ((SCROLL_ADJUST) && (SCROLL_ADJUST_SPLIT))
|
|
//-----------------------------------------------------------------------------
|
|
// H-Blank interrupt hook
|
|
void HBlankHook()
|
|
{
|
|
if (g_HBlank == 0)
|
|
{
|
|
Scroll_HBlankAdjust(1);
|
|
g_HBlank++;
|
|
}
|
|
else
|
|
{
|
|
Scroll_HBlankAdjust(2);
|
|
}
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// H_KEYI interrupt hook
|
|
void InterruptHook()
|
|
{
|
|
__asm
|
|
// Get S#1
|
|
ld a, #1
|
|
out (P_VDP_ADDR), a
|
|
ld a, #(0x80 + 15)
|
|
out (P_VDP_ADDR), a
|
|
in a, (P_VDP_STAT)
|
|
// Call H-Blank if bit #0 of S#1 is set
|
|
rrca
|
|
jp nc, _no_hblank
|
|
call _HBlankHook // call to C function HBlankHook()
|
|
_no_hblank:
|
|
// Reset R#15 to S#0
|
|
xor a
|
|
out (P_VDP_ADDR), a
|
|
ld a, #(0x80 + 15)
|
|
out (P_VDP_ADDR),a
|
|
__endasm;
|
|
|
|
// Call((u16)HookBackup_KEYI);
|
|
}
|
|
#endif // ((SCROLL_ADJUST) && (SCROLL_ADJUST_SPLIT))
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// H_TIMI interrupt hook
|
|
void VBlankHook()
|
|
{
|
|
g_VBlank = 1;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Wait for V-Blank period
|
|
void WaitVBlank()
|
|
{
|
|
while (g_VBlank == 0) {}
|
|
g_VBlank = 0;
|
|
#if ((SCROLL_ADJUST) && (SCROLL_ADJUST_SPLIT))
|
|
g_HBlank = 0;
|
|
Scroll_HBlankAdjust(0);
|
|
#endif
|
|
}
|
|
|
|
//=============================================================================
|
|
// MAIN LOOP
|
|
//=============================================================================
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Program entry point
|
|
void main()
|
|
{
|
|
// Initialize video
|
|
#if !(MSX_VERSION & MSX_1)
|
|
VDP_SetMode(VDP_MODE_GRAPHIC3); // Screen mode 4 (G3)
|
|
#else
|
|
VDP_SetMode(VDP_MODE_GRAPHIC2); // Screen mode 2 (G2)
|
|
#endif
|
|
// VRAM Tables Address
|
|
VDP_SetLayoutTable(0x3800);
|
|
VDP_SetColorTable(0x2000);
|
|
VDP_SetPatternTable(0x0000);
|
|
VDP_SetSpritePatternTable(0x1800);
|
|
VDP_SetSpriteAttributeTable(0x3E00);
|
|
// Setup video
|
|
VDP_SetColor(0xF0);
|
|
VDP_ClearVRAM();
|
|
VDP_EnableVBlank(TRUE);
|
|
#if ((SCROLL_ADJUST) && (SCROLL_ADJUST_SPLIT))
|
|
VDP_EnableHBlank(TRUE);
|
|
BIOS_SetHookCallback(H_KEYI, InterruptHook);
|
|
#endif
|
|
BIOS_SetHookCallback(H_TIMI, VBlankHook);
|
|
|
|
// Initialize text
|
|
Print_SetTextFont(g_Font_MGL_Sample8, 96);
|
|
VDP_FillLayout_GM2(96, 0, 0, 32, 24);
|
|
// Header
|
|
Print_DrawText(MSX_GL " SCROLL SAMPLE");
|
|
Print_DrawLineH(0, 1, 32);
|
|
// Footer
|
|
Print_DrawLineH(0, 22, 32);
|
|
Print_SetPosition(0, 23);
|
|
Print_DrawFormat("\x81\x82\x80:Scroll \x83:Speed(%i)", g_ScrollSpeed);
|
|
|
|
// Load tiles pattern
|
|
VDP_LoadPattern_GM2(g_DataMapGM2_Patterns, 94, 0);
|
|
VDP_LoadColor_GM2(g_DataMapGM2_Colors, 94, 0);
|
|
|
|
// Initialize scroll module
|
|
u8 sprt = Scroll_Initialize((u16)g_DataMapGM2_Names);
|
|
Scroll_SetOffsetV(16);
|
|
|
|
// Initialize sprite
|
|
// VDP_EnableSprite(TRUE);
|
|
VDP_SetSpriteFlag(VDP_SPRITE_SIZE_16 | VDP_SPRITE_SCALE_2);
|
|
VDP_LoadSpritePattern(g_DataSprtLayer, 32, 13*4*4);
|
|
SET_SPRITE(sprt+0, 70, 130, 32, COLOR_BLACK);
|
|
SET_SPRITE(sprt+1, 70, 130, 36, COLOR_WHITE);
|
|
SET_SPRITE(sprt+2, 70, 130, 40, COLOR_LIGHT_RED);
|
|
VDP_DisableSpritesFrom(sprt+3);
|
|
|
|
u8 frame = 0;
|
|
u8 prevRow8 = 0xFF;
|
|
while (1)
|
|
{
|
|
// Wait for v-synch
|
|
WaitVBlank();
|
|
|
|
// Update scrolling rendering
|
|
Scroll_Update();
|
|
|
|
u8 sprtOffset = g_Scroll_OffsetX % 8;
|
|
VDP_SetSpritePositionX(sprt+0, 70 + sprtOffset);
|
|
VDP_SetSpritePositionX(sprt+1, 70 + sprtOffset);
|
|
VDP_SetSpritePositionX(sprt+2, 70 + sprtOffset);
|
|
|
|
u8 shape = 6;
|
|
|
|
u8 row8 = Keyboard_Read(8);
|
|
// Update scrolling speed
|
|
if (IS_KEY_PRESSED(row8, KEY_SPACE) && !IS_KEY_PRESSED(prevRow8, KEY_SPACE))
|
|
{
|
|
if (g_ScrollSpeed < 8)
|
|
g_ScrollSpeed++;
|
|
else
|
|
g_ScrollSpeed = 1;
|
|
Print_SetPosition(19, 23);
|
|
Print_DrawInt(g_ScrollSpeed);
|
|
}
|
|
else if (IS_KEY_PRESSED(row8, KEY_HOME) && !IS_KEY_PRESSED(prevRow8, KEY_HOME))
|
|
{
|
|
if (g_ScrollSpeed > 1)
|
|
g_ScrollSpeed--;
|
|
else
|
|
g_ScrollSpeed = 7;
|
|
Print_SetPosition(19, 23);
|
|
Print_DrawInt(g_ScrollSpeed);
|
|
}
|
|
// Update horizontal scrolling offset
|
|
if (IS_KEY_PRESSED(row8, KEY_RIGHT))
|
|
{
|
|
Scroll_SetOffsetH(g_ScrollSpeed);
|
|
shape = (frame >> 2) % 6;
|
|
}
|
|
else if (IS_KEY_PRESSED(row8, KEY_LEFT))
|
|
{
|
|
Scroll_SetOffsetH(-g_ScrollSpeed);
|
|
shape = (frame >> 2) % 6;
|
|
}
|
|
// Update vertical scrolling offset
|
|
if (IS_KEY_PRESSED(row8, KEY_DOWN))
|
|
{
|
|
Scroll_SetOffsetV(g_ScrollSpeed);
|
|
}
|
|
else if (IS_KEY_PRESSED(row8, KEY_UP))
|
|
{
|
|
Scroll_SetOffsetV(-g_ScrollSpeed);
|
|
}
|
|
prevRow8 = row8;
|
|
|
|
VDP_SetSpritePattern(sprt+0, 32 + shape * 16);
|
|
VDP_SetSpritePattern(sprt+1, 36 + shape * 16);
|
|
VDP_SetSpritePattern(sprt+2, 40 + shape * 16);
|
|
|
|
frame++;
|
|
}
|
|
} |