Files

340 lines
9.2 KiB
C

// ____________________________
// ██▀▀█▀▀██▀▀▀▀▀▀▀█▀▀█ │ ▄▄▄ ▄▄
// ██ ▀ █▄ ▀██▄ ▀ ▄█ ▄▀▀ █ │ ▀█▄ ▄▀██ ▄█▄█ ██▀▄ ██ ▄███
// █ █ █ ▀▀ ▄█ █ █ ▀▄█ █▄ │ ▄▄█▀ ▀▄██ ██ █ ██▀ ▀█▄ ▀█▄▄
// ▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀────────┘ ▀▀
// ROM mapper sample
//─────────────────────────────────────────────────────────────────────────────
#include "msxgl.h"
//=============================================================================
// DEFINES
//=============================================================================
// Library's logo
#define MSX_GL "\x01\x02\x03\x04\x05\x06"
#if (ROM_MAPPER == ROM_NEO8)
#define SET_SEGMENT(s) SET_BANK_SEGMENT(4, s)
#define SET_SEGMENT_LOW(s) SET_BANK_SEGMENT_LOW(4, s)
#define SET_SEGMENT_HIGH(s) SET_BANK_SEGMENT_HIGH(4, s)
#define GET_SEGMENT() GET_BANK_SEGMENT(4)
#define BANK_NUM 6
#define BANK_SIZE 0x2000
#define TEST_BANK 4
#define TEST_ADDR 0x8000
#elif (ROM_MAPPER == ROM_NEO16)
#define SET_SEGMENT(s) SET_BANK_SEGMENT(2, s)
#define SET_SEGMENT_LOW(s) SET_BANK_SEGMENT_LOW(2, s)
#define SET_SEGMENT_HIGH(s) SET_BANK_SEGMENT_HIGH(2, s)
#define GET_SEGMENT() GET_BANK_SEGMENT(2)
#define BANK_NUM 3
#define BANK_SIZE 0x4000
#define TEST_BANK 2
#define TEST_ADDR 0x8000
#else
#error Error: Invalide ROM mapper type (ROM_MAPPER)
#endif
#define MIRROR_MASK 0b0000011111111110
struct SignEntry
{
u16 Segment;
const c8* Sign;
};
//=============================================================================
// READ-ONLY DATA
//=============================================================================
// Fonts
#include "font/font_mgl_sample6.h"
// Animation characters
const u8 g_ChrAnim[] = { '|', '\\', '-', '/' };
// Sample data
__at(0x00030000) const c8 g_S003Data[] = "S003";
__at(0x00110000) const c8 g_S011Data[] = "S011";
__at(0x01110000) const c8 g_S111Data[] = "S111";
__at(0x01120000) const c8 g_S000Data[] = "S112";
__at(0x00FF0000) const c8 g_S0FFData[] = "S0FF";
__at(0x01000000) const c8 g_S100Data[] = "S100";
__at(0x01230000) const c8 g_S123Data[] = "S123";
__at(0x01FF0000) const c8 g_S1FFData[] = "S1FF";
const struct SignEntry g_Signs[] =
{
{ 0x0003, "S003" },
{ 0x0011, "S011" },
{ 0x0111, "S111" },
{ 0x0112, "S112" },
{ 0x00FF, "S0FF" },
{ 0x0100, "S100" },
{ 0x0123, "S123" },
{ 0x01FF, "S1FF" },
};
const u16 g_SwitchAddr[BANK_NUM] =
{
#if (ROM_MAPPER == ROM_NEO8)
0x5000,
0x5800,
0x6000,
0x6800,
0x7000,
0x7800,
#elif (ROM_MAPPER == ROM_NEO16)
0x5000,
0x6000,
0x7000,
#endif
};
//=============================================================================
// FUNCTIONS
//=============================================================================
//-----------------------------------------------------------------------------
//
bool CheckSign(const u8* addr, const u8* sign)
{
loop (i, 4)
if (*addr++ != *sign++)
return FALSE;
return TRUE;
}
//-----------------------------------------------------------------------------
//
void Print_Slot(u8 slot)
{
Print_DrawInt(Sys_SlotGetPrimary(slot));
if (Sys_SlotIsExpended(slot))
{
Print_DrawChar('-');
Print_DrawInt(Sys_SlotGetSecondary(slot));
}
}
//-----------------------------------------------------------------------------
//
const c8* GetTargetType(u8 target)
{
switch (target)
{
case TYPE_BIN: return "BASIC";
case TYPE_ROM: return "ROM";
case TYPE_DOS: return "DOS";
};
return "Unknow";
}
//-----------------------------------------------------------------------------
//
const c8* GetROMMapper(u8 mapper)
{
switch (mapper)
{
case ROM_PLAIN: return "Plain";
case ROM_ASCII8: return "ASCII-8";
case ROM_ASCII16: return "ASCII-16";
case ROM_KONAMI: return "Konami";
case ROM_KONAMI_SCC: return "Konami SCC";
case ROM_NEO8: return "NEO-8";
case ROM_NEO16: return "NEO-16";
case ROM_YAMANOOTO: return "YAMANOOTO";
case ROM_ASCII16X: return "ASCII16-X";
};
return "Unknow";
}
//-----------------------------------------------------------------------------
//
const c8* GetROMSize(u8 size)
{
switch (size)
{
case ROM_8K: return "8 KB";
case ROM_16K: return "16 KB";
case ROM_24K: return "24 KB";
case ROM_32K: return "32 KB";
case ROM_48K: return "48 KB";
case ROM_64K: return "64 KB";
};
return "Unknow";
}
//-----------------------------------------------------------------------------
// Display from address
void DisplayMemory(u16 addr)
{
const u8* ptr = (const u8*)addr;
loop (i, 28)
Print_DrawChar(*ptr++);
}
//-----------------------------------------------------------------------------
// Interrupt handler
void VDP_InterruptHandler()
{
}
//-----------------------------------------------------------------------------
// Program entry point
void main()
{
VDP_SetMode(VDP_MODE_SCREEN0); // Initialize screen mode 0 (text)
VDP_ClearVRAM();
#if (ROM_MAPPER == ROM_NEO8)
SET_BANK_SEGMENT(0, 4); // Bank 0 (0000-1FFF) = Segment 4
SET_BANK_SEGMENT(1, 5); // Bank 1 (2000-3FFF) = Segment 5
SET_BANK_SEGMENT(2, 0); // Bank 2 (4000-5FFF) = Segment 0
SET_BANK_SEGMENT(3, 1); // Bank 3 (6000-7FFF) = Segment 1
SET_BANK_SEGMENT(4, 2); // Bank 4 (8000-9FFF) = Segment 2
SET_BANK_SEGMENT(5, 3); // Bank 5 (A000-BFFF) = Segment 3
#elif (ROM_MAPPER == ROM_NEO16)
SET_BANK_SEGMENT(0, 2); // Bank 0 (0000-3FFF) = Segment 2
SET_BANK_SEGMENT(1, 0); // Bank 1 (4000-7FFF) = Segment 0
SET_BANK_SEGMENT(2, 1); // Bank 2 (8000-BFFF) = Segment 1
#endif
// Title
Print_SetTextFont(g_Font_MGL_Sample6, 1); // Initialize font
Print_DrawText(MSX_GL " NEO MAPPER SAMPLE"); // Display title
Print_DrawLineH(0, 1, 40);
// Information
Print_SetPosition(0, 2);
Print_DrawFormat("%s\n\n", TARGET_NAME);
Print_DrawFormat("Type: %s\n", GetTargetType(TARGET_TYPE));
Print_DrawFormat("Mapper: %s\n", GetROMMapper(ROM_MAPPER));
if (ROM_SIZE > 1024)
Print_DrawFormat("Size: %iMB\n", ROM_SIZE / 1024);
else
Print_DrawFormat("Size: %iKB\n", ROM_SIZE);
Print_DrawFormat("Seg num: %i\n", ROM_SEGMENTS);
// Slot selection
loop (i, 4)
{
u8 slotId = Sys_GetPageSlot(i);
Print_SetPosition(20, 4+i);
Print_DrawFormat("Page[%i]: ", i);
Print_Slot(slotId);
}
Print_DrawLineH(0, 8, 40);
Print_SetPosition(0, 8);
Print_DrawText("\nBank test:");
loop (b, BANK_NUM)
{
u16 s = 0;
switch (b)
{
case 0:
s = GET_BANK_SEGMENT(0);
break;
case 1:
s = GET_BANK_SEGMENT(1);
break;
case 2:
s = GET_BANK_SEGMENT(2);
break;
#if (ROM_MAPPER == ROM_NEO8)
case 3:
s = GET_BANK_SEGMENT(3);
break;
case 4:
s = GET_BANK_SEGMENT(4);
break;
case 5:
s = GET_BANK_SEGMENT(5);
break;
#endif
}
Print_DrawFormat("\n\x7""[%i]->%03i: ", b, s);
DisplayMemory(BANK_SIZE * b);
}
Print_DrawText("\n\nAccess test:");
Print_DrawText("\n\x7SET_BANK_SEGMENT() ");
SET_SEGMENT(0);
loop (i, numberof(g_Signs))
{
const struct SignEntry* e = &g_Signs[i];
SET_SEGMENT(e->Segment); // Set segment in bank
Print_DrawText(CheckSign((const u8*)TEST_ADDR, e->Sign) ? "\xC " : "\xB ");
}
Print_DrawText("\n\x7""16b access ");
SET_SEGMENT(0);
loop (i, numberof(g_Signs))
{
const struct SignEntry* e = &g_Signs[i];
Poke16(g_SwitchAddr[TEST_BANK], e->Segment); // Set segment in bank
Print_DrawText(CheckSign((const u8*)TEST_ADDR, e->Sign) ? "\xC " : "\xB ");
}
Print_DrawText("\n\x7""16b access + mask ");
SET_SEGMENT(0);
loop (i, numberof(g_Signs))
{
const struct SignEntry* e = &g_Signs[i];
u16 addr = g_SwitchAddr[TEST_BANK] | MIRROR_MASK;
Poke16(addr, e->Segment); // Set segment in bank
Print_DrawText(CheckSign((const u8*)TEST_ADDR, e->Sign) ? "\xC " : "\xB ");
}
Print_DrawText("\n\x7""8b access ");
SET_SEGMENT(0);
loop (i, numberof(g_Signs))
{
const struct SignEntry* e = &g_Signs[i];
u16 addr = g_SwitchAddr[TEST_BANK];
switch (i)
{
case 0: // 0x0003
SET_SEGMENT_LOW(0x03);
break;
case 1: // 0x0011
SET_SEGMENT_LOW(0x11);
break;
case 2: // 0x0111
SET_SEGMENT_HIGH(0x01);
break;
case 3: // 0x0112
SET_SEGMENT_LOW(0x12);
break;
case 4: // 0x00FF
SET_SEGMENT_HIGH(0x00);
SET_SEGMENT_LOW(0xFF);
break;
case 5: // 0x0100
SET_SEGMENT_HIGH(0x01);
SET_SEGMENT_LOW(0x00);
break;
case 6: // 0x0123
SET_SEGMENT_LOW(0x23);
break;
case 7: // 0x01FF
SET_SEGMENT_LOW(0xFF);
break;
}
Print_DrawText(CheckSign((const u8*)TEST_ADDR, e->Sign) ? "\xC " : "\xB ");
}
u8 count = 0;
while (!Keyboard_IsKeyPressed(KEY_ESC))
{
Halt();
Print_SetPosition(39, 0);
Print_DrawChar(g_ChrAnim[count++ & 0x03]);
}
}