Difference between revisions of "NEO mapper/Extension2"

From MSX Game Library

< NEO mapper

(→‎0x05: Reserved)
(Replaced content with "#REDICT NEO mapper/Extension")
 
(61 intermediate revisions by the same user not shown)
Line 1: Line 1:
−
{{WARNING|This page is still in the proposal stage and should not yet be considered an official specification.}}
+
#REDICT [[NEO mapper/Extension]]
−
 
 
−
Proposal for an extension to the [[NEO mapper]] format.
 
−
 
 
−
== Specifications ==
 
−
 
 
−
=== Principles ===
 
−
 
 
−
Any write operation to the NEO mapper with address bits 11-13 set to 0 is considered as 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 address contains an 4-bit function ID, and a 3-bit destination bank value for function that applied to a given mapper's bank.
 
−
 
 
−
The data can be use by the function as a parameter.
 
−
 
 
−
{|
 
−
|-
 
−
|
 
−
{| class="wikitable"
 
−
|+ ADDRESS
 
−
|-
 
−
! 15 || 14 || 13 || 12 || 11 || 10 || 9 || 8 || 7 || 6 || 5 || 4 || 3 || 2 || 1 || 0
 
−
|-
 
−
|style="background-color:#BBB;" colspan="2"| Page
 
−
|style="background-color:#FAA;"| 0
 
−
|style="background-color:#FAA;"| 0
 
−
|style="background-color:#FAA;"| 0
 
−
|style="background-color:#AAF;" colspan="3"| Bank
 
−
|style="background-color:#BBB;"| 0
 
−
|style="background-color:#BBB;"| 0
 
−
|style="background-color:#BBB;"| 0
 
−
|style="background-color:#BBB;"| 0
 
−
|style="background-color:#AAF;" colspan="4"| Function
 
−
|}
 
−
|
 
−
{| class="wikitable"
 
−
|+ DATA
 
−
|-
 
−
! 7 || 6 || 5 || 4 || 3 || 2 || 1 || 0
 
−
|-
 
−
|style="background-color:#AAF;" colspan="8"| Parameter
 
−
|}
 
−
|}
 
−
 
 
−
The implementation of functions 0 and 1 is mandatory. All others are optional. Function 1 provides a list of the functions supported by the cartridge.
 
−
 
 
−
=== Functions ===
 
−
==== 0x00: ROM mapper (mandatory) ====
 
−
Activate access to the cartridge ROM mapper through the given bank (default mode)
 
−
 
 
−
Parameter:
 
−
{| class="wikitable"
 
−
! 8 || 7 || 6 || 5 || 4 || 3 || 2 || 1
 
−
|- style="background-color:#BBB;"
 
−
| 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0
 
−
|}
 
−
 
 
−
==== 0x01: Cartridge information (mandatory) ====
 
−
Activate read access to the cartridge information data through the given bank (256 bytes mirrored)
 
−
 
 
−
Parameter:
 
−
{| class="wikitable"
 
−
! 8 || 7 || 6 || 5 || 4 || 3 || 2 || 1
 
−
|- style="background-color:#BBB;"
 
−
| 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0
 
−
|}
 
−
 
 
−
Information format:
 
−
{| class="wikitable"
 
−
!rowspan="2"| Offset !!rowspan="2"| Size !!rowspan="2"| Description !!colspan="8"| Content
 
−
|-
 
−
! 8 || 7 || 6 || 5 || 4 || 3 || 2 || 1
 
−
|-
 
−
| 0 || 3 || Signature ||colspan="8" style="background-color:#FAA;"| "NEO"
 
−
|-
 
−
| 3 || 1 || NEO-mapper version (major/minor) ||colspan="4" style="background-color:#FAA;"| 1 ||colspan="4" style="background-color:#FAA;"| 3
 
−
|-
 
−
| 4 || 1
 
−
| Flag
 
−
* S: Bank size (0=8KB, 1=16KB)
 
−
| 0 || 0 || 0 || 0 || 0 || 0 || 0 || S
 
−
|- style="background-color:#BBB;"
 
−
| 5 || 1 || ''Reserved'' ||colspan="8"| 0
 
−
|-
 
−
| 6 || 2 || Number of segments ||colspan="8"| 4~16384
 
−
|- style="background-color:#BBB;"
 
−
| 8 || 8 || ''Reserved'' ||colspan="8"| 0
 
−
|-
 
−
| 16 || 1 || Function 0 support (ROM) ||colspan="8" style="background-color:#FAA;"| 1
 
−
|-
 
−
| 17 || 1 || Function 1 support (Info) ||colspan="8" style="background-color:#FAA;"| 1
 
−
|-
 
−
| 18 || 1 || Function 2 support ||colspan="8"| >0 if supported
 
−
|-
 
−
| 19 || 1 || Function 3 support ||colspan="8"| >0 if supported
 
−
|-
 
−
| 20 || 1 || Function 4 support (RAM) ||colspan="8"| >0 if supported
 
−
|-
 
−
| 21 || 1 || Function 5 support ||colspan="8"| >0 if supported
 
−
|-
 
−
| 22 || 1 || Function 6 support (SRAM) ||colspan="8"| >0 if supported
 
−
|-
 
−
| 23 || 1 || Function 7 support ||colspan="8"| >0 if supported
 
−
|-
 
−
| 24 || 1 || Function 8 support (SCC) ||colspan="8"| >0 if supported
 
−
|-
 
−
| 25 || 1 || Function 9 support (SPC700) ||colspan="8"| >0 if supported
 
−
|-
 
−
| 26 || 1 || Function 10 support ||colspan="8"| >0 if supported
 
−
|-
 
−
| 27 || 1 || Function 11 support ||colspan="8"| >0 if supported
 
−
|-
 
−
| 28 || 1 || Function 12 support ||colspan="8"| >0 if supported
 
−
|-
 
−
| 29 || 1 || Function 13 support ||colspan="8"| >0 if supported
 
−
|-
 
−
| 30 || 1 || Function 14 support ||colspan="8"| >0 if supported
 
−
|-
 
−
| 31 || 1 || Function 15 support ||colspan="8"| >0 if supported
 
−
|- style="background-color:#BBB;"
 
−
| 32 || 224 || ''Reserved'' ||colspan="8"| 0
 
−
|}
 
−
 
 
−
==== 0x02: ''Reserved'' ====
 
−
Reserved for possible future use to control the NEO cartridge from within the program.
 
−
 
 
−
==== 0x03: ''Reserved'' ====
 
−
 
 
−
==== 0x04: RAM ====
 
−
Activate read/write access to RAM through the given bank
 
−
 
 
−
Parameter:
 
−
{| class="wikitable"
 
−
! 8 || 7 || 6 || 5 || 4 || 3 || 2 || 1
 
−
|-
 
−
|style="background-color:#AAF;" colspan="8"| RAM segment
 
−
|}
 
−
 
 
−
==== 0x05: ''Reserved'' ====
 
−
Reserved to potentially allow the use of a 16-bit mapper for RAM.
 
−
 
 
−
==== 0x06: SRAM/FRAM ====
 
−
Activate read/write access to SRAM/FRAM through the given bank (8 KB mirrored on NEO-16)
 
−
 
 
−
Parameter:
 
−
{| class="wikitable"
 
−
! 8 || 7 || 6 || 5 || 4 || 3 || 2 || 1
 
−
|-
 
−
|style="background-color:#BBB;"| 0
 
−
|style="background-color:#BBB;"| 0
 
−
|style="background-color:#BBB;"| 0
 
−
|style="background-color:#BBB;"| 0
 
−
|style="background-color:#AAF;" colspan="4"| Segment
 
−
|}
 
−
 
 
−
==== 0x07: ''Reserved'' ====
 
−
 
 
−
==== 0x08: SCC/SCC+ ====
 
−
Activate SCC to be accessed through memory area from 9800h to 9FFFh (4 KB mirrored)
 
−
Any bank number is valid, but bank #4 is recommanded for NEO-8 and #2 for NEO-16 to use standard address for
 
−
 
 
−
{| class="wikitable"
 
−
! 8 || 7 || 6 || 5 || 4 || 3 || 2 || 1
 
−
|-
 
−
|style="background-color:#AAF;"| C
 
−
|style="background-color:#BBB;"| 0
 
−
|style="background-color:#BBB;"| 0
 
−
|style="background-color:#BBB;"| 0
 
−
|style="background-color:#BBB;"| 0
 
−
|style="background-color:#BBB;"| 0
 
−
|style="background-color:#BBB;"| 0
 
−
|style="background-color:#BBB;"| 0
 
−
|}
 
−
* C: 0=SCC, 1=SCC+
 
−
 
 
−
==== 0x09: SPC700 ====
 
−
 
 
−
== 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:
 
−
<syntaxhighlight lang="c">
 
−
#define BANK_NUM 3
 
−
#define BANK_SIZE (16 * 1024)
 
−
#define ROM_SEG_NUM 1024
 
−
#define ROM_SEG_MASK (ROM_SEG_NUM - 1)
 
−
#define ROM_SIZE (ROM_SEG_NUM * BANK_SIZE)
 
−
#define FUNC_NUM 16
 
−
 
 
−
// Extended function prototypes
 
−
typedef void (*funcSelect_t)(uint8, uint8);
 
−
typedef void (*funcWrite_t)(uint16, uint8);
 
−
typedef uint8 (*funcRead_t)(uint16);
 
−
 
 
−
// Extended functions tables
 
−
funcSelect_t funcSelectTable[FUNC_NUM];
 
−
funcWrite_t funcWriteTable[BANK_NUM];
 
−
funcRead_t funcReadTable[BANK_NUM];
 
−
 
 
−
// Supported extended function initialization
 
−
void initMapper();
 
−
void initInfo();
 
−
void initRAM();
 
−
void initSRAM();
 
−
 
 
−
//=============================================================================
 
−
// NEO-16 Interface
 
−
//=============================================================================
 
−
 
 
−
// Handle device initialization
 
−
void NEO16_Init()
 
−
{
 
−
// Mandatory functions
 
−
initMapper();
 
−
initInfo();
 
−
// Optional functions
 
−
initRAM();
 
−
initSRAM();
 
−
}
 
−
 
 
−
// Handle write access
 
−
void NEO16_Write(uint16 address, uint8 data)
 
−
{
 
−
uint8 bank = ((address >> 12) & 0x03) - 1; // Get the corresponding bank number
 
−
if (bank < BANK_NUM)
 
−
{
 
−
funcWriteTable[bank](address, data);
 
−
}
 
−
else // Extended function
 
−
{
 
−
uint8 funcId = address & 0x0F; // Get function ID
 
−
bank = (address >> 8) & 0x07; // Get destination bank
 
−
if ((bank < BANK_NUM) && (funcSelectTable[funcId] != NULL)) // Is function supported?
 
−
funcSelectTable[funcId](bank, data); // Initialize function specific code
 
−
}
 
−
}
 
−
 
 
−
// Handle read access
 
−
uint8 NEO16_Read(uint16 address)
 
−
{
 
−
uint8 bank = address >> 14; // Get the corresponding bank number
 
−
if (bank < BANK_NUM)
 
−
return funcReadTable[bank](address);
 
−
 
 
−
return 0xFF; // skip
 
−
}
 
−
 
 
−
//=============================================================================
 
−
// Function 0x00 - ROM Mapper
 
−
//=============================================================================
 
−
 
 
−
// ROM data
 
−
extern const uint8* romData;
 
−
 
 
−
// Bank switching register value
 
−
uint16 romSegment[BANK_NUM];
 
−
 
 
−
void writeMapper(uint16 address, uint8 data)
 
−
{
 
−
if (address & 1) // Set bank register MSB
 
−
romSegment[bank] = ((data & 0x0F) << 8) | (romSegment[bank] & 0x00FF);
 
−
else // Set bank register LSB
 
−
romSegment[bank] = (romSegment[bank] & 0xFF00) | (data);
 
−
}
 
−
 
 
−
uint8 readMapper(uint16 address)
 
−
{
 
−
return romData[((romSegment[bank]) << 14) + (address & 0x3FFF)];
 
−
}
 
−
 
 
−
void selectMapper(uint8 bank, uint8 data)
 
−
{
 
−
funcWriteTable[bank] = writeMapper;
 
−
funcReadTable[bank] = readMapper;
 
−
}
 
−
 
 
−
void initMapper()
 
−
{
 
−
for (uint8 i = 0; i < BANK_NUM; i++)
 
−
{
 
−
romSegment[i] = 0x0000;
 
−
selectMapper(i, 0);
 
−
}
 
−
funcSelectTable[0] = selectMapper;
 
−
}
 
−
 
−
//=============================================================================
 
−
// Function 0x01 - Cartridge Information
 
−
//=============================================================================
 
−
 
 
−
struct info
 
−
{
 
−
char Sign[3];
 
−
uint8 Version;
 
−
uint8 Flag;
 
−
uint8 _reserved1;
 
−
uint16 SegmentNum;
 
−
uint8 _reserved2[8];
 
−
uint8 Functions[FUNC_NUM]; // Must be different from 0 for supported functions
 
−
};
 
−
 
 
−
const struct infoData =
 
−
{
 
−
{ 'N', 'E', 'O' },
 
−
0x13, // Version 1.3
 
−
0x01, // NEO-16
 
−
0,
 
−
ROM_SEG_NUM, // 1204 segments (16 MB)
 
−
{ 0, 0, 0, 0, 0, 0, 0, 0 },
 
−
{
 
−
1, // Mapper
 
−
1, // Info
 
−
0,
 
−
32, // RAM
 
−
32, // SRAM/FRAM
 
−
0,
 
−
0,
 
−
0, // SCC
 
−
0,
 
−
0,
 
−
0,
 
−
0,
 
−
0,
 
−
0,
 
−
0,
 
−
0,
 
−
},
 
−
};
 
−
 
 
−
void writeInfo(uint16 address, uint8 data) {}
 
−
 
 
−
uint8 readInfo(uint16 address)
 
−
{
 
−
uint8 index = address & 0xFF; // mirrored every 256 bytes
 
−
if (index > sizeof(info))
 
−
return 0;
 
−
return ((const uint8*)&infoData)[index];
 
−
}
 
−
 
 
−
void selectInfo(uint8 bank, uint8 data)
 
−
{
 
−
funcWriteTable[bank] = writeInfo;
 
−
funcReadTable[bank] = readInfo;
 
−
}
 
−
 
 
−
void initInfo()
 
−
{
 
−
funcSelectTable[1] = selectInfo;
 
−
}
 
−
 
 
−
//=============================================================================
 
−
// Function 0x03 - RAM
 
−
//=============================================================================
 
−
 
 
−
#define RAM_SEG_NUM 32
 
−
#define RAM_SEG_MASK (RAM_SEG_NUM - 1)
 
−
 
 
−
// RAM data
 
−
uint8 ramData[16 * 1024 * RAM_SEG_NUM]; // 32 * 16 KB = 512 KB
 
−
 
 
−
// Bank switching register value
 
−
uint8 ramSegment[BANK_NUM];
 
−
 
 
−
void writeRAM(uint16 address, uint8 data)
 
−
{
 
−
ramData[((ramSegment[bank]) << 14) + (address & 0x3FFF)] = data;
 
−
}
 
−
 
 
−
uint8 readRAM(uint16 address)
 
−
{
 
−
return ramData[((ramSegment[bank]) << 14) + (address & 0x3FFF)];
 
−
}
 
−
 
 
−
void selectRAM(uint8 bank, uint8 data)
 
−
{
 
−
ramSegment[bank] = data & RAM_SEG_MASK;
 
−
funcWriteTable[bank] = writeRAM;
 
−
funcReadTable[bank] = readRAM;
 
−
}
 
−
 
 
−
void initRAM()
 
−
{
 
−
for (uint8 i = 0; i < BANK_NUM; i++)
 
−
ramSegment = 0;
 
−
funcSelectTable[3] = selectRAM;
 
−
}
 
−
 
 
−
//=============================================================================
 
−
// Function 0x04 - SRAM
 
−
//=============================================================================
 
−
 
 
−
#define SRAM_SEG_NUM 16
 
−
#define SRAM_SEG_MASK (SRAM_SEG_NUM - 1)
 
−
 
 
−
// SRAM data
 
−
uint8 sramData[8 * 1024 * SRAM_SEG_NUM]; // 16 * 8 KB = 128 KB
 
−
 
 
−
// Bank switching register value
 
−
uint8 sramSegment[BANK_NUM];
 
−
 
 
−
void writeSRAM(uint16 address, uint8 data)
 
−
{
 
−
sramData[((sramSegment[bank]) << 13) + (address & 0x1FFF)] = data;
 
−
}
 
−
 
 
−
uint8 readSRAM(uint16 address)
 
−
{
 
−
return sramData[((sramSegment[bank]) << 13) + (address & 0x1FFF)];
 
−
}
 
−
 
 
−
void selectSRAM(uint8 bank, uint8 data)
 
−
{
 
−
sramSegment[bank] = data & SRAM_SEG_MASK;
 
−
funcWriteTable[bank] = writeSRAM;
 
−
funcReadTable[bank] = readSRAM;
 
−
}
 
−
 
 
−
void initSRAM()
 
−
{
 
−
for (uint8 i = 0; i < BANK_NUM; i++)
 
−
sramSegment = 0;
 
−
funcSelectTable[4] = selectSRAM;
 
−
}
 
−
</syntaxhighlight>
 

Latest revision as of 01:06, 1 November 2026