NEO mapper/Extension
From MSX Game Library
Proposal for an extension to the NEO mapper format.
Contents
Specifications
Principles
Any write operation to the NEO mapper with data bit 7 set to 1 and address bit 0 set to 1 is considered an access to extended features. In that case, the mapper bank register is not modified.
All other write operations should be considered normal access to the mapper's bank register.
The data contains:
- The number of an extended function in the mapper
- A bit indicating whether the function should be enabled or disabled
The address contains an 8-bit parameter to be passed to the function.
|
| ||||||||||||||||||||||||||||||||||||||||||||||||
Functions
0x00: Cartridge information
When activated, any read access to the given bank will return the cartridge information (8 KB, mirrored on NEO-16).
| 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | ||
|---|---|---|---|---|---|---|---|---|---|
| 0 | 0 | 0 | 0 | 0 | Bank | ||||
0x01: Cartridge configuration
0x04: Activate SRAM/FRAM
When activated, any read/write access to the specified bank (defined in the parameter) is redirected to the selected segment of the SRAM/FRAM.
SRAM/FRAM is accessed through 8 KB segments (on the NEO-16, the segment is mirrored).
Up to 16 segments can be accessed, for a total capacity of 128 KB.
| 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | ||
|---|---|---|---|---|---|---|---|---|---|
| Segment | 0 | Bank | |||||||
0x05: Activate device
Activate or disactivate the given device.
| 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 |
|---|---|---|---|---|---|---|---|
| 0 | 0 | 0 | Device | ||||
Devices:
- 00: MSX-Music (OPLL)
- 01: MSX-Audio
- 02: SCC
- 03: SCC+
- 04: 2nd PSG (port 10h)
- 05: Darky (2 x ePSG)
- 06: Darky Jr. (2 x PSG)
- 08: OPM (SFK-01, SFG-01 et SFG-05 ver.1)
- 09: OPP (SFG-05 ver.2)
- 12: OPL4
- 15: SAM2695
Appendix
Programmable processor and emulation
Here is a pseudo code in C to handle NEO mappers extension for programmable processor based cartridges or for emulators:
NEO-16 mapper:
const uint8* romData; // ROM data
uint16 bankValue[3]; // Bank switching register value
// Extended function prototypes
typedef void (*funcEnable_t)(bool, uint8);
typedef void (*funcWrite_t)(uint16, uint8);
typedef uint8 (*funcRead_t)(uint16);
// Extended functions table
funcEnable_t funcEnableTable[32];
funcWrite_t funcWriteTable[3];
funcRead_t funcReadTable[3];
// Handle device initialization
void NEO16_Init()
{
for (uint8 i = 0; i < 3; i++)
{
bankValue[i] = 0x0000;
funcWriteTable[i] = NULL;
funcReadTable[i] = NULL;
}
for (uint8 i = 0; i < 32; i++)
funcTab[i] = NULL;
}
// Handle write access
void NEO16_Write(uint16 address, uint8 value)
{
uint8 bank = ((address >> 12) & 0x03) - 1; // Get the corresponding bank number
if (bank > 2)
return; // skip
if (funcWriteTable[bank] != NULL) // Check for bank write callback
{
funcWriteTable[bank](address, value);
}
else if ((address & 0x0001) && (value & 0x80)) // Handle extended function
{
uint8 funcId = value & 0x3F; // Get function ID
if (funcEnableTable[funcId] != NULL)
funcEnableTable[funcId](value & 0x40, (address >> 1) & 0xFF); // Execute function specific code
}
else // Write to the given bank register
{
if (address & 1) // Set bank register MSB
bankValue[bank] = ((value & 0x0F) << 8) | (bankValue[bank] & 0x00FF);
else // Set bank register LSB
bankValue[bank] = (bankValue[bank] & 0xFF00) | (value);
}
}
// Handle read access
uint8 NEO16_Read(uint16 address)
{
uint8 bank = address >> 14; // Get the corresponding bank number
if (bank > 2)
return 0xFF; // skip
if (funcReadTable[bank] != NULL) // Check for bank read callback
return funcReadTable[bank](address);
else
return romData[(bankValue[bank]) << 14 + (address & 0x3FFF)];
}