Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
191 lines
6.4 KiB
C
191 lines
6.4 KiB
C
// ____________________________
|
|
// ██▀▀█▀▀██▀▀▀▀▀▀▀█▀▀█ │ ▄▄▄ ▄▄
|
|
// ██ ▀ █▄ ▀██▄ ▀ ▄█ ▄▀▀ █ │ ▀█▄ ▄▀██ ▄█▄█ ██▀▄ ██ ▄███
|
|
// █ █ █ ▀▀ ▄█ █ █ ▀▄█ █▄ │ ▄▄█▀ ▀▄██ ██ █ ██▀ ▀█▄ ▀█▄▄
|
|
// ▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀────────┘ ▀▀
|
|
// ROM mapper sample
|
|
//─────────────────────────────────────────────────────────────────────────────
|
|
#include "msxgl.h"
|
|
|
|
//=============================================================================
|
|
// DEFINES
|
|
//=============================================================================
|
|
|
|
// Library's logo
|
|
#define MSX_GL "\x01\x02\x03\x04\x05\x06"
|
|
|
|
#define SEG_PANEL_X 25
|
|
|
|
extern const c8* Seg4Data1;
|
|
extern const c8* Seg4Data2;
|
|
extern const u16 Seg5AsmData;
|
|
|
|
void Seg4Func1(u8 id) __banked;
|
|
|
|
//=============================================================================
|
|
// READ-ONLY DATA
|
|
//=============================================================================
|
|
|
|
// Fonts
|
|
#include "font/font_mgl_sample6.h"
|
|
|
|
// Animation characters
|
|
const u8 g_ChrAnim[] = { '|', '\\', '-', '/' };
|
|
|
|
//
|
|
const c8 g_SampleText[] = "Sample text";
|
|
|
|
__at(0x0F8000) const c8 g_SampleText15[] = "Seg 15 text";
|
|
// __at(0xFFA000) const c8 g_SampleText255[] = "Seg 255 text";
|
|
|
|
//=============================================================================
|
|
// MEMORY DATA
|
|
//=============================================================================
|
|
|
|
// Screen mode setting index
|
|
u8 g_VBlank = 0;
|
|
u8 g_Frame = 0;
|
|
u8 g_Phase = 0;
|
|
u8 g_Temp;
|
|
|
|
//=============================================================================
|
|
// FUNCTIONS
|
|
//=============================================================================
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// H_TIMI interrupt hook
|
|
void VBlankHook()
|
|
{
|
|
g_VBlank = 1;
|
|
g_Frame++;
|
|
|
|
u8 sb3 = GET_BANK_SEGMENT(3);
|
|
SET_BANK_SEGMENT(3, g_Frame); // Make segment #1 visible through bank #3
|
|
g_Temp = GET_BANK_SEGMENT(3);
|
|
SET_BANK_SEGMENT(3, sb3); // Restore segment in bank #2
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Wait for V-Blank period
|
|
void WaitVBlank()
|
|
{
|
|
while (g_VBlank == 0) {}
|
|
g_VBlank = 0;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
//
|
|
void DrawSegments(u8 y, const c8* txt)
|
|
{
|
|
Print_DrawTextAt(0, y, txt);
|
|
Print_DrawIntAt(SEG_PANEL_X, y, GET_BANK_SEGMENT(0));
|
|
Print_DrawIntAt(SEG_PANEL_X + 4, y, GET_BANK_SEGMENT(1));
|
|
Print_DrawIntAt(SEG_PANEL_X + 8, y, GET_BANK_SEGMENT(2));
|
|
Print_DrawIntAt(SEG_PANEL_X + 12, y, GET_BANK_SEGMENT(3));
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Program entry point
|
|
void main()
|
|
{
|
|
// Initial bank setting (initialized into crt0 code):
|
|
// Bank 0 => Segment 0
|
|
// Bank 1 => Segment 1
|
|
// Bank 2 => Segment 2
|
|
// Bank 3 => Segment 3
|
|
|
|
VDP_SetMode(VDP_MODE_SCREEN0); // Initialize screen mode 0 (text)
|
|
VDP_ClearVRAM();
|
|
|
|
Print_SetTextFont(g_Font_MGL_Sample6, 1); // Initialize font
|
|
Print_DrawText(MSX_GL " MAPPER SAMPLE"); // Display title
|
|
Print_DrawLineH(0, 1, 40);
|
|
|
|
Print_SetPosition(SEG_PANEL_X, 3);
|
|
Print_DrawText("B#0 B#1 B#2 B#3");
|
|
|
|
// INIT
|
|
// Bank 0 => Segment 0
|
|
// Bank 1 => Segment 1
|
|
// Bank 2 => Segment 2
|
|
// Bank 3 => Segment 3
|
|
DrawSegments(5, "Initial segments");
|
|
|
|
// SIMPLE SWITCH
|
|
// Bank 0 => Segment 0
|
|
// Bank 1 => Segment 1
|
|
// Bank 2 => Segment 2
|
|
// Bank 3 => Segment 5 (content of s_mapper_s5_b3.asm)
|
|
SET_BANK_SEGMENT(3, 5); // Make segment #5 visible through bank #3
|
|
DrawSegments(7, "Switch bank 3 to seg 5");
|
|
Print_SetPosition(0, 8);
|
|
Print_DrawFormat("Data: [%s]", &Seg5AsmData);
|
|
|
|
// BANKED CALL
|
|
// Bank 0 => Segment 0
|
|
// Bank 1 => Segment 1
|
|
// Bank 2 => Segment 2 (before/after calling) | 4 (content of s_mapper_s4_b2.c during banked call)
|
|
// Bank 3 => Segment 5 (content of s_mapper_s5_b3.asm)
|
|
Print_DrawTextAt(0, 10, "Call banked functions");
|
|
Seg4Func1(11); // Bank 2 => Segment 4 (content of s_mapper_s4_b2.c)
|
|
Seg4Func1(12); // Bank 2 => Segment 4 (content of s_mapper_s4_b2.c)
|
|
DrawSegments(13, "After banked call");
|
|
|
|
// MIRRORING
|
|
// Bank 0 => Segment 0
|
|
// Bank 1 => Segment 1
|
|
// Bank 2 => Segment 0
|
|
// Bank 3 => Segment 1
|
|
u8 sb2 = GET_BANK_SEGMENT(2);
|
|
SET_BANK_SEGMENT(2, 0); // Make segment #0 visible through bank #2
|
|
u8 sb3 = GET_BANK_SEGMENT(3);
|
|
SET_BANK_SEGMENT(3, 1); // Make segment #1 visible through bank #3
|
|
DrawSegments(15, "Set mirroring");
|
|
Print_SetPosition(0, 16);
|
|
Print_DrawFormat("At %4xh: [%s]", g_SampleText, g_SampleText);
|
|
Print_SetPosition(0, 17);
|
|
Print_DrawFormat("At %4xh: [%s]", g_SampleText + 0x4000, g_SampleText + 0x4000);
|
|
|
|
// RESTORE
|
|
// Bank 0 => Segment 0
|
|
// Bank 1 => Segment 1
|
|
// Bank 2 => Segment 2
|
|
// Bank 3 => Segment 5 (content of s_mapper_s5_b3.asm)
|
|
SET_BANK_SEGMENT(2, sb2); // Make previous segment visible through bank #2
|
|
SET_BANK_SEGMENT(3, sb3); // Make previous segment visible through bank #3
|
|
DrawSegments(19, "Restore segments");
|
|
|
|
// OUT OF BOUNDS
|
|
// Bank 0 => Segment 0
|
|
// Bank 1 => Segment 1
|
|
// Bank 2 => Segment 15 (last segment)
|
|
// Bank 3 => Segment 255
|
|
SET_BANK_SEGMENT(2, 15); // Make segment #15 visible through bank #2
|
|
SET_BANK_SEGMENT(3, 255); // Make segment #255 visible through bank #3
|
|
DrawSegments(19, "Out of bounds seg");
|
|
Print_SetPosition(0, 20);
|
|
Print_DrawFormat("Bank 2: [%s]", g_SampleText15);
|
|
Print_SetPosition(0, 21);
|
|
Print_DrawFormat("Bank 3: [%s]", 0xA000);
|
|
|
|
VDP_EnableVBlank(TRUE);
|
|
BIOS_SetHookCallback(H_TIMI, VBlankHook);
|
|
|
|
u8 frameCount = 0;
|
|
u8 errorCount = 0;
|
|
while (!Keyboard_IsKeyPressed(KEY_ESC))
|
|
{
|
|
// WaitVBlank();
|
|
|
|
SET_BANK_SEGMENT(3, frameCount);
|
|
|
|
if (GET_BANK_SEGMENT(3) != frameCount)
|
|
errorCount++;
|
|
|
|
Print_DrawIntAt(0, 23, errorCount);
|
|
Print_DrawCharAt(39, 0, g_ChrAnim[frameCount++ & 0x03]);
|
|
}
|
|
|
|
BIOS_ClearHook(H_TIMI);
|
|
BIOS_Exit(0);
|
|
} |