NEO mapper

From MSX Game Library

Revision as of 22:26, 8 February 2024 by Aoineko (talk | contribs)

Here's a proposal for a mapper format operating with a 16-bit segment register and allowing ROMs larger than the 2/4 MB limit of classic mappers.

Principles

This mapper format is designed to facilitate the creation of MSX games, not only by increasing the size of the ROM available for content, but also by offering programmers new possibilities for organizing their code and data.

Like conventional mappers, the basic idea is to use data write signals to the cartridge to change the value of the ROM segment visible in each of the mapper's banks (sub-pages). So, predefined addresses can be used to write to the mapper registers (see tables below). Read accesses, however, work as normal accesses to the memory visible through the banks.

The format is inspired by ASCII8/16 mappers and is even compatible with most ROMs using these formats (the only exception being the rare programs that use odd-numbered addresses to switch banks). The aim of this proximity to these classic mappers is to facilitate the work of manufacturers to create this new mapper format cartridge.

Compared to conventional mappers, this proposal is based on two new main features:

  • A 16-bit segment register,
  • Banks covering page #0 of MSX memory space.

Usage of page #0 makes it easy to have an extra 16 KB accessible at any time (either by temporarily disabling interrupts for the duration of accesses, or by adding its own ISR).

For the time being, we propose to reserve the 4 most significant bits of the 16-bit bank registers for future extensions of the format (such as SRAM or sound chips support for example). This leaves 12 bits to select which segment is visible in each bank, for a maximum of 4096 segments. The reserved bits, must be set to 0.

Higher byte Lower byte
15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
0 0 0 0 Segment MSB Segment LSB

The maximum ROM size is therefore 32 MB (for 8 KB segments) or 64 MB (for 16 KB segments).

Format

Write access to the mapper is use to change the value of the segment switching register of each bank. Here is the list of the predefined segment switching addresses.

As this new mapper uses 16-bit segment switching registers, it uses 2 bytes for the segment number to be selected in each bank. All even-numbered addresses (bit #0 of the address set to 0) access the low byte of the 16-bit register, while odd-numbered addresses (bit #0 of the address set to 1) access the high byte. This way, the segment number can be initialized at once with the Z80 instructions for 16-bit memory write access.

NEO-8 mapper

  • Size of a segment: 8 KB
  • Segment switching addresses:
Bank (8kB) Switching address Initial segment
0: 0000h~1FFFh 5000h (mirror at 1000h and 9000h) 0000h
1: 2000h~3FFFh 5800h (mirror at 1800h and 9800h) 0000h
2: 4000h~5FFFh 6000h (mirror at 2000h and A000h) 0000h
3: 6000h~7FFFh 6800h (mirror at 2800h and A800h) 0000h
4: 8000h~9FFFh 7000h (mirror at 3000h and B000h) 0000h
5: A000h~BFFFh 7800h (mirror at 3800h and B800h) 0000h
  • Maximum number of segments: 4096
  • Maximum ROM size: 32 MB

NEO-16 mapper

  • Size of a segment: 16 KB
  • Segment switching addresses:
Bank (16kB) Switching address Initial segment
0: 0000h~3FFFh 5000h (mirror at 1000h and 9000h) 0000h
1: 4000h~7FFFh 6000h (mirror at 2000h and A000h) 0000h
2: 8000h~BFFFh 7000h (mirror at 3000h and B000h) 0000h
  • Maximum number of segments: 4096
  • Maximum ROM size: 64 MB

Detection

For emulators and flash tool to detect the NEO mappers, the ROM have to include the following 8 bytes signature right after the 16 bytes ROM header:

  • "NEOMAP08" for NEO-8 mapper,
  • "NEOMAP16" for NEO-16 mapper.

The ROM header (starting with "AB") must be in the first ROM segment at offset 0. The signature is therefore located at offset 16 of the ROM and will be visible to the Z80 on start-up at addresses 0010h, 4010h and 8010h.


Support

Hardware

  • MSX Pico: From firmware 1.22
  • Easy-USB: Incomming hardware...

Emulator

  • Emulicious: Full support for NEO-8 and NEO-16 mappers.
  • openMSX: Support pending...

MSXgl

MSXgl uses macros to wrap quick bank switching mechanisms. It would therefore be totally transparent for a user to switch, for example, from an ASCII8 or even Konami-SCC mapper, to an NEO-8 mapper.

#define SET_BANK_SEGMENT(bank, segment) /* ... */

// Make segment #30 visible through bank #1
SET_BANK_SEGMENT(1, 30);

Appendix

Segment switching address format

From a software point of view, the segment switching address is defined as:

16-bit address
15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
P P B B B x x x x x x x x x x R

Where:

  • 'PP' (0-3) is the page selection for the MSX to redirect access to the mappers slot (those bits are ignored by the mapper and contribute to mirroring).
  • 'BBB' (0-7) is the bank's register to write in.
Bank NEO-8 NEO-16
0 010 010
1 011 100
2 100 110
3 101
4 110
5 111
  • 'R' (0-1) is the segment switching register's byte selector (0: less significant byte; 1: most significant byte).
  • 'x' can be any value (generating mirroring).

So, mirroring occurs on all addresses from the given switching address +2 to fhe switching address +7FEh on all even-numbered addresses. For example, 5000h is mirrored at 5002h~57FEh.

Bank switching cost

The cost of switching only the lower or higher byte of the 16-bit segment register is the same that switching segment for standard ASCII/Konami mappers.

; Direct access
LD A,n      ;  8 t-states
LD (nn),A   ; 14 t-states

; Indirect access
LD HL,nn    ; 11 t-states
LD (HL),n   ; 11 t-states

Although a program can avoid having to change the 2 bytes of the segment register at once, there are cases where this may be necessary. In such cases, the cost is higher, but remains reasonable.

; Direct access
LD HL,nn    ; 11 t-states
LD (nn),HL  ; 17 t-states

; Indirect access
LD DE,nn    ; 11 t-states
LD HL,nn    ; 11 t-states
LD (HL),E   ;  8 t-states
INC HL      ;  7 t-states
LD (HL),D   ;  8 t-states