Version 5.5 with enhanced ECS support. See readme.md for details.

This commit is contained in:
Dave Bernazzani 2024-09-23 08:01:57 -04:00
parent 9395894634
commit e0f644981e
23 changed files with 323 additions and 239 deletions

View File

@ -14,7 +14,7 @@ include $(DEVKITARM)/ds_rules
export TARGET := NINTV-DS
export TOPDIR := $(CURDIR)
export VERSION := 5.4
export VERSION := 5.5
ICON := -b $(CURDIR)/logo.bmp "NINTV-DS $(VERSION);wavemotion-dave;https://github.com/wavemotion-dave/NINTV-DS"

Binary file not shown.

View File

@ -164,6 +164,9 @@ Credits :
--------------------------------------------------------------------------------
History :
--------------------------------------------------------------------------------
V5.5 : 23-Sep-2024 by wavemotion-dave
* Improved ECS support with new full-screen ECS Keyboard and ability to switch between keypad controllers, disc and full keyboard.
V5.4 : 10-Sep-2024 by wavemotion-dave
* Full Tutorvision Mode supported. See Tutorvision section in this README for details.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 22 KiB

After

Width:  |  Height:  |  Size: 27 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 40 KiB

After

Width:  |  Height:  |  Size: 41 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 46 KiB

After

Width:  |  Height:  |  Size: 46 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 36 KiB

After

Width:  |  Height:  |  Size: 37 KiB

View File

@ -149,7 +149,7 @@ static void SetDefaultGameConfig(UINT32 crc)
{
myConfig.game_crc = 0x00000000;
myConfig.frame_skip = myGlobalConfig.frame_skip;
myConfig.overlay = 0;
myConfig.spare1 = 0;
myConfig.key_A_map = OVL_BTN_FIRE;
myConfig.key_B_map = OVL_BTN_FIRE;
myConfig.key_X_map = OVL_BTN_R_ACT;
@ -373,7 +373,7 @@ void FindAndLoadConfig(UINT32 crc)
fclose(fp);
// ----------------------------------------------------------------------------------------
// If we were config version 0x0009, we perform a one-time upgrade to version 0x000A
// If we were config version 0x0009, we perform a one-time upgrade to version 0x000B
// and replace the default START key map to the OVL_META_DISC to swap in the disc overlay.
// ----------------------------------------------------------------------------------------
if (allConfigs.config_ver == 0x0009) // One time upgrade
@ -383,13 +383,33 @@ void FindAndLoadConfig(UINT32 crc)
for (int slot=0; slot<MAX_CONFIGS; slot++)
{
if (allConfigs.game_config[slot].key_START_map == OVL_KEY_ENTER) allConfigs.game_config[slot].key_START_map = OVL_META_DISC;
allConfigs.game_config[slot].spare1 = 0;
}
allConfigs.config_ver = CONFIG_VER;
memcpy(&myGlobalConfig, &allConfigs.global_config, sizeof(struct GlobalConfig_t));
SaveConfig(0x00000000, FALSE);
dsPrintValue(0,1,0, (char*)" ");
}
// ----------------------------------------------------------------------------------------
// If we were config version 0x000A, we perform a one-time upgrade to version 0x000B
// and patch up OVL_META_DISC which moved from meta index 27 to its new home...
// ----------------------------------------------------------------------------------------
if (allConfigs.config_ver == 0x000A) // One time upgrade
{
dsPrintValue(0,1,0, (char*)"PLEASE WAIT...");
allConfigs.global_config.key_START_map_default = OVL_META_DISC;
for (int slot=0; slot<MAX_CONFIGS; slot++)
{
if (allConfigs.game_config[slot].key_START_map == 27) allConfigs.game_config[slot].key_START_map = OVL_META_DISC;
allConfigs.game_config[slot].spare1 = 0;
}
allConfigs.config_ver = CONFIG_VER;
memcpy(&myGlobalConfig, &allConfigs.global_config, sizeof(struct GlobalConfig_t));
SaveConfig(0x00000000, FALSE);
dsPrintValue(0,1,0, (char*)" ");
}
if (allConfigs.config_ver != CONFIG_VER)
{
dsPrintValue(0,1,0, (char*)"PLEASE WAIT...");
@ -445,27 +465,26 @@ void FindAndLoadConfig(UINT32 crc)
struct options_t
{
const char *label;
const char *option[28];
const char *option[29];
UINT8 *option_val;
UINT8 option_max;
};
#define KEY_MAP_OPTIONS "KEY-1", "KEY-2", "KEY-3", "KEY-4", "KEY-5", "KEY-6", "KEY-7", "KEY-8", "KEY-9", "KEY-CLR", "KEY-0", "KEY-ENT", "FIRE", "L-ACT", "R-ACT", "RESET", "LOAD", "CONFIG", "SCORES", "QUIT", "STATE", "MENU", "SWITCH", "MANUAL", "DISC UP", "DISC DOWN", "SPEEDUP", "SHOW DISC"
#define KEY_MAP_OPTIONS "KEY-1", "KEY-2", "KEY-3", "KEY-4", "KEY-5", "KEY-6", "KEY-7", "KEY-8", "KEY-9", "KEY-CLR", "KEY-0", "KEY-ENT", "FIRE", "L-ACT", "R-ACT", "RESET", "LOAD", "CONFIG", "SCORES", "QUIT", "STATE", "MENU", "SWITCH", "MANUAL", "SHOW DISC", "SHOW KBD", "DISC UP", "DISC DOWN", "SPEEDUP"
const struct options_t Option_Table[3][20] =
{
// Page 1 options
{
{"OVERLAY", {"NORMAL", "ECS"}, &myConfig.overlay, 2},
{"A BUTTON", {KEY_MAP_OPTIONS}, &myConfig.key_A_map, 28},
{"B BUTTON", {KEY_MAP_OPTIONS}, &myConfig.key_B_map, 28},
{"X BUTTON", {KEY_MAP_OPTIONS}, &myConfig.key_X_map, 28},
{"Y BUTTON", {KEY_MAP_OPTIONS}, &myConfig.key_Y_map, 28},
{"L BUTTON", {KEY_MAP_OPTIONS}, &myConfig.key_L_map, 28},
{"R BUTTON", {KEY_MAP_OPTIONS}, &myConfig.key_R_map, 28},
{"START BTN", {KEY_MAP_OPTIONS}, &myConfig.key_START_map, 28},
{"SELECT BTN", {KEY_MAP_OPTIONS}, &myConfig.key_SELECT_map, 28},
{"A+X BUTTON", {KEY_MAP_OPTIONS}, &myConfig.key_AX_map, 26}, // These can't be mapped to SPEEDUP so the array here is one shorter
{"A BUTTON", {KEY_MAP_OPTIONS}, &myConfig.key_A_map, 29},
{"B BUTTON", {KEY_MAP_OPTIONS}, &myConfig.key_B_map, 29},
{"X BUTTON", {KEY_MAP_OPTIONS}, &myConfig.key_X_map, 29},
{"Y BUTTON", {KEY_MAP_OPTIONS}, &myConfig.key_Y_map, 29},
{"L BUTTON", {KEY_MAP_OPTIONS}, &myConfig.key_L_map, 29},
{"R BUTTON", {KEY_MAP_OPTIONS}, &myConfig.key_R_map, 29},
{"START BTN", {KEY_MAP_OPTIONS}, &myConfig.key_START_map, 29},
{"SELECT BTN", {KEY_MAP_OPTIONS}, &myConfig.key_SELECT_map, 29},
{"A+X BUTTON", {KEY_MAP_OPTIONS}, &myConfig.key_AX_map, 26}, // These can't be mapped to SPEEDUP, SHOW DISK or SHOW KEYBOARD so the array here is one shorter
{"X+Y BUTTON", {KEY_MAP_OPTIONS}, &myConfig.key_XY_map, 26},
{"Y+B BUTTON", {KEY_MAP_OPTIONS}, &myConfig.key_YB_map, 26},
{"B+A BUTTON", {KEY_MAP_OPTIONS}, &myConfig.key_BA_map, 26},
@ -475,6 +494,7 @@ const struct options_t Option_Table[3][20] =
{"SOUND QUAL", {"LOW", "MEDIUM", "HIGH", "ULTIMATE"}, &myConfig.sound_quality, 4},
{"TGT SPEED", {"60 FPS (100%)","66 FPS (110%)","72 FPS (120%)","78 FPS (130%)","84 FPS (140%)","90 FPS (150%)","54 FPS (90%)","MAX SPEED"}, &myConfig.target_fps, 8},
{"PALETTE", {"ORIGINAL", "MUTED", "BRIGHT", "PAL", "CUSTOM"}, &myConfig.palette, 5},
{"KEYBD CLICK", {"NO" , "YES"}, &myConfig.key_click, 2},
{NULL, {"", ""}, NULL, 1},
},
@ -483,7 +503,6 @@ const struct options_t Option_Table[3][20] =
{"BACKTAB", {"NOT LATCHED", "LATCHED"}, &myConfig.bLatched, 2},
{"GRAM SIZE", {"512B (NORMAL)", "2K (EXPANDED)"}, &myConfig.gramSize, 2},
{"CPU FUDGE", {"NONE", "LOW", "MEDIUM", "HIGH", "MAX"}, &myConfig.fudgeTiming, 5},
{"KEYBD CLICK", {"NO" , "YES"}, &myConfig.key_click, 2},
{"SKIP BLANKS", {"NO" , "YES"}, &myConfig.bSkipBlanks, 2},
{NULL, {"", ""}, NULL, 1},
},
@ -497,8 +516,8 @@ const struct options_t Option_Table[3][20] =
{"OVL DIR", {"SAME AS ROMS", "/ROMS/OVL", "/ROMS/INTV/OVL", "/DATA/OVL"}, &myGlobalConfig.ovl_dir, 4},
{"ROM DIR", {"SAME AS EMU", "/ROMS", "/ROMS/INTV"}, &myGlobalConfig.rom_dir, 3},
{"MAN DIR", {"SAME AS ROMS", "/ROMS/MAN", "/ROMS/INTV/MAN", "/DATA/MAN"}, &myGlobalConfig.man_dir, 4},
{"START DEF", {KEY_MAP_OPTIONS}, &myGlobalConfig.key_START_map_default, 28},
{"SELECT DEF", {KEY_MAP_OPTIONS}, &myGlobalConfig.key_SELECT_map_default, 28},
{"START DEF", {KEY_MAP_OPTIONS}, &myGlobalConfig.key_START_map_default, 29},
{"SELECT DEF", {KEY_MAP_OPTIONS}, &myGlobalConfig.key_SELECT_map_default, 29},
{"DEF SOUND", {"LOW", "MEDIUM", "HIGH"}, &myGlobalConfig.def_sound_quality, 3},
{"DEF PALETTE", {"ORIGINAL", "MUTED", "BRIGHT", "PAL", "CUSTOM"}, &myGlobalConfig.def_palette, 5},
{"DEF FRAMSKP", {"OFF", "ON (ODD)", "ON (EVEN)"}, &myGlobalConfig.frame_skip, 3},

View File

@ -18,7 +18,7 @@
// ---------------------------
// Config handling...
// ---------------------------
#define CONFIG_VER 0x000A
#define CONFIG_VER 0x000B
#define MAX_CONFIGS 625
@ -28,7 +28,7 @@ struct Config_t
{
UINT32 game_crc; // CRC32 of the game itself
UINT8 frame_skip;
UINT8 overlay;
UINT8 spare1;
UINT8 key_A_map;
UINT8 key_B_map;
UINT8 key_X_map;

View File

@ -106,6 +106,7 @@ ITCM_CODE void AY38914_Registers::poke(UINT16 location, UINT16 value)
break;
case 0x08:
psg_memory[location] = value;
value = value & 0x00FF;
ay38914->channel0.toneDisabled = !!(value & 0x0001);
ay38914->channel1.toneDisabled = !!(value & 0x0002);
@ -119,7 +120,6 @@ ITCM_CODE void AY38914_Registers::poke(UINT16 location, UINT16 value)
ay38914->noiseIdle = ay38914->channel0.noiseDisabled &
ay38914->channel1.noiseDisabled &
ay38914->channel2.noiseDisabled;
psg_memory[location] = value;
ay38914->psgIO0->setDirectionIO(value);
ay38914->psgIO1->setDirectionIO(value);
break;
@ -168,11 +168,13 @@ ITCM_CODE void AY38914_Registers::poke(UINT16 location, UINT16 value)
break;
case 0x0E:
ay38914->psgIO1->setOutputValue(value);
// Make sure we are configured for output...
if ((psg_memory[0x08] & 0x40)) ay38914->psgIO1->setOutputValue(value);
break;
case 0x0F:
ay38914->psgIO0->setOutputValue(value);
// Make sure we are configured for output...
if ((psg_memory[0x08] & 0x80)) ay38914->psgIO0->setOutputValue(value);
break;
}
}

View File

@ -24,7 +24,7 @@ class AY38914_Registers : public RAM
void reset();
void poke(UINT16 location, UINT16 value);
UINT16 peek(UINT16 location);
UINT16 psg_memory[0x0E];
UINT16 psg_memory[0x0E];
private:
AY38914_Registers(UINT16 address);

View File

@ -18,6 +18,7 @@ ECS::ECS()
: Peripheral("Electronic Computer System", "ECS"),
keyboard(2),
ecsRAM(ECS_RAM_SIZE, ECS_RAM_LOCATION, 0xFFFF, 0xFFFF, 8),
uartRAM(4, 0x00E0, 0xFFFF, 0xFFFF, 8),
psg2(0x00F0, &keyboard, &keyboard),
bank0("ECS ROM #1", "ecs.bin", 0, 2, 0x1000, 0x2000),
banker0(&bank0, 0x2FFF, 0xFFF0, 0x2A50, 0x000F, 1),
@ -38,7 +39,8 @@ ECS::ECS()
AddROM(&bank2);
AddRAM(&banker2);
AddRAM(&ecsRAM);
AddRAM(&ecsRAM);
AddRAM(&uartRAM);
#ifdef DEBUG_ENABLE
debug_psg2 = &psg2;

View File

@ -52,6 +52,7 @@ class ECS : public Peripheral
ROM bank1;
ROM bank2;
RAM ecsRAM;
RAM uartRAM;
AY38914 psg2;
ROMBanker banker0;
ROMBanker banker1;

View File

@ -13,6 +13,8 @@
#include "HandController.h"
UINT8 ecs_key_pressed = 0;
UINT8 ecs_shift_key = 0;
UINT8 ecs_ctrl_key = 0;
ECSKeyboard::ECSKeyboard(INT32 id)
: InputConsumer(id),
@ -29,8 +31,7 @@ ECSKeyboard::~ECSKeyboard()
void ECSKeyboard::resetInputConsumer()
{
rowsOrColumnsToScan = 0;
for (UINT16 i = 0; i < 8; i++)
rowInputValues[i] = 0;
memset(rowInputValues, 0, sizeof(rowInputValues));
}
// $00FE | $00FF bits
@ -48,91 +49,70 @@ void ECSKeyboard::evaluateInputs()
{
extern UINT8 bUseECS;
for (UINT16 i = 0; i < 8; i++) rowInputValues[i] = 0x00;
memset(rowInputValues, 0, sizeof(rowInputValues));
if (ecs_key_pressed == 255) // No mini-keyboard so just use dual-purpose the main keypad
// If a key on the ECS Keyboard was pressed...
switch (ecs_key_pressed)
{
if (ds_key_input[0][0]) rowInputValues[5] |= 0x10; // '1'
if (ds_key_input[0][1]) rowInputValues[4] |= 0x20; // '2'
if (ds_key_input[0][2]) rowInputValues[4] |= 0x10; // '3'
if (ds_key_input[0][3]) rowInputValues[3] |= 0x20; // '4'
if (ds_key_input[0][4]) rowInputValues[3] |= 0x10; // '5'
if (bUseECS == 2) // Special for Mind Strike which needs START to run... sigh...
{
if (ds_key_input[0][5]) rowInputValues[4] |= 0x04; // 'S'
if (ds_key_input[0][6]) rowInputValues[3] |= 0x40; // 'T'
if (ds_key_input[0][7]) rowInputValues[5] |= 0x80; // 'A'
if (ds_key_input[0][8]) rowInputValues[3] |= 0x08; // 'R'
}
else
{
if (ds_key_input[0][5]) rowInputValues[2] |= 0x20; // '6'
if (ds_key_input[0][6]) rowInputValues[2] |= 0x10; // '7'
if (ds_key_input[0][7]) rowInputValues[1] |= 0x20; // '8'
if (ds_key_input[0][8]) rowInputValues[1] |= 0x10; // '9'
}
if (ds_key_input[0][9]) rowInputValues[5] |= 0x01; // SP
if (ds_key_input[0][10]) rowInputValues[2] |= 0x01; // 'N'
if (ds_key_input[0][11]) rowInputValues[0] |= 0x40; // CR
}
else
{
// If a key on the ECS Mini-Keyboard was pressed...
switch (ecs_key_pressed)
{
case (1) : rowInputValues[5] |= 0x10; break; // '1'
case (2) : rowInputValues[4] |= 0x20; break; // '2'
case (3) : rowInputValues[4] |= 0x10; break; // '3'
case (4) : rowInputValues[3] |= 0x20; break; // '4'
case (5) : rowInputValues[3] |= 0x10; break; // '5'
case (6) : rowInputValues[2] |= 0x20; break; // '6'
case (7) : rowInputValues[2] |= 0x10; break; // '7'
case (8) : rowInputValues[1] |= 0x20; break; // '8'
case (9) : rowInputValues[1] |= 0x10; break; // '9'
case (10): rowInputValues[0] |= 0x20; break; // '0'
case (11): rowInputValues[5] |= 0x80; break; // 'A'
case (12): rowInputValues[2] |= 0x02; break; // 'B'
case (13): rowInputValues[3] |= 0x02; break; // 'C'
case (14): rowInputValues[4] |= 0x80; break; // 'D'
case (15): rowInputValues[4] |= 0x40; break; // 'E'
case (16): rowInputValues[3] |= 0x04; break; // 'F'
case (17): rowInputValues[3] |= 0x80; break; // 'G'
case (18): rowInputValues[2] |= 0x04; break; // 'H'
case (19): rowInputValues[1] |= 0x08; break; // 'I'
case (20): rowInputValues[2] |= 0x80; break; // 'J'
case (21): rowInputValues[1] |= 0x04; break; // 'K'
case (22): rowInputValues[1] |= 0x80; break; // 'L'
case (23): rowInputValues[1] |= 0x02; break; // 'M'
case (24): rowInputValues[2] |= 0x01; break; // 'N'
case (25): rowInputValues[1] |= 0x40; break; // 'O'
case (26): rowInputValues[0] |= 0x08; break; // 'P'
case (27): rowInputValues[5] |= 0x08; break; // 'Q'
case (28): rowInputValues[3] |= 0x08; break; // 'R'
case (29): rowInputValues[4] |= 0x04; break; // 'S'
case (30): rowInputValues[3] |= 0x40; break; // 'T'
case (31): rowInputValues[2] |= 0x40; break; // 'U'
case (32): rowInputValues[3] |= 0x01; break; // 'V'
case (33): rowInputValues[4] |= 0x08; break; // 'W'
case (34): rowInputValues[4] |= 0x01; break; // 'X'
case (35): rowInputValues[2] |= 0x08; break; // 'Y'
case (36): rowInputValues[4] |= 0x02; break; // 'Z'
case (37): rowInputValues[0] |= 0x01; break; // LEFT
case (38): rowInputValues[5] |= 0x02; break; // DOWN
case (39): rowInputValues[5] |= 0x04; break; // UP
case (40): rowInputValues[5] |= 0x20; break; // RIGHT
case (41): rowInputValues[5] |= 0x01; break; // SPACE
case (42): rowInputValues[0] |= 0x40; break; // RETURN (CR)
}
case (1) : rowInputValues[5] |= 0x10; break; // '1'
case (2) : rowInputValues[4] |= 0x20; break; // '2'
case (3) : rowInputValues[4] |= 0x10; break; // '3'
case (4) : rowInputValues[3] |= 0x20; break; // '4'
case (5) : rowInputValues[3] |= 0x10; break; // '5'
case (6) : rowInputValues[2] |= 0x20; break; // '6'
case (7) : rowInputValues[2] |= 0x10; break; // '7'
case (8) : rowInputValues[1] |= 0x20; break; // '8'
case (9) : rowInputValues[1] |= 0x10; break; // '9'
case (10): rowInputValues[0] |= 0x20; break; // '0'
case (11): rowInputValues[5] |= 0x80; break; // 'A'
case (12): rowInputValues[2] |= 0x02; break; // 'B'
case (13): rowInputValues[3] |= 0x02; break; // 'C'
case (14): rowInputValues[4] |= 0x80; break; // 'D'
case (15): rowInputValues[4] |= 0x40; break; // 'E'
case (16): rowInputValues[3] |= 0x04; break; // 'F'
case (17): rowInputValues[3] |= 0x80; break; // 'G'
case (18): rowInputValues[2] |= 0x04; break; // 'H'
case (19): rowInputValues[1] |= 0x08; break; // 'I'
case (20): rowInputValues[2] |= 0x80; break; // 'J'
case (21): rowInputValues[1] |= 0x04; break; // 'K'
case (22): rowInputValues[1] |= 0x80; break; // 'L'
case (23): rowInputValues[1] |= 0x02; break; // 'M'
case (24): rowInputValues[2] |= 0x01; break; // 'N'
case (25): rowInputValues[1] |= 0x40; break; // 'O'
case (26): rowInputValues[0] |= 0x08; break; // 'P'
case (27): rowInputValues[5] |= 0x08; break; // 'Q'
case (28): rowInputValues[3] |= 0x08; break; // 'R'
case (29): rowInputValues[4] |= 0x04; break; // 'S'
case (30): rowInputValues[3] |= 0x40; break; // 'T'
case (31): rowInputValues[2] |= 0x40; break; // 'U'
case (32): rowInputValues[3] |= 0x01; break; // 'V'
case (33): rowInputValues[4] |= 0x08; break; // 'W'
case (34): rowInputValues[4] |= 0x01; break; // 'X'
case (35): rowInputValues[2] |= 0x08; break; // 'Y'
case (36): rowInputValues[4] |= 0x02; break; // 'Z'
case (37): rowInputValues[0] |= 0x01; break; // LEFT
case (38): rowInputValues[5] |= 0x02; break; // DOWN
case (39): rowInputValues[5] |= 0x04; break; // UP
case (40): rowInputValues[5] |= 0x20; break; // RIGHT
case (41): rowInputValues[5] |= 0x01; break; // SPACE
case (42): rowInputValues[0] |= 0x40; break; // RETURN (CR)
case (43): rowInputValues[0] |= 0x10; break; // ESC key
case (44): rowInputValues[0] |= 0x04; break; // Semicolon
case (45): rowInputValues[1] |= 0x01; break; // Comma
case (46): rowInputValues[0] |= 0x02; break; // Period
}
// Shift and Control are special modifier keys...
if (ecs_ctrl_key) rowInputValues[5] |= 0x40; // Ctrl key
if (ecs_shift_key) rowInputValues[6] |= 0x80; // Shift key
}
UINT16 ECSKeyboard::getInputValue()
{
UINT16 inputValue = 0;
if ((directionIO & 0xC0) == 0x40) // Normal key scanning row/column
if ((directionIO & 0xC0) == 0x40) // Normal key scanning row/column (Write on 0xE and read on 0xF)
{
UINT16 rowMask = 1;
for (UINT16 row = 0; row < 8; row++)
@ -144,7 +124,7 @@ UINT16 ECSKeyboard::getInputValue()
rowMask = (UINT16)(rowMask << 1);
}
}
else if ((directionIO & 0xC0) == 0x80) // Transposed key scanning column/row
else if ((directionIO & 0xC0) == 0x80) // Transposed key scanning column/row (Write on 0xF and read on 0xE)
{
UINT16 colMask = 1;
for (UINT16 col = 0; col < 8; col++)
@ -158,7 +138,7 @@ UINT16 ECSKeyboard::getInputValue()
}
colMask = (UINT16)(colMask << 1);
}
}
} // Either both ports configured for output (illegal) or input... good enough to return 0x00FF below
return (UINT16)(0xFF ^ inputValue);
}

View File

@ -19,6 +19,8 @@
// For the ECS Keybaord (if present)
// -------------------------------------------------------------
extern UINT8 ecs_key_pressed;
extern UINT8 ecs_shift_key;
extern UINT8 ecs_ctrl_key;
class EmulationDirector;

View File

@ -60,7 +60,7 @@ class RAM : public Memory
UINT16 getReadAddress();
UINT16 getReadAddressMask();
// The only time a read or write mask is needed is for GRAM which has a dedicated class to handle that... we skip it here for speed.
// The only time a read mask is needed is for GRAM which has a dedicated class to handle that... we skip it here for speed.
virtual UINT16 peek(UINT16 location) {return image[location - this->location];}
virtual void poke(UINT16 location, UINT16 value) {image[location - this->location] = (value & trimmer);}

View File

@ -56,12 +56,15 @@ UINT8 bUseDiscOverlay __attribute__((section(".dtcm"))) = false;
UINT8 bGameLoaded __attribute__((section(".dtcm"))) = false;
UINT8 bMetaSpeedup __attribute__((section(".dtcm"))) = false;
UINT8 bShowDisc __attribute__((section(".dtcm"))) = false;
UINT8 bShowKeyboard __attribute__((section(".dtcm"))) = false;
UINT8 hud_x = 3;
UINT8 hud_y = 0;
UINT16 keypad_pressed = 0;
UINT16 ecs_debounce_timer = 0;
// -------------------------------------------------------------
// This one is accessed rather often so we'll put it in .dtcm
// -------------------------------------------------------------
@ -390,7 +393,7 @@ void dsShowEmuInfo(void)
// so we now just store all the extra goodies in this menu... By default the SELECT
// button will bring this up.
// -------------------------------------------------------------------------------------
#define MAIN_MENU_ITEMS 12
#define MAIN_MENU_ITEMS 14
const char *main_menu[MAIN_MENU_ITEMS] =
{
"RESET EMULATOR",
@ -399,10 +402,12 @@ const char *main_menu[MAIN_MENU_ITEMS] =
"GAME SCORES",
"SAVE/RESTORE STATE",
"GAME MANUAL",
"SCREEN STRETCH",
"GLOBAL CONFIG",
"SELECT CHEATS",
"GAME/EMULATOR INFO",
"SCREEN STRETCH",
"SHOW DISC",
"SHOW KEYBOARD",
"QUIT EMULATOR",
"EXIT THIS MENU",
};
@ -470,21 +475,27 @@ int menu_entry(void)
return OVL_META_MANUAL;
break;
case 6:
return OVL_META_STRETCH;
break;
case 7:
return OVL_META_GCONFIG;
break;
case 8:
case 7:
return OVL_META_CHEATS;
break;
case 9:
case 8:
return OVL_META_EMUINFO;
break;
case 9:
return OVL_META_STRETCH;
break;
case 10:
return OVL_META_QUIT;
return OVL_META_DISC;
break;
case 11:
return OVL_META_KEYBOARD;
break;
case 12:
return OVL_META_QUIT;
break;
case 13:
bDone=1;
break;
}
@ -677,7 +688,12 @@ void ds_handle_meta(int meta_key)
case OVL_META_DISC:
bShowDisc ^= 1;
show_overlay(bShowDisc);
show_overlay(bShowKeyboard, bShowDisc);
break;
case OVL_META_KEYBOARD:
bShowKeyboard ^= 1;
show_overlay(bShowKeyboard, bShowDisc);
break;
}
}
@ -763,93 +779,127 @@ UINT8 poll_touch_screen(UINT16 ctrl_disc, UINT16 ctrl_keys, UINT16 ctrl_side)
{
ds_handle_meta(OVL_META_MENU);
}
// SWITCH
// SWITCH (SWAP) CONTROLLER
else if (touch.px > myOverlay[OVL_META_SWITCH].x1 && touch.px < myOverlay[OVL_META_SWITCH].x2 && touch.py > myOverlay[OVL_META_SWITCH].y1 && touch.py < myOverlay[OVL_META_SWITCH].y2)
{
ds_handle_meta(OVL_META_SWITCH);
}
// MANUAL
// INSTRUCTION MANUAL
else if (touch.px > myOverlay[OVL_META_MANUAL].x1 && touch.px < myOverlay[OVL_META_MANUAL].x2 && touch.py > myOverlay[OVL_META_MANUAL].y1 && touch.py < myOverlay[OVL_META_MANUAL].y2)
{
ds_handle_meta(OVL_META_MANUAL);
}
// ---------------------------------------------------------------------------------------------------------
// And, finally, if the ECS mini-keypad is being shown, we can directly check for any ECS keyboard keys...
// ---------------------------------------------------------------------------------------------------------
if (myConfig.overlay == 1)
// SHOW DISC
else if (touch.px > myOverlay[OVL_META_DISC].x1 && touch.px < myOverlay[OVL_META_DISC].x2 && touch.py > myOverlay[OVL_META_DISC].y1 && touch.py < myOverlay[OVL_META_DISC].y2)
{
if ((touch.px > 5) && (touch.px < 98))
{
if (touch.py >= 25 && touch.py < 43) // Row: 1 2 3 4 5
{
if (touch.px <= 23) ecs_key_pressed = 1;
else if (touch.px <= 41) ecs_key_pressed = 2;
else if (touch.px <= 60) ecs_key_pressed = 3;
else if (touch.px <= 78) ecs_key_pressed = 4;
else if (touch.px <= 97) ecs_key_pressed = 5;
ds_handle_meta(OVL_META_DISC);
}
// SHOW KEYBOARD
else if (touch.px > myOverlay[OVL_META_KEYBOARD].x1 && touch.px < myOverlay[OVL_META_KEYBOARD].x2 && touch.py > myOverlay[OVL_META_KEYBOARD].y1 && touch.py < myOverlay[OVL_META_KEYBOARD].y2)
{
ds_handle_meta(OVL_META_KEYBOARD);
while (keysCurrent() & KEY_TOUCH) // Wait for release
{
WAITVBL;
}
WAITVBL;
}
}
else if (touch.py >= 43 && touch.py < 60) // Row: 6 7 8 9 0
// ---------------------------------------------------------------------------------------------------------
// And, finally, if the ECS keyboard is being shown, we must check for any presses on this virtual keyboard
// ---------------------------------------------------------------------------------------------------------
else if (bShowKeyboard)
{
if (touch.py >= 14 && touch.py < 50) // Row: 1 2 3 4 5 6 7 8 9 0 ESC
{
if (touch.px <= 24) ecs_key_pressed = 1;
else if (touch.px <= 47) ecs_key_pressed = 2;
else if (touch.px <= 70) ecs_key_pressed = 3;
else if (touch.px <= 93) ecs_key_pressed = 4;
else if (touch.px <= 116) ecs_key_pressed = 5;
else if (touch.px <= 139) ecs_key_pressed = 6;
else if (touch.px <= 162) ecs_key_pressed = 7;
else if (touch.px <= 185) ecs_key_pressed = 8;
else if (touch.px <= 207) ecs_key_pressed = 9;
else if (touch.px <= 237) ecs_key_pressed = 10;
else if (touch.px <= 255) ecs_key_pressed = 43;
}
else if (touch.py >= 50 && touch.py < 85) // Row: QWERTY (top row)
{
if (touch.px <= 10) ecs_key_pressed = ecs_key_pressed; // Nothing here
if (touch.px <= 35) ecs_key_pressed = 27; // Q
else if (touch.px <= 58) ecs_key_pressed = 33; // W
else if (touch.px <= 81) ecs_key_pressed = 15; // E
else if (touch.px <= 103) ecs_key_pressed = 28; // R
else if (touch.px <= 127) ecs_key_pressed = 30; // T
else if (touch.px <= 150) ecs_key_pressed = 35; // Y
else if (touch.px <= 173) ecs_key_pressed = 31; // U
else if (touch.px <= 196) ecs_key_pressed = 19; // I
else if (touch.px <= 219) ecs_key_pressed = 25; // O
else if (touch.px <= 243) ecs_key_pressed = 26; // P
}
else if (touch.py >= 85 && touch.py < 120) // Row: ASDF (home row)
{
if (touch.px <= 18) ecs_key_pressed = ecs_key_pressed; // Nothing here
else if (touch.px <= 44) ecs_key_pressed = 11; // A
else if (touch.px <= 67) ecs_key_pressed = 29; // S
else if (touch.px <= 90) ecs_key_pressed = 14; // D
else if (touch.px <= 113) ecs_key_pressed = 16; // F
else if (touch.px <= 136) ecs_key_pressed = 17; // G
else if (touch.px <= 159) ecs_key_pressed = 18; // H
else if (touch.px <= 182) ecs_key_pressed = 20; // J
else if (touch.px <= 205) ecs_key_pressed = 21; // K
else if (touch.px <= 228) ecs_key_pressed = 22; // L
else if (touch.px <= 251) ecs_key_pressed = 44; // ;
}
else if (touch.py >= 120 && touch.py < 155) // Row: ZXCV (bottom row)
{
if (touch.px <= 40)
{
if (touch.px <= 23) ecs_key_pressed = 6;
else if (touch.px <= 41) ecs_key_pressed = 7;
else if (touch.px <= 60) ecs_key_pressed = 8;
else if (touch.px <= 78) ecs_key_pressed = 9;
else if (touch.px <= 97) ecs_key_pressed = 10;
if ((touch.px <= 20) && (touch.py < 139)) ecs_key_pressed = 39; // UP
else if ((touch.px <= 40) && (touch.py < 139)) ecs_key_pressed = 37; // LEFT
else
if ((touch.px <= 20) && (touch.py < 155)) ecs_key_pressed = 38; // DOWN
else if ((touch.px <= 40) && (touch.py < 155)) ecs_key_pressed = 40; // RIGHT
}
else if (touch.px <= 64) ecs_key_pressed = 36; // Z
else if (touch.px <= 87) ecs_key_pressed = 34; // X
else if (touch.px <= 110) ecs_key_pressed = 13; // C
else if (touch.px <= 133) ecs_key_pressed = 32; // V
else if (touch.px <= 156) ecs_key_pressed = 12; // B
else if (touch.px <= 179) ecs_key_pressed = 24; // N
else if (touch.px <= 202) ecs_key_pressed = 23; // M
else if (touch.px <= 225) ecs_key_pressed = 45; // Comma
else if (touch.px <= 250) ecs_key_pressed = 46; // Period
}
else if (touch.py >= 155 && touch.py < 192) // Very bottom row... Shift, Space and RETURN
{
if (touch.px <= 28)
{
if (!ecs_debounce_timer)
{
ecs_ctrl_key ^= 1; // Ctrl is special
ecs_debounce_timer = 20;
dsPrintValue(1,22,ecs_ctrl_key?1:0,ecs_ctrl_key ? (char*)"@": (char*)" ");
}
}
else if (touch.py >= 60 && touch.py < 78) // Row: A B C D E
{
if (touch.px <= 23) ecs_key_pressed = 11;
else if (touch.px <= 41) ecs_key_pressed = 12;
else if (touch.px <= 60) ecs_key_pressed = 13;
else if (touch.px <= 78) ecs_key_pressed = 14;
else if (touch.px <= 97) ecs_key_pressed = 15;
else if (touch.px <= 55)
{
if (!ecs_debounce_timer)
{
ecs_shift_key ^= 1; // Shift is special
ecs_debounce_timer = 20;
dsPrintValue(5,22,0,ecs_shift_key ? (char*)"@": (char*)" ");
}
}
else if (touch.py >= 78 && touch.py < 95) // Row: F G H I J
else if (touch.px <= 194) ecs_key_pressed = 41; // Space
else if (touch.px <= 231) ecs_key_pressed = 42; // Return
else if (touch.px <= 254) // Switch to Hand Controller
{
if (touch.px <= 23) ecs_key_pressed = 16;
else if (touch.px <= 41) ecs_key_pressed = 17;
else if (touch.px <= 60) ecs_key_pressed = 18;
else if (touch.px <= 78) ecs_key_pressed = 19;
else if (touch.px <= 97) ecs_key_pressed = 20;
}
else if (touch.py >= 95 && touch.py < 112) // Row: K L M N O
{
if (touch.px <= 23) ecs_key_pressed = 21;
else if (touch.px <= 41) ecs_key_pressed = 22;
else if (touch.px <= 60) ecs_key_pressed = 23;
else if (touch.px <= 78) ecs_key_pressed = 24;
else if (touch.px <= 97) ecs_key_pressed = 25;
}
else if (touch.py >= 112 && touch.py < 130) // Row: P Q R S T
{
if (touch.px <= 23) ecs_key_pressed = 26;
else if (touch.px <= 41) ecs_key_pressed = 27;
else if (touch.px <= 60) ecs_key_pressed = 28;
else if (touch.px <= 78) ecs_key_pressed = 29;
else if (touch.px <= 97) ecs_key_pressed = 30;
}
else if (touch.py >= 130 && touch.py < 148) // Row: U V W X Y
{
if (touch.px <= 23) ecs_key_pressed = 31;
else if (touch.px <= 41) ecs_key_pressed = 32;
else if (touch.px <= 60) ecs_key_pressed = 33;
else if (touch.px <= 78) ecs_key_pressed = 34;
else if (touch.px <= 97) ecs_key_pressed = 35;
}
else if (touch.py >= 148 && touch.py < 166) // Row: Z [arrows]
{
if (touch.px <= 23) ecs_key_pressed = 36;
else if (touch.px <= 41) ecs_key_pressed = 37;
else if (touch.px <= 60) ecs_key_pressed = 38;
else if (touch.px <= 78) ecs_key_pressed = 39;
else if (touch.px <= 97) ecs_key_pressed = 40;
}
else if (touch.py >= 166 && touch.py < 190) // Row: SPC RET
{
if (touch.px <= 50) ecs_key_pressed = 41;
else if (touch.px <= 97) ecs_key_pressed = 42;
bShowKeyboard = 0;
show_overlay(bShowKeyboard, bShowDisc);
}
}
}
@ -875,6 +925,12 @@ UINT8 poll_touch_screen(UINT16 ctrl_disc, UINT16 ctrl_keys, UINT16 ctrl_side)
else if ((touch.px >= 62) && (touch.px < 96) && (touch.py >= 28) && (touch.py < 64)) ds_disc_input[ctrl_disc][14]= 1;
else if ((touch.px >= 87) && (touch.px < 104) && (touch.py >= 53) && (touch.py < 73)) ds_disc_input[ctrl_disc][14]= 1;
else if ((touch.px >= 96) && (touch.px < 117) && (touch.py >= 20) && (touch.py < 52)) ds_disc_input[ctrl_disc][15]= 1;
else if ((touch.px >= 235) && (touch.py >= 155)) // Exit back to hand-controller
{
bShowDisc = 0;
show_overlay(bShowKeyboard, bShowDisc);
}
}
return pad_pressed;
@ -1238,7 +1294,7 @@ ITCM_CODE void pollInputs(void)
last_pressed = keys_pressed;
ecs_key_pressed = (myConfig.overlay == 1) ? 0:255;
ecs_key_pressed = 0;
// -----------------------------------------------------------------
// Now handle the on-screen Intellivision overlay and meta keys...
@ -1255,7 +1311,12 @@ ITCM_CODE void pollInputs(void)
}
}
} else keypad_pressed = 0;
} else keypad_pressed = 0;
}
else
{
keypad_pressed = 0;
if (ecs_debounce_timer) ecs_debounce_timer--;
}
}
@ -1293,7 +1354,7 @@ void dsShowScreenMain(bool bFull, bool bPlayJingle)
#ifdef DEBUG_ENABLE
show_debug_overlay();
#else
show_overlay(bShowDisc);
show_overlay(bShowKeyboard, bShowDisc);
#endif
}

View File

@ -21,6 +21,7 @@
#include "nintv-ds.h"
#include "overlay.h"
#include "config.h"
#include "ECSKeyboard.h"
#include "bgBottom.h"
#include "bgBottom-ECS.h"
#include "bgBottom-disc.h"
@ -63,36 +64,36 @@ struct Overlay_t defaultOverlay[OVL_MAX] =
{ 10, 87, 10, 40}, // META_RESET
{ 10, 87, 41, 70}, // META_LOAD
{ 10, 87, 71, 100}, // META_CONFIG
{ 10, 87, 101, 131}, // META_SCORE
{255, 255, 255, 255}, // META_SCORE
{255, 255, 255, 255}, // META_QUIT
{ 10, 87, 131, 160}, // META_STATE
{ 10, 87, 161, 191}, // META_MENU
{ 10, 87, 101, 131}, // META_STATE
{ 10, 87, 131, 160}, // META_MENU
{255, 255, 255, 255}, // META_SWAP
{255, 255, 255, 255}, // META_MANUAL
{255, 255, 255, 255}, // META_STRETCH
{255, 255, 255, 255}, // META_GCONFIG
{ 50, 86, 161, 191}, // META_DISC
{ 8, 49, 161, 191}, // META_KEYBOARD
};
// ----------------------------------------------------------------------------------------
// This is the ECS overlay with reduced menu options...
// This is the ECS overlay with no menu options...
// ----------------------------------------------------------------------------------------
struct Overlay_t ecsOverlay[OVL_MAX] =
{
{120, 155, 30, 60}, // KEY_1
{158, 192, 30, 60}, // KEY_2
{195, 230, 30, 60}, // KEY_3
{255, 255, 255, 255}, // KEY_1
{255, 255, 255, 255}, // KEY_2
{255, 255, 255, 255}, // KEY_3
{120, 155, 65, 95}, // KEY_4
{158, 192, 65, 95}, // KEY_5
{195, 230, 65, 95}, // KEY_6
{255, 255, 255, 255}, // KEY_4
{255, 255, 255, 255}, // KEY_5
{255, 255, 255, 255}, // KEY_6
{120, 155, 101, 135}, // KEY_7
{158, 192, 101, 135}, // KEY_8
{195, 230, 101, 135}, // KEY_9
{255, 255, 255, 255}, // KEY_7
{255, 255, 255, 255}, // KEY_8
{255, 255, 255, 255}, // KEY_9
{120, 155, 140, 175}, // KEY_CLEAR
{158, 192, 140, 175}, // KEY_0
{195, 230, 140, 175}, // KEY_ENTER
{255, 255, 255, 255}, // KEY_CLEAR
{255, 255, 255, 255}, // KEY_0
{255, 255, 255, 255}, // KEY_ENTER
{255, 255, 255, 255}, // KEY_FIRE
{255, 255, 255, 255}, // KEY_L_ACT
@ -104,15 +105,15 @@ struct Overlay_t ecsOverlay[OVL_MAX] =
{255, 255, 255, 255}, // META_SCORE
{255, 255, 255, 255}, // META_QUIT
{255, 255, 255, 255}, // META_STATE
{ 55, 101, 2, 20}, // META_MENU
{255, 255, 255, 255}, // META_MENU
{255, 255, 255, 255}, // META_SWAP
{255, 255, 255, 255}, // META_MANUAL
{255, 255, 255, 255}, // META_STRETCH
{255, 255, 255, 255}, // META_GCONFIG
{255, 255, 255, 255}, // META_DISC
{255, 255, 255, 255}, // META_KEYBOARD
};
// ----------------------------------------------------------------------------------------
// This is the ECS overlay with reduced menu options...
// This is the Disc overlay with no menu options...
// ----------------------------------------------------------------------------------------
struct Overlay_t discOverlay[OVL_MAX] =
{
@ -145,8 +146,8 @@ struct Overlay_t discOverlay[OVL_MAX] =
{255, 255, 255, 255}, // META_MENU
{255, 255, 255, 255}, // META_SWAP
{255, 255, 255, 255}, // META_MANUAL
{255, 255, 255, 255}, // META_STRETCH
{255, 255, 255, 255}, // META_GCONFIG
{255, 255, 255, 255}, // META_DISC
{255, 255, 255, 255}, // META_KEYBOARD
};
struct Overlay_t myOverlay[OVL_MAX];
@ -350,14 +351,14 @@ void load_custom_overlay(bool bCustomGeneric)
// This puts the overlay on the main screen. It can be one of the built-in
// overlays or it might be a custom overlay that will be rendered...
// ---------------------------------------------------------------------------
void show_overlay(u8 bShowDisc)
void show_overlay(u8 bShowKeyboard, u8 bShowDisc)
{
// Assume default overlay... custom can change it below...
memcpy(&myOverlay, &defaultOverlay, sizeof(myOverlay));
swiWaitForVBlank();
if (myConfig.overlay == 1) // ECS mini keyboard overlay
if (bShowKeyboard) // ECS keyboard overlay
{
decompress(bgBottom_ECSTiles, bgGetGfxPtr(bg0b), LZ77Vram);
decompress(bgBottom_ECSMap, (void*) bgGetMapPtr(bg0b), LZ77Vram);
@ -387,6 +388,12 @@ void show_overlay(u8 bShowDisc)
REG_BLDCNT=0; REG_BLDCNT_SUB=0; REG_BLDY=0; REG_BLDY_SUB=0;
swiWaitForVBlank();
if (bShowKeyboard) // ECS keyboard overlay
{
dsPrintValue(1,22,ecs_ctrl_key?1:0,ecs_ctrl_key ? (char*)"@": (char*)" ");
dsPrintValue(5,22,0,ecs_shift_key ? (char*)"@": (char*)" ");
}
}
// End of Line

View File

@ -44,27 +44,29 @@ struct Overlay_t
#define OVL_BTN_L_ACT 13
#define OVL_BTN_R_ACT 14
#define OVL_META_RESET 15
#define OVL_META_LOAD 16
#define OVL_META_CONFIG 17
#define OVL_META_SCORES 18
#define OVL_META_QUIT 19
#define OVL_META_STATE 20
#define OVL_META_MENU 21
#define OVL_META_SWITCH 22
#define OVL_META_MANUAL 23
#define OVL_META_DISC_UP 24
#define OVL_META_DISC_DN 25
#define OVL_META_SPEEDUP 26
#define OVL_META_DISC 27
#define OVL_META_RESET 15
#define OVL_META_LOAD 16
#define OVL_META_CONFIG 17
#define OVL_META_SCORES 18
#define OVL_META_QUIT 19
#define OVL_META_STATE 20
#define OVL_META_MENU 21
#define OVL_META_SWITCH 22
#define OVL_META_MANUAL 23
#define OVL_META_DISC 24
#define OVL_META_KEYBOARD 25
#define OVL_META_STRETCH 28
#define OVL_META_GCONFIG 29
#define OVL_META_CHEATS 30
#define OVL_META_EMUINFO 31
// These are not likely mapped anywhere... keep them near the back end
#define OVL_META_DISC_UP 26
#define OVL_META_DISC_DN 27
#define OVL_META_SPEEDUP 28
#define OVL_META_STRETCH 29
#define OVL_META_GCONFIG 30
#define OVL_META_CHEATS 31
#define OVL_META_EMUINFO 32
#define OVL_MAX 32
#define DISC_MAX 16
#define OVL_MAX 33
#define DISC_MAX 16
// For the various controller types...
@ -78,6 +80,6 @@ extern struct Overlay_t myOverlay[OVL_MAX];
extern struct Overlay_t myDisc[DISC_MAX];
extern void load_custom_overlay(void);
extern void show_overlay(u8 bShowDisc);
extern void show_overlay(u8 bShowKeyboard, u8 bShowDisc);
#endif

Binary file not shown.

View File

@ -27,6 +27,8 @@
.ovl 255, 255, 255, 255, //META_MENU - UNUSED for Astrosmash
.ovl 255, 255, 255, 255, //META_SWAP - UNUSED for Astrosmash
.ovl 255, 255, 255, 255, //META_MANUAL - UNUSED for Astrosmash
.ovl 255, 255, 255, 255, //META_DISC - UNUSED for Astrosmash
.ovl 255, 255, 255, 255, //META_KEYBOARD - UNUSED for Astrosmash
.tile 0x0041C010,0xF000003C,0xF001F001,0xAA095001,0x01F0FEAA,0x01F001F0,0x01F001F0,0x01E001F0
.tile 0x13F0C720,0x20AA01F0,0x00271020,0xFF070005,0x04700520,0x28402DF0,0x01F001F0,0x1AF03F90

View File

@ -25,8 +25,9 @@
.ovl 23, 82, 161, 181, // META_MENU
.ovl 255, 255, 255, 255, // META_SWAP
.ovl 255, 255, 255, 255, // META_MANUAL
.ovl 255, 255, 255, 255, // META_DISC
.ovl 255, 255, 255, 255, // META_KEYBOARD
.tile 0x00AF0010,0xF000003C,0xF001F001,0x73095001,0x01F0F273,0x01F001F0,0xCD1A0950,0x80310110
.tile 0x622E0600,0x2E565681,0xCD81001A,0xCD2E56CD,0xCD0081CD,0x1ACD5681,0x001A8162,0xCD2E1A2A
.tile 0x1A1A2E81,0x811A5610,0xCD1A2200,0x62021A56,0x2A81D056,0xD038001A,0x482A5600,0x56D0CD2E

View File

@ -25,6 +25,8 @@
.ovl 100, 155, 0, 30, // META_MENU (top center)
.ovl 255, 255, 255, 255, // META_SWAP
.ovl 255, 255, 255, 255, // META_MANUAL
.ovl 255, 255, 255, 255, // META_DISC
.ovl 255, 255, 255, 255, // META_KEYBOARD
.disc 255, 255, 255, 255, // DISC_NORTH
.disc 255, 255, 255, 255, // DISC_NORTH_NORTH_EAST