<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
		<id>https://aoineko.org/msxgl/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Aoineko</id>
		<title>MSX Game Library - User contributions [en]</title>
		<link rel="self" type="application/atom+xml" href="https://aoineko.org/msxgl/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Aoineko"/>
		<link rel="alternate" type="text/html" href="https://aoineko.org/msxgl/index.php?title=Special:Contributions/Aoineko"/>
		<updated>2026-09-11T13:03:11Z</updated>
		<subtitle>User contributions</subtitle>
		<generator>MediaWiki 1.30.2</generator>

	<entry>
		<id>https://aoineko.org/msxgl/index.php?title=Modules/ndp/ndp_player/Desc&amp;diff=4009</id>
		<title>Modules/ndp/ndp player/Desc</title>
		<link rel="alternate" type="text/html" href="https://aoineko.org/msxgl/index.php?title=Modules/ndp/ndp_player/Desc&amp;diff=4009"/>
				<updated>2026-08-09T12:19:28Z</updated>
		
		<summary type="html">&lt;p&gt;Aoineko: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;The {{MOD|ndp/ndp_player}} module lets you play music in '''NDP''' format (PSG only).&lt;br /&gt;
&lt;br /&gt;
The NDP format is a music format that allows users to create very high-quality music on the MSX.&lt;br /&gt;
It was created by Naturo2413, who also provided an MML compiler for creating music in the NDP format, as well as an assembly-language player for playing it back on a real MSX.&lt;br /&gt;
&lt;br /&gt;
MSXgl includes version 1.07 of the replayer, adapted for a C program under SDCC.&lt;br /&gt;
&lt;br /&gt;
Original assembly source and documentation of the NPD replayer can be found on the site [https://ndp.squares.net/web https://ndp.squares.net/web].&lt;/div&gt;</summary>
		<author><name>Aoineko</name></author>	</entry>

	<entry>
		<id>https://aoineko.org/msxgl/index.php?title=Modules/ndp/ndp_player/Desc&amp;diff=4008</id>
		<title>Modules/ndp/ndp player/Desc</title>
		<link rel="alternate" type="text/html" href="https://aoineko.org/msxgl/index.php?title=Modules/ndp/ndp_player/Desc&amp;diff=4008"/>
				<updated>2026-08-09T12:19:15Z</updated>
		
		<summary type="html">&lt;p&gt;Aoineko: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;The {{MOD|ndp/ndp_player}} module lets you play music in '''NDP''' format (PSG only).&lt;br /&gt;
&lt;br /&gt;
The NDP format is a music format that allows users to create very high-quality music on the MSX.&lt;br /&gt;
It was created by Naturo2413, who also provided an MML compiler for creating music in the NDP format, as well as an assembly-language player for playing it back on a real MSX.&lt;br /&gt;
&lt;br /&gt;
MSXgl includes version 1.07 of the replayer, adapted for a C program under SDCC.&lt;br /&gt;
&lt;br /&gt;
Original assembly source and documentation of the NPD replayer can be found on the site [https://ndp.squares.net/web].&lt;/div&gt;</summary>
		<author><name>Aoineko</name></author>	</entry>

	<entry>
		<id>https://aoineko.org/msxgl/index.php?title=Resources&amp;diff=4007</id>
		<title>Resources</title>
		<link rel="alternate" type="text/html" href="https://aoineko.org/msxgl/index.php?title=Resources&amp;diff=4007"/>
				<updated>2026-08-01T21:39:26Z</updated>
		
		<summary type="html">&lt;p&gt;Aoineko: /* About development using MSXgl */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;On this page you will find external information resources that can help you in the development of an MSX project.&lt;br /&gt;
&lt;br /&gt;
== About development using MSXgl ==&lt;br /&gt;
* Articles:&lt;br /&gt;
** ''[https://github.com/hsk/msxgl/tree/main Let's Start Game Programming with MSXgl]'' by HSK (Japanese)&lt;br /&gt;
** ''[https://jacco.ompf2.com/2023/09/14/writing-an-msx2-game-in-2023-part-1/ Writing an MSX2 game… in 2023 – PART 1]'' (using MSXgl) by Jacco Bikker&lt;br /&gt;
** ''[https://www.youtube.com/watch?v=TJ7m68QkEbI Programming on MSXgl and V9990]'' by Andrés De Pedro (Spanish)&lt;br /&gt;
** Articles about MSXgl in Future Disk 48 &amp;amp; 49&lt;br /&gt;
** Articles by [https://moltsxalats.wixsite.com/fusionc MoltSXalats]:&lt;br /&gt;
*** ''[https://moltsxalats.wixsite.com/fusionc/post/msxgl-introduction-and-migration-guide MSXgl: Introduction and Migration Guide]''&lt;br /&gt;
*** ''[https://moltsxalats.wixsite.com/fusionc/post/animations-with-the-msxgl-pawn-module Animations with the MSXgl Pawn Module]''&lt;br /&gt;
*** ''[https://moltsxalats.wixsite.com/fusionc/post/understanding-an-animated-sprite-in-msx2-with-msxgl Understanding an Animated Sprite in MSX2 with MSXgl]''&lt;br /&gt;
*** ''[https://moltsxalats.wixsite.com/fusionc/post/memory-paging-using-msx-dos-2 Memory Paging Using MSX-DOS 2]''&lt;br /&gt;
*** ''[https://moltsxalats.wixsite.com/fusionc/post/moving-from-dos-to-rom-rom-memory-mapper Moving from DOS to ROM (Rom Memory mapper)]''&lt;br /&gt;
&lt;br /&gt;
* Source exemples:&lt;br /&gt;
** [https://github.com/aoineko-fr/MSXgl/tree/main/projects/samples MSXgl's samples]&lt;br /&gt;
** ''[https://github.com/aoineko-fr/Crawlers Crawlers]''&lt;br /&gt;
** ''[https://github.com/Asso-MO5/room5 Room 5]''&lt;br /&gt;
** ''[https://github.com/aoineko-fr/PengPong Peng Pong]''&lt;br /&gt;
** ''[https://github.com/AssociazioneMsxItalia/Chrono-runners Chrono Runner]''&lt;br /&gt;
&lt;br /&gt;
== About the MSX development in general ==&lt;br /&gt;
* MSX Assembly Page by Grauw:&lt;br /&gt;
** [https://map.grauw.nl/resources/ collection of online MSX resources] (BIOS, MSX-DOS, VDP...)&lt;br /&gt;
** [https://map.grauw.nl/articles/ collection of articles about MSX programming] (tutorials and tips)&lt;br /&gt;
&lt;br /&gt;
* MSX Resource Center [https://www.msx.org/wiki/Category:Programming wiki's &amp;quot;programming&amp;quot; section]&lt;br /&gt;
* MSX game making-of:&lt;br /&gt;
** ''[https://www.teambomba.net/bombaman/makingof.html The Making Of Bombaman]'', Team Bomba (2003)&lt;br /&gt;
** ''[https://santiontanon.blogspot.com/2017/09/procedural-content-generation-in.html Procedural Content Generation in XSPelunker]'', Santiago Ontañón (2017)&lt;br /&gt;
** ''[https://santiontanon.blogspot.com/2017/09/raycasting-in-tales-of-popolon-msx.html Raycasting in Tales of Popolon]'', Santiago Ontañón (2017)&lt;br /&gt;
** ''[https://santiontanon.blogspot.com/2019/04/smooth-scroll-in-xracing.html Smooth Scroll in XRacing]'', Santiago Ontañón (2019)&lt;br /&gt;
** ''[https://santiontanon.blogspot.com/2019/02/the-flag-effect-in-xracing.html The Flag Effect in XRacing]'', Santiago Ontañón (2019)&lt;br /&gt;
** ''[https://santiontanon.blogspot.com/2020/10/quick-technical-overview-of-menace-from.html Quick Technical Overview of The Menace from Triton]'', Santiago Ontañón (2020)&lt;br /&gt;
** ''[http://defdanny.de/2022/10/22/making-of-diced-tournament Making of DICED – Tournament]'', DefDanny (2022)&lt;br /&gt;
** ''[https://thegeps.blogspot.com/2022/04/freedom-fighter-smooth-scrolling-eng.html Freedom Fighter smooth scrolling]'', Giuseppe Ettore &amp;quot;thegeps&amp;quot; Pintus (2022)&lt;br /&gt;
** ''[https://bengalack.blogspot.com/p/lillyparti.html Under The Hood - Lilly's Saga - The stones of Evergreen]'', Fabulous 8bit (2023)&lt;br /&gt;
** ''[https://jacco.ompf2.com/2026/03/07/rendering-for-delta-3d-on-msx2/?_thumbnail_id=2396 Rendering for DELTA – 3D on MSX2]'', by Jacco Bikker (2026)&lt;br /&gt;
* MSX game creators:&lt;br /&gt;
** [https://santiontanon.blogspot.com/ Santiago Ontañón's blog]&lt;br /&gt;
** [https://bengalack.blogspot.com/ Bengalack's blog]&lt;br /&gt;
&lt;br /&gt;
== About C development ==&lt;br /&gt;
* [https://sdcc.sourceforge.net SDCC]: ''[https://sdcc.sourceforge.net/doc/sdccman.pdf SDCC Compiler User Guide]''&lt;br /&gt;
* Other C library:&lt;br /&gt;
** [https://github.com/ericb59/Fusion-C-v1.2 Fusion-C 1.2] (C library for SDCC compiler).&lt;br /&gt;
** [https://github.com/mori0091/libmsx libmsx] (C library for SDCC compiler).&lt;br /&gt;
** [https://github.com/lfantoniosi/sdcc_stdio/tree/main sdcc_stdio] (stdio lib implementation for SDCC compiler for CP/M-80).&lt;/div&gt;</summary>
		<author><name>Aoineko</name></author>	</entry>

	<entry>
		<id>https://aoineko.org/msxgl/index.php?title=Help&amp;diff=4006</id>
		<title>Help</title>
		<link rel="alternate" type="text/html" href="https://aoineko.org/msxgl/index.php?title=Help&amp;diff=4006"/>
				<updated>2026-07-16T20:44:13Z</updated>
		
		<summary type="html">&lt;p&gt;Aoineko: /* Proposal */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Topics ==&lt;br /&gt;
* Main&lt;br /&gt;
** [[What is MSXgl?]]&lt;br /&gt;
** [[Install|Install and Setup]]&lt;br /&gt;
** [[Code documentation]]&lt;br /&gt;
** [[Create a plain ROM]]&lt;br /&gt;
** [[Create a mapped ROM]]&lt;br /&gt;
* Programming&lt;br /&gt;
** Use of [[Literal expression]]&lt;br /&gt;
** [[Boolean]]&lt;br /&gt;
** [[Free call to BIOS routine]]&lt;br /&gt;
** [[VRAM access timing]]&lt;br /&gt;
** [[Z80 wait instructions]]&lt;br /&gt;
** [[Fixed-point number]]&lt;br /&gt;
** [[Collision early elimination method]]&lt;br /&gt;
** [[Gameplay synchronization]]&lt;br /&gt;
** [[Interrupt handler]]&lt;br /&gt;
* Misc&lt;br /&gt;
** [[Release]]&lt;br /&gt;
** [[AppSignature|Application signature]] (for identification)&lt;br /&gt;
** [[Lexicon]]&lt;br /&gt;
** [[Contribute|Want to help improve MSXgl?]]&lt;br /&gt;
** [[Credits]]&lt;br /&gt;
&lt;br /&gt;
== MSXgl format description ==&lt;br /&gt;
* [[lVGM]] (light-VGM music)&lt;br /&gt;
* [[MGI]] (image)&lt;br /&gt;
* [[MGV]] (video)&lt;br /&gt;
* [[RLEp]] (pattern-based RLE compression)&lt;br /&gt;
&lt;br /&gt;
== Proposal ==&lt;br /&gt;
* [[NEO mapper]] (16-bit register based ROM mapper)&lt;br /&gt;
* [[ROM type signature]]&lt;br /&gt;
* [[Debug device]]&lt;br /&gt;
* [[JSX]] (protocol to handle joypads with a variable number of sticks and buttons), [[JSX-B]], [[JSX-C]]&lt;br /&gt;
&lt;br /&gt;
== Q&amp;amp;A ==&lt;br /&gt;
&lt;br /&gt;
{{QA|What if I prefer to have the MSXgl directory in my project directory and not the opposite?|See the [[alternative file layout]].}}&lt;br /&gt;
&lt;br /&gt;
{{QA|How can I convert my Batch project setting to new JS based Build tool?|See the [[batch to JS conversion guide]].}}&lt;br /&gt;
&lt;br /&gt;
{{QA|Do I have to mention that I use MSXgl in my game?|No, it's not mandatory: do as you like. If you mention that the game is made with MSXgl, that's cool, because it might inspire others to create MSX games with this library. The [https://creativecommons.org/licenses/by-sa/4.0/ CC BY-SA] license applies mainly to people who want to modify and distribute the library on their own. In this case, the author must be cited and the derivative work must retain the same license.}}&lt;/div&gt;</summary>
		<author><name>Aoineko</name></author>	</entry>

	<entry>
		<id>https://aoineko.org/msxgl/index.php?title=NEO_mapper&amp;diff=4005</id>
		<title>NEO mapper</title>
		<link rel="alternate" type="text/html" href="https://aoineko.org/msxgl/index.php?title=NEO_mapper&amp;diff=4005"/>
				<updated>2026-07-11T03:15:47Z</updated>
		
		<summary type="html">&lt;p&gt;Aoineko: /* Emulator */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;div style=&amp;quot;float:right&amp;quot;&amp;gt;[[NEO mapper|EN]] | [[NEO mapper/JA|JA]]&amp;lt;/div&amp;gt;&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
== Specifications ==&lt;br /&gt;
&lt;br /&gt;
=== Principles ===&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
Like conventional mappers, the basic idea is to use data write signals to the cartridge to change mapper registers value and thus, 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 [[#Format|tables below]]).&lt;br /&gt;
Read accesses, however, work as normal accesses to the memory visible through the banks.&lt;br /&gt;
&lt;br /&gt;
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 cartridge in this new mapper format.&lt;br /&gt;
&lt;br /&gt;
Compared to conventional mappers, this proposal is based on two new main features:&lt;br /&gt;
* A 16-bit segment register,&lt;br /&gt;
* Banks covering page #0 of MSX memory space (address 0000h~3FFFh).&lt;br /&gt;
&lt;br /&gt;
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).&lt;br /&gt;
&lt;br /&gt;
For the time being, we propose to reserve the 2 most significant bits of the 16-bit bank registers for future extensions of the format (such as SRAM or sound chips support for example).&lt;br /&gt;
This leaves 14 bits to select which segment is visible in each bank, for a maximum of 16384 segments.&lt;br /&gt;
The reserved bits, must be set to 0.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
!colspan=&amp;quot;8&amp;quot;| Higher byte&lt;br /&gt;
|&lt;br /&gt;
!colspan=&amp;quot;8&amp;quot;| Lower byte &lt;br /&gt;
|-&lt;br /&gt;
! 15 || 14 || 13 || 12 || 11 || 10 || 9 || 8 &lt;br /&gt;
|&lt;br /&gt;
! 7 || 6 || 5 || 4 || 3 || 2 || 1 || 0&lt;br /&gt;
|-&lt;br /&gt;
| 0 || 0&lt;br /&gt;
|colspan=&amp;quot;6&amp;quot;| Segment MSB&lt;br /&gt;
| &lt;br /&gt;
|colspan=&amp;quot;8&amp;quot;| Segment LSB &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The maximum ROM size is therefore 128 MB (for 8 KB segments) or 256 MB (for 16 KB segments).&lt;br /&gt;
&lt;br /&gt;
=== Write Access ===&lt;br /&gt;
&lt;br /&gt;
Write access to the mapper is use to change the value of the bank switching register (where you can select the ROM segment visible through a bank).&lt;br /&gt;
Bellow is the list of the predefined segment switching addresses.&lt;br /&gt;
&lt;br /&gt;
As this new mapper uses 16-bit segment switching registers, it uses 2 bytes for the segment number to be selected in each bank.&lt;br /&gt;
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.&lt;br /&gt;
This way, the segment number can be initialized at once with the [[#Bank switching cost|Z80 instructions for 16-bit memory write access]].&lt;br /&gt;
&lt;br /&gt;
==== NEO-8 mapper ====&lt;br /&gt;
&lt;br /&gt;
* Size of a segment: 8 KB&lt;br /&gt;
* Segment switching addresses:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Bank (8kB) !! Switching address !! Initial segment&lt;br /&gt;
|-&lt;br /&gt;
| 0: 0000h~1FFFh || 5000h (mirror at 1000h, 9000h and D000h) || 0000h&lt;br /&gt;
|-&lt;br /&gt;
| 1: 2000h~3FFFh || 5800h (mirror at 1800h, 9800h and D800h) || 0000h&lt;br /&gt;
|-&lt;br /&gt;
| 2: 4000h~5FFFh || 6000h (mirror at 2000h, A000h and E000h) || 0000h&lt;br /&gt;
|-&lt;br /&gt;
| 3: 6000h~7FFFh || 6800h (mirror at 2800h, A800h and E800h) || 0000h&lt;br /&gt;
|-&lt;br /&gt;
| 4: 8000h~9FFFh || 7000h (mirror at 3000h, B000h and F000h) || 0000h&lt;br /&gt;
|-&lt;br /&gt;
| 5: A000h~BFFFh || 7800h (mirror at 3800h, B800h and F800h) || 0000h&lt;br /&gt;
|}&lt;br /&gt;
* Maximum number of segments: 16384&lt;br /&gt;
* Maximum ROM size: 128 MB&lt;br /&gt;
&lt;br /&gt;
==== NEO-16 mapper ====&lt;br /&gt;
&lt;br /&gt;
* Size of a segment: 16 KB&lt;br /&gt;
* Segment switching addresses:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Bank (16kB) !! Switching address !! Initial segment&lt;br /&gt;
|-&lt;br /&gt;
| 0: 0000h~3FFFh || 5000h (mirror at 1000h, 9000h and D000h) || 0000h&lt;br /&gt;
|-&lt;br /&gt;
| 1: 4000h~7FFFh || 6000h (mirror at 2000h, A000h and E000h) || 0000h&lt;br /&gt;
|-&lt;br /&gt;
| 2: 8000h~BFFFh || 7000h (mirror at 3000h, B000h and F000h) || 0000h&lt;br /&gt;
|}&lt;br /&gt;
* Maximum number of segments: 16384&lt;br /&gt;
* Maximum ROM size: 256 MB&lt;br /&gt;
&lt;br /&gt;
=== Read Access ===&lt;br /&gt;
When mapper is selected, read accesses to memory pages 0, 1 and 2 (addresses 0000h to BFFFh), are redirected to a given ROM segment according to the value of the bank register corresponding to the address.&lt;br /&gt;
&lt;br /&gt;
For page 3, read accesses are invalid and the value returned is undefined and should not be used. Implementations of the NEO mapper should return the value FFh if page 3 is read, but this value is not guaranteed by the mapper specifications.&lt;br /&gt;
&lt;br /&gt;
=== Detection ===&lt;br /&gt;
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:&lt;br /&gt;
* &amp;quot;&amp;lt;tt&amp;gt;ROM_NEO8&amp;lt;/tt&amp;gt;&amp;quot; for NEO-8 mapper,&lt;br /&gt;
* &amp;quot;&amp;lt;tt&amp;gt;ROM_NE16&amp;lt;/tt&amp;gt;&amp;quot; for NEO-16 mapper.&lt;br /&gt;
&lt;br /&gt;
The ROM header (starting with &amp;quot;AB&amp;quot;) must be in the first ROM segment at offset 0.&lt;br /&gt;
The signature is therefore located at offset 16 of the ROM and may be visible to the Z80 on start-up at addresses 0010h, 4010h and 8010h.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;Note&amp;lt;/u&amp;gt;: Signature characters have been carefully choosed to prevent existing ROMs to generate false positive signature (See [[ROM type signature]]).&lt;br /&gt;
&lt;br /&gt;
== Support ==&lt;br /&gt;
&lt;br /&gt;
=== Hardware ===&lt;br /&gt;
Hardware supporting NEO mapper:&lt;br /&gt;
* '''[https://www.msxpico.com/ MSX Pico]''' (normal or WiFi): Support for NEO-8 and NEO-16 mappers up to ~15 MB (firmware 1.25 or above).&lt;br /&gt;
* '''[https://www.msxpico.com/ MSX Pico+]''': Support for NEO-8 and NEO-16 mappers up to ~14 MB (firmware 2.12 or above).&lt;br /&gt;
* '''[https://github.com/cristianoag/msx-picoverse-public PicoVerse] 2040 and 2350''': Support for NEO-8 and NEO-16 mappers up to ~15 MB.&lt;br /&gt;
* '''[https://github.com/arkadiuszmakarenko/RISKYMSX RISKY MSX]''': Support for NEO-8 and NEO-16 mappers up to 256 KB.&lt;br /&gt;
* '''[https://github.com/piigaa-densetu-two-dai/MSXpi MSXπ]''': Support for NEO-16 mappers up to 16 MB&lt;br /&gt;
* '''[https://github.com/piigaa-densetu-two-dai/MSXpi_plus_v2 MSXπ Plus (V2)]''': Support for NEO-16 mappers up to 16 MB&lt;br /&gt;
&lt;br /&gt;
=== Emulator ===&lt;br /&gt;
Emulators supporting NEO mapper:&lt;br /&gt;
* {{blueMSX}} '''blueMSX+''': Full support for NEO-8 and NEO-16 mappers.&lt;br /&gt;
* {{Emulicious}} '''Emulicious''': Full support for NEO-8 and NEO-16 mappers.&lt;br /&gt;
* {{MSXEC}} '''MSXEC''': Support NEO-8 and NEO-16 mappers up to 64 MB (version 20260303 or above).&lt;br /&gt;
* {{openMSX}} '''openMSX''': Full support for NEO-8 and NEO-16 mappers (version 20.0 or above).&lt;br /&gt;
* {{WebMSX}} '''WebMSX''': Full support for NEO-8 and NEO-16 mappers (version 6.0.7 or above).&lt;br /&gt;
&lt;br /&gt;
=== MSXgl ===&lt;br /&gt;
&lt;br /&gt;
Both NEO-8 and NEO-16 mappers are supported. Use respectively &amp;lt;tt&amp;gt;ROM_NEO8&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;ROM_NEO16&amp;lt;/tt&amp;gt; as [[target|target format]].&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
#define SET_BANK_SEGMENT(bank, segment) /* ... */&lt;br /&gt;
&lt;br /&gt;
// Make segment #30 visible through bank #1&lt;br /&gt;
SET_BANK_SEGMENT(1, 30);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
MSXgl initialize the banks with a unique segment each, to offer the largest possible space available to the user:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;img style=&amp;quot;width:400px; margin:0.5em;&amp;quot; src=&amp;quot;https://raw.githubusercontent.com/aoineko-fr/MSXgl/main/engine/doc/mapper_neo8.png&amp;quot; /&amp;gt;&lt;br /&gt;
&amp;lt;img style=&amp;quot;width:400px; margin:0.5em;&amp;quot; src=&amp;quot;https://raw.githubusercontent.com/aoineko-fr/MSXgl/main/engine/doc/mapper_neo16.png&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;Note&amp;lt;/u&amp;gt;: When the application start, segment at 0x4000 always point to segment 0 that include the ROM header. See [[Create a mapped ROM#NEO mapper]] for more details.&lt;br /&gt;
&lt;br /&gt;
== Appendix ==&lt;br /&gt;
&lt;br /&gt;
=== Segment switching address format ===&lt;br /&gt;
&lt;br /&gt;
From a software point of view, the segment switching address is defined as:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
!colspan=&amp;quot;17&amp;quot;| 16-bit address&lt;br /&gt;
|-&lt;br /&gt;
! 15 || 14 || 13 || 12 || 11 || 10 || 9 || 8 &lt;br /&gt;
|&lt;br /&gt;
! 7 || 6 || 5 || 4 || 3 || 2 || 1 || 0&lt;br /&gt;
|-&lt;br /&gt;
| P || P || B || B || B || x || x || x || || x || x || x || x || x || x || x || R&lt;br /&gt;
|}&lt;br /&gt;
Where:&lt;br /&gt;
* '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, but the mapper registers can only be accessed from selected pages.&lt;br /&gt;
* 'BBB' (0-7) is the bank's register to write in. All unspecified values are discarded.&lt;br /&gt;
:{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Bank !! NEO-8 !! NEO-16&lt;br /&gt;
|-&lt;br /&gt;
| 0 || 010 || 010&lt;br /&gt;
|-&lt;br /&gt;
| 1 || 011 || 100&lt;br /&gt;
|-&lt;br /&gt;
| 2 || 100 || 110&lt;br /&gt;
|-&lt;br /&gt;
| 3 || 101 || &lt;br /&gt;
|-&lt;br /&gt;
| 4 || 110 || &lt;br /&gt;
|-&lt;br /&gt;
| 5 || 111 || &lt;br /&gt;
|}&lt;br /&gt;
* 'R' (0-1) is the segment switching register's byte selector (0: less significant byte; 1: most significant byte).&lt;br /&gt;
* 'x' can be any value (generating mirroring).&lt;br /&gt;
&lt;br /&gt;
So, mirroring occurs on all addresses from the given switching address +2 to the switching address +7FEh on all even-numbered addresses. For example, 5000h is mirrored at 5002h~57FEh.&lt;br /&gt;
&lt;br /&gt;
=== Programmable processor and emulation ===&lt;br /&gt;
Here is a pseudo code in C to handle NEO mappers for programmable processor based cartridges or for emulators:&lt;br /&gt;
{|&lt;br /&gt;
|-&lt;br /&gt;
| NEO-8 mapper:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
const uint8* romData; // ROM data&lt;br /&gt;
uint16 bankValue[6]; // Bank switching register value&lt;br /&gt;
&lt;br /&gt;
// Handle device initialization&lt;br /&gt;
void NEO8_Init()&lt;br /&gt;
{&lt;br /&gt;
   for (uint8 i=0; i&amp;lt;6; i++)&lt;br /&gt;
      bankValue[i] = 0;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// Handle write access&lt;br /&gt;
void NEO8_Write(uint16 address, uint8 value)&lt;br /&gt;
{&lt;br /&gt;
   uint8 bank = ((address &amp;gt;&amp;gt; 11) &amp;amp; 0x07) - 2;&lt;br /&gt;
   if (bank &amp;gt; 5)&lt;br /&gt;
      return; // skip&lt;br /&gt;
   if (address &amp;amp; 1) // Set bank register MSB&lt;br /&gt;
      bankValue[bank] = ((value &amp;amp; 0x0F) &amp;lt;&amp;lt; 8) | (bankValue[bank] &amp;amp; 0x00FF);&lt;br /&gt;
   else // Set bank register LSB&lt;br /&gt;
      bankValue[bank] = (bankValue[bank] &amp;amp; 0xFF00) | (value);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// Handle read access&lt;br /&gt;
uint8 NEO8_Read(uint16 address)&lt;br /&gt;
{&lt;br /&gt;
   uint8 bank = address &amp;gt;&amp;gt; 13;&lt;br /&gt;
   if (bank &amp;gt; 5)&lt;br /&gt;
      return 0xFF; // skip&lt;br /&gt;
   return romData[(bankValue[bank]) &amp;lt;&amp;lt; 13 + (address &amp;amp; 0x1FFF)];&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
| NEO-16 mapper:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
const uint8* romData; // ROM data&lt;br /&gt;
uint16 bankValue[3]; // Bank switching register value&lt;br /&gt;
&lt;br /&gt;
// Handle device initialization&lt;br /&gt;
void NEO16_Init()&lt;br /&gt;
{&lt;br /&gt;
   bankValue[0] = bankValue[1] = bankValue[2] = 0;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// Handle write access&lt;br /&gt;
void NEO16_Write(uint16 address, uint8 value)&lt;br /&gt;
{&lt;br /&gt;
   uint8 bank = ((address &amp;gt;&amp;gt; 12) &amp;amp; 0x03) - 1;&lt;br /&gt;
   if (bank &amp;gt; 2)&lt;br /&gt;
      return; // skip&lt;br /&gt;
   if (address &amp;amp; 1) // Set bank register MSB&lt;br /&gt;
      bankValue[bank] = ((value &amp;amp; 0x0F) &amp;lt;&amp;lt; 8) | (bankValue[bank] &amp;amp; 0x00FF);&lt;br /&gt;
   else // Set bank register LSB&lt;br /&gt;
      bankValue[bank] = (bankValue[bank] &amp;amp; 0xFF00) | (value);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// Handle read access&lt;br /&gt;
uint8 NEO16_Read(uint16 address)&lt;br /&gt;
{&lt;br /&gt;
   uint8 bank = address &amp;gt;&amp;gt; 14;&lt;br /&gt;
   if (bank &amp;gt; 2)&lt;br /&gt;
      return 0xFF; // skip&lt;br /&gt;
   return romData[(bankValue[bank]) &amp;lt;&amp;lt; 14 + (address &amp;amp; 0x3FFF)];&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Sample program ===&lt;br /&gt;
A sample program is available for testing purpose on: https://aoineko.org/msx/targets/rom/&lt;br /&gt;
&lt;br /&gt;
It is available in various sizes:&lt;br /&gt;
* NEO-8: 256 KB to 32 MB&lt;br /&gt;
* NEO-16: 256 KB to 64 MB&lt;br /&gt;
&lt;br /&gt;
=== Bank switching cost ===&lt;br /&gt;
For a program using NEO mapper, 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.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;ini&amp;quot;&amp;gt;&lt;br /&gt;
; Direct access (22 t-states)&lt;br /&gt;
LD A,n      ;  8 t-states&lt;br /&gt;
LD (nn),A   ; 14 t-states&lt;br /&gt;
&lt;br /&gt;
; Indirect access (22 t-states)&lt;br /&gt;
LD HL,nn    ; 11 t-states&lt;br /&gt;
LD (HL),n   ; 11 t-states&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Although a program can avoid having to change the 2 bytes (16-bit) of the segment register at once, there are cases where this may be necessary. In such cases, the cost is higher, but remains reasonable.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;ini&amp;quot;&amp;gt;&lt;br /&gt;
; Direct access (28 t-states)&lt;br /&gt;
LD HL,nn    ; 11 t-states&lt;br /&gt;
LD (nn),HL  ; 17 t-states&lt;br /&gt;
&lt;br /&gt;
; Indirect access (40 t-states)&lt;br /&gt;
LD HL,nn    ; 11 t-states&lt;br /&gt;
LD (HL),n   ; 11 t-states&lt;br /&gt;
INC HL      ;  7 t-states&lt;br /&gt;
LD (HL),n   ; 11 t-states&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Logos ===&lt;br /&gt;
Here are the logos you can use to indicate that a product is compatible with the NEO mapper:&lt;br /&gt;
&lt;br /&gt;
[https://aoineko.org/msx/files/neomapper8b-logo.png &amp;lt;img style=&amp;quot;width:128px&amp;quot; src=&amp;quot;https://aoineko.org/msx/files/neomapper8b-logo.png&amp;quot; /&amp;gt;]&lt;br /&gt;
[https://aoineko.org/msx/files/neomapper8w-logo.png &amp;lt;img style=&amp;quot;width:128px&amp;quot; src=&amp;quot;https://aoineko.org/msx/files/neomapper8w-logo.png&amp;quot; /&amp;gt;]&lt;br /&gt;
[https://aoineko.org/msx/files/neomapper16b-logo.png &amp;lt;img style=&amp;quot;width:128px&amp;quot; src=&amp;quot;https://aoineko.org/msx/files/neomapper16b-logo.png&amp;quot; /&amp;gt;]&lt;br /&gt;
[https://aoineko.org/msx/files/neomapper16w-logo.png &amp;lt;img style=&amp;quot;width:128px&amp;quot; src=&amp;quot;https://aoineko.org/msx/files/neomapper16w-logo.png&amp;quot; /&amp;gt;]&lt;br /&gt;
&lt;br /&gt;
== Change log ==&lt;br /&gt;
* Version 1.0 (2024/02/12)&lt;br /&gt;
** Original version&lt;br /&gt;
* Version 1.1 (2024/02/20)&lt;br /&gt;
** Changed mappers signature to minimize the risk of an old cartridge generating a false positive and to comply to [[ROM type signature]] format.&lt;br /&gt;
** Added clarification on PP and BBB values for bank switching addresses.&lt;br /&gt;
** Added clarification for read access to the mapper and especially when try to read the page 3.&lt;br /&gt;
* Version 1.2 (2026/04/06)&lt;br /&gt;
** Added optional official logo for NEO mapper product.&lt;br /&gt;
** Added bits 12 and 13 to the register value, increasing the maximum number of segments from 4096 to 16384.&lt;br /&gt;
[[Category:Proposal]][[Category:Proposal/Mapper]]&lt;/div&gt;</summary>
		<author><name>Aoineko</name></author>	</entry>

	<entry>
		<id>https://aoineko.org/msxgl/index.php?title=Emulators&amp;diff=4004</id>
		<title>Emulators</title>
		<link rel="alternate" type="text/html" href="https://aoineko.org/msxgl/index.php?title=Emulators&amp;diff=4004"/>
				<updated>2026-07-11T03:15:36Z</updated>
		
		<summary type="html">&lt;p&gt;Aoineko: /* {{bleuMSX}} blueMSX */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;br /&gt;
== Support ==&lt;br /&gt;
MSXgl's [[Build tool]] can automatically launch the emulator of your choice with a configuration that match your project options. Not all emulators support all available options.&lt;br /&gt;
&lt;br /&gt;
Here's a list of supported options for each emulator.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;html&amp;gt;&amp;lt;iframe&lt;br /&gt;
    width=&amp;quot;100%&amp;quot;&lt;br /&gt;
    height=&amp;quot;450px&amp;quot;&lt;br /&gt;
    title=&amp;quot;Emulator support&amp;quot;&lt;br /&gt;
    src=&amp;quot;https://docs.google.com/spreadsheets/d/e/2PACX-1vQ_k1n0StRUX8zagkpZrF-ZtkFYwanLKVA6wUm2jlcjMFjCr44wIb6aEKDQcAD7wn0XLwRjYNL7Lk_e/pubhtml&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;/iframe&amp;gt;&amp;lt;/html&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Specific setting ==&lt;br /&gt;
&lt;br /&gt;
=== {{openMSX}} openMSX ===&lt;br /&gt;
To enable MSX turbo R, FM-PAC or OPL4 emulation, you need to get proprietary system ROMs not included in [https://openmsx.org/ openMSX] for copyright reason. You can find them on the Internet ([http://www.msxarchive.nl/pub/msx/emulator/openMSX/systemroms.zip here] or [https://download.file-hunter.com/System%20ROMs/Full%20Set%20System%20ROM's%20(OpenMSX)%20-%2022-03-2022.zip here] for example).&lt;br /&gt;
&lt;br /&gt;
You also need those system ROMs to launch MSX-DOS or BASIC binaries application from a disk. Once you have installed the system ROMs, you need to select a machine that contains a disk: for example the Philips VG-8235 (PAL) or Sony HB-F1XD (NTSC). Set the machine as the default one in openMSX and set &amp;lt;tt&amp;gt;EmulMachine&amp;lt;/tt&amp;gt; to false in your project configuration (to prevent the Build tool to reset the machine a launch).&lt;br /&gt;
&lt;br /&gt;
Check the openMSX documentation for more information: https://openmsx.org/docs.html&lt;br /&gt;
&lt;br /&gt;
=== {{Emulicious}} Emulicious ===&lt;br /&gt;
Here is some tips to test your MSXgl program using [https://emulicious.net/ Emulicious].&lt;br /&gt;
&lt;br /&gt;
==== How to run a MSX-DOS or BASIC program ====&lt;br /&gt;
&lt;br /&gt;
Emulicious contains only the basic C-BIOS free BIOS, which can only run programs in ROM format. By changing a few options in &amp;quot;Options&amp;quot; &amp;gt; &amp;quot;Emulation&amp;quot; &amp;gt; &amp;quot;MSX&amp;quot; menu, you can run programs on disk using proprietary BIOSes.&lt;br /&gt;
&lt;br /&gt;
First, change BIOS:&lt;br /&gt;
* MSX 1: Set ''&amp;quot;MSX1 BIOSes&amp;quot;'' option to [https://aoineko.org/msx/roms/MSX.ROM MSX.ROM],&lt;br /&gt;
* MSX 2: Set ''&amp;quot;MSX2 BIOSes&amp;quot;'' option to [https://aoineko.org/msx/roms/MSX2.ROM MSX2.ROM] and [https://aoineko.org/msx/roms/MSX2EXT.ROM MSX2EXT.ROM].&lt;br /&gt;
&lt;br /&gt;
For MSX-DOS 1 or BASIC:&lt;br /&gt;
* Set ''&amp;quot;Disk ROM&amp;quot;'' option to [https://aoineko.org/msx/roms/DISK.ROM DISK.ROM].&lt;br /&gt;
&lt;br /&gt;
For MSX-DOS 2:&lt;br /&gt;
* Set ''&amp;quot;Disk ROM&amp;quot;'' option to [https://aoineko.org/msx/roms/DISK.ROM DISK.ROM].&lt;br /&gt;
* Set ''&amp;quot;MSXDOS2 ROMs&amp;quot;'' option to [https://aoineko.org/msx/roms/MSXDOS2.ROM MSXDOS2.ROM].&lt;br /&gt;
&lt;br /&gt;
Now you can auto-launch your disk program from [[Build tool]] or load your .DSK file directly from Emulicious.&lt;br /&gt;
&lt;br /&gt;
==== How to enable MSX-Music ====&lt;br /&gt;
&lt;br /&gt;
Set ''&amp;quot;FM PAC ROMs&amp;quot;'' option in &amp;quot;Options&amp;quot; &amp;gt; &amp;quot;Emulation&amp;quot; &amp;gt; &amp;quot;MSX&amp;quot; menu to [https://aoineko.org/msx/roms/FMPAC.ROM FMPAC.ROM].&lt;br /&gt;
&lt;br /&gt;
==== How to debug using VS Code ====&lt;br /&gt;
&lt;br /&gt;
Here are the steps for debugging your program with Emulicious from [[VS Code]]:&lt;br /&gt;
&lt;br /&gt;
1. Install [https://marketplace.visualstudio.com/items?itemName=emulicious.emulicious-debugger Emulicious VS Code extension].&lt;br /&gt;
&lt;br /&gt;
2. Setup &amp;quot;Emulicious Path&amp;quot; in Emulicious extension's settings.&lt;br /&gt;
&lt;br /&gt;
3. Create a &amp;lt;tt&amp;gt;launch.json&amp;lt;/tt&amp;gt; from the &amp;quot;Run and Debug&amp;quot; panel. Configuration section should look like:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;json&amp;quot;&amp;gt;&lt;br /&gt;
&amp;quot;configurations&amp;quot;: [&lt;br /&gt;
        {&lt;br /&gt;
            &amp;quot;type&amp;quot;: &amp;quot;emulicious-debugger&amp;quot;,&lt;br /&gt;
            &amp;quot;request&amp;quot;: &amp;quot;attach&amp;quot;,&lt;br /&gt;
            &amp;quot;name&amp;quot;: &amp;quot;Attach to Emulicious&amp;quot;,&lt;br /&gt;
            &amp;quot;port&amp;quot;: 58870&lt;br /&gt;
        },&lt;br /&gt;
        {&lt;br /&gt;
            &amp;quot;type&amp;quot;: &amp;quot;emulicious-debugger&amp;quot;,&lt;br /&gt;
            &amp;quot;request&amp;quot;: &amp;quot;launch&amp;quot;,&lt;br /&gt;
            &amp;quot;name&amp;quot;: &amp;quot;Launch in Emulicious&amp;quot;,&lt;br /&gt;
            &amp;quot;program&amp;quot;: &amp;quot;${workspaceFolder}/emul/rom/mygame.rom&amp;quot;,&lt;br /&gt;
            &amp;quot;port&amp;quot;: 58870,&lt;br /&gt;
            &amp;quot;stopOnEntry&amp;quot;: true&lt;br /&gt;
        }&lt;br /&gt;
    ]&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Replace &amp;lt;tt&amp;gt;${command:AskForProgramName}&amp;lt;/tt&amp;gt; by &amp;lt;tt&amp;gt;emul/rom/mygame.rom&amp;lt;/tt&amp;gt; (where &amp;quot;mygame&amp;quot; is your own game name).&lt;br /&gt;
If you already have a &amp;lt;tt&amp;gt;launch.json&amp;lt;/tt&amp;gt;, select the &amp;quot;Add configuration&amp;quot; option and select one of the 2 Emulicious configuration.&lt;br /&gt;
&lt;br /&gt;
4. Enable remote debugging in Emulicious. Launch Emulicious and set &amp;quot;Enabled&amp;quot; in &amp;quot;Tools&amp;quot; &amp;gt; &amp;quot;Remote Debugging&amp;quot; menu.&lt;br /&gt;
&lt;br /&gt;
5. Now you are ready to debug your application from VS Code. Go to &amp;quot;Run and Debug&amp;quot; panel and select Attach (to attach to a currently running game on Emulicious) or Launch (to launch your game in Emulicious). If &amp;quot;stopOnEntry&amp;quot; is set to true in your &amp;lt;tt&amp;gt;launch.json&amp;lt;/tt&amp;gt;, the VS Code debugger should break at the beginning of your &amp;lt;tt&amp;gt;main()&amp;lt;/tt&amp;gt; function.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;img style=&amp;quot;width:50%;&amp;quot; src=&amp;quot;https://raw.githubusercontent.com/aoineko-fr/MSXgl/main/engine/doc/img/tools/emulicious_2.jpg&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You can found more information about the VS Code debugger on Internet. For example: https://code.visualstudio.com/docs/editor/debugging&lt;br /&gt;
&lt;br /&gt;
=== {{blueMSX}} blueMSX ===&lt;br /&gt;
To setup the emulation of the [https://www.msx.org/articles/obsonet ObsoNET cartridge], please follow this tutorial: https://www.msx.org/forum/msx-talk/emulation/bluemsx-emulating-obsonet-and-tcp-ip-unapi&lt;br /&gt;
&lt;br /&gt;
== VRAM access timing emulation ==&lt;br /&gt;
[[VRAM access timing]] limitations are supported by few emulators.&lt;br /&gt;
&lt;br /&gt;
{{:VRAM access timing/Emulation}}&lt;/div&gt;</summary>
		<author><name>Aoineko</name></author>	</entry>

	<entry>
		<id>https://aoineko.org/msxgl/index.php?title=Template:BlueMSX&amp;diff=4002</id>
		<title>Template:BlueMSX</title>
		<link rel="alternate" type="text/html" href="https://aoineko.org/msxgl/index.php?title=Template:BlueMSX&amp;diff=4002"/>
				<updated>2026-07-11T03:15:05Z</updated>
		
		<summary type="html">&lt;p&gt;Aoineko: Aoineko moved page Template:BleuMSX to Template:BlueMSX&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[file:bluemsx.png|20px]]&lt;/div&gt;</summary>
		<author><name>Aoineko</name></author>	</entry>

	<entry>
		<id>https://aoineko.org/msxgl/index.php?title=Template:BleuMSX&amp;diff=4003</id>
		<title>Template:BleuMSX</title>
		<link rel="alternate" type="text/html" href="https://aoineko.org/msxgl/index.php?title=Template:BleuMSX&amp;diff=4003"/>
				<updated>2026-07-11T03:15:05Z</updated>
		
		<summary type="html">&lt;p&gt;Aoineko: Aoineko moved page Template:BleuMSX to Template:BlueMSX&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;#REDIRECT [[Template:BlueMSX]]&lt;/div&gt;</summary>
		<author><name>Aoineko</name></author>	</entry>

	<entry>
		<id>https://aoineko.org/msxgl/index.php?title=NEO_mapper&amp;diff=4001</id>
		<title>NEO mapper</title>
		<link rel="alternate" type="text/html" href="https://aoineko.org/msxgl/index.php?title=NEO_mapper&amp;diff=4001"/>
				<updated>2026-07-11T03:14:28Z</updated>
		
		<summary type="html">&lt;p&gt;Aoineko: /* Emulator */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;div style=&amp;quot;float:right&amp;quot;&amp;gt;[[NEO mapper|EN]] | [[NEO mapper/JA|JA]]&amp;lt;/div&amp;gt;&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
== Specifications ==&lt;br /&gt;
&lt;br /&gt;
=== Principles ===&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
Like conventional mappers, the basic idea is to use data write signals to the cartridge to change mapper registers value and thus, 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 [[#Format|tables below]]).&lt;br /&gt;
Read accesses, however, work as normal accesses to the memory visible through the banks.&lt;br /&gt;
&lt;br /&gt;
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 cartridge in this new mapper format.&lt;br /&gt;
&lt;br /&gt;
Compared to conventional mappers, this proposal is based on two new main features:&lt;br /&gt;
* A 16-bit segment register,&lt;br /&gt;
* Banks covering page #0 of MSX memory space (address 0000h~3FFFh).&lt;br /&gt;
&lt;br /&gt;
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).&lt;br /&gt;
&lt;br /&gt;
For the time being, we propose to reserve the 2 most significant bits of the 16-bit bank registers for future extensions of the format (such as SRAM or sound chips support for example).&lt;br /&gt;
This leaves 14 bits to select which segment is visible in each bank, for a maximum of 16384 segments.&lt;br /&gt;
The reserved bits, must be set to 0.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
!colspan=&amp;quot;8&amp;quot;| Higher byte&lt;br /&gt;
|&lt;br /&gt;
!colspan=&amp;quot;8&amp;quot;| Lower byte &lt;br /&gt;
|-&lt;br /&gt;
! 15 || 14 || 13 || 12 || 11 || 10 || 9 || 8 &lt;br /&gt;
|&lt;br /&gt;
! 7 || 6 || 5 || 4 || 3 || 2 || 1 || 0&lt;br /&gt;
|-&lt;br /&gt;
| 0 || 0&lt;br /&gt;
|colspan=&amp;quot;6&amp;quot;| Segment MSB&lt;br /&gt;
| &lt;br /&gt;
|colspan=&amp;quot;8&amp;quot;| Segment LSB &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The maximum ROM size is therefore 128 MB (for 8 KB segments) or 256 MB (for 16 KB segments).&lt;br /&gt;
&lt;br /&gt;
=== Write Access ===&lt;br /&gt;
&lt;br /&gt;
Write access to the mapper is use to change the value of the bank switching register (where you can select the ROM segment visible through a bank).&lt;br /&gt;
Bellow is the list of the predefined segment switching addresses.&lt;br /&gt;
&lt;br /&gt;
As this new mapper uses 16-bit segment switching registers, it uses 2 bytes for the segment number to be selected in each bank.&lt;br /&gt;
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.&lt;br /&gt;
This way, the segment number can be initialized at once with the [[#Bank switching cost|Z80 instructions for 16-bit memory write access]].&lt;br /&gt;
&lt;br /&gt;
==== NEO-8 mapper ====&lt;br /&gt;
&lt;br /&gt;
* Size of a segment: 8 KB&lt;br /&gt;
* Segment switching addresses:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Bank (8kB) !! Switching address !! Initial segment&lt;br /&gt;
|-&lt;br /&gt;
| 0: 0000h~1FFFh || 5000h (mirror at 1000h, 9000h and D000h) || 0000h&lt;br /&gt;
|-&lt;br /&gt;
| 1: 2000h~3FFFh || 5800h (mirror at 1800h, 9800h and D800h) || 0000h&lt;br /&gt;
|-&lt;br /&gt;
| 2: 4000h~5FFFh || 6000h (mirror at 2000h, A000h and E000h) || 0000h&lt;br /&gt;
|-&lt;br /&gt;
| 3: 6000h~7FFFh || 6800h (mirror at 2800h, A800h and E800h) || 0000h&lt;br /&gt;
|-&lt;br /&gt;
| 4: 8000h~9FFFh || 7000h (mirror at 3000h, B000h and F000h) || 0000h&lt;br /&gt;
|-&lt;br /&gt;
| 5: A000h~BFFFh || 7800h (mirror at 3800h, B800h and F800h) || 0000h&lt;br /&gt;
|}&lt;br /&gt;
* Maximum number of segments: 16384&lt;br /&gt;
* Maximum ROM size: 128 MB&lt;br /&gt;
&lt;br /&gt;
==== NEO-16 mapper ====&lt;br /&gt;
&lt;br /&gt;
* Size of a segment: 16 KB&lt;br /&gt;
* Segment switching addresses:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Bank (16kB) !! Switching address !! Initial segment&lt;br /&gt;
|-&lt;br /&gt;
| 0: 0000h~3FFFh || 5000h (mirror at 1000h, 9000h and D000h) || 0000h&lt;br /&gt;
|-&lt;br /&gt;
| 1: 4000h~7FFFh || 6000h (mirror at 2000h, A000h and E000h) || 0000h&lt;br /&gt;
|-&lt;br /&gt;
| 2: 8000h~BFFFh || 7000h (mirror at 3000h, B000h and F000h) || 0000h&lt;br /&gt;
|}&lt;br /&gt;
* Maximum number of segments: 16384&lt;br /&gt;
* Maximum ROM size: 256 MB&lt;br /&gt;
&lt;br /&gt;
=== Read Access ===&lt;br /&gt;
When mapper is selected, read accesses to memory pages 0, 1 and 2 (addresses 0000h to BFFFh), are redirected to a given ROM segment according to the value of the bank register corresponding to the address.&lt;br /&gt;
&lt;br /&gt;
For page 3, read accesses are invalid and the value returned is undefined and should not be used. Implementations of the NEO mapper should return the value FFh if page 3 is read, but this value is not guaranteed by the mapper specifications.&lt;br /&gt;
&lt;br /&gt;
=== Detection ===&lt;br /&gt;
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:&lt;br /&gt;
* &amp;quot;&amp;lt;tt&amp;gt;ROM_NEO8&amp;lt;/tt&amp;gt;&amp;quot; for NEO-8 mapper,&lt;br /&gt;
* &amp;quot;&amp;lt;tt&amp;gt;ROM_NE16&amp;lt;/tt&amp;gt;&amp;quot; for NEO-16 mapper.&lt;br /&gt;
&lt;br /&gt;
The ROM header (starting with &amp;quot;AB&amp;quot;) must be in the first ROM segment at offset 0.&lt;br /&gt;
The signature is therefore located at offset 16 of the ROM and may be visible to the Z80 on start-up at addresses 0010h, 4010h and 8010h.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;Note&amp;lt;/u&amp;gt;: Signature characters have been carefully choosed to prevent existing ROMs to generate false positive signature (See [[ROM type signature]]).&lt;br /&gt;
&lt;br /&gt;
== Support ==&lt;br /&gt;
&lt;br /&gt;
=== Hardware ===&lt;br /&gt;
Hardware supporting NEO mapper:&lt;br /&gt;
* '''[https://www.msxpico.com/ MSX Pico]''' (normal or WiFi): Support for NEO-8 and NEO-16 mappers up to ~15 MB (firmware 1.25 or above).&lt;br /&gt;
* '''[https://www.msxpico.com/ MSX Pico+]''': Support for NEO-8 and NEO-16 mappers up to ~14 MB (firmware 2.12 or above).&lt;br /&gt;
* '''[https://github.com/cristianoag/msx-picoverse-public PicoVerse] 2040 and 2350''': Support for NEO-8 and NEO-16 mappers up to ~15 MB.&lt;br /&gt;
* '''[https://github.com/arkadiuszmakarenko/RISKYMSX RISKY MSX]''': Support for NEO-8 and NEO-16 mappers up to 256 KB.&lt;br /&gt;
* '''[https://github.com/piigaa-densetu-two-dai/MSXpi MSXπ]''': Support for NEO-16 mappers up to 16 MB&lt;br /&gt;
* '''[https://github.com/piigaa-densetu-two-dai/MSXpi_plus_v2 MSXπ Plus (V2)]''': Support for NEO-16 mappers up to 16 MB&lt;br /&gt;
&lt;br /&gt;
=== Emulator ===&lt;br /&gt;
Emulators supporting NEO mapper:&lt;br /&gt;
* {{bleuMSX}} '''blueMSX+''': Full support for NEO-8 and NEO-16 mappers.&lt;br /&gt;
* {{Emulicious}} '''Emulicious''': Full support for NEO-8 and NEO-16 mappers.&lt;br /&gt;
* {{MSXEC}} '''MSXEC''': Support NEO-8 and NEO-16 mappers up to 64 MB (version 20260303 or above).&lt;br /&gt;
* {{openMSX}} '''openMSX''': Full support for NEO-8 and NEO-16 mappers (version 20.0 or above).&lt;br /&gt;
* {{WebMSX}} '''WebMSX''': Full support for NEO-8 and NEO-16 mappers (version 6.0.7 or above).&lt;br /&gt;
&lt;br /&gt;
=== MSXgl ===&lt;br /&gt;
&lt;br /&gt;
Both NEO-8 and NEO-16 mappers are supported. Use respectively &amp;lt;tt&amp;gt;ROM_NEO8&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;ROM_NEO16&amp;lt;/tt&amp;gt; as [[target|target format]].&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
#define SET_BANK_SEGMENT(bank, segment) /* ... */&lt;br /&gt;
&lt;br /&gt;
// Make segment #30 visible through bank #1&lt;br /&gt;
SET_BANK_SEGMENT(1, 30);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
MSXgl initialize the banks with a unique segment each, to offer the largest possible space available to the user:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;img style=&amp;quot;width:400px; margin:0.5em;&amp;quot; src=&amp;quot;https://raw.githubusercontent.com/aoineko-fr/MSXgl/main/engine/doc/mapper_neo8.png&amp;quot; /&amp;gt;&lt;br /&gt;
&amp;lt;img style=&amp;quot;width:400px; margin:0.5em;&amp;quot; src=&amp;quot;https://raw.githubusercontent.com/aoineko-fr/MSXgl/main/engine/doc/mapper_neo16.png&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;Note&amp;lt;/u&amp;gt;: When the application start, segment at 0x4000 always point to segment 0 that include the ROM header. See [[Create a mapped ROM#NEO mapper]] for more details.&lt;br /&gt;
&lt;br /&gt;
== Appendix ==&lt;br /&gt;
&lt;br /&gt;
=== Segment switching address format ===&lt;br /&gt;
&lt;br /&gt;
From a software point of view, the segment switching address is defined as:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
!colspan=&amp;quot;17&amp;quot;| 16-bit address&lt;br /&gt;
|-&lt;br /&gt;
! 15 || 14 || 13 || 12 || 11 || 10 || 9 || 8 &lt;br /&gt;
|&lt;br /&gt;
! 7 || 6 || 5 || 4 || 3 || 2 || 1 || 0&lt;br /&gt;
|-&lt;br /&gt;
| P || P || B || B || B || x || x || x || || x || x || x || x || x || x || x || R&lt;br /&gt;
|}&lt;br /&gt;
Where:&lt;br /&gt;
* '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, but the mapper registers can only be accessed from selected pages.&lt;br /&gt;
* 'BBB' (0-7) is the bank's register to write in. All unspecified values are discarded.&lt;br /&gt;
:{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Bank !! NEO-8 !! NEO-16&lt;br /&gt;
|-&lt;br /&gt;
| 0 || 010 || 010&lt;br /&gt;
|-&lt;br /&gt;
| 1 || 011 || 100&lt;br /&gt;
|-&lt;br /&gt;
| 2 || 100 || 110&lt;br /&gt;
|-&lt;br /&gt;
| 3 || 101 || &lt;br /&gt;
|-&lt;br /&gt;
| 4 || 110 || &lt;br /&gt;
|-&lt;br /&gt;
| 5 || 111 || &lt;br /&gt;
|}&lt;br /&gt;
* 'R' (0-1) is the segment switching register's byte selector (0: less significant byte; 1: most significant byte).&lt;br /&gt;
* 'x' can be any value (generating mirroring).&lt;br /&gt;
&lt;br /&gt;
So, mirroring occurs on all addresses from the given switching address +2 to the switching address +7FEh on all even-numbered addresses. For example, 5000h is mirrored at 5002h~57FEh.&lt;br /&gt;
&lt;br /&gt;
=== Programmable processor and emulation ===&lt;br /&gt;
Here is a pseudo code in C to handle NEO mappers for programmable processor based cartridges or for emulators:&lt;br /&gt;
{|&lt;br /&gt;
|-&lt;br /&gt;
| NEO-8 mapper:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
const uint8* romData; // ROM data&lt;br /&gt;
uint16 bankValue[6]; // Bank switching register value&lt;br /&gt;
&lt;br /&gt;
// Handle device initialization&lt;br /&gt;
void NEO8_Init()&lt;br /&gt;
{&lt;br /&gt;
   for (uint8 i=0; i&amp;lt;6; i++)&lt;br /&gt;
      bankValue[i] = 0;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// Handle write access&lt;br /&gt;
void NEO8_Write(uint16 address, uint8 value)&lt;br /&gt;
{&lt;br /&gt;
   uint8 bank = ((address &amp;gt;&amp;gt; 11) &amp;amp; 0x07) - 2;&lt;br /&gt;
   if (bank &amp;gt; 5)&lt;br /&gt;
      return; // skip&lt;br /&gt;
   if (address &amp;amp; 1) // Set bank register MSB&lt;br /&gt;
      bankValue[bank] = ((value &amp;amp; 0x0F) &amp;lt;&amp;lt; 8) | (bankValue[bank] &amp;amp; 0x00FF);&lt;br /&gt;
   else // Set bank register LSB&lt;br /&gt;
      bankValue[bank] = (bankValue[bank] &amp;amp; 0xFF00) | (value);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// Handle read access&lt;br /&gt;
uint8 NEO8_Read(uint16 address)&lt;br /&gt;
{&lt;br /&gt;
   uint8 bank = address &amp;gt;&amp;gt; 13;&lt;br /&gt;
   if (bank &amp;gt; 5)&lt;br /&gt;
      return 0xFF; // skip&lt;br /&gt;
   return romData[(bankValue[bank]) &amp;lt;&amp;lt; 13 + (address &amp;amp; 0x1FFF)];&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
| NEO-16 mapper:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
const uint8* romData; // ROM data&lt;br /&gt;
uint16 bankValue[3]; // Bank switching register value&lt;br /&gt;
&lt;br /&gt;
// Handle device initialization&lt;br /&gt;
void NEO16_Init()&lt;br /&gt;
{&lt;br /&gt;
   bankValue[0] = bankValue[1] = bankValue[2] = 0;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// Handle write access&lt;br /&gt;
void NEO16_Write(uint16 address, uint8 value)&lt;br /&gt;
{&lt;br /&gt;
   uint8 bank = ((address &amp;gt;&amp;gt; 12) &amp;amp; 0x03) - 1;&lt;br /&gt;
   if (bank &amp;gt; 2)&lt;br /&gt;
      return; // skip&lt;br /&gt;
   if (address &amp;amp; 1) // Set bank register MSB&lt;br /&gt;
      bankValue[bank] = ((value &amp;amp; 0x0F) &amp;lt;&amp;lt; 8) | (bankValue[bank] &amp;amp; 0x00FF);&lt;br /&gt;
   else // Set bank register LSB&lt;br /&gt;
      bankValue[bank] = (bankValue[bank] &amp;amp; 0xFF00) | (value);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// Handle read access&lt;br /&gt;
uint8 NEO16_Read(uint16 address)&lt;br /&gt;
{&lt;br /&gt;
   uint8 bank = address &amp;gt;&amp;gt; 14;&lt;br /&gt;
   if (bank &amp;gt; 2)&lt;br /&gt;
      return 0xFF; // skip&lt;br /&gt;
   return romData[(bankValue[bank]) &amp;lt;&amp;lt; 14 + (address &amp;amp; 0x3FFF)];&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Sample program ===&lt;br /&gt;
A sample program is available for testing purpose on: https://aoineko.org/msx/targets/rom/&lt;br /&gt;
&lt;br /&gt;
It is available in various sizes:&lt;br /&gt;
* NEO-8: 256 KB to 32 MB&lt;br /&gt;
* NEO-16: 256 KB to 64 MB&lt;br /&gt;
&lt;br /&gt;
=== Bank switching cost ===&lt;br /&gt;
For a program using NEO mapper, 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.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;ini&amp;quot;&amp;gt;&lt;br /&gt;
; Direct access (22 t-states)&lt;br /&gt;
LD A,n      ;  8 t-states&lt;br /&gt;
LD (nn),A   ; 14 t-states&lt;br /&gt;
&lt;br /&gt;
; Indirect access (22 t-states)&lt;br /&gt;
LD HL,nn    ; 11 t-states&lt;br /&gt;
LD (HL),n   ; 11 t-states&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Although a program can avoid having to change the 2 bytes (16-bit) of the segment register at once, there are cases where this may be necessary. In such cases, the cost is higher, but remains reasonable.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;ini&amp;quot;&amp;gt;&lt;br /&gt;
; Direct access (28 t-states)&lt;br /&gt;
LD HL,nn    ; 11 t-states&lt;br /&gt;
LD (nn),HL  ; 17 t-states&lt;br /&gt;
&lt;br /&gt;
; Indirect access (40 t-states)&lt;br /&gt;
LD HL,nn    ; 11 t-states&lt;br /&gt;
LD (HL),n   ; 11 t-states&lt;br /&gt;
INC HL      ;  7 t-states&lt;br /&gt;
LD (HL),n   ; 11 t-states&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Logos ===&lt;br /&gt;
Here are the logos you can use to indicate that a product is compatible with the NEO mapper:&lt;br /&gt;
&lt;br /&gt;
[https://aoineko.org/msx/files/neomapper8b-logo.png &amp;lt;img style=&amp;quot;width:128px&amp;quot; src=&amp;quot;https://aoineko.org/msx/files/neomapper8b-logo.png&amp;quot; /&amp;gt;]&lt;br /&gt;
[https://aoineko.org/msx/files/neomapper8w-logo.png &amp;lt;img style=&amp;quot;width:128px&amp;quot; src=&amp;quot;https://aoineko.org/msx/files/neomapper8w-logo.png&amp;quot; /&amp;gt;]&lt;br /&gt;
[https://aoineko.org/msx/files/neomapper16b-logo.png &amp;lt;img style=&amp;quot;width:128px&amp;quot; src=&amp;quot;https://aoineko.org/msx/files/neomapper16b-logo.png&amp;quot; /&amp;gt;]&lt;br /&gt;
[https://aoineko.org/msx/files/neomapper16w-logo.png &amp;lt;img style=&amp;quot;width:128px&amp;quot; src=&amp;quot;https://aoineko.org/msx/files/neomapper16w-logo.png&amp;quot; /&amp;gt;]&lt;br /&gt;
&lt;br /&gt;
== Change log ==&lt;br /&gt;
* Version 1.0 (2024/02/12)&lt;br /&gt;
** Original version&lt;br /&gt;
* Version 1.1 (2024/02/20)&lt;br /&gt;
** Changed mappers signature to minimize the risk of an old cartridge generating a false positive and to comply to [[ROM type signature]] format.&lt;br /&gt;
** Added clarification on PP and BBB values for bank switching addresses.&lt;br /&gt;
** Added clarification for read access to the mapper and especially when try to read the page 3.&lt;br /&gt;
* Version 1.2 (2026/04/06)&lt;br /&gt;
** Added optional official logo for NEO mapper product.&lt;br /&gt;
** Added bits 12 and 13 to the register value, increasing the maximum number of segments from 4096 to 16384.&lt;br /&gt;
[[Category:Proposal]][[Category:Proposal/Mapper]]&lt;/div&gt;</summary>
		<author><name>Aoineko</name></author>	</entry>

	<entry>
		<id>https://aoineko.org/msxgl/index.php?title=NEO_mapper&amp;diff=4000</id>
		<title>NEO mapper</title>
		<link rel="alternate" type="text/html" href="https://aoineko.org/msxgl/index.php?title=NEO_mapper&amp;diff=4000"/>
				<updated>2026-07-11T03:13:41Z</updated>
		
		<summary type="html">&lt;p&gt;Aoineko: /* Emulator */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;div style=&amp;quot;float:right&amp;quot;&amp;gt;[[NEO mapper|EN]] | [[NEO mapper/JA|JA]]&amp;lt;/div&amp;gt;&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
== Specifications ==&lt;br /&gt;
&lt;br /&gt;
=== Principles ===&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
Like conventional mappers, the basic idea is to use data write signals to the cartridge to change mapper registers value and thus, 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 [[#Format|tables below]]).&lt;br /&gt;
Read accesses, however, work as normal accesses to the memory visible through the banks.&lt;br /&gt;
&lt;br /&gt;
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 cartridge in this new mapper format.&lt;br /&gt;
&lt;br /&gt;
Compared to conventional mappers, this proposal is based on two new main features:&lt;br /&gt;
* A 16-bit segment register,&lt;br /&gt;
* Banks covering page #0 of MSX memory space (address 0000h~3FFFh).&lt;br /&gt;
&lt;br /&gt;
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).&lt;br /&gt;
&lt;br /&gt;
For the time being, we propose to reserve the 2 most significant bits of the 16-bit bank registers for future extensions of the format (such as SRAM or sound chips support for example).&lt;br /&gt;
This leaves 14 bits to select which segment is visible in each bank, for a maximum of 16384 segments.&lt;br /&gt;
The reserved bits, must be set to 0.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
!colspan=&amp;quot;8&amp;quot;| Higher byte&lt;br /&gt;
|&lt;br /&gt;
!colspan=&amp;quot;8&amp;quot;| Lower byte &lt;br /&gt;
|-&lt;br /&gt;
! 15 || 14 || 13 || 12 || 11 || 10 || 9 || 8 &lt;br /&gt;
|&lt;br /&gt;
! 7 || 6 || 5 || 4 || 3 || 2 || 1 || 0&lt;br /&gt;
|-&lt;br /&gt;
| 0 || 0&lt;br /&gt;
|colspan=&amp;quot;6&amp;quot;| Segment MSB&lt;br /&gt;
| &lt;br /&gt;
|colspan=&amp;quot;8&amp;quot;| Segment LSB &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The maximum ROM size is therefore 128 MB (for 8 KB segments) or 256 MB (for 16 KB segments).&lt;br /&gt;
&lt;br /&gt;
=== Write Access ===&lt;br /&gt;
&lt;br /&gt;
Write access to the mapper is use to change the value of the bank switching register (where you can select the ROM segment visible through a bank).&lt;br /&gt;
Bellow is the list of the predefined segment switching addresses.&lt;br /&gt;
&lt;br /&gt;
As this new mapper uses 16-bit segment switching registers, it uses 2 bytes for the segment number to be selected in each bank.&lt;br /&gt;
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.&lt;br /&gt;
This way, the segment number can be initialized at once with the [[#Bank switching cost|Z80 instructions for 16-bit memory write access]].&lt;br /&gt;
&lt;br /&gt;
==== NEO-8 mapper ====&lt;br /&gt;
&lt;br /&gt;
* Size of a segment: 8 KB&lt;br /&gt;
* Segment switching addresses:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Bank (8kB) !! Switching address !! Initial segment&lt;br /&gt;
|-&lt;br /&gt;
| 0: 0000h~1FFFh || 5000h (mirror at 1000h, 9000h and D000h) || 0000h&lt;br /&gt;
|-&lt;br /&gt;
| 1: 2000h~3FFFh || 5800h (mirror at 1800h, 9800h and D800h) || 0000h&lt;br /&gt;
|-&lt;br /&gt;
| 2: 4000h~5FFFh || 6000h (mirror at 2000h, A000h and E000h) || 0000h&lt;br /&gt;
|-&lt;br /&gt;
| 3: 6000h~7FFFh || 6800h (mirror at 2800h, A800h and E800h) || 0000h&lt;br /&gt;
|-&lt;br /&gt;
| 4: 8000h~9FFFh || 7000h (mirror at 3000h, B000h and F000h) || 0000h&lt;br /&gt;
|-&lt;br /&gt;
| 5: A000h~BFFFh || 7800h (mirror at 3800h, B800h and F800h) || 0000h&lt;br /&gt;
|}&lt;br /&gt;
* Maximum number of segments: 16384&lt;br /&gt;
* Maximum ROM size: 128 MB&lt;br /&gt;
&lt;br /&gt;
==== NEO-16 mapper ====&lt;br /&gt;
&lt;br /&gt;
* Size of a segment: 16 KB&lt;br /&gt;
* Segment switching addresses:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Bank (16kB) !! Switching address !! Initial segment&lt;br /&gt;
|-&lt;br /&gt;
| 0: 0000h~3FFFh || 5000h (mirror at 1000h, 9000h and D000h) || 0000h&lt;br /&gt;
|-&lt;br /&gt;
| 1: 4000h~7FFFh || 6000h (mirror at 2000h, A000h and E000h) || 0000h&lt;br /&gt;
|-&lt;br /&gt;
| 2: 8000h~BFFFh || 7000h (mirror at 3000h, B000h and F000h) || 0000h&lt;br /&gt;
|}&lt;br /&gt;
* Maximum number of segments: 16384&lt;br /&gt;
* Maximum ROM size: 256 MB&lt;br /&gt;
&lt;br /&gt;
=== Read Access ===&lt;br /&gt;
When mapper is selected, read accesses to memory pages 0, 1 and 2 (addresses 0000h to BFFFh), are redirected to a given ROM segment according to the value of the bank register corresponding to the address.&lt;br /&gt;
&lt;br /&gt;
For page 3, read accesses are invalid and the value returned is undefined and should not be used. Implementations of the NEO mapper should return the value FFh if page 3 is read, but this value is not guaranteed by the mapper specifications.&lt;br /&gt;
&lt;br /&gt;
=== Detection ===&lt;br /&gt;
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:&lt;br /&gt;
* &amp;quot;&amp;lt;tt&amp;gt;ROM_NEO8&amp;lt;/tt&amp;gt;&amp;quot; for NEO-8 mapper,&lt;br /&gt;
* &amp;quot;&amp;lt;tt&amp;gt;ROM_NE16&amp;lt;/tt&amp;gt;&amp;quot; for NEO-16 mapper.&lt;br /&gt;
&lt;br /&gt;
The ROM header (starting with &amp;quot;AB&amp;quot;) must be in the first ROM segment at offset 0.&lt;br /&gt;
The signature is therefore located at offset 16 of the ROM and may be visible to the Z80 on start-up at addresses 0010h, 4010h and 8010h.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;Note&amp;lt;/u&amp;gt;: Signature characters have been carefully choosed to prevent existing ROMs to generate false positive signature (See [[ROM type signature]]).&lt;br /&gt;
&lt;br /&gt;
== Support ==&lt;br /&gt;
&lt;br /&gt;
=== Hardware ===&lt;br /&gt;
Hardware supporting NEO mapper:&lt;br /&gt;
* '''[https://www.msxpico.com/ MSX Pico]''' (normal or WiFi): Support for NEO-8 and NEO-16 mappers up to ~15 MB (firmware 1.25 or above).&lt;br /&gt;
* '''[https://www.msxpico.com/ MSX Pico+]''': Support for NEO-8 and NEO-16 mappers up to ~14 MB (firmware 2.12 or above).&lt;br /&gt;
* '''[https://github.com/cristianoag/msx-picoverse-public PicoVerse] 2040 and 2350''': Support for NEO-8 and NEO-16 mappers up to ~15 MB.&lt;br /&gt;
* '''[https://github.com/arkadiuszmakarenko/RISKYMSX RISKY MSX]''': Support for NEO-8 and NEO-16 mappers up to 256 KB.&lt;br /&gt;
* '''[https://github.com/piigaa-densetu-two-dai/MSXpi MSXπ]''': Support for NEO-16 mappers up to 16 MB&lt;br /&gt;
* '''[https://github.com/piigaa-densetu-two-dai/MSXpi_plus_v2 MSXπ Plus (V2)]''': Support for NEO-16 mappers up to 16 MB&lt;br /&gt;
&lt;br /&gt;
=== Emulator ===&lt;br /&gt;
Emulators supporting NEO mapper:&lt;br /&gt;
* {{blueMSX}} '''blueMSX+''': Full support for NEO-8 and NEO-16 mappers.&lt;br /&gt;
* {{Emulicious}} '''Emulicious''': Full support for NEO-8 and NEO-16 mappers.&lt;br /&gt;
* {{MSXEC}} '''MSXEC''': Support NEO-8 and NEO-16 mappers up to 64 MB (version 20260303 or above).&lt;br /&gt;
* {{openMSX}} '''openMSX''': Full support for NEO-8 and NEO-16 mappers (version 20.0 or above).&lt;br /&gt;
* {{WebMSX}} '''WebMSX''': Full support for NEO-8 and NEO-16 mappers (version 6.0.7 or above).&lt;br /&gt;
&lt;br /&gt;
=== MSXgl ===&lt;br /&gt;
&lt;br /&gt;
Both NEO-8 and NEO-16 mappers are supported. Use respectively &amp;lt;tt&amp;gt;ROM_NEO8&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;ROM_NEO16&amp;lt;/tt&amp;gt; as [[target|target format]].&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
#define SET_BANK_SEGMENT(bank, segment) /* ... */&lt;br /&gt;
&lt;br /&gt;
// Make segment #30 visible through bank #1&lt;br /&gt;
SET_BANK_SEGMENT(1, 30);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
MSXgl initialize the banks with a unique segment each, to offer the largest possible space available to the user:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;img style=&amp;quot;width:400px; margin:0.5em;&amp;quot; src=&amp;quot;https://raw.githubusercontent.com/aoineko-fr/MSXgl/main/engine/doc/mapper_neo8.png&amp;quot; /&amp;gt;&lt;br /&gt;
&amp;lt;img style=&amp;quot;width:400px; margin:0.5em;&amp;quot; src=&amp;quot;https://raw.githubusercontent.com/aoineko-fr/MSXgl/main/engine/doc/mapper_neo16.png&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;Note&amp;lt;/u&amp;gt;: When the application start, segment at 0x4000 always point to segment 0 that include the ROM header. See [[Create a mapped ROM#NEO mapper]] for more details.&lt;br /&gt;
&lt;br /&gt;
== Appendix ==&lt;br /&gt;
&lt;br /&gt;
=== Segment switching address format ===&lt;br /&gt;
&lt;br /&gt;
From a software point of view, the segment switching address is defined as:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
!colspan=&amp;quot;17&amp;quot;| 16-bit address&lt;br /&gt;
|-&lt;br /&gt;
! 15 || 14 || 13 || 12 || 11 || 10 || 9 || 8 &lt;br /&gt;
|&lt;br /&gt;
! 7 || 6 || 5 || 4 || 3 || 2 || 1 || 0&lt;br /&gt;
|-&lt;br /&gt;
| P || P || B || B || B || x || x || x || || x || x || x || x || x || x || x || R&lt;br /&gt;
|}&lt;br /&gt;
Where:&lt;br /&gt;
* '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, but the mapper registers can only be accessed from selected pages.&lt;br /&gt;
* 'BBB' (0-7) is the bank's register to write in. All unspecified values are discarded.&lt;br /&gt;
:{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Bank !! NEO-8 !! NEO-16&lt;br /&gt;
|-&lt;br /&gt;
| 0 || 010 || 010&lt;br /&gt;
|-&lt;br /&gt;
| 1 || 011 || 100&lt;br /&gt;
|-&lt;br /&gt;
| 2 || 100 || 110&lt;br /&gt;
|-&lt;br /&gt;
| 3 || 101 || &lt;br /&gt;
|-&lt;br /&gt;
| 4 || 110 || &lt;br /&gt;
|-&lt;br /&gt;
| 5 || 111 || &lt;br /&gt;
|}&lt;br /&gt;
* 'R' (0-1) is the segment switching register's byte selector (0: less significant byte; 1: most significant byte).&lt;br /&gt;
* 'x' can be any value (generating mirroring).&lt;br /&gt;
&lt;br /&gt;
So, mirroring occurs on all addresses from the given switching address +2 to the switching address +7FEh on all even-numbered addresses. For example, 5000h is mirrored at 5002h~57FEh.&lt;br /&gt;
&lt;br /&gt;
=== Programmable processor and emulation ===&lt;br /&gt;
Here is a pseudo code in C to handle NEO mappers for programmable processor based cartridges or for emulators:&lt;br /&gt;
{|&lt;br /&gt;
|-&lt;br /&gt;
| NEO-8 mapper:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
const uint8* romData; // ROM data&lt;br /&gt;
uint16 bankValue[6]; // Bank switching register value&lt;br /&gt;
&lt;br /&gt;
// Handle device initialization&lt;br /&gt;
void NEO8_Init()&lt;br /&gt;
{&lt;br /&gt;
   for (uint8 i=0; i&amp;lt;6; i++)&lt;br /&gt;
      bankValue[i] = 0;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// Handle write access&lt;br /&gt;
void NEO8_Write(uint16 address, uint8 value)&lt;br /&gt;
{&lt;br /&gt;
   uint8 bank = ((address &amp;gt;&amp;gt; 11) &amp;amp; 0x07) - 2;&lt;br /&gt;
   if (bank &amp;gt; 5)&lt;br /&gt;
      return; // skip&lt;br /&gt;
   if (address &amp;amp; 1) // Set bank register MSB&lt;br /&gt;
      bankValue[bank] = ((value &amp;amp; 0x0F) &amp;lt;&amp;lt; 8) | (bankValue[bank] &amp;amp; 0x00FF);&lt;br /&gt;
   else // Set bank register LSB&lt;br /&gt;
      bankValue[bank] = (bankValue[bank] &amp;amp; 0xFF00) | (value);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// Handle read access&lt;br /&gt;
uint8 NEO8_Read(uint16 address)&lt;br /&gt;
{&lt;br /&gt;
   uint8 bank = address &amp;gt;&amp;gt; 13;&lt;br /&gt;
   if (bank &amp;gt; 5)&lt;br /&gt;
      return 0xFF; // skip&lt;br /&gt;
   return romData[(bankValue[bank]) &amp;lt;&amp;lt; 13 + (address &amp;amp; 0x1FFF)];&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
| NEO-16 mapper:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
const uint8* romData; // ROM data&lt;br /&gt;
uint16 bankValue[3]; // Bank switching register value&lt;br /&gt;
&lt;br /&gt;
// Handle device initialization&lt;br /&gt;
void NEO16_Init()&lt;br /&gt;
{&lt;br /&gt;
   bankValue[0] = bankValue[1] = bankValue[2] = 0;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// Handle write access&lt;br /&gt;
void NEO16_Write(uint16 address, uint8 value)&lt;br /&gt;
{&lt;br /&gt;
   uint8 bank = ((address &amp;gt;&amp;gt; 12) &amp;amp; 0x03) - 1;&lt;br /&gt;
   if (bank &amp;gt; 2)&lt;br /&gt;
      return; // skip&lt;br /&gt;
   if (address &amp;amp; 1) // Set bank register MSB&lt;br /&gt;
      bankValue[bank] = ((value &amp;amp; 0x0F) &amp;lt;&amp;lt; 8) | (bankValue[bank] &amp;amp; 0x00FF);&lt;br /&gt;
   else // Set bank register LSB&lt;br /&gt;
      bankValue[bank] = (bankValue[bank] &amp;amp; 0xFF00) | (value);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// Handle read access&lt;br /&gt;
uint8 NEO16_Read(uint16 address)&lt;br /&gt;
{&lt;br /&gt;
   uint8 bank = address &amp;gt;&amp;gt; 14;&lt;br /&gt;
   if (bank &amp;gt; 2)&lt;br /&gt;
      return 0xFF; // skip&lt;br /&gt;
   return romData[(bankValue[bank]) &amp;lt;&amp;lt; 14 + (address &amp;amp; 0x3FFF)];&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Sample program ===&lt;br /&gt;
A sample program is available for testing purpose on: https://aoineko.org/msx/targets/rom/&lt;br /&gt;
&lt;br /&gt;
It is available in various sizes:&lt;br /&gt;
* NEO-8: 256 KB to 32 MB&lt;br /&gt;
* NEO-16: 256 KB to 64 MB&lt;br /&gt;
&lt;br /&gt;
=== Bank switching cost ===&lt;br /&gt;
For a program using NEO mapper, 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.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;ini&amp;quot;&amp;gt;&lt;br /&gt;
; Direct access (22 t-states)&lt;br /&gt;
LD A,n      ;  8 t-states&lt;br /&gt;
LD (nn),A   ; 14 t-states&lt;br /&gt;
&lt;br /&gt;
; Indirect access (22 t-states)&lt;br /&gt;
LD HL,nn    ; 11 t-states&lt;br /&gt;
LD (HL),n   ; 11 t-states&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Although a program can avoid having to change the 2 bytes (16-bit) of the segment register at once, there are cases where this may be necessary. In such cases, the cost is higher, but remains reasonable.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;ini&amp;quot;&amp;gt;&lt;br /&gt;
; Direct access (28 t-states)&lt;br /&gt;
LD HL,nn    ; 11 t-states&lt;br /&gt;
LD (nn),HL  ; 17 t-states&lt;br /&gt;
&lt;br /&gt;
; Indirect access (40 t-states)&lt;br /&gt;
LD HL,nn    ; 11 t-states&lt;br /&gt;
LD (HL),n   ; 11 t-states&lt;br /&gt;
INC HL      ;  7 t-states&lt;br /&gt;
LD (HL),n   ; 11 t-states&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Logos ===&lt;br /&gt;
Here are the logos you can use to indicate that a product is compatible with the NEO mapper:&lt;br /&gt;
&lt;br /&gt;
[https://aoineko.org/msx/files/neomapper8b-logo.png &amp;lt;img style=&amp;quot;width:128px&amp;quot; src=&amp;quot;https://aoineko.org/msx/files/neomapper8b-logo.png&amp;quot; /&amp;gt;]&lt;br /&gt;
[https://aoineko.org/msx/files/neomapper8w-logo.png &amp;lt;img style=&amp;quot;width:128px&amp;quot; src=&amp;quot;https://aoineko.org/msx/files/neomapper8w-logo.png&amp;quot; /&amp;gt;]&lt;br /&gt;
[https://aoineko.org/msx/files/neomapper16b-logo.png &amp;lt;img style=&amp;quot;width:128px&amp;quot; src=&amp;quot;https://aoineko.org/msx/files/neomapper16b-logo.png&amp;quot; /&amp;gt;]&lt;br /&gt;
[https://aoineko.org/msx/files/neomapper16w-logo.png &amp;lt;img style=&amp;quot;width:128px&amp;quot; src=&amp;quot;https://aoineko.org/msx/files/neomapper16w-logo.png&amp;quot; /&amp;gt;]&lt;br /&gt;
&lt;br /&gt;
== Change log ==&lt;br /&gt;
* Version 1.0 (2024/02/12)&lt;br /&gt;
** Original version&lt;br /&gt;
* Version 1.1 (2024/02/20)&lt;br /&gt;
** Changed mappers signature to minimize the risk of an old cartridge generating a false positive and to comply to [[ROM type signature]] format.&lt;br /&gt;
** Added clarification on PP and BBB values for bank switching addresses.&lt;br /&gt;
** Added clarification for read access to the mapper and especially when try to read the page 3.&lt;br /&gt;
* Version 1.2 (2026/04/06)&lt;br /&gt;
** Added optional official logo for NEO mapper product.&lt;br /&gt;
** Added bits 12 and 13 to the register value, increasing the maximum number of segments from 4096 to 16384.&lt;br /&gt;
[[Category:Proposal]][[Category:Proposal/Mapper]]&lt;/div&gt;</summary>
		<author><name>Aoineko</name></author>	</entry>

	<entry>
		<id>https://aoineko.org/msxgl/index.php?title=Build_tool/InstallRAMISR&amp;diff=3999</id>
		<title>Build tool/InstallRAMISR</title>
		<link rel="alternate" type="text/html" href="https://aoineko.org/msxgl/index.php?title=Build_tool/InstallRAMISR&amp;diff=3999"/>
				<updated>2026-07-09T21:07:23Z</updated>
		
		<summary type="html">&lt;p&gt;Aoineko: /* RAMISR_PAGE3 */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Build tool]] option '''InstallRAMISR''' is used mainly to automatically select RAM in page 0 then copy data there at startup, so ROM cartridge can take advantage of (almost) 16 KB of additional RAM.&lt;br /&gt;
&lt;br /&gt;
This option requires MSX to have at least 64 KB of RAM (otherwise, no RAM will be available on page 0). So only some MSX1 may be compatible but all the MSX2, MSX2+ and MSX turbo R are.&lt;br /&gt;
&lt;br /&gt;
As page 0 (addresses 0x0000-0x3FFF) is the place where MSX will search for interruption handler (ISR), the build tool will automatically copy the selected ISR (see [[Build tool/CustomISR|CustomISR]] option).&lt;br /&gt;
&lt;br /&gt;
InstallRAMISR can also be used to install ISR in page 3 and activate Interrupt mode 2 (IM2) so the system will no longer access to page 0 during interrupt and user can switch page 0 content freely.&lt;br /&gt;
&lt;br /&gt;
InstallRAMISR can take those values:&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;RAMISR_NONE&amp;quot;&amp;lt;/tt&amp;gt;: Don't switch page 0 to RAM &lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;RAMISR_PAGE0&amp;quot;&amp;lt;/tt&amp;gt;: Switch page 0 to RAM then install ISR at 0x0038 (mandatory address)&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;RAMISR_SEGMENT0&amp;quot;&amp;lt;/tt&amp;gt;: Switch page 0 to RAM, install ISR at 0x0038 , then copy segment data at 0x0100 (for mapped-ROM)&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;RAMISR_PAGE3&amp;quot;&amp;lt;/tt&amp;gt;: Install ISR in RAM in page 3 and use interrupt mode 2 (IM2)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;Note&amp;lt;/u&amp;gt;: In the past, this option was a Boolean. We recommend changing its value to one of the above strings, but note that if you keep a Boolean value, the 'true' will be interpreted as &amp;lt;tt&amp;gt;&amp;quot;RAMISR_PAGE0&amp;quot;&amp;lt;/tt&amp;gt; and the 'false' as &amp;lt;tt&amp;gt;&amp;quot;RAMISR_NONE&amp;quot;&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== RAMISR_PAGE0 ==&lt;br /&gt;
When using &amp;lt;tt&amp;gt;RAMISR_PAGE0&amp;lt;/tt&amp;gt; option, you have additional RAM of be used from 0x0100 to 0x3FFF.&lt;br /&gt;
You can use SDCC's &amp;lt;tt&amp;gt;__at()&amp;lt;/tt&amp;gt; directive to place variables in the memory space.&lt;br /&gt;
&lt;br /&gt;
== RAMISR_SEGMENT0 ==&lt;br /&gt;
When using &amp;lt;tt&amp;gt;RAMISR_SEGMENT0 &amp;lt;/tt&amp;gt; option, you have to define a source code file named &amp;lt;tt&amp;gt;{projectName}_p0.c&amp;lt;/tt&amp;gt; (or &amp;lt;tt&amp;gt;.asm&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;.s&amp;lt;/tt&amp;gt; to add assembler source) and it will be automatically added to your mapper data and copy at statup in page 0.&lt;br /&gt;
Code and data from your &amp;lt;tt&amp;gt;_p0&amp;lt;/tt&amp;gt; file will be available starting from address 0x0100 (after the ISR) so you have a little less than 16 KB available in page 0 (16 KB - 0x100 = 16128 bytes).&lt;br /&gt;
&lt;br /&gt;
The 16 KB content of &amp;lt;tt&amp;gt;_p0&amp;lt;/tt&amp;gt; will be place in segment after the 32 KB of your main program. Segment number depend of the mapper format your are using:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Mapper !! Segments&lt;br /&gt;
|-&lt;br /&gt;
| ASCII-8 || #4 and #5&lt;br /&gt;
|-&lt;br /&gt;
| ASCII-16 || #2&lt;br /&gt;
|-&lt;br /&gt;
| KONAMI K4 || #4 and #5&lt;br /&gt;
|-&lt;br /&gt;
| KONAMI K5 (SCC) || #4 and #5&lt;br /&gt;
|-&lt;br /&gt;
| NEO-8 || #6 and #7&lt;br /&gt;
|-&lt;br /&gt;
| NEO-16 || #3&lt;br /&gt;
|-&lt;br /&gt;
| YAMANOOTO || #4 and #5&lt;br /&gt;
|-&lt;br /&gt;
| ASCII16-X || #2&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
When you use this option, these segments are reserved for code and data to be copied on page 0 and cannot be used for anything else.&lt;br /&gt;
&lt;br /&gt;
[[Samples#Software_Sprite|s_swsprt]] sample (software sprite) showcase the use of this option.&lt;br /&gt;
&lt;br /&gt;
== RAMISR_PAGE3 ==&lt;br /&gt;
When using &amp;lt;tt&amp;gt;RAMISR_PAGE3&amp;lt;/tt&amp;gt; option, the boot sequence install the interrupt handler in RAM, setup a vector table and activate Interrupt mode 2 (IM2) so that, when an interrupt occurs, only page 3 will be accessed.&lt;br /&gt;
&lt;br /&gt;
As page 0 is not used anymore by the system, the user can freely use it to have:&lt;br /&gt;
* A fixed chunk of 16 KB of ROM (for 48 KB plain-ROM),&lt;br /&gt;
* Freely switchable segments using [[NEO mapper]]:&lt;br /&gt;
** NEO-16: 1 bank of 16 KB (0x0000h~0x3FFF),&lt;br /&gt;
** NEO-8: 2 banks of 8 KB (0x0000~0x1FFF and 0x2000~0x3FFF).&lt;br /&gt;
* 16 KB of RAM (for MSX with at least 64 KB of RAM).&lt;br /&gt;
** For MSX computers equipped with a Memory mapper, you can freely change the segment displayed on page 0.&lt;br /&gt;
&lt;br /&gt;
This option can only be used with &amp;lt;tt&amp;gt;ForceRamAddr=0xC000&amp;lt;/tt&amp;gt; (or the default &amp;lt;tt&amp;gt;ForceRamAddr=0&amp;lt;/tt&amp;gt; as it is equivalent).&lt;br /&gt;
In this case, C variables will be accumulated starting from address 0xC1C4.&lt;br /&gt;
Thus, 452 bytes are used for the vector tables (257 bytes) and the ISR code itself.&lt;br /&gt;
&lt;br /&gt;
Note: As IM2 mode use Z80 register &amp;lt;tt&amp;gt;I&amp;lt;/tt&amp;gt; to know where to jump when an interrupt occurs, programmers that would like to use &amp;lt;tt&amp;gt;RAMISR_PAGE3&amp;lt;/tt&amp;gt; option must not use inline assembler code that change this register value.&lt;br /&gt;
&lt;br /&gt;
[[Samples#Graph_Mode_3|s_gm3]] sample (GM3 mode) showcase the use of this option.&lt;/div&gt;</summary>
		<author><name>Aoineko</name></author>	</entry>

	<entry>
		<id>https://aoineko.org/msxgl/index.php?title=Build_tool/InstallRAMISR&amp;diff=3998</id>
		<title>Build tool/InstallRAMISR</title>
		<link rel="alternate" type="text/html" href="https://aoineko.org/msxgl/index.php?title=Build_tool/InstallRAMISR&amp;diff=3998"/>
				<updated>2026-07-09T21:07:04Z</updated>
		
		<summary type="html">&lt;p&gt;Aoineko: /* RAMISR_PAGE3 */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Build tool]] option '''InstallRAMISR''' is used mainly to automatically select RAM in page 0 then copy data there at startup, so ROM cartridge can take advantage of (almost) 16 KB of additional RAM.&lt;br /&gt;
&lt;br /&gt;
This option requires MSX to have at least 64 KB of RAM (otherwise, no RAM will be available on page 0). So only some MSX1 may be compatible but all the MSX2, MSX2+ and MSX turbo R are.&lt;br /&gt;
&lt;br /&gt;
As page 0 (addresses 0x0000-0x3FFF) is the place where MSX will search for interruption handler (ISR), the build tool will automatically copy the selected ISR (see [[Build tool/CustomISR|CustomISR]] option).&lt;br /&gt;
&lt;br /&gt;
InstallRAMISR can also be used to install ISR in page 3 and activate Interrupt mode 2 (IM2) so the system will no longer access to page 0 during interrupt and user can switch page 0 content freely.&lt;br /&gt;
&lt;br /&gt;
InstallRAMISR can take those values:&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;RAMISR_NONE&amp;quot;&amp;lt;/tt&amp;gt;: Don't switch page 0 to RAM &lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;RAMISR_PAGE0&amp;quot;&amp;lt;/tt&amp;gt;: Switch page 0 to RAM then install ISR at 0x0038 (mandatory address)&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;RAMISR_SEGMENT0&amp;quot;&amp;lt;/tt&amp;gt;: Switch page 0 to RAM, install ISR at 0x0038 , then copy segment data at 0x0100 (for mapped-ROM)&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;RAMISR_PAGE3&amp;quot;&amp;lt;/tt&amp;gt;: Install ISR in RAM in page 3 and use interrupt mode 2 (IM2)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;Note&amp;lt;/u&amp;gt;: In the past, this option was a Boolean. We recommend changing its value to one of the above strings, but note that if you keep a Boolean value, the 'true' will be interpreted as &amp;lt;tt&amp;gt;&amp;quot;RAMISR_PAGE0&amp;quot;&amp;lt;/tt&amp;gt; and the 'false' as &amp;lt;tt&amp;gt;&amp;quot;RAMISR_NONE&amp;quot;&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== RAMISR_PAGE0 ==&lt;br /&gt;
When using &amp;lt;tt&amp;gt;RAMISR_PAGE0&amp;lt;/tt&amp;gt; option, you have additional RAM of be used from 0x0100 to 0x3FFF.&lt;br /&gt;
You can use SDCC's &amp;lt;tt&amp;gt;__at()&amp;lt;/tt&amp;gt; directive to place variables in the memory space.&lt;br /&gt;
&lt;br /&gt;
== RAMISR_SEGMENT0 ==&lt;br /&gt;
When using &amp;lt;tt&amp;gt;RAMISR_SEGMENT0 &amp;lt;/tt&amp;gt; option, you have to define a source code file named &amp;lt;tt&amp;gt;{projectName}_p0.c&amp;lt;/tt&amp;gt; (or &amp;lt;tt&amp;gt;.asm&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;.s&amp;lt;/tt&amp;gt; to add assembler source) and it will be automatically added to your mapper data and copy at statup in page 0.&lt;br /&gt;
Code and data from your &amp;lt;tt&amp;gt;_p0&amp;lt;/tt&amp;gt; file will be available starting from address 0x0100 (after the ISR) so you have a little less than 16 KB available in page 0 (16 KB - 0x100 = 16128 bytes).&lt;br /&gt;
&lt;br /&gt;
The 16 KB content of &amp;lt;tt&amp;gt;_p0&amp;lt;/tt&amp;gt; will be place in segment after the 32 KB of your main program. Segment number depend of the mapper format your are using:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Mapper !! Segments&lt;br /&gt;
|-&lt;br /&gt;
| ASCII-8 || #4 and #5&lt;br /&gt;
|-&lt;br /&gt;
| ASCII-16 || #2&lt;br /&gt;
|-&lt;br /&gt;
| KONAMI K4 || #4 and #5&lt;br /&gt;
|-&lt;br /&gt;
| KONAMI K5 (SCC) || #4 and #5&lt;br /&gt;
|-&lt;br /&gt;
| NEO-8 || #6 and #7&lt;br /&gt;
|-&lt;br /&gt;
| NEO-16 || #3&lt;br /&gt;
|-&lt;br /&gt;
| YAMANOOTO || #4 and #5&lt;br /&gt;
|-&lt;br /&gt;
| ASCII16-X || #2&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
When you use this option, these segments are reserved for code and data to be copied on page 0 and cannot be used for anything else.&lt;br /&gt;
&lt;br /&gt;
[[Samples#Software_Sprite|s_swsprt]] sample (software sprite) showcase the use of this option.&lt;br /&gt;
&lt;br /&gt;
== RAMISR_PAGE3 ==&lt;br /&gt;
When using &amp;lt;tt&amp;gt;RAMISR_PAGE3&amp;lt;/tt&amp;gt; option, the boot sequence install the interrupt handler in RAM, setup a vector table and activate Interrupt mode 2 (IM2) so that, when an interrupt occurs, only page 3 will be accessed.&lt;br /&gt;
&lt;br /&gt;
As page 0 is not used anymore by the system, the user can freely use it to have:&lt;br /&gt;
* A fixed chunk of 16 KB of ROM (for 48 KB plain-ROM),&lt;br /&gt;
* Freely switchable segments using [[NEO mapper]]:&lt;br /&gt;
** NEO-16: 1 bank of 16 KB (0x0000h~0x3FFF),&lt;br /&gt;
** NEO-8: 2 banks of 8 KB (0x0000~0x1FFF and 0x2000~0x3FFF).&lt;br /&gt;
* 16 KB of RAM (for MSX with at least 64 KB of RAM).&lt;br /&gt;
** For MSX computers equipped with a Memory mapper, you can freely change the segment displayed on page 0.&lt;br /&gt;
&lt;br /&gt;
This option can only be used with &amp;lt;tt&amp;gt;ForceRamAddr=0xC000&amp;lt;/tt&amp;gt; (or the default &amp;lt;tt&amp;gt;ForceRamAddr=0&amp;lt;/tt&amp;gt; as it is equivalent).&lt;br /&gt;
In this case, C variables will be accumulated starting from address 0xC1C4.&lt;br /&gt;
Thus, 452 bytes are used for the vector tables (257 bytes) and the ISR code itself.&lt;br /&gt;
&lt;br /&gt;
Note: As IM2 mode use Z80 register &amp;lt;tt&amp;gt;I&amp;lt;/tt&amp;gt; to know where to jump when an interrupt occurs, programmers that would like to use &amp;lt;tt&amp;gt;RAMISR_PAGE3&amp;lt;/tt&amp;gt; option must not use inline assembler code that use this register.&lt;br /&gt;
&lt;br /&gt;
[[Samples#Graph_Mode_3|s_gm3]] sample (GM3 mode) showcase the use of this option.&lt;/div&gt;</summary>
		<author><name>Aoineko</name></author>	</entry>

	<entry>
		<id>https://aoineko.org/msxgl/index.php?title=Build_tool/InstallRAMISR&amp;diff=3997</id>
		<title>Build tool/InstallRAMISR</title>
		<link rel="alternate" type="text/html" href="https://aoineko.org/msxgl/index.php?title=Build_tool/InstallRAMISR&amp;diff=3997"/>
				<updated>2026-07-09T21:06:37Z</updated>
		
		<summary type="html">&lt;p&gt;Aoineko: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Build tool]] option '''InstallRAMISR''' is used mainly to automatically select RAM in page 0 then copy data there at startup, so ROM cartridge can take advantage of (almost) 16 KB of additional RAM.&lt;br /&gt;
&lt;br /&gt;
This option requires MSX to have at least 64 KB of RAM (otherwise, no RAM will be available on page 0). So only some MSX1 may be compatible but all the MSX2, MSX2+ and MSX turbo R are.&lt;br /&gt;
&lt;br /&gt;
As page 0 (addresses 0x0000-0x3FFF) is the place where MSX will search for interruption handler (ISR), the build tool will automatically copy the selected ISR (see [[Build tool/CustomISR|CustomISR]] option).&lt;br /&gt;
&lt;br /&gt;
InstallRAMISR can also be used to install ISR in page 3 and activate Interrupt mode 2 (IM2) so the system will no longer access to page 0 during interrupt and user can switch page 0 content freely.&lt;br /&gt;
&lt;br /&gt;
InstallRAMISR can take those values:&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;RAMISR_NONE&amp;quot;&amp;lt;/tt&amp;gt;: Don't switch page 0 to RAM &lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;RAMISR_PAGE0&amp;quot;&amp;lt;/tt&amp;gt;: Switch page 0 to RAM then install ISR at 0x0038 (mandatory address)&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;RAMISR_SEGMENT0&amp;quot;&amp;lt;/tt&amp;gt;: Switch page 0 to RAM, install ISR at 0x0038 , then copy segment data at 0x0100 (for mapped-ROM)&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;RAMISR_PAGE3&amp;quot;&amp;lt;/tt&amp;gt;: Install ISR in RAM in page 3 and use interrupt mode 2 (IM2)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;Note&amp;lt;/u&amp;gt;: In the past, this option was a Boolean. We recommend changing its value to one of the above strings, but note that if you keep a Boolean value, the 'true' will be interpreted as &amp;lt;tt&amp;gt;&amp;quot;RAMISR_PAGE0&amp;quot;&amp;lt;/tt&amp;gt; and the 'false' as &amp;lt;tt&amp;gt;&amp;quot;RAMISR_NONE&amp;quot;&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== RAMISR_PAGE0 ==&lt;br /&gt;
When using &amp;lt;tt&amp;gt;RAMISR_PAGE0&amp;lt;/tt&amp;gt; option, you have additional RAM of be used from 0x0100 to 0x3FFF.&lt;br /&gt;
You can use SDCC's &amp;lt;tt&amp;gt;__at()&amp;lt;/tt&amp;gt; directive to place variables in the memory space.&lt;br /&gt;
&lt;br /&gt;
== RAMISR_SEGMENT0 ==&lt;br /&gt;
When using &amp;lt;tt&amp;gt;RAMISR_SEGMENT0 &amp;lt;/tt&amp;gt; option, you have to define a source code file named &amp;lt;tt&amp;gt;{projectName}_p0.c&amp;lt;/tt&amp;gt; (or &amp;lt;tt&amp;gt;.asm&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;.s&amp;lt;/tt&amp;gt; to add assembler source) and it will be automatically added to your mapper data and copy at statup in page 0.&lt;br /&gt;
Code and data from your &amp;lt;tt&amp;gt;_p0&amp;lt;/tt&amp;gt; file will be available starting from address 0x0100 (after the ISR) so you have a little less than 16 KB available in page 0 (16 KB - 0x100 = 16128 bytes).&lt;br /&gt;
&lt;br /&gt;
The 16 KB content of &amp;lt;tt&amp;gt;_p0&amp;lt;/tt&amp;gt; will be place in segment after the 32 KB of your main program. Segment number depend of the mapper format your are using:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Mapper !! Segments&lt;br /&gt;
|-&lt;br /&gt;
| ASCII-8 || #4 and #5&lt;br /&gt;
|-&lt;br /&gt;
| ASCII-16 || #2&lt;br /&gt;
|-&lt;br /&gt;
| KONAMI K4 || #4 and #5&lt;br /&gt;
|-&lt;br /&gt;
| KONAMI K5 (SCC) || #4 and #5&lt;br /&gt;
|-&lt;br /&gt;
| NEO-8 || #6 and #7&lt;br /&gt;
|-&lt;br /&gt;
| NEO-16 || #3&lt;br /&gt;
|-&lt;br /&gt;
| YAMANOOTO || #4 and #5&lt;br /&gt;
|-&lt;br /&gt;
| ASCII16-X || #2&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
When you use this option, these segments are reserved for code and data to be copied on page 0 and cannot be used for anything else.&lt;br /&gt;
&lt;br /&gt;
[[Samples#Software_Sprite|s_swsprt]] sample (software sprite) showcase the use of this option.&lt;br /&gt;
&lt;br /&gt;
== RAMISR_PAGE3 ==&lt;br /&gt;
When using &amp;lt;tt&amp;gt;RAMISR_PAGE3&amp;lt;/tt&amp;gt; option, the boot sequence install the interrupt handler in RAM, setup a vector table and activate Interrupt mode 2 (IM2) so that, when an interrupt occurs, only page 3 will be accessed.&lt;br /&gt;
&lt;br /&gt;
As page 0 is not used anymore by the system, the user can freely use it to have:&lt;br /&gt;
* A fixed chunk of 16 KB of ROM (for 48 KB plain-ROM),&lt;br /&gt;
* Freely switchable segments using [[NEO mapper]]:&lt;br /&gt;
** NEO-16: 1 bank of 16 KB (0x0000h~0x3FFF),&lt;br /&gt;
** NEO-8: 2 banks of 8 KB (0x0000~0x1FFF and 0x2000~0x3FFF).&lt;br /&gt;
* 16 KB of RAM (for MSX with at least 64 KB of RAM).&lt;br /&gt;
** For MSX computers equipped with a Memory mapper, you can freely change the segment displayed on page 0.&lt;br /&gt;
&lt;br /&gt;
This option can only be used with &amp;lt;tt&amp;gt;ForceRamAddr=0xC000&amp;lt;/tt&amp;gt; (or the default &amp;lt;tt&amp;gt;ForceRamAddr=0&amp;lt;/tt&amp;gt; as it is equivalent).&lt;br /&gt;
In this case, C variables will be accumulated starting from address 0xC1C4.&lt;br /&gt;
Thus, 452 bytes are used for the vector tables (257 bytes) and the ISR code itself.&lt;br /&gt;
&lt;br /&gt;
Note: As IM2 mode use Z80 register &amp;lt;tt&amp;gt;I&amp;lt;/tt&amp;gt; to know where to jump when an interrupt occurs, programmers that like to use &amp;lt;tt&amp;gt;RAMISR_PAGE3&amp;lt;/tt&amp;gt; option must not use inline assembler code that use this register.&lt;br /&gt;
&lt;br /&gt;
[[Samples#Graph_Mode_3|s_gm3]] sample (GM3 mode) showcase the use of this option.&lt;/div&gt;</summary>
		<author><name>Aoineko</name></author>	</entry>

	<entry>
		<id>https://aoineko.org/msxgl/index.php?title=Build_tool/InstallRAMISR&amp;diff=3996</id>
		<title>Build tool/InstallRAMISR</title>
		<link rel="alternate" type="text/html" href="https://aoineko.org/msxgl/index.php?title=Build_tool/InstallRAMISR&amp;diff=3996"/>
				<updated>2026-07-07T12:35:29Z</updated>
		
		<summary type="html">&lt;p&gt;Aoineko: /* RAMISR_PAGE3 */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Build tool]] option '''InstallRAMISR''' is used mainly to automatically select RAM in page 0 then copy data there at startup, so ROM cartridge can take advantage of (almost) 16 KB of additional RAM.&lt;br /&gt;
&lt;br /&gt;
This option requires MSX to have at least 64 KB of RAM (otherwise, no RAM will be available on page 0). So only some MSX1 may be compatible but all the MSX2, MSX2+ and MSX turbo R are.&lt;br /&gt;
&lt;br /&gt;
As page 0 (addresses 0x0000-0x3FFF) is the place where MSX will search for interruption handler (ISR), the build tool will automatically copy the selected ISR (see [[Build tool/CustomISR|CustomISR]] option).&lt;br /&gt;
&lt;br /&gt;
InstallRAMISR can also be used to install ISR in page 3 and activate Interrupt mode 2 (IM2) so the system will no longer access to page 0 during interrupt and user can switch page 0 content freely.&lt;br /&gt;
&lt;br /&gt;
InstallRAMISR can take those values:&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;RAMISR_NONE&amp;quot;&amp;lt;/tt&amp;gt;: Don't switch page 0 to RAM &lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;RAMISR_PAGE0&amp;quot;&amp;lt;/tt&amp;gt;: Switch page 0 to RAM then install ISR at 0x0038 (mandatory address)&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;RAMISR_SEGMENT0&amp;quot;&amp;lt;/tt&amp;gt;: Switch page 0 to RAM, install ISR at 0x0038 , then copy segment data at 0x0100 (for mapped-ROM)&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;RAMISR_PAGE3&amp;quot;&amp;lt;/tt&amp;gt;: Install ISR in RAM in page 3 and use interrupt mode 2 (IM2)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;Note&amp;lt;/u&amp;gt;: In the past, this option was a Boolean. We recommend changing its value to one of the above strings, but note that if you keep a Boolean value, the 'true' will be interpreted as &amp;lt;tt&amp;gt;&amp;quot;RAMISR_PAGE0&amp;quot;&amp;lt;/tt&amp;gt; and the 'false' as &amp;lt;tt&amp;gt;&amp;quot;RAMISR_NONE&amp;quot;&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== RAMISR_PAGE0 ==&lt;br /&gt;
When using &amp;lt;tt&amp;gt;RAMISR_PAGE0&amp;lt;/tt&amp;gt; option, you have additional RAM of be used from 0x0100 to 0x3FFF.&lt;br /&gt;
You can use SDCC's &amp;lt;tt&amp;gt;__at()&amp;lt;/tt&amp;gt; directive to place variables in the memory space.&lt;br /&gt;
&lt;br /&gt;
== RAMISR_SEGMENT0 ==&lt;br /&gt;
When using &amp;lt;tt&amp;gt;RAMISR_SEGMENT0 &amp;lt;/tt&amp;gt; option, you have to define a source code file named &amp;lt;tt&amp;gt;{projectName}_p0.c&amp;lt;/tt&amp;gt; (or &amp;lt;tt&amp;gt;.asm&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;.s&amp;lt;/tt&amp;gt; to add assembler source) and it will be automatically added to your mapper data and copy at statup in page 0.&lt;br /&gt;
Code and data from your &amp;lt;tt&amp;gt;_p0&amp;lt;/tt&amp;gt; file will be available starting from address 0x0100 (after the ISR) so you have a little less than 16 KB available in page 0 (16 KB - 0x100 = 16128 bytes).&lt;br /&gt;
&lt;br /&gt;
The 16 KB content of &amp;lt;tt&amp;gt;_p0&amp;lt;/tt&amp;gt; will be place in segment after the 32 KB of your main program. Segment number depend of the mapper format your are using:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Mapper !! Segments&lt;br /&gt;
|-&lt;br /&gt;
| ASCII-8 || #4 and #5&lt;br /&gt;
|-&lt;br /&gt;
| ASCII-16 || #2&lt;br /&gt;
|-&lt;br /&gt;
| KONAMI K4 || #4 and #5&lt;br /&gt;
|-&lt;br /&gt;
| KONAMI K5 (SCC) || #4 and #5&lt;br /&gt;
|-&lt;br /&gt;
| NEO-8 || #6 and #7&lt;br /&gt;
|-&lt;br /&gt;
| NEO-16 || #3&lt;br /&gt;
|-&lt;br /&gt;
| YAMANOOTO || #4 and #5&lt;br /&gt;
|-&lt;br /&gt;
| ASCII16-X || #2&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
When you use this option, these segments are reserved for code and data to be copied on page 0 and cannot be used for anything else.&lt;br /&gt;
&lt;br /&gt;
[[Samples#Software_Sprite|s_swsprt]] sample (software sprite) showcase the use of this option.&lt;br /&gt;
&lt;br /&gt;
== RAMISR_PAGE3 ==&lt;br /&gt;
When using &amp;lt;tt&amp;gt;RAMISR_PAGE3&amp;lt;/tt&amp;gt; option, the boot sequence install the interrupt handler in RAM, setup a vector table and activate Interrupt mode 2 (IM2) so that, when an interrupt occurs, only page 3 will be accessed.&lt;br /&gt;
&lt;br /&gt;
As page 0 is not used anymore by the system, the user can freely use it to have:&lt;br /&gt;
* A fixed chunk of 16 KB of ROM (for 48 KB plain-ROM),&lt;br /&gt;
* Freely switchable segments using [[NEO mapper]]:&lt;br /&gt;
** NEO-16: 1 bank of 16 KB (0x0000h~0x3FFF),&lt;br /&gt;
** NEO-8: 2 banks of 8 KB (0x0000~0x1FFF and 0x2000~0x3FFF).&lt;br /&gt;
* 16 KB of RAM (for MSX with at least 64 KB of RAM).&lt;br /&gt;
** For MSX computers equipped with a Memory mapper, you can freely change the segment displayed on page 0.&lt;br /&gt;
&lt;br /&gt;
This option can only be used with &amp;lt;tt&amp;gt;ForceRamAddr=0xC000&amp;lt;/tt&amp;gt; (or the default &amp;lt;tt&amp;gt;ForceRamAddr=0&amp;lt;/tt&amp;gt; as it is equivalent).&lt;br /&gt;
In this case, C variables will be accumulated starting from address 0xC1C4.&lt;br /&gt;
Thus, 452 bytes are used for the vector tables (257 bytes) and the ISR code itself.&lt;br /&gt;
&lt;br /&gt;
[[Samples#Graph_Mode_3|s_gm3]] sample (GM3 mode) showcase the use of this option.&lt;/div&gt;</summary>
		<author><name>Aoineko</name></author>	</entry>

	<entry>
		<id>https://aoineko.org/msxgl/index.php?title=NEO_mapper&amp;diff=3995</id>
		<title>NEO mapper</title>
		<link rel="alternate" type="text/html" href="https://aoineko.org/msxgl/index.php?title=NEO_mapper&amp;diff=3995"/>
				<updated>2026-07-02T03:04:37Z</updated>
		
		<summary type="html">&lt;p&gt;Aoineko: /* MSXgl */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;div style=&amp;quot;float:right&amp;quot;&amp;gt;[[NEO mapper|EN]] | [[NEO mapper/JA|JA]]&amp;lt;/div&amp;gt;&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
== Specifications ==&lt;br /&gt;
&lt;br /&gt;
=== Principles ===&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
Like conventional mappers, the basic idea is to use data write signals to the cartridge to change mapper registers value and thus, 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 [[#Format|tables below]]).&lt;br /&gt;
Read accesses, however, work as normal accesses to the memory visible through the banks.&lt;br /&gt;
&lt;br /&gt;
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 cartridge in this new mapper format.&lt;br /&gt;
&lt;br /&gt;
Compared to conventional mappers, this proposal is based on two new main features:&lt;br /&gt;
* A 16-bit segment register,&lt;br /&gt;
* Banks covering page #0 of MSX memory space (address 0000h~3FFFh).&lt;br /&gt;
&lt;br /&gt;
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).&lt;br /&gt;
&lt;br /&gt;
For the time being, we propose to reserve the 2 most significant bits of the 16-bit bank registers for future extensions of the format (such as SRAM or sound chips support for example).&lt;br /&gt;
This leaves 14 bits to select which segment is visible in each bank, for a maximum of 16384 segments.&lt;br /&gt;
The reserved bits, must be set to 0.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
!colspan=&amp;quot;8&amp;quot;| Higher byte&lt;br /&gt;
|&lt;br /&gt;
!colspan=&amp;quot;8&amp;quot;| Lower byte &lt;br /&gt;
|-&lt;br /&gt;
! 15 || 14 || 13 || 12 || 11 || 10 || 9 || 8 &lt;br /&gt;
|&lt;br /&gt;
! 7 || 6 || 5 || 4 || 3 || 2 || 1 || 0&lt;br /&gt;
|-&lt;br /&gt;
| 0 || 0&lt;br /&gt;
|colspan=&amp;quot;6&amp;quot;| Segment MSB&lt;br /&gt;
| &lt;br /&gt;
|colspan=&amp;quot;8&amp;quot;| Segment LSB &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The maximum ROM size is therefore 128 MB (for 8 KB segments) or 256 MB (for 16 KB segments).&lt;br /&gt;
&lt;br /&gt;
=== Write Access ===&lt;br /&gt;
&lt;br /&gt;
Write access to the mapper is use to change the value of the bank switching register (where you can select the ROM segment visible through a bank).&lt;br /&gt;
Bellow is the list of the predefined segment switching addresses.&lt;br /&gt;
&lt;br /&gt;
As this new mapper uses 16-bit segment switching registers, it uses 2 bytes for the segment number to be selected in each bank.&lt;br /&gt;
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.&lt;br /&gt;
This way, the segment number can be initialized at once with the [[#Bank switching cost|Z80 instructions for 16-bit memory write access]].&lt;br /&gt;
&lt;br /&gt;
==== NEO-8 mapper ====&lt;br /&gt;
&lt;br /&gt;
* Size of a segment: 8 KB&lt;br /&gt;
* Segment switching addresses:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Bank (8kB) !! Switching address !! Initial segment&lt;br /&gt;
|-&lt;br /&gt;
| 0: 0000h~1FFFh || 5000h (mirror at 1000h, 9000h and D000h) || 0000h&lt;br /&gt;
|-&lt;br /&gt;
| 1: 2000h~3FFFh || 5800h (mirror at 1800h, 9800h and D800h) || 0000h&lt;br /&gt;
|-&lt;br /&gt;
| 2: 4000h~5FFFh || 6000h (mirror at 2000h, A000h and E000h) || 0000h&lt;br /&gt;
|-&lt;br /&gt;
| 3: 6000h~7FFFh || 6800h (mirror at 2800h, A800h and E800h) || 0000h&lt;br /&gt;
|-&lt;br /&gt;
| 4: 8000h~9FFFh || 7000h (mirror at 3000h, B000h and F000h) || 0000h&lt;br /&gt;
|-&lt;br /&gt;
| 5: A000h~BFFFh || 7800h (mirror at 3800h, B800h and F800h) || 0000h&lt;br /&gt;
|}&lt;br /&gt;
* Maximum number of segments: 16384&lt;br /&gt;
* Maximum ROM size: 128 MB&lt;br /&gt;
&lt;br /&gt;
==== NEO-16 mapper ====&lt;br /&gt;
&lt;br /&gt;
* Size of a segment: 16 KB&lt;br /&gt;
* Segment switching addresses:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Bank (16kB) !! Switching address !! Initial segment&lt;br /&gt;
|-&lt;br /&gt;
| 0: 0000h~3FFFh || 5000h (mirror at 1000h, 9000h and D000h) || 0000h&lt;br /&gt;
|-&lt;br /&gt;
| 1: 4000h~7FFFh || 6000h (mirror at 2000h, A000h and E000h) || 0000h&lt;br /&gt;
|-&lt;br /&gt;
| 2: 8000h~BFFFh || 7000h (mirror at 3000h, B000h and F000h) || 0000h&lt;br /&gt;
|}&lt;br /&gt;
* Maximum number of segments: 16384&lt;br /&gt;
* Maximum ROM size: 256 MB&lt;br /&gt;
&lt;br /&gt;
=== Read Access ===&lt;br /&gt;
When mapper is selected, read accesses to memory pages 0, 1 and 2 (addresses 0000h to BFFFh), are redirected to a given ROM segment according to the value of the bank register corresponding to the address.&lt;br /&gt;
&lt;br /&gt;
For page 3, read accesses are invalid and the value returned is undefined and should not be used. Implementations of the NEO mapper should return the value FFh if page 3 is read, but this value is not guaranteed by the mapper specifications.&lt;br /&gt;
&lt;br /&gt;
=== Detection ===&lt;br /&gt;
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:&lt;br /&gt;
* &amp;quot;&amp;lt;tt&amp;gt;ROM_NEO8&amp;lt;/tt&amp;gt;&amp;quot; for NEO-8 mapper,&lt;br /&gt;
* &amp;quot;&amp;lt;tt&amp;gt;ROM_NE16&amp;lt;/tt&amp;gt;&amp;quot; for NEO-16 mapper.&lt;br /&gt;
&lt;br /&gt;
The ROM header (starting with &amp;quot;AB&amp;quot;) must be in the first ROM segment at offset 0.&lt;br /&gt;
The signature is therefore located at offset 16 of the ROM and may be visible to the Z80 on start-up at addresses 0010h, 4010h and 8010h.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;Note&amp;lt;/u&amp;gt;: Signature characters have been carefully choosed to prevent existing ROMs to generate false positive signature (See [[ROM type signature]]).&lt;br /&gt;
&lt;br /&gt;
== Support ==&lt;br /&gt;
&lt;br /&gt;
=== Hardware ===&lt;br /&gt;
Hardware supporting NEO mapper:&lt;br /&gt;
* '''[https://www.msxpico.com/ MSX Pico]''' (normal or WiFi): Support for NEO-8 and NEO-16 mappers up to ~15 MB (firmware 1.25 or above).&lt;br /&gt;
* '''[https://www.msxpico.com/ MSX Pico+]''': Support for NEO-8 and NEO-16 mappers up to ~14 MB (firmware 2.12 or above).&lt;br /&gt;
* '''[https://github.com/cristianoag/msx-picoverse-public PicoVerse] 2040 and 2350''': Support for NEO-8 and NEO-16 mappers up to ~15 MB.&lt;br /&gt;
* '''[https://github.com/arkadiuszmakarenko/RISKYMSX RISKY MSX]''': Support for NEO-8 and NEO-16 mappers up to 256 KB.&lt;br /&gt;
* '''[https://github.com/piigaa-densetu-two-dai/MSXpi MSXπ]''': Support for NEO-16 mappers up to 16 MB&lt;br /&gt;
* '''[https://github.com/piigaa-densetu-two-dai/MSXpi_plus_v2 MSXπ Plus (V2)]''': Support for NEO-16 mappers up to 16 MB&lt;br /&gt;
&lt;br /&gt;
=== Emulator ===&lt;br /&gt;
Emulators supporting NEO mapper:&lt;br /&gt;
* {{Emulicious}} '''Emulicious''': Full support for NEO-8 and NEO-16 mappers.&lt;br /&gt;
* {{MSXEC}} '''MSXEC''': Support NEO-8 and NEO-16 mappers up to 64 MB (version 20260303 or above).&lt;br /&gt;
* {{openMSX}} '''openMSX''': Full support for NEO-8 and NEO-16 mappers (version 20.0 or above).&lt;br /&gt;
* {{WebMSX}} '''WebMSX''': Full support for NEO-8 and NEO-16 mappers (version 6.0.7 or above).&lt;br /&gt;
&lt;br /&gt;
=== MSXgl ===&lt;br /&gt;
&lt;br /&gt;
Both NEO-8 and NEO-16 mappers are supported. Use respectively &amp;lt;tt&amp;gt;ROM_NEO8&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;ROM_NEO16&amp;lt;/tt&amp;gt; as [[target|target format]].&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
#define SET_BANK_SEGMENT(bank, segment) /* ... */&lt;br /&gt;
&lt;br /&gt;
// Make segment #30 visible through bank #1&lt;br /&gt;
SET_BANK_SEGMENT(1, 30);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
MSXgl initialize the banks with a unique segment each, to offer the largest possible space available to the user:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;img style=&amp;quot;width:400px; margin:0.5em;&amp;quot; src=&amp;quot;https://raw.githubusercontent.com/aoineko-fr/MSXgl/main/engine/doc/mapper_neo8.png&amp;quot; /&amp;gt;&lt;br /&gt;
&amp;lt;img style=&amp;quot;width:400px; margin:0.5em;&amp;quot; src=&amp;quot;https://raw.githubusercontent.com/aoineko-fr/MSXgl/main/engine/doc/mapper_neo16.png&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;Note&amp;lt;/u&amp;gt;: When the application start, segment at 0x4000 always point to segment 0 that include the ROM header. See [[Create a mapped ROM#NEO mapper]] for more details.&lt;br /&gt;
&lt;br /&gt;
== Appendix ==&lt;br /&gt;
&lt;br /&gt;
=== Segment switching address format ===&lt;br /&gt;
&lt;br /&gt;
From a software point of view, the segment switching address is defined as:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
!colspan=&amp;quot;17&amp;quot;| 16-bit address&lt;br /&gt;
|-&lt;br /&gt;
! 15 || 14 || 13 || 12 || 11 || 10 || 9 || 8 &lt;br /&gt;
|&lt;br /&gt;
! 7 || 6 || 5 || 4 || 3 || 2 || 1 || 0&lt;br /&gt;
|-&lt;br /&gt;
| P || P || B || B || B || x || x || x || || x || x || x || x || x || x || x || R&lt;br /&gt;
|}&lt;br /&gt;
Where:&lt;br /&gt;
* '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, but the mapper registers can only be accessed from selected pages.&lt;br /&gt;
* 'BBB' (0-7) is the bank's register to write in. All unspecified values are discarded.&lt;br /&gt;
:{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Bank !! NEO-8 !! NEO-16&lt;br /&gt;
|-&lt;br /&gt;
| 0 || 010 || 010&lt;br /&gt;
|-&lt;br /&gt;
| 1 || 011 || 100&lt;br /&gt;
|-&lt;br /&gt;
| 2 || 100 || 110&lt;br /&gt;
|-&lt;br /&gt;
| 3 || 101 || &lt;br /&gt;
|-&lt;br /&gt;
| 4 || 110 || &lt;br /&gt;
|-&lt;br /&gt;
| 5 || 111 || &lt;br /&gt;
|}&lt;br /&gt;
* 'R' (0-1) is the segment switching register's byte selector (0: less significant byte; 1: most significant byte).&lt;br /&gt;
* 'x' can be any value (generating mirroring).&lt;br /&gt;
&lt;br /&gt;
So, mirroring occurs on all addresses from the given switching address +2 to the switching address +7FEh on all even-numbered addresses. For example, 5000h is mirrored at 5002h~57FEh.&lt;br /&gt;
&lt;br /&gt;
=== Programmable processor and emulation ===&lt;br /&gt;
Here is a pseudo code in C to handle NEO mappers for programmable processor based cartridges or for emulators:&lt;br /&gt;
{|&lt;br /&gt;
|-&lt;br /&gt;
| NEO-8 mapper:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
const uint8* romData; // ROM data&lt;br /&gt;
uint16 bankValue[6]; // Bank switching register value&lt;br /&gt;
&lt;br /&gt;
// Handle device initialization&lt;br /&gt;
void NEO8_Init()&lt;br /&gt;
{&lt;br /&gt;
   for (uint8 i=0; i&amp;lt;6; i++)&lt;br /&gt;
      bankValue[i] = 0;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// Handle write access&lt;br /&gt;
void NEO8_Write(uint16 address, uint8 value)&lt;br /&gt;
{&lt;br /&gt;
   uint8 bank = ((address &amp;gt;&amp;gt; 11) &amp;amp; 0x07) - 2;&lt;br /&gt;
   if (bank &amp;gt; 5)&lt;br /&gt;
      return; // skip&lt;br /&gt;
   if (address &amp;amp; 1) // Set bank register MSB&lt;br /&gt;
      bankValue[bank] = ((value &amp;amp; 0x0F) &amp;lt;&amp;lt; 8) | (bankValue[bank] &amp;amp; 0x00FF);&lt;br /&gt;
   else // Set bank register LSB&lt;br /&gt;
      bankValue[bank] = (bankValue[bank] &amp;amp; 0xFF00) | (value);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// Handle read access&lt;br /&gt;
uint8 NEO8_Read(uint16 address)&lt;br /&gt;
{&lt;br /&gt;
   uint8 bank = address &amp;gt;&amp;gt; 13;&lt;br /&gt;
   if (bank &amp;gt; 5)&lt;br /&gt;
      return 0xFF; // skip&lt;br /&gt;
   return romData[(bankValue[bank]) &amp;lt;&amp;lt; 13 + (address &amp;amp; 0x1FFF)];&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
| NEO-16 mapper:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
const uint8* romData; // ROM data&lt;br /&gt;
uint16 bankValue[3]; // Bank switching register value&lt;br /&gt;
&lt;br /&gt;
// Handle device initialization&lt;br /&gt;
void NEO16_Init()&lt;br /&gt;
{&lt;br /&gt;
   bankValue[0] = bankValue[1] = bankValue[2] = 0;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// Handle write access&lt;br /&gt;
void NEO16_Write(uint16 address, uint8 value)&lt;br /&gt;
{&lt;br /&gt;
   uint8 bank = ((address &amp;gt;&amp;gt; 12) &amp;amp; 0x03) - 1;&lt;br /&gt;
   if (bank &amp;gt; 2)&lt;br /&gt;
      return; // skip&lt;br /&gt;
   if (address &amp;amp; 1) // Set bank register MSB&lt;br /&gt;
      bankValue[bank] = ((value &amp;amp; 0x0F) &amp;lt;&amp;lt; 8) | (bankValue[bank] &amp;amp; 0x00FF);&lt;br /&gt;
   else // Set bank register LSB&lt;br /&gt;
      bankValue[bank] = (bankValue[bank] &amp;amp; 0xFF00) | (value);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// Handle read access&lt;br /&gt;
uint8 NEO16_Read(uint16 address)&lt;br /&gt;
{&lt;br /&gt;
   uint8 bank = address &amp;gt;&amp;gt; 14;&lt;br /&gt;
   if (bank &amp;gt; 2)&lt;br /&gt;
      return 0xFF; // skip&lt;br /&gt;
   return romData[(bankValue[bank]) &amp;lt;&amp;lt; 14 + (address &amp;amp; 0x3FFF)];&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Sample program ===&lt;br /&gt;
A sample program is available for testing purpose on: https://aoineko.org/msx/targets/rom/&lt;br /&gt;
&lt;br /&gt;
It is available in various sizes:&lt;br /&gt;
* NEO-8: 256 KB to 32 MB&lt;br /&gt;
* NEO-16: 256 KB to 64 MB&lt;br /&gt;
&lt;br /&gt;
=== Bank switching cost ===&lt;br /&gt;
For a program using NEO mapper, 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.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;ini&amp;quot;&amp;gt;&lt;br /&gt;
; Direct access (22 t-states)&lt;br /&gt;
LD A,n      ;  8 t-states&lt;br /&gt;
LD (nn),A   ; 14 t-states&lt;br /&gt;
&lt;br /&gt;
; Indirect access (22 t-states)&lt;br /&gt;
LD HL,nn    ; 11 t-states&lt;br /&gt;
LD (HL),n   ; 11 t-states&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Although a program can avoid having to change the 2 bytes (16-bit) of the segment register at once, there are cases where this may be necessary. In such cases, the cost is higher, but remains reasonable.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;ini&amp;quot;&amp;gt;&lt;br /&gt;
; Direct access (28 t-states)&lt;br /&gt;
LD HL,nn    ; 11 t-states&lt;br /&gt;
LD (nn),HL  ; 17 t-states&lt;br /&gt;
&lt;br /&gt;
; Indirect access (40 t-states)&lt;br /&gt;
LD HL,nn    ; 11 t-states&lt;br /&gt;
LD (HL),n   ; 11 t-states&lt;br /&gt;
INC HL      ;  7 t-states&lt;br /&gt;
LD (HL),n   ; 11 t-states&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Logos ===&lt;br /&gt;
Here are the logos you can use to indicate that a product is compatible with the NEO mapper:&lt;br /&gt;
&lt;br /&gt;
[https://aoineko.org/msx/files/neomapper8b-logo.png &amp;lt;img style=&amp;quot;width:128px&amp;quot; src=&amp;quot;https://aoineko.org/msx/files/neomapper8b-logo.png&amp;quot; /&amp;gt;]&lt;br /&gt;
[https://aoineko.org/msx/files/neomapper8w-logo.png &amp;lt;img style=&amp;quot;width:128px&amp;quot; src=&amp;quot;https://aoineko.org/msx/files/neomapper8w-logo.png&amp;quot; /&amp;gt;]&lt;br /&gt;
[https://aoineko.org/msx/files/neomapper16b-logo.png &amp;lt;img style=&amp;quot;width:128px&amp;quot; src=&amp;quot;https://aoineko.org/msx/files/neomapper16b-logo.png&amp;quot; /&amp;gt;]&lt;br /&gt;
[https://aoineko.org/msx/files/neomapper16w-logo.png &amp;lt;img style=&amp;quot;width:128px&amp;quot; src=&amp;quot;https://aoineko.org/msx/files/neomapper16w-logo.png&amp;quot; /&amp;gt;]&lt;br /&gt;
&lt;br /&gt;
== Change log ==&lt;br /&gt;
* Version 1.0 (2024/02/12)&lt;br /&gt;
** Original version&lt;br /&gt;
* Version 1.1 (2024/02/20)&lt;br /&gt;
** Changed mappers signature to minimize the risk of an old cartridge generating a false positive and to comply to [[ROM type signature]] format.&lt;br /&gt;
** Added clarification on PP and BBB values for bank switching addresses.&lt;br /&gt;
** Added clarification for read access to the mapper and especially when try to read the page 3.&lt;br /&gt;
* Version 1.2 (2026/04/06)&lt;br /&gt;
** Added optional official logo for NEO mapper product.&lt;br /&gt;
** Added bits 12 and 13 to the register value, increasing the maximum number of segments from 4096 to 16384.&lt;br /&gt;
[[Category:Proposal]][[Category:Proposal/Mapper]]&lt;/div&gt;</summary>
		<author><name>Aoineko</name></author>	</entry>

	<entry>
		<id>https://aoineko.org/msxgl/index.php?title=Build_tool/InstallRAMISR&amp;diff=3994</id>
		<title>Build tool/InstallRAMISR</title>
		<link rel="alternate" type="text/html" href="https://aoineko.org/msxgl/index.php?title=Build_tool/InstallRAMISR&amp;diff=3994"/>
				<updated>2026-07-01T13:18:43Z</updated>
		
		<summary type="html">&lt;p&gt;Aoineko: /* RAMISR_SEGMENT0 */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Build tool]] option '''InstallRAMISR''' is used mainly to automatically select RAM in page 0 then copy data there at startup, so ROM cartridge can take advantage of (almost) 16 KB of additional RAM.&lt;br /&gt;
&lt;br /&gt;
This option requires MSX to have at least 64 KB of RAM (otherwise, no RAM will be available on page 0). So only some MSX1 may be compatible but all the MSX2, MSX2+ and MSX turbo R are.&lt;br /&gt;
&lt;br /&gt;
As page 0 (addresses 0x0000-0x3FFF) is the place where MSX will search for interruption handler (ISR), the build tool will automatically copy the selected ISR (see [[Build tool/CustomISR|CustomISR]] option).&lt;br /&gt;
&lt;br /&gt;
InstallRAMISR can also be used to install ISR in page 3 and activate Interrupt mode 2 (IM2) so the system will no longer access to page 0 during interrupt and user can switch page 0 content freely.&lt;br /&gt;
&lt;br /&gt;
InstallRAMISR can take those values:&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;RAMISR_NONE&amp;quot;&amp;lt;/tt&amp;gt;: Don't switch page 0 to RAM &lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;RAMISR_PAGE0&amp;quot;&amp;lt;/tt&amp;gt;: Switch page 0 to RAM then install ISR at 0x0038 (mandatory address)&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;RAMISR_SEGMENT0&amp;quot;&amp;lt;/tt&amp;gt;: Switch page 0 to RAM, install ISR at 0x0038 , then copy segment data at 0x0100 (for mapped-ROM)&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;RAMISR_PAGE3&amp;quot;&amp;lt;/tt&amp;gt;: Install ISR in RAM in page 3 and use interrupt mode 2 (IM2)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;Note&amp;lt;/u&amp;gt;: In the past, this option was a Boolean. We recommend changing its value to one of the above strings, but note that if you keep a Boolean value, the 'true' will be interpreted as &amp;lt;tt&amp;gt;&amp;quot;RAMISR_PAGE0&amp;quot;&amp;lt;/tt&amp;gt; and the 'false' as &amp;lt;tt&amp;gt;&amp;quot;RAMISR_NONE&amp;quot;&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== RAMISR_PAGE0 ==&lt;br /&gt;
When using &amp;lt;tt&amp;gt;RAMISR_PAGE0&amp;lt;/tt&amp;gt; option, you have additional RAM of be used from 0x0100 to 0x3FFF.&lt;br /&gt;
You can use SDCC's &amp;lt;tt&amp;gt;__at()&amp;lt;/tt&amp;gt; directive to place variables in the memory space.&lt;br /&gt;
&lt;br /&gt;
== RAMISR_SEGMENT0 ==&lt;br /&gt;
When using &amp;lt;tt&amp;gt;RAMISR_SEGMENT0 &amp;lt;/tt&amp;gt; option, you have to define a source code file named &amp;lt;tt&amp;gt;{projectName}_p0.c&amp;lt;/tt&amp;gt; (or &amp;lt;tt&amp;gt;.asm&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;.s&amp;lt;/tt&amp;gt; to add assembler source) and it will be automatically added to your mapper data and copy at statup in page 0.&lt;br /&gt;
Code and data from your &amp;lt;tt&amp;gt;_p0&amp;lt;/tt&amp;gt; file will be available starting from address 0x0100 (after the ISR) so you have a little less than 16 KB available in page 0 (16 KB - 0x100 = 16128 bytes).&lt;br /&gt;
&lt;br /&gt;
The 16 KB content of &amp;lt;tt&amp;gt;_p0&amp;lt;/tt&amp;gt; will be place in segment after the 32 KB of your main program. Segment number depend of the mapper format your are using:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Mapper !! Segments&lt;br /&gt;
|-&lt;br /&gt;
| ASCII-8 || #4 and #5&lt;br /&gt;
|-&lt;br /&gt;
| ASCII-16 || #2&lt;br /&gt;
|-&lt;br /&gt;
| KONAMI K4 || #4 and #5&lt;br /&gt;
|-&lt;br /&gt;
| KONAMI K5 (SCC) || #4 and #5&lt;br /&gt;
|-&lt;br /&gt;
| NEO-8 || #6 and #7&lt;br /&gt;
|-&lt;br /&gt;
| NEO-16 || #3&lt;br /&gt;
|-&lt;br /&gt;
| YAMANOOTO || #4 and #5&lt;br /&gt;
|-&lt;br /&gt;
| ASCII16-X || #2&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
When you use this option, these segments are reserved for code and data to be copied on page 0 and cannot be used for anything else.&lt;br /&gt;
&lt;br /&gt;
[[Samples#Software_Sprite|s_swsprt]] sample (software sprite) showcase the use of this option.&lt;br /&gt;
&lt;br /&gt;
== RAMISR_PAGE3 ==&lt;br /&gt;
When using &amp;lt;tt&amp;gt;RAMISR_PAGE3&amp;lt;/tt&amp;gt; option, the boot sequence activate Interrupt mode 2 (IM2) and setup a vector table so that, when an interrupt occurs, only page 3 will be accessed.&lt;br /&gt;
&lt;br /&gt;
As page 0 is not used anymore by the system, the user can freely use it to have:&lt;br /&gt;
* A fixed chunk of 16 KB of ROM (for 48 KB plain-ROM),&lt;br /&gt;
* Freely switchable segments using [[NEO mapper]]:&lt;br /&gt;
** NEO-16: 1 bank of 16 KB (0x0000h~0x3FFF),&lt;br /&gt;
** NEO-8: 2 banks of 8 KB (0x0000~0x1FFF and 0x2000~0x3FFF).&lt;br /&gt;
* 16 KB of RAM (for MSX with at least 64 KB of RAM).&lt;br /&gt;
** For MSX computers equipped with a Memory mapper, you can freely change the segment displayed on page 0.&lt;br /&gt;
&lt;br /&gt;
This option can only be used with &amp;lt;tt&amp;gt;ForceRamAddr=0xC000&amp;lt;/tt&amp;gt; (or &amp;lt;tt&amp;gt;ForceRamAddr=0&amp;lt;/tt&amp;gt; as it is equivalent).&lt;br /&gt;
In this case, C variables will be accumulated starting from address 0xC1C4.&lt;br /&gt;
Thus, 452 bytes are used for the vector tables (257 bytes) and the ISR code itself.&lt;br /&gt;
&lt;br /&gt;
[[Samples#Graph_Mode_3|s_gm3]] sample (GM3 mode) showcase the use of this option.&lt;/div&gt;</summary>
		<author><name>Aoineko</name></author>	</entry>

	<entry>
		<id>https://aoineko.org/msxgl/index.php?title=Build_tool/InstallRAMISR&amp;diff=3993</id>
		<title>Build tool/InstallRAMISR</title>
		<link rel="alternate" type="text/html" href="https://aoineko.org/msxgl/index.php?title=Build_tool/InstallRAMISR&amp;diff=3993"/>
				<updated>2026-07-01T13:16:22Z</updated>
		
		<summary type="html">&lt;p&gt;Aoineko: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Build tool]] option '''InstallRAMISR''' is used mainly to automatically select RAM in page 0 then copy data there at startup, so ROM cartridge can take advantage of (almost) 16 KB of additional RAM.&lt;br /&gt;
&lt;br /&gt;
This option requires MSX to have at least 64 KB of RAM (otherwise, no RAM will be available on page 0). So only some MSX1 may be compatible but all the MSX2, MSX2+ and MSX turbo R are.&lt;br /&gt;
&lt;br /&gt;
As page 0 (addresses 0x0000-0x3FFF) is the place where MSX will search for interruption handler (ISR), the build tool will automatically copy the selected ISR (see [[Build tool/CustomISR|CustomISR]] option).&lt;br /&gt;
&lt;br /&gt;
InstallRAMISR can also be used to install ISR in page 3 and activate Interrupt mode 2 (IM2) so the system will no longer access to page 0 during interrupt and user can switch page 0 content freely.&lt;br /&gt;
&lt;br /&gt;
InstallRAMISR can take those values:&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;RAMISR_NONE&amp;quot;&amp;lt;/tt&amp;gt;: Don't switch page 0 to RAM &lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;RAMISR_PAGE0&amp;quot;&amp;lt;/tt&amp;gt;: Switch page 0 to RAM then install ISR at 0x0038 (mandatory address)&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;RAMISR_SEGMENT0&amp;quot;&amp;lt;/tt&amp;gt;: Switch page 0 to RAM, install ISR at 0x0038 , then copy segment data at 0x0100 (for mapped-ROM)&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;RAMISR_PAGE3&amp;quot;&amp;lt;/tt&amp;gt;: Install ISR in RAM in page 3 and use interrupt mode 2 (IM2)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;Note&amp;lt;/u&amp;gt;: In the past, this option was a Boolean. We recommend changing its value to one of the above strings, but note that if you keep a Boolean value, the 'true' will be interpreted as &amp;lt;tt&amp;gt;&amp;quot;RAMISR_PAGE0&amp;quot;&amp;lt;/tt&amp;gt; and the 'false' as &amp;lt;tt&amp;gt;&amp;quot;RAMISR_NONE&amp;quot;&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== RAMISR_PAGE0 ==&lt;br /&gt;
When using &amp;lt;tt&amp;gt;RAMISR_PAGE0&amp;lt;/tt&amp;gt; option, you have additional RAM of be used from 0x0100 to 0x3FFF.&lt;br /&gt;
You can use SDCC's &amp;lt;tt&amp;gt;__at()&amp;lt;/tt&amp;gt; directive to place variables in the memory space.&lt;br /&gt;
&lt;br /&gt;
== RAMISR_SEGMENT0 ==&lt;br /&gt;
When using &amp;lt;tt&amp;gt;RAMISR_SEGMENT0 &amp;lt;/tt&amp;gt; option, you have to define a source code file named &amp;lt;tt&amp;gt;{projectName}_p0.c&amp;lt;/tt&amp;gt; (or &amp;lt;tt&amp;gt;.asm&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;.s&amp;lt;/tt&amp;gt; to add assembler source) and it will be automatically added to your mapper data and copy at statup in page 0.&lt;br /&gt;
Code and data from your &amp;lt;tt&amp;gt;_p0&amp;lt;/tt&amp;gt; file will be available starting from address 0x0100 (after the ISR) so you have a little less than 16 KB available in page 0 (16 KB - 0x100 = 16128 bytes).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;_p0&amp;lt;/tt&amp;gt; will be place in segment after the 32 KB of your main program. Segment number depend of the mapper format your are using:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Mapper !! Segments&lt;br /&gt;
|-&lt;br /&gt;
| ASCII-8 || #4 and #5&lt;br /&gt;
|-&lt;br /&gt;
| ASCII-16 || #2&lt;br /&gt;
|-&lt;br /&gt;
| KONAMI K4 || #4 and #5&lt;br /&gt;
|-&lt;br /&gt;
| KONAMI K5 (SCC) || #4 and #5&lt;br /&gt;
|-&lt;br /&gt;
| NEO-8 || #6 and #7&lt;br /&gt;
|-&lt;br /&gt;
| NEO-16 || #3&lt;br /&gt;
|-&lt;br /&gt;
| YAMANOOTO || #4 and #5&lt;br /&gt;
|-&lt;br /&gt;
| ASCII16-X || #2&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
When you use this option, these segments are reserved for code and data to be copied on page 0 and cannot be used for anything else.&lt;br /&gt;
&lt;br /&gt;
[[Samples#Software_Sprite|s_swsprt]] sample (software sprite) showcase the use of this option.&lt;br /&gt;
&lt;br /&gt;
== RAMISR_PAGE3 ==&lt;br /&gt;
When using &amp;lt;tt&amp;gt;RAMISR_PAGE3&amp;lt;/tt&amp;gt; option, the boot sequence activate Interrupt mode 2 (IM2) and setup a vector table so that, when an interrupt occurs, only page 3 will be accessed.&lt;br /&gt;
&lt;br /&gt;
As page 0 is not used anymore by the system, the user can freely use it to have:&lt;br /&gt;
* A fixed chunk of 16 KB of ROM (for 48 KB plain-ROM),&lt;br /&gt;
* Freely switchable segments using [[NEO mapper]]:&lt;br /&gt;
** NEO-16: 1 bank of 16 KB (0x0000h~0x3FFF),&lt;br /&gt;
** NEO-8: 2 banks of 8 KB (0x0000~0x1FFF and 0x2000~0x3FFF).&lt;br /&gt;
* 16 KB of RAM (for MSX with at least 64 KB of RAM).&lt;br /&gt;
** For MSX computers equipped with a Memory mapper, you can freely change the segment displayed on page 0.&lt;br /&gt;
&lt;br /&gt;
This option can only be used with &amp;lt;tt&amp;gt;ForceRamAddr=0xC000&amp;lt;/tt&amp;gt; (or &amp;lt;tt&amp;gt;ForceRamAddr=0&amp;lt;/tt&amp;gt; as it is equivalent).&lt;br /&gt;
In this case, C variables will be accumulated starting from address 0xC1C4.&lt;br /&gt;
Thus, 452 bytes are used for the vector tables (257 bytes) and the ISR code itself.&lt;br /&gt;
&lt;br /&gt;
[[Samples#Graph_Mode_3|s_gm3]] sample (GM3 mode) showcase the use of this option.&lt;/div&gt;</summary>
		<author><name>Aoineko</name></author>	</entry>

	<entry>
		<id>https://aoineko.org/msxgl/index.php?title=Build_tool/InstallRAMISR&amp;diff=3992</id>
		<title>Build tool/InstallRAMISR</title>
		<link rel="alternate" type="text/html" href="https://aoineko.org/msxgl/index.php?title=Build_tool/InstallRAMISR&amp;diff=3992"/>
				<updated>2026-07-01T13:15:14Z</updated>
		
		<summary type="html">&lt;p&gt;Aoineko: /* RAMISR_PAGE3 */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Build tool]] option '''InstallRAMISR''' is used mainly to automatically select RAM in page 0 then copy data there at startup, so ROM cartridge can take advantage of (almost) 16 KB of additional RAM.&lt;br /&gt;
&lt;br /&gt;
This option requires MSX to have at least 64 KB of RAM (otherwise, no RAM will be available on page 0). So only some MSX1 may be compatible but all the MSX2, MSX2+ and MSX turbo R are.&lt;br /&gt;
&lt;br /&gt;
As page 0 (addresses 0x0000-0x3FFF) is the place where MSX will search for interruption handler (ISR), the build tool will automatically copy the selected ISR (see [[Build tool/CustomISR|CustomISR]] option).&lt;br /&gt;
&lt;br /&gt;
InstallRAMISR can also be used to install ISR in page 3 and activate Interrupt mode 2 (IM2) so the system will no longer access to page 0 during interrupt and user can switch page 0 content freely.&lt;br /&gt;
&lt;br /&gt;
InstallRAMISR can take those values:&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;RAMISR_NONE&amp;quot;&amp;lt;/tt&amp;gt;: Don't switch page 0 to RAM &lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;RAMISR_PAGE0&amp;quot;&amp;lt;/tt&amp;gt;: Switch page 0 to RAM then install ISR at 0x0038 (mandatory address)&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;RAMISR_SEGMENT0&amp;quot;&amp;lt;/tt&amp;gt;: Switch page 0 to RAM, install ISR at 0x0038 , then copy segment data at 0x0100 (for mapped-ROM)&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;RAMISR_PAGE3&amp;quot;&amp;lt;/tt&amp;gt;: Install ISR in RAM in page 3 and use interrupt mode 2 (IM2)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;Note&amp;lt;/u&amp;gt;: In the past, this option was a Boolean. We recommend changing its value to one of the above strings, but note that if you keep a Boolean value, the 'true' will be interpreted as &amp;lt;tt&amp;gt;&amp;quot;RAMISR_PAGE0&amp;quot;&amp;lt;/tt&amp;gt; and the 'false' as &amp;lt;tt&amp;gt;&amp;quot;RAMISR_NONE&amp;quot;&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== RAMISR_PAGE0 ==&lt;br /&gt;
When using &amp;lt;tt&amp;gt;RAMISR_PAGE0&amp;lt;/tt&amp;gt; option, you have additional RAM of be used from 0x0100 to 0x3FFF.&lt;br /&gt;
You can use SDCC's &amp;lt;tt&amp;gt;__at()&amp;lt;/tt&amp;gt; directive to place variables in the memory space.&lt;br /&gt;
&lt;br /&gt;
== RAMISR_SEGMENT0 ==&lt;br /&gt;
When using &amp;lt;tt&amp;gt;RAMISR_SEGMENT0 &amp;lt;/tt&amp;gt; option, you have to define a source code file named &amp;lt;tt&amp;gt;{projectName}_p0.c&amp;lt;/tt&amp;gt; (or &amp;lt;tt&amp;gt;.asm&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;.s&amp;lt;/tt&amp;gt; to add assembler source) and it will be automatically added to your mapper data and copy at statup in page 0.&lt;br /&gt;
Code and data from your &amp;lt;tt&amp;gt;_p0&amp;lt;/tt&amp;gt; file will be available starting from address 0x0100 (after the ISR) so you have a little less than 16 KB available in page 0 (16 KB - 0x100 = 16128 bytes).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;_p0&amp;lt;/tt&amp;gt; will be place in segment after the 32 KB of your main program. Segment number depend of the mapper format your are using:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Mapper !! Segments&lt;br /&gt;
|-&lt;br /&gt;
| ASCII-8 || #4 and #5&lt;br /&gt;
|-&lt;br /&gt;
| ASCII-16 || #2&lt;br /&gt;
|-&lt;br /&gt;
| KONAMI K4 || #4 and #5&lt;br /&gt;
|-&lt;br /&gt;
| KONAMI K5 (SCC) || #4 and #5&lt;br /&gt;
|-&lt;br /&gt;
| NEO-8 || #6 and #7&lt;br /&gt;
|-&lt;br /&gt;
| NEO-16 || #3&lt;br /&gt;
|-&lt;br /&gt;
| YAMANOOTO || #4 and #5&lt;br /&gt;
|-&lt;br /&gt;
| ASCII16-X || #2&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
When you use this option, these segments are reserved for code and data to be copied on page 0 and cannot be used for anything else.&lt;br /&gt;
&lt;br /&gt;
[[Samples#Software_Sprite|s_swsprt]] sample (software sprite) showcase the use of this option.&lt;br /&gt;
&lt;br /&gt;
== RAMISR_PAGE3 ==&lt;br /&gt;
When using &amp;lt;tt&amp;gt;RAMISR_PAGE3&amp;lt;/tt&amp;gt; option, the boot sequence activate Interrupt mode 2 (IM2) and setup a vector table so that, when an interrupt occurs, only page 3 will be accessed.&lt;br /&gt;
&lt;br /&gt;
As page 0 is not used anymore by the system, the user can freely use it to have:&lt;br /&gt;
* A fixed chunk of 16 KB of ROM (for 48 KB plain-ROM),&lt;br /&gt;
* Freely switchable segments using [[NEO mapper]]:&lt;br /&gt;
** NEO-16: 1 bank of 16 KB (0x0000h~0x3FFF),&lt;br /&gt;
** NEO-8: 2 banks of 8 KB (0x0000~0x1FFF and 0x2000~0x3FFF).&lt;br /&gt;
* 16 KB of RAM (for MSX with at least 64 KB of RAM).&lt;br /&gt;
** For MSX computers equipped with a Memory mapper, you can freely change the segment displayed on page 0.&lt;br /&gt;
&lt;br /&gt;
This option can only be used with &amp;lt;tt&amp;gt;ForceRamAddr=0xC000&amp;lt;/tt&amp;gt; (or &amp;lt;tt&amp;gt;ForceRamAddr=0&amp;lt;/tt&amp;gt; as it is equivalent).&lt;br /&gt;
In this case, RAM variable will be accumulated starting to address 0xC1C4.&lt;br /&gt;
Thus, 452 bytes are used for the vector tables (257 bytes) and the ISR code itself.&lt;br /&gt;
&lt;br /&gt;
[[Samples#Graph_Mode_3|s_gm3]] sample (GM3 mode) showcase the use of this option.&lt;/div&gt;</summary>
		<author><name>Aoineko</name></author>	</entry>

	<entry>
		<id>https://aoineko.org/msxgl/index.php?title=Build_tool/InstallRAMISR&amp;diff=3991</id>
		<title>Build tool/InstallRAMISR</title>
		<link rel="alternate" type="text/html" href="https://aoineko.org/msxgl/index.php?title=Build_tool/InstallRAMISR&amp;diff=3991"/>
				<updated>2026-07-01T13:09:29Z</updated>
		
		<summary type="html">&lt;p&gt;Aoineko: /* RAMISR_PAGE3 */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Build tool]] option '''InstallRAMISR''' is used mainly to automatically select RAM in page 0 then copy data there at startup, so ROM cartridge can take advantage of (almost) 16 KB of additional RAM.&lt;br /&gt;
&lt;br /&gt;
This option requires MSX to have at least 64 KB of RAM (otherwise, no RAM will be available on page 0). So only some MSX1 may be compatible but all the MSX2, MSX2+ and MSX turbo R are.&lt;br /&gt;
&lt;br /&gt;
As page 0 (addresses 0x0000-0x3FFF) is the place where MSX will search for interruption handler (ISR), the build tool will automatically copy the selected ISR (see [[Build tool/CustomISR|CustomISR]] option).&lt;br /&gt;
&lt;br /&gt;
InstallRAMISR can also be used to install ISR in page 3 and activate Interrupt mode 2 (IM2) so the system will no longer access to page 0 during interrupt and user can switch page 0 content freely.&lt;br /&gt;
&lt;br /&gt;
InstallRAMISR can take those values:&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;RAMISR_NONE&amp;quot;&amp;lt;/tt&amp;gt;: Don't switch page 0 to RAM &lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;RAMISR_PAGE0&amp;quot;&amp;lt;/tt&amp;gt;: Switch page 0 to RAM then install ISR at 0x0038 (mandatory address)&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;RAMISR_SEGMENT0&amp;quot;&amp;lt;/tt&amp;gt;: Switch page 0 to RAM, install ISR at 0x0038 , then copy segment data at 0x0100 (for mapped-ROM)&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;RAMISR_PAGE3&amp;quot;&amp;lt;/tt&amp;gt;: Install ISR in RAM in page 3 and use interrupt mode 2 (IM2)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;Note&amp;lt;/u&amp;gt;: In the past, this option was a Boolean. We recommend changing its value to one of the above strings, but note that if you keep a Boolean value, the 'true' will be interpreted as &amp;lt;tt&amp;gt;&amp;quot;RAMISR_PAGE0&amp;quot;&amp;lt;/tt&amp;gt; and the 'false' as &amp;lt;tt&amp;gt;&amp;quot;RAMISR_NONE&amp;quot;&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== RAMISR_PAGE0 ==&lt;br /&gt;
When using &amp;lt;tt&amp;gt;RAMISR_PAGE0&amp;lt;/tt&amp;gt; option, you have additional RAM of be used from 0x0100 to 0x3FFF.&lt;br /&gt;
You can use SDCC's &amp;lt;tt&amp;gt;__at()&amp;lt;/tt&amp;gt; directive to place variables in the memory space.&lt;br /&gt;
&lt;br /&gt;
== RAMISR_SEGMENT0 ==&lt;br /&gt;
When using &amp;lt;tt&amp;gt;RAMISR_SEGMENT0 &amp;lt;/tt&amp;gt; option, you have to define a source code file named &amp;lt;tt&amp;gt;{projectName}_p0.c&amp;lt;/tt&amp;gt; (or &amp;lt;tt&amp;gt;.asm&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;.s&amp;lt;/tt&amp;gt; to add assembler source) and it will be automatically added to your mapper data and copy at statup in page 0.&lt;br /&gt;
Code and data from your &amp;lt;tt&amp;gt;_p0&amp;lt;/tt&amp;gt; file will be available starting from address 0x0100 (after the ISR) so you have a little less than 16 KB available in page 0 (16 KB - 0x100 = 16128 bytes).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;_p0&amp;lt;/tt&amp;gt; will be place in segment after the 32 KB of your main program. Segment number depend of the mapper format your are using:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Mapper !! Segments&lt;br /&gt;
|-&lt;br /&gt;
| ASCII-8 || #4 and #5&lt;br /&gt;
|-&lt;br /&gt;
| ASCII-16 || #2&lt;br /&gt;
|-&lt;br /&gt;
| KONAMI K4 || #4 and #5&lt;br /&gt;
|-&lt;br /&gt;
| KONAMI K5 (SCC) || #4 and #5&lt;br /&gt;
|-&lt;br /&gt;
| NEO-8 || #6 and #7&lt;br /&gt;
|-&lt;br /&gt;
| NEO-16 || #3&lt;br /&gt;
|-&lt;br /&gt;
| YAMANOOTO || #4 and #5&lt;br /&gt;
|-&lt;br /&gt;
| ASCII16-X || #2&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
When you use this option, these segments are reserved for code and data to be copied on page 0 and cannot be used for anything else.&lt;br /&gt;
&lt;br /&gt;
[[Samples#Software_Sprite|s_swsprt]] sample (software sprite) showcase the use of this option.&lt;br /&gt;
&lt;br /&gt;
== RAMISR_PAGE3 ==&lt;br /&gt;
When using &amp;lt;tt&amp;gt;RAMISR_PAGE3&amp;lt;/tt&amp;gt; option, the boot sequence activate Interrupt mode 2 (IM2) and setup a vector table so that, when an interrupt occurs, only page 3 will be accessed.&lt;br /&gt;
&lt;br /&gt;
As page 0 is not used anymore by the system, the user can freely use it to have:&lt;br /&gt;
* A fixed chunk of 16 KB of ROM (for 48 KB plain-ROM),&lt;br /&gt;
* Freely switchable segments using [[NEO mapper]]:&lt;br /&gt;
** NEO-16: 1 bank of 16 KB (0x0000h~0x3FFF),&lt;br /&gt;
** NEO-8: 2 banks of 8 KB (0x0000~0x1FFF and 0x2000~0x3FFF).&lt;br /&gt;
* 16 KB of RAM (for MSX with at least 64 KB of RAM).&lt;br /&gt;
** For MSX computers equipped with a Memory mapper, you can freely change the segment displayed on page 0.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Samples#Graph_Mode_3|s_gm3]] sample (GM3 mode) showcase the use of this option.&lt;/div&gt;</summary>
		<author><name>Aoineko</name></author>	</entry>

	<entry>
		<id>https://aoineko.org/msxgl/index.php?title=Build_tool/InstallRAMISR&amp;diff=3990</id>
		<title>Build tool/InstallRAMISR</title>
		<link rel="alternate" type="text/html" href="https://aoineko.org/msxgl/index.php?title=Build_tool/InstallRAMISR&amp;diff=3990"/>
				<updated>2026-07-01T13:08:59Z</updated>
		
		<summary type="html">&lt;p&gt;Aoineko: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Build tool]] option '''InstallRAMISR''' is used mainly to automatically select RAM in page 0 then copy data there at startup, so ROM cartridge can take advantage of (almost) 16 KB of additional RAM.&lt;br /&gt;
&lt;br /&gt;
This option requires MSX to have at least 64 KB of RAM (otherwise, no RAM will be available on page 0). So only some MSX1 may be compatible but all the MSX2, MSX2+ and MSX turbo R are.&lt;br /&gt;
&lt;br /&gt;
As page 0 (addresses 0x0000-0x3FFF) is the place where MSX will search for interruption handler (ISR), the build tool will automatically copy the selected ISR (see [[Build tool/CustomISR|CustomISR]] option).&lt;br /&gt;
&lt;br /&gt;
InstallRAMISR can also be used to install ISR in page 3 and activate Interrupt mode 2 (IM2) so the system will no longer access to page 0 during interrupt and user can switch page 0 content freely.&lt;br /&gt;
&lt;br /&gt;
InstallRAMISR can take those values:&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;RAMISR_NONE&amp;quot;&amp;lt;/tt&amp;gt;: Don't switch page 0 to RAM &lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;RAMISR_PAGE0&amp;quot;&amp;lt;/tt&amp;gt;: Switch page 0 to RAM then install ISR at 0x0038 (mandatory address)&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;RAMISR_SEGMENT0&amp;quot;&amp;lt;/tt&amp;gt;: Switch page 0 to RAM, install ISR at 0x0038 , then copy segment data at 0x0100 (for mapped-ROM)&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;RAMISR_PAGE3&amp;quot;&amp;lt;/tt&amp;gt;: Install ISR in RAM in page 3 and use interrupt mode 2 (IM2)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;Note&amp;lt;/u&amp;gt;: In the past, this option was a Boolean. We recommend changing its value to one of the above strings, but note that if you keep a Boolean value, the 'true' will be interpreted as &amp;lt;tt&amp;gt;&amp;quot;RAMISR_PAGE0&amp;quot;&amp;lt;/tt&amp;gt; and the 'false' as &amp;lt;tt&amp;gt;&amp;quot;RAMISR_NONE&amp;quot;&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== RAMISR_PAGE0 ==&lt;br /&gt;
When using &amp;lt;tt&amp;gt;RAMISR_PAGE0&amp;lt;/tt&amp;gt; option, you have additional RAM of be used from 0x0100 to 0x3FFF.&lt;br /&gt;
You can use SDCC's &amp;lt;tt&amp;gt;__at()&amp;lt;/tt&amp;gt; directive to place variables in the memory space.&lt;br /&gt;
&lt;br /&gt;
== RAMISR_SEGMENT0 ==&lt;br /&gt;
When using &amp;lt;tt&amp;gt;RAMISR_SEGMENT0 &amp;lt;/tt&amp;gt; option, you have to define a source code file named &amp;lt;tt&amp;gt;{projectName}_p0.c&amp;lt;/tt&amp;gt; (or &amp;lt;tt&amp;gt;.asm&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;.s&amp;lt;/tt&amp;gt; to add assembler source) and it will be automatically added to your mapper data and copy at statup in page 0.&lt;br /&gt;
Code and data from your &amp;lt;tt&amp;gt;_p0&amp;lt;/tt&amp;gt; file will be available starting from address 0x0100 (after the ISR) so you have a little less than 16 KB available in page 0 (16 KB - 0x100 = 16128 bytes).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;_p0&amp;lt;/tt&amp;gt; will be place in segment after the 32 KB of your main program. Segment number depend of the mapper format your are using:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Mapper !! Segments&lt;br /&gt;
|-&lt;br /&gt;
| ASCII-8 || #4 and #5&lt;br /&gt;
|-&lt;br /&gt;
| ASCII-16 || #2&lt;br /&gt;
|-&lt;br /&gt;
| KONAMI K4 || #4 and #5&lt;br /&gt;
|-&lt;br /&gt;
| KONAMI K5 (SCC) || #4 and #5&lt;br /&gt;
|-&lt;br /&gt;
| NEO-8 || #6 and #7&lt;br /&gt;
|-&lt;br /&gt;
| NEO-16 || #3&lt;br /&gt;
|-&lt;br /&gt;
| YAMANOOTO || #4 and #5&lt;br /&gt;
|-&lt;br /&gt;
| ASCII16-X || #2&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
When you use this option, these segments are reserved for code and data to be copied on page 0 and cannot be used for anything else.&lt;br /&gt;
&lt;br /&gt;
[[Samples#Software_Sprite|s_swsprt]] sample (software sprite) showcase the use of this option.&lt;br /&gt;
&lt;br /&gt;
== RAMISR_PAGE3 ==&lt;br /&gt;
When using &amp;lt;tt&amp;gt;RAMISR_PAGE3&amp;lt;/tt&amp;gt; option, the boot sequence activate Interrupt mode 2 (IM2) and setup a vector table so that, when an interrupt occurs, only page 3 will be accessed.&lt;br /&gt;
&lt;br /&gt;
As page 0 is not used anymore by the system, the user can freely use it to have:&lt;br /&gt;
* A fixed chunk of 16 KB of ROM (for 48 KB plain-ROM),&lt;br /&gt;
* Freely switchable segments using [[NEO mapper]]:&lt;br /&gt;
** NEO-16: 1 bank of 16 KB (0x0000h-0x3FFF),&lt;br /&gt;
** NEO-8: 2 banks of 8 KB (0x0000-0x1FFF and 0x2000-0x3FFF).&lt;br /&gt;
* 16 KB of RAM (for MSX with at least 64 KB of RAM).&lt;br /&gt;
** For MSX computers equipped with a Memory mapper, you can freely change the segment displayed on page 0.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Samples#Graph_Mode_3|s_gm3]] sample (GM3 mode) showcase the use of this option.&lt;/div&gt;</summary>
		<author><name>Aoineko</name></author>	</entry>

	<entry>
		<id>https://aoineko.org/msxgl/index.php?title=Build_tool/InstallRAMISR&amp;diff=3989</id>
		<title>Build tool/InstallRAMISR</title>
		<link rel="alternate" type="text/html" href="https://aoineko.org/msxgl/index.php?title=Build_tool/InstallRAMISR&amp;diff=3989"/>
				<updated>2026-07-01T13:08:02Z</updated>
		
		<summary type="html">&lt;p&gt;Aoineko: /* RAMISR_PAGE3 */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Build tool]] option '''InstallRAMISR''' is used mainly to automatically select RAM in page 0 then copy data there at startup, so ROM cartridge can take advantage of (almost) 16 KB of additional RAM.&lt;br /&gt;
&lt;br /&gt;
This option requires MSX to have at least 64 KB of RAM (otherwise, no RAM will be available on page 0). So only some MSX1 may be compatible but all the MSX2, MSX2+ and MSX turbo R are.&lt;br /&gt;
&lt;br /&gt;
As page 0 (addresses 0x0000-0x3FFF) is the place where MSX will search for interruption handler (ISR), the build tool will automatically copy the selected ISR (see [[Build tool/CustomISR|CustomISR]] option).&lt;br /&gt;
&lt;br /&gt;
InstallRAMISR can also be used to install ISR in page 3 and activate Interrupt mode 2 (IM2) so the system will no longer access to page 0 during interrupt and user can switch page 0 content freely.&lt;br /&gt;
&lt;br /&gt;
InstallRAMISR can take those values:&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;RAMISR_NONE&amp;quot;&amp;lt;/tt&amp;gt;: Don't switch page 0 to RAM &lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;RAMISR_PAGE0&amp;quot;&amp;lt;/tt&amp;gt;: Switch page 0 to RAM then install ISR at 0x0038 (mandatory address)&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;RAMISR_SEGMENT0&amp;quot;&amp;lt;/tt&amp;gt;: Switch page 0 to RAM, install ISR at 0x0038 , then copy segment data at 0x0100 (for mapped-ROM)&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;RAMISR_PAGE3&amp;quot;&amp;lt;/tt&amp;gt;: Install ISR in RAM in page 3 and use interrupt mode 2 (IM2)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;Note&amp;lt;/u&amp;gt;: In the past, this option was a Boolean. We recommend changing its value to one of the above strings, but note that if you keep a Boolean value, the 'true' will be interpreted as &amp;lt;tt&amp;gt;&amp;quot;RAMISR_PAGE0&amp;quot;&amp;lt;/tt&amp;gt; and the 'false' as &amp;lt;tt&amp;gt;&amp;quot;RAMISR_NONE&amp;quot;&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== RAMISR_PAGE0 ==&lt;br /&gt;
When using &amp;lt;tt&amp;gt;RAMISR_PAGE0&amp;lt;/tt&amp;gt; option, you have additional RAM of be used from 0x0100 to 0x3FFF.&lt;br /&gt;
You can use SDCC's &amp;lt;tt&amp;gt;__at()&amp;lt;/tt&amp;gt; directive to place variables in the memory space.&lt;br /&gt;
&lt;br /&gt;
== RAMISR_SEGMENT0 ==&lt;br /&gt;
When using &amp;lt;tt&amp;gt;RAMISR_SEGMENT0 &amp;lt;/tt&amp;gt; option, you have to define a source code file named &amp;lt;tt&amp;gt;{projectName}_p0.c&amp;lt;/tt&amp;gt; (or &amp;lt;tt&amp;gt;.asm&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;.s&amp;lt;/tt&amp;gt; to add assembler source) and it will be automatically added to your mapper data and copy at statup in page 0.&lt;br /&gt;
Code and data from your &amp;lt;tt&amp;gt;_p0&amp;lt;/tt&amp;gt; file will be available starting from address 0x0100 (after the ISR) so you have a little less than 16 KB available in page 0 (16 KB - 0x100 = 16128 bytes).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;_p0&amp;lt;/tt&amp;gt; will be place in segment after the 32 KB of your main program. Segment number depend of the mapper format your are using:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Mapper !! Segments&lt;br /&gt;
|-&lt;br /&gt;
| ASCII-8 || #4 and #5&lt;br /&gt;
|-&lt;br /&gt;
| ASCII-16 || #2&lt;br /&gt;
|-&lt;br /&gt;
| KONAMI K4 || #4 and #5&lt;br /&gt;
|-&lt;br /&gt;
| KONAMI K5 (SCC) || #4 and #5&lt;br /&gt;
|-&lt;br /&gt;
| NEO-8 || #6 and #7&lt;br /&gt;
|-&lt;br /&gt;
| NEO-16 || #3&lt;br /&gt;
|-&lt;br /&gt;
| YAMANOOTO || #4 and #5&lt;br /&gt;
|-&lt;br /&gt;
| ASCII16-X || #2&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
When you use this option, these segments are reserved for code and data to be copied on page 0 and cannot be used for anything else.&lt;br /&gt;
&lt;br /&gt;
[[Samples#Software_Sprite|s_swsprt]] sample (software sprite) showcase the use of this option.&lt;br /&gt;
&lt;br /&gt;
== RAMISR_PAGE3 ==&lt;br /&gt;
When using &amp;lt;tt&amp;gt;RAMISR_PAGE3&amp;lt;/tt&amp;gt; option, the boot sequence activate Interrupt mode 2 (IM2) and setup a vector table so that, when an interrupt occurs, only page 3 will be accessed.&lt;br /&gt;
&lt;br /&gt;
As page 0 is not used anymore by the system, the user can freely use it to have:&lt;br /&gt;
* A fixed chunk of 16 KB of ROM (for 48 KB plain-ROM),&lt;br /&gt;
* Freely switchable segments using [[NEO mapper]]:&lt;br /&gt;
** NEO-16: 1 bank of 16 KB (0000h-3FFFh),&lt;br /&gt;
** NEO-8: 2 banks of 8 KB (0000h-1FFFh and 2000h-3FFFh).&lt;br /&gt;
* 16 KB of RAM (for MSX with at least 64 KB of RAM).&lt;br /&gt;
** For MSX computers equipped with a Memory mapper, you can freely change the segment displayed on page 0.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Samples#Graph_Mode_3|s_gm3]] sample (GM3 mode) showcase the use of this option.&lt;/div&gt;</summary>
		<author><name>Aoineko</name></author>	</entry>

	<entry>
		<id>https://aoineko.org/msxgl/index.php?title=Build_tool/InstallRAMISR&amp;diff=3988</id>
		<title>Build tool/InstallRAMISR</title>
		<link rel="alternate" type="text/html" href="https://aoineko.org/msxgl/index.php?title=Build_tool/InstallRAMISR&amp;diff=3988"/>
				<updated>2026-07-01T13:05:02Z</updated>
		
		<summary type="html">&lt;p&gt;Aoineko: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Build tool]] option '''InstallRAMISR''' is used mainly to automatically select RAM in page 0 then copy data there at startup, so ROM cartridge can take advantage of (almost) 16 KB of additional RAM.&lt;br /&gt;
&lt;br /&gt;
This option requires MSX to have at least 64 KB of RAM (otherwise, no RAM will be available on page 0). So only some MSX1 may be compatible but all the MSX2, MSX2+ and MSX turbo R are.&lt;br /&gt;
&lt;br /&gt;
As page 0 (addresses 0x0000-0x3FFF) is the place where MSX will search for interruption handler (ISR), the build tool will automatically copy the selected ISR (see [[Build tool/CustomISR|CustomISR]] option).&lt;br /&gt;
&lt;br /&gt;
InstallRAMISR can also be used to install ISR in page 3 and activate Interrupt mode 2 (IM2) so the system will no longer access to page 0 during interrupt and user can switch page 0 content freely.&lt;br /&gt;
&lt;br /&gt;
InstallRAMISR can take those values:&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;RAMISR_NONE&amp;quot;&amp;lt;/tt&amp;gt;: Don't switch page 0 to RAM &lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;RAMISR_PAGE0&amp;quot;&amp;lt;/tt&amp;gt;: Switch page 0 to RAM then install ISR at 0x0038 (mandatory address)&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;RAMISR_SEGMENT0&amp;quot;&amp;lt;/tt&amp;gt;: Switch page 0 to RAM, install ISR at 0x0038 , then copy segment data at 0x0100 (for mapped-ROM)&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;RAMISR_PAGE3&amp;quot;&amp;lt;/tt&amp;gt;: Install ISR in RAM in page 3 and use interrupt mode 2 (IM2)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;Note&amp;lt;/u&amp;gt;: In the past, this option was a Boolean. We recommend changing its value to one of the above strings, but note that if you keep a Boolean value, the 'true' will be interpreted as &amp;lt;tt&amp;gt;&amp;quot;RAMISR_PAGE0&amp;quot;&amp;lt;/tt&amp;gt; and the 'false' as &amp;lt;tt&amp;gt;&amp;quot;RAMISR_NONE&amp;quot;&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== RAMISR_PAGE0 ==&lt;br /&gt;
When using &amp;lt;tt&amp;gt;RAMISR_PAGE0&amp;lt;/tt&amp;gt; option, you have additional RAM of be used from 0x0100 to 0x3FFF.&lt;br /&gt;
You can use SDCC's &amp;lt;tt&amp;gt;__at()&amp;lt;/tt&amp;gt; directive to place variables in the memory space.&lt;br /&gt;
&lt;br /&gt;
== RAMISR_SEGMENT0 ==&lt;br /&gt;
When using &amp;lt;tt&amp;gt;RAMISR_SEGMENT0 &amp;lt;/tt&amp;gt; option, you have to define a source code file named &amp;lt;tt&amp;gt;{projectName}_p0.c&amp;lt;/tt&amp;gt; (or &amp;lt;tt&amp;gt;.asm&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;.s&amp;lt;/tt&amp;gt; to add assembler source) and it will be automatically added to your mapper data and copy at statup in page 0.&lt;br /&gt;
Code and data from your &amp;lt;tt&amp;gt;_p0&amp;lt;/tt&amp;gt; file will be available starting from address 0x0100 (after the ISR) so you have a little less than 16 KB available in page 0 (16 KB - 0x100 = 16128 bytes).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;_p0&amp;lt;/tt&amp;gt; will be place in segment after the 32 KB of your main program. Segment number depend of the mapper format your are using:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Mapper !! Segments&lt;br /&gt;
|-&lt;br /&gt;
| ASCII-8 || #4 and #5&lt;br /&gt;
|-&lt;br /&gt;
| ASCII-16 || #2&lt;br /&gt;
|-&lt;br /&gt;
| KONAMI K4 || #4 and #5&lt;br /&gt;
|-&lt;br /&gt;
| KONAMI K5 (SCC) || #4 and #5&lt;br /&gt;
|-&lt;br /&gt;
| NEO-8 || #6 and #7&lt;br /&gt;
|-&lt;br /&gt;
| NEO-16 || #3&lt;br /&gt;
|-&lt;br /&gt;
| YAMANOOTO || #4 and #5&lt;br /&gt;
|-&lt;br /&gt;
| ASCII16-X || #2&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
When you use this option, these segments are reserved for code and data to be copied on page 0 and cannot be used for anything else.&lt;br /&gt;
&lt;br /&gt;
[[Samples#Software_Sprite|s_swsprt]] sample (software sprite) showcase the use of this option.&lt;br /&gt;
&lt;br /&gt;
== RAMISR_PAGE3 ==&lt;br /&gt;
When using &amp;lt;tt&amp;gt;RAMISR_PAGE3&amp;lt;/tt&amp;gt; option, the boot sequence activate Interrupt mode 2 (IM2) and setup a vector table so that, when an interrupt occurs, only page 3 will be accessed.&lt;br /&gt;
&lt;br /&gt;
As page 0 is not used by the system, the user can freely use it to have:&lt;br /&gt;
* A fixed section of 16 KB of ROM (for 48 KB plain-ROM),&lt;br /&gt;
* Switchable bank using [[NEO mapper]]&lt;br /&gt;
** NEO-16: 1 segment of 16 KB (bank 0: 0000h-3FFFh),&lt;br /&gt;
** NEO-8: 2 segments of 8 KB (bank 0: 0000h-1FFFh and bank 1: 2000h-3FFFh).&lt;br /&gt;
* 16 KB of RAM (for MSX with at least 64 KB of RAM).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Samples#Graph_Mode_3|s_gm3]] sample (GM3 mode) showcase the use of this option.&lt;/div&gt;</summary>
		<author><name>Aoineko</name></author>	</entry>

	<entry>
		<id>https://aoineko.org/msxgl/index.php?title=Build_tool/InstallRAMISR&amp;diff=3987</id>
		<title>Build tool/InstallRAMISR</title>
		<link rel="alternate" type="text/html" href="https://aoineko.org/msxgl/index.php?title=Build_tool/InstallRAMISR&amp;diff=3987"/>
				<updated>2026-07-01T13:01:24Z</updated>
		
		<summary type="html">&lt;p&gt;Aoineko: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Build tool]] option '''InstallRAMISR''' is used mainly to automatically select RAM in page 0 then copy data there at startup, so ROM cartridge can take advantage of (almost) 16 KB of additional RAM.&lt;br /&gt;
&lt;br /&gt;
This option requires MSX to have at least 64 KB of RAM (otherwise, no RAM will be available on page 0). So only some MSX1 may be compatible but all the MSX2, MSX2+ and MSX turbo R are.&lt;br /&gt;
&lt;br /&gt;
As page 0 (addresses 0x0000-0x3FFF) is the place where MSX will search for interruption handler (ISR), the build tool will automatically copy the selected ISR (see [[Build tool/CustomISR|CustomISR]] option).&lt;br /&gt;
&lt;br /&gt;
InstallRAMISR can also be used to install ISR in page 3 and activate Interrupt mode 2 (IM2) so the system will no longer access to page 0 during interrupt and user can switch page 0 content freely.&lt;br /&gt;
&lt;br /&gt;
InstallRAMISR can take those values:&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;RAMISR_NONE&amp;quot;&amp;lt;/tt&amp;gt;: Don't switch page 0 to RAM &lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;RAMISR_PAGE0&amp;quot;&amp;lt;/tt&amp;gt;: Switch page 0 to RAM then install ISR at 0x0038 (mandatory address)&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;RAMISR_SEGMENT0&amp;quot;&amp;lt;/tt&amp;gt;: Switch page 0 to RAM, install ISR at 0x0038 , then copy segment data at 0x0100 (for mapped-ROM)&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;RAMISR_PAGE3&amp;quot;&amp;lt;/tt&amp;gt;: Install ISR in RAM in page 3 and use interrupt mode 2 (IM2)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;Note&amp;lt;/u&amp;gt;: In the past, this option was a Boolean. We recommend changing its value to one of the above strings, but note that if you keep a Boolean value, the 'true' will be interpreted as &amp;lt;tt&amp;gt;&amp;quot;RAMISR_PAGE0&amp;quot;&amp;lt;/tt&amp;gt; and the 'false' as &amp;lt;tt&amp;gt;&amp;quot;RAMISR_NONE&amp;quot;&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== RAMISR_PAGE0 ==&lt;br /&gt;
When using &amp;lt;tt&amp;gt;RAMISR_PAGE0&amp;lt;/tt&amp;gt; option, you have additional RAM of be used from 0x0100 to 0x3FFF.&lt;br /&gt;
You can use SDCC's &amp;lt;tt&amp;gt;__at()&amp;lt;/tt&amp;gt; directive to place variables in the memory space.&lt;br /&gt;
&lt;br /&gt;
== RAMISR_SEGMENT0 ==&lt;br /&gt;
When using &amp;lt;tt&amp;gt;RAMISR_SEGMENT0 &amp;lt;/tt&amp;gt; option, you have to define a source code file named &amp;lt;tt&amp;gt;{projectName}_p0.c&amp;lt;/tt&amp;gt; (or &amp;lt;tt&amp;gt;.asm&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;.s&amp;lt;/tt&amp;gt; to add assembler source) and it will be automatically added to your mapper data and copy at statup in page 0.&lt;br /&gt;
Code and data from your &amp;lt;tt&amp;gt;_p0&amp;lt;/tt&amp;gt; file will be available starting from address 0x0100 (after the ISR) so you have a little less than 16 KB available in page 0 (16 KB - 0x100 = 16128 bytes).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;_p0&amp;lt;/tt&amp;gt; will be place in segment after the 32 KB of your main program. Segment number depend of the mapper format your are using:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Mapper !! Segments&lt;br /&gt;
|-&lt;br /&gt;
| ASCII-8 || #4 and #5&lt;br /&gt;
|-&lt;br /&gt;
| ASCII-16 || #2&lt;br /&gt;
|-&lt;br /&gt;
| KONAMI K4 || #4 and #5&lt;br /&gt;
|-&lt;br /&gt;
| KONAMI K5 (SCC) || #4 and #5&lt;br /&gt;
|-&lt;br /&gt;
| NEO-8 || #6 and #7&lt;br /&gt;
|-&lt;br /&gt;
| NEO-16 || #3&lt;br /&gt;
|-&lt;br /&gt;
| YAMANOOTO || #4 and #5&lt;br /&gt;
|-&lt;br /&gt;
| ASCII16-X || #2&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
When you use this option, these segments are reserved for code and data to be copied on page 0 and cannot be used for anything else.&lt;br /&gt;
&lt;br /&gt;
[[Samples#Software_Sprite|s_swsprt]] sample (software sprite) showcase the use of this option.&lt;br /&gt;
&lt;br /&gt;
== RAMISR_PAGE3 ==&lt;br /&gt;
When using &amp;lt;tt&amp;gt;RAMISR_PAGE3&amp;lt;/tt&amp;gt; option, page 0 is not used by the system and suer can use it freely to have:&lt;br /&gt;
* A fixed portion of ROM (for 48 KB plain-ROM),&lt;br /&gt;
* Switchable bank using [[NEO mapper]] (2 segments of 8 KB, or 1 segment of 16 KB),&lt;br /&gt;
* 16 KB of RAM (for MSX with at least 64 KB of RAM).&lt;br /&gt;
&lt;br /&gt;
Boot sequence activate Interrupt mode 2 (IM2) and setup a vector table so that, when an interrupt occurs, only page 3 will be accessed.&lt;br /&gt;
&lt;br /&gt;
[[Samples#Graph_Mode_3|s_gm3]] sample (GM3 mode) showcase the use of this option.&lt;/div&gt;</summary>
		<author><name>Aoineko</name></author>	</entry>

	<entry>
		<id>https://aoineko.org/msxgl/index.php?title=Build_tool/InstallRAMISR&amp;diff=3986</id>
		<title>Build tool/InstallRAMISR</title>
		<link rel="alternate" type="text/html" href="https://aoineko.org/msxgl/index.php?title=Build_tool/InstallRAMISR&amp;diff=3986"/>
				<updated>2026-07-01T13:00:03Z</updated>
		
		<summary type="html">&lt;p&gt;Aoineko: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Build tool]] option '''InstallRAMISR''' is used mainly to automatically select RAM in page 0 then copy data there at startup, so ROM cartridge can take advantage of (almost) 16 KB of additional RAM.&lt;br /&gt;
&lt;br /&gt;
This option requires MSX to have at least 64 KB of RAM (otherwise, no RAM will be available on page 0). So only some MSX1 may be compatible but all the MSX2, MSX2+ and MSX turbo R are.&lt;br /&gt;
&lt;br /&gt;
As page 0 (addresses 0x0000-0x3FFF) is the place where MSX will search for interruption handler (ISR), the build tool will automatically copy the selected ISR (see [[Build tool/CustomISR|CustomISR]] option).&lt;br /&gt;
&lt;br /&gt;
InstallRAMISR can also be used to install ISR in page 3 and activate Interrupt mode 2 (IM2) so the system will no longer access to page 0 during interrupt and user can switch page 0 content freely.&lt;br /&gt;
&lt;br /&gt;
InstallRAMISR can take those values:&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;RAMISR_NONE&amp;quot;&amp;lt;/tt&amp;gt;: Don't switch page 0 to RAM &lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;RAMISR_PAGE0&amp;quot;&amp;lt;/tt&amp;gt;: Switch page 0 to RAM then install ISR at 0x0038 (mandatory address)&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;RAMISR_SEGMENT0&amp;quot;&amp;lt;/tt&amp;gt;: Switch page 0 to RAM, install ISR at 0x0038 , then copy segment data at 0x0100 (for mapped-ROM)&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;RAMISR_PAGE3&amp;quot;&amp;lt;/tt&amp;gt;: Install ISR in RAM in page 3 and use interrupt mode 2 (IM2)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;Note&amp;lt;/u&amp;gt;: In the past, this option was a Boolean. We recommend changing its value to one of the above strings, but note that if you keep a Boolean value, the 'true' will be interpreted as &amp;lt;tt&amp;gt;&amp;quot;RAMISR_PAGE0&amp;quot;&amp;lt;/tt&amp;gt; and the 'false' as &amp;lt;tt&amp;gt;&amp;quot;RAMISR_NONE&amp;quot;&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== RAMISR_PAGE0 ==&lt;br /&gt;
When using &amp;lt;tt&amp;gt;RAMISR_PAGE0&amp;lt;/tt&amp;gt; option, you have additional RAM of be used from 0x0100 to 0x3FFF.&lt;br /&gt;
You can use SDCC's &amp;lt;tt&amp;gt;__at()&amp;lt;/tt&amp;gt; directive to place variables in the memory space.&lt;br /&gt;
&lt;br /&gt;
== RAMISR_SEGMENT0 ==&lt;br /&gt;
When using &amp;lt;tt&amp;gt;RAMISR_SEGMENT0 &amp;lt;/tt&amp;gt; option, you have to define a source code file named &amp;lt;tt&amp;gt;{projectName}_p0.c&amp;lt;/tt&amp;gt; (or &amp;lt;tt&amp;gt;.asm&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;.s&amp;lt;/tt&amp;gt; to add assembler source) and it will be automatically added to your mapper data and copy at statup in page 0.&lt;br /&gt;
Code and data from your &amp;lt;tt&amp;gt;_p0&amp;lt;/tt&amp;gt; file will be available starting from address 0x0100 (after the ISR) so you have a little less than 16 KB available in page 0 (16 KB - 0x100 = 16128 bytes).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;_p0&amp;lt;/tt&amp;gt; will be place in segment after the 32 KB of your main program. Segment number depend of the mapper format your are using:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Mapper !! Segments&lt;br /&gt;
|-&lt;br /&gt;
| ASCII-8 || #4 and #5&lt;br /&gt;
|-&lt;br /&gt;
| ASCII-16 || #2&lt;br /&gt;
|-&lt;br /&gt;
| KONAMI K4 || #4 and #5&lt;br /&gt;
|-&lt;br /&gt;
| KONAMI K5 (SCC) || #4 and #5&lt;br /&gt;
|-&lt;br /&gt;
| NEO-8 || #6 and #7&lt;br /&gt;
|-&lt;br /&gt;
| NEO-16 || #3&lt;br /&gt;
|-&lt;br /&gt;
| YAMANOOTO || #4 and #5&lt;br /&gt;
|-&lt;br /&gt;
| ASCII16-X || #2&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
When you use this option, these segments are reserved for code and data to be copied on page 0 and cannot be used for anything else.&lt;br /&gt;
&lt;br /&gt;
[[Samples#Software_Sprite|s_swsprt]] sample (software sprite) showcase the use of this option.&lt;br /&gt;
&lt;br /&gt;
== RAMISR_PAGE3 ==&lt;br /&gt;
When using &amp;lt;tt&amp;gt;RAMISR_PAGE3&amp;lt;/tt&amp;gt; option, page 0 is not used by the system and suer can use it freely to have:&lt;br /&gt;
* A fixed portion of ROM (for 48 KB plain-ROM),&lt;br /&gt;
* Switchable bank using [[NEO mapper]] (2 segments of 8 KB, or 1 segment of 16 KB),&lt;br /&gt;
* 16 KB of RAM (for MSX with at least 64 KB of RAM).&lt;br /&gt;
&lt;br /&gt;
Boot sequence activate Interrupt mode 2 (IM2) and setup a vector table so that, when an interrupt occurs, only page 3 will be accessed.&lt;/div&gt;</summary>
		<author><name>Aoineko</name></author>	</entry>

	<entry>
		<id>https://aoineko.org/msxgl/index.php?title=Build_tool/InstallRAMISR&amp;diff=3985</id>
		<title>Build tool/InstallRAMISR</title>
		<link rel="alternate" type="text/html" href="https://aoineko.org/msxgl/index.php?title=Build_tool/InstallRAMISR&amp;diff=3985"/>
				<updated>2026-07-01T12:57:54Z</updated>
		
		<summary type="html">&lt;p&gt;Aoineko: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Build tool]] option '''InstallRAMISR''' is used mainly to automatically select RAM in page 0 then copy data there at startup, so ROM cartridge can take advantage of (almost) 16 KB of additional RAM.&lt;br /&gt;
&lt;br /&gt;
This option requires MSX to have at least 64 KB of RAM (otherwise, no RAM will be available on page 0). So only some MSX1 may be compatible but all the MSX2, MSX2+ and MSX turbo R are.&lt;br /&gt;
&lt;br /&gt;
As page 0 (addresses 0x0000-0x3FFF) is the place where MSX will search for interruption handler (ISR), the build tool will automatically copy the selected ISR (see [[Build tool/CustomISR|CustomISR]] option).&lt;br /&gt;
&lt;br /&gt;
InstallRAMISR can also be used to install ISR in page 3 and activate Interrupt mode 2 (IM2) so the system will no longer access to page 0 during interrupt and user can switch page 0 content freely.&lt;br /&gt;
&lt;br /&gt;
InstallRAMISR can take those values:&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;RAMISR_NONE&amp;quot;&amp;lt;/tt&amp;gt;: Don't switch page 0 to RAM &lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;RAMISR_PAGE0&amp;quot;&amp;lt;/tt&amp;gt;: Switch page 0 to RAM then install ISR at 0x0038 (mandatory address)&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;RAMISR_SEGMENT0&amp;quot;&amp;lt;/tt&amp;gt;: Switch page 0 to RAM, install ISR at 0x0038 , then copy segment data at 0x0100 (for mapped-ROM)&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;RAMISR_PAGE3&amp;quot;&amp;lt;/tt&amp;gt;: Install ISR in RAM in page 3 and use interrupt mode 2 (IM2)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;Note&amp;lt;/u&amp;gt;: In the past, this option was a Boolean. We recommend changing its value to one of the above strings, but note that if you keep a Boolean value, the 'true' will be interpreted as &amp;lt;tt&amp;gt;&amp;quot;RAMISR_PAGE0&amp;quot;&amp;lt;/tt&amp;gt; and the 'false' as &amp;lt;tt&amp;gt;&amp;quot;RAMISR_NONE&amp;quot;&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== RAMISR_PAGE0 ==&lt;br /&gt;
When using &amp;lt;tt&amp;gt;RAMISR_PAGE0&amp;lt;/tt&amp;gt; option, you have additional RAM of be used from 0x0100 to 0x3FFF.&lt;br /&gt;
You can use SDCC's &amp;lt;tt&amp;gt;__at()&amp;lt;/tt&amp;gt; directive to place variables in the memory space.&lt;br /&gt;
&lt;br /&gt;
== RAMISR_SEGMENT0 ==&lt;br /&gt;
When using &amp;lt;tt&amp;gt;RAMISR_SEGMENT0 &amp;lt;/tt&amp;gt; option, you have to define a source code file named &amp;lt;tt&amp;gt;{projectName}_p0.c&amp;lt;/tt&amp;gt; (or &amp;lt;tt&amp;gt;.asm&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;.s&amp;lt;/tt&amp;gt; to add assembler source) and it will be automatically added to your mapper data and copy at statup in page 0.&lt;br /&gt;
Code and data from your &amp;lt;tt&amp;gt;_p0&amp;lt;/tt&amp;gt; file will be available starting from address 0x0100 (after the ISR) so you have a little less than 16 KB available in page 0 (16 KB - 0x100 = 16128 bytes).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;_p0&amp;lt;/tt&amp;gt; will be place in segment after the 32 KB of your main program. Segment number depend of the mapper format your are using:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Mapper !! Segments&lt;br /&gt;
|-&lt;br /&gt;
| ASCII-8 || #4 and #5&lt;br /&gt;
|-&lt;br /&gt;
| ASCII-16 || #2&lt;br /&gt;
|-&lt;br /&gt;
| KONAMI K4 || #4 and #5&lt;br /&gt;
|-&lt;br /&gt;
| KONAMI K5 (SCC) || #4 and #5&lt;br /&gt;
|-&lt;br /&gt;
| NEO-8 || #6 and #7&lt;br /&gt;
|-&lt;br /&gt;
| NEO-16 || #3&lt;br /&gt;
|-&lt;br /&gt;
| YAMANOOTO || #4 and #5&lt;br /&gt;
|-&lt;br /&gt;
| ASCII16-X || #2&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
When you use this option, these segments are reserved for code and data to be copied on page 0 and cannot be used for anything else.&lt;br /&gt;
&lt;br /&gt;
[[Samples#Software_Sprite|s_swsprt]] sample (software sprite) showcase the use of this option.&lt;br /&gt;
&lt;br /&gt;
== RAMISR_PAGE3 ==&lt;br /&gt;
When using &amp;lt;tt&amp;gt;RAMISR_PAGE3&amp;lt;/tt&amp;gt; option, page 0 is not used by the system and suer can use it freely to have:&lt;br /&gt;
* A fixed portion of ROM (for 48 KB plain-ROM),&lt;br /&gt;
* Switchable bank using [[NEO mapper]] (2 segments of 8 KB, or 1 segment of 16 KB),&lt;br /&gt;
* 16 KB of RAM (for MSX with at least 64 KB of RAM).&lt;/div&gt;</summary>
		<author><name>Aoineko</name></author>	</entry>

	<entry>
		<id>https://aoineko.org/msxgl/index.php?title=Build_tool/InstallRAMISR&amp;diff=3984</id>
		<title>Build tool/InstallRAMISR</title>
		<link rel="alternate" type="text/html" href="https://aoineko.org/msxgl/index.php?title=Build_tool/InstallRAMISR&amp;diff=3984"/>
				<updated>2026-07-01T12:57:27Z</updated>
		
		<summary type="html">&lt;p&gt;Aoineko: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Build tool]] option '''InstallRAMISR''' is used mainly to automatically select RAM in page 0 then copy data there at startup, so ROM cartridge can take advantage of (almost) 16 KB of additional RAM.&lt;br /&gt;
&lt;br /&gt;
This option requires MSX to have at least 64 KB of RAM (otherwise, no RAM will be available on page 0). So only some MSX1 may be compatible but all the MSX2, MSX2+ and MSX turbo R are.&lt;br /&gt;
&lt;br /&gt;
As page 0 (addresses 0x0000-0x3FFF) is the place where MSX will search for interruption handler (ISR), the build tool will automatically copy the selected ISR (see [[Build tool/CustomISR|CustomISR]] option).&lt;br /&gt;
&lt;br /&gt;
InstallRAMISR can also be used to install ISR in page 3 and activate Interrupt mode 2 (IM2) so the system will no longer access to page 0 during interrupt and user can switch page 0 content freely.&lt;br /&gt;
&lt;br /&gt;
InstallRAMISR can take those values:&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;RAMISR_NONE&amp;quot;&amp;lt;/tt&amp;gt;: Don't switch page 0 to RAM &lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;RAMISR_PAGE0&amp;quot;&amp;lt;/tt&amp;gt;: Switch page 0 to RAM then install ISR at 0x0038 (mandatory address)&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;RAMISR_SEGMENT0&amp;quot;&amp;lt;/tt&amp;gt;: Switch page 0 to RAM, install ISR at 0x0038 , then copy segment data at 0x0100 (for mapped-ROM)&lt;br /&gt;
* &amp;lt;tt&amp;gt;&amp;quot;RAMISR_PAGE3&amp;quot;&amp;lt;/tt&amp;gt;: Install ISR in RAM in page 3 and use interrupt mode 2 (IM2)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;Note&amp;lt;/u&amp;gt;: In the past, this option was a Boolean. We recommend changing its value to one of the above strings, but note that if you keep a Boolean value, the 'true' will be interpreted as &amp;lt;tt&amp;gt;&amp;quot;RAM0_ISR&amp;quot;&amp;lt;/tt&amp;gt; and the 'false' as &amp;lt;tt&amp;gt;&amp;quot;RAM0_NONE&amp;quot;&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== RAMISR_PAGE0 ==&lt;br /&gt;
When using &amp;lt;tt&amp;gt;RAMISR_PAGE0&amp;lt;/tt&amp;gt; option, you have additional RAM of be used from 0x0100 to 0x3FFF.&lt;br /&gt;
You can use SDCC's &amp;lt;tt&amp;gt;__at()&amp;lt;/tt&amp;gt; directive to place variables in the memory space.&lt;br /&gt;
&lt;br /&gt;
== RAMISR_SEGMENT0 ==&lt;br /&gt;
When using &amp;lt;tt&amp;gt;RAMISR_SEGMENT0 &amp;lt;/tt&amp;gt; option, you have to define a source code file named &amp;lt;tt&amp;gt;{projectName}_p0.c&amp;lt;/tt&amp;gt; (or &amp;lt;tt&amp;gt;.asm&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;.s&amp;lt;/tt&amp;gt; to add assembler source) and it will be automatically added to your mapper data and copy at statup in page 0.&lt;br /&gt;
Code and data from your &amp;lt;tt&amp;gt;_p0&amp;lt;/tt&amp;gt; file will be available starting from address 0x0100 (after the ISR) so you have a little less than 16 KB available in page 0 (16 KB - 0x100 = 16128 bytes).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;_p0&amp;lt;/tt&amp;gt; will be place in segment after the 32 KB of your main program. Segment number depend of the mapper format your are using:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Mapper !! Segments&lt;br /&gt;
|-&lt;br /&gt;
| ASCII-8 || #4 and #5&lt;br /&gt;
|-&lt;br /&gt;
| ASCII-16 || #2&lt;br /&gt;
|-&lt;br /&gt;
| KONAMI K4 || #4 and #5&lt;br /&gt;
|-&lt;br /&gt;
| KONAMI K5 (SCC) || #4 and #5&lt;br /&gt;
|-&lt;br /&gt;
| NEO-8 || #6 and #7&lt;br /&gt;
|-&lt;br /&gt;
| NEO-16 || #3&lt;br /&gt;
|-&lt;br /&gt;
| YAMANOOTO || #4 and #5&lt;br /&gt;
|-&lt;br /&gt;
| ASCII16-X || #2&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
When you use this option, these segments are reserved for code and data to be copied on page 0 and cannot be used for anything else.&lt;br /&gt;
&lt;br /&gt;
[[Samples#Software_Sprite|s_swsprt]] sample (software sprite) showcase the use of this option.&lt;br /&gt;
&lt;br /&gt;
== RAMISR_PAGE3 ==&lt;br /&gt;
When using &amp;lt;tt&amp;gt;RAMISR_PAGE3&amp;lt;/tt&amp;gt; option, page 0 is not used by the system and suer can use it freely to have:&lt;br /&gt;
* A fixed portion of ROM (for 48 KB plain-ROM),&lt;br /&gt;
* Switchable bank using [[NEO mapper]] (2 segments of 8 KB, or 1 segment of 16 KB),&lt;br /&gt;
* 16 KB of RAM (for MSX with at least 64 KB of RAM).&lt;/div&gt;</summary>
		<author><name>Aoineko</name></author>	</entry>

	<entry>
		<id>https://aoineko.org/msxgl/index.php?title=SDCC&amp;diff=3983</id>
		<title>SDCC</title>
		<link rel="alternate" type="text/html" href="https://aoineko.org/msxgl/index.php?title=SDCC&amp;diff=3983"/>
				<updated>2026-06-26T09:44:37Z</updated>
		
		<summary type="html">&lt;p&gt;Aoineko: /* SDCC 4.5.0 */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''[https://sdcc.sourceforge.net SDCC]''' is the toolchain used in {{MSXGL}} to compile, assemble and link the sources files.&lt;br /&gt;
&lt;br /&gt;
Supported version:&lt;br /&gt;
* Embedded: &amp;lt;tt&amp;gt;SDCC 4.6.0&amp;lt;/tt&amp;gt;&lt;br /&gt;
* Last tested: &amp;lt;tt&amp;gt;SDCC 4.6.0&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Assembler ==&lt;br /&gt;
&lt;br /&gt;
The assembler used by SDCC, '''[https://shop-pdp.net/ashtml/asmlnk.pdf sdasz80]''', is based on ASxxxx cross assembler (ASZ80).&lt;br /&gt;
&lt;br /&gt;
sdasz80 syntax is almost standard except for:&lt;br /&gt;
* Define instructions numeral values: must be prefixed with &amp;lt;tt&amp;gt;#&amp;lt;/tt&amp;gt; character.&lt;br /&gt;
* Define directive: must be prefix with &amp;lt;tt&amp;gt;.&amp;lt;/tt&amp;gt; character.&lt;br /&gt;
* Access to IX and IY register using offset: offset have to be write before the register name into parentheses.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Standard&lt;br /&gt;
! sdasz80&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;syntaxhighlight lang=&amp;quot;z80asm&amp;quot;&amp;gt;&lt;br /&gt;
; Numeral&lt;br /&gt;
ld      a, 100&lt;br /&gt;
and     01111100b&lt;br /&gt;
ld      hl, 1234h&lt;br /&gt;
&lt;br /&gt;
; Directive&lt;br /&gt;
db      100&lt;br /&gt;
dw      1234h&lt;br /&gt;
&lt;br /&gt;
; IX/IY offset&lt;br /&gt;
ld      e, iy[0]&lt;br /&gt;
ld      d, iy[1]&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
| &amp;lt;syntaxhighlight lang=&amp;quot;z80asm&amp;quot;&amp;gt;&lt;br /&gt;
; Numeral&lt;br /&gt;
ld      a, #100&lt;br /&gt;
and     #0b01111100&lt;br /&gt;
ld      hl, #0x1234&lt;br /&gt;
&lt;br /&gt;
; Directive&lt;br /&gt;
.db     100&lt;br /&gt;
.dw     0x1234&lt;br /&gt;
&lt;br /&gt;
; IX/IY offset&lt;br /&gt;
ld      e, 0(iy)&lt;br /&gt;
ld      d, 1(iy)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Versions ==&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;SDCC 4.2.0&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
* ⭐ '''Main features:'''&lt;br /&gt;
** New calling convention (use register to pass function parameters)&lt;br /&gt;
&lt;br /&gt;
* 🧾 '''Full change-log:'''&lt;br /&gt;
** C23 &amp;lt;tt&amp;gt;memset_explicit&amp;lt;/tt&amp;gt;&lt;br /&gt;
** Support for &amp;lt;tt&amp;gt;--oldralloc&amp;lt;/tt&amp;gt; has been removed from the z80 backends.&lt;br /&gt;
** Full support for &amp;lt;tt&amp;gt;__z88dk_callee&amp;lt;/tt&amp;gt; for the z80 backends.&lt;br /&gt;
** Support for a new &amp;lt;tt&amp;gt;__sdcccall(1)&amp;lt;/tt&amp;gt; calling convention in the z80 AS NEW DEFAULT.&lt;br /&gt;
** Removed support for &amp;lt;tt&amp;gt;--profile&amp;lt;/tt&amp;gt; for z80 backends.&lt;br /&gt;
** The z80n port Z80N Core minimum version has been raised from 1.0 to 2.0.&lt;br /&gt;
** Improved rematerialization support in the z80 backends.&lt;br /&gt;
&lt;br /&gt;
* ⚠️ '''Known issues:'''&lt;br /&gt;
** None&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;SDCC 4.3.0&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
* ⭐ '''Main features:'''&lt;br /&gt;
** Support for undocumented Z80 instructions&lt;br /&gt;
&lt;br /&gt;
* 🧾 '''Full change-log:'''&lt;br /&gt;
** Added all new general mnemonics from ASxxxx 5.40 except for .bank and enabled for all ports&lt;br /&gt;
** sm83: sdasgb now can output cycles in listing and sz80 has accurate cycles for this processor except for branching&lt;br /&gt;
** struct / union parameters and return.&lt;br /&gt;
** div standard library function family.&lt;br /&gt;
** Many fixes for the type system and _Generic.&lt;br /&gt;
** Adopted more of GCC, QuickC and tinycc tests.&lt;br /&gt;
** C2X bit-precise integer types and bit-fields thereof for. C2X nullptr, char8_t, memalignment, unreachable, typeof, typeof_unqual, auto. C2X keywords bool, true, false, alignas, alignof, static_assert. C2X bit and byte utilities.&lt;br /&gt;
** C90-C17 function declarators without prototypes.&lt;br /&gt;
** C99 variably modified types.&lt;br /&gt;
** &amp;lt;tt&amp;gt;call_once&amp;lt;/tt&amp;gt;.&lt;br /&gt;
** &amp;lt;tt&amp;gt;_sdcc_external_startup&amp;lt;/tt&amp;gt; renamed to &amp;lt;tt&amp;gt;__sdcc_external_startup&amp;lt;/tt&amp;gt; and supported for all ports.&lt;br /&gt;
** makeshift support for long double as another alias for float.&lt;br /&gt;
&lt;br /&gt;
* ⚠️ '''Known issues:'''&lt;br /&gt;
** Most of the projects can increase significantly in final size.&lt;br /&gt;
** Bug with undocumented Z80 instructions generation that can generate compilation errors.&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;SDCC 4.4.0&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
* ⭐ '''Main features:'''&lt;br /&gt;
** Native support for ASCII R800, the MSX turbo R's CPU.&lt;br /&gt;
&lt;br /&gt;
* 🧾 '''Full change-log:'''&lt;br /&gt;
** Optimizations for rotations.&lt;br /&gt;
** Generalized constant propagation.&lt;br /&gt;
** New command line option &amp;lt;tt&amp;gt;--syntax-only&amp;lt;/tt&amp;gt; to only parse the input.&lt;br /&gt;
** Added C99 header &amp;lt;tt&amp;gt;inttypes.h&amp;lt;/tt&amp;gt;&lt;br /&gt;
** Added library functions imaxabs, imaxdiv, llabs, strtoimax, strtoll, strtoull, strtoumax, wcsncmp, wcstoimax, wcstol, wcstoll, wcstoul, wcstoull, wcstoumax&lt;br /&gt;
** New r800 port to better support the ASCII Corp R800 and Zilog Z280.&lt;br /&gt;
** Improved optimizations for code speed for stm8, pdk, z80 (and related).&lt;br /&gt;
&lt;br /&gt;
* ⚠️ '''Known issues:'''&lt;br /&gt;
** On Windows, win32 version just doesn't works and win64 is... absent. You can use [https://sourceforge.net/projects/sdcc/files/sdcc-win64/4.4.0/ win64 version of &amp;lt;tt&amp;gt;SDCC 4.4.0 RC3&amp;lt;/tt&amp;gt;] (same content than the official release).&lt;br /&gt;
** Some projects can increase significantly in final size.&lt;br /&gt;
** Some projects are broken when compiled with SDCC 4.4.0 (''Clock'' sample and ''Phenix Corrupta'' project).&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;SDCC 4.5.0&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
* ⭐ '''Main features:'''&lt;br /&gt;
** C feature improvement&lt;br /&gt;
** A big gain in final program size (often better than SDCC 4.2).&amp;lt;br/&amp;gt;&amp;lt;u&amp;gt;Note:&amp;lt;/u&amp;gt; It has not yet been confirmed whether this gain in size will be reflected (for better or worse) in performance.&lt;br /&gt;
&lt;br /&gt;
* 🧾 '''Full change-log:'''&lt;br /&gt;
** ISO C2y case range expressions&lt;br /&gt;
** ISO C2y _Generic selection expression with a type operand&lt;br /&gt;
** K&amp;amp;R-style function syntax (preliminarily with the semantics of non-K&amp;amp;R ISO-style functions)&lt;br /&gt;
** ISO C23 enums with user-specified underlying type&lt;br /&gt;
** struct / union in initializers&lt;br /&gt;
&lt;br /&gt;
* ⚠️ '''Known issues:'''&lt;br /&gt;
** Major code generation [https://sourceforge.net/p/sdcc/bugs/3834/ bug] in specific condition&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;SDCC 4.6.0&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
Currently recommended version for MSXgl.&lt;br /&gt;
&lt;br /&gt;
* ⭐ '''Main features:'''&lt;br /&gt;
** C feature improvement&lt;br /&gt;
** A big gain in final program size (often better than SDCC 4.2).&amp;lt;br/&amp;gt;&amp;lt;u&amp;gt;Note:&amp;lt;/u&amp;gt; It has not yet been confirmed whether this gain in size will be reflected (for better or worse) in performance.&lt;br /&gt;
&lt;br /&gt;
* 🧾 '''Full change-log:'''&lt;br /&gt;
** Support for Dynamic C calling convention&lt;br /&gt;
** Substantially improved code generation&lt;br /&gt;
** C99 compound literals&lt;br /&gt;
** realloc(ptr, 0) now follows C99 semantics instead of C90 semantics&lt;br /&gt;
** C23 compound literals with storage class specifiers&lt;br /&gt;
** C23 constexpr (mostly)&lt;br /&gt;
** C23 va_start and variadic functions&lt;br /&gt;
** C2y _Countof operator&lt;br /&gt;
** C2y octal&lt;br /&gt;
** C2y if-declaration&lt;br /&gt;
** C2y Conditional operator with omitted second operand (originally a GNU extension)&lt;br /&gt;
** C2y signed bit-precise integer type of width 1&lt;br /&gt;
** C2y bit-precise integer types as fixed underlying type for enum&lt;br /&gt;
** C2y umaxabs&lt;br /&gt;
** C2y bit utilities&lt;br /&gt;
** C2y functions uabs, ulabs, ullabs&lt;br /&gt;
** C2y containerof macro&lt;br /&gt;
** Improved diagnostics on invalid C2y (some of which was UB up to C23)&lt;br /&gt;
** Diagnostics based on [static assignment-expression] array parameter syntax&lt;br /&gt;
** Warnings for array parameters where accesses fall outside the bounds&lt;br /&gt;
** Basic parameter forward declarations (GNU extension)&lt;br /&gt;
** _Optional qualifier&lt;br /&gt;
** Plain int bit-fields are signed&lt;br /&gt;
** strsep&lt;br /&gt;
&lt;br /&gt;
* ⚠️ '''Known issues:'''&lt;br /&gt;
** None&lt;br /&gt;
&lt;br /&gt;
== Links ==&lt;br /&gt;
&lt;br /&gt;
For more information:&lt;br /&gt;
* [https://sdcc.sourceforge.net/ SDCC homepage]&lt;br /&gt;
* [https://sdcc.sourceforge.net/doc/sdccman.pdf SDCC documentation]&lt;br /&gt;
* [https://shop-pdp.net/ashtml/asmlnk.pdf ASxxxx documentation]&lt;/div&gt;</summary>
		<author><name>Aoineko</name></author>	</entry>

	<entry>
		<id>https://aoineko.org/msxgl/index.php?title=SDCC&amp;diff=3982</id>
		<title>SDCC</title>
		<link rel="alternate" type="text/html" href="https://aoineko.org/msxgl/index.php?title=SDCC&amp;diff=3982"/>
				<updated>2026-06-26T09:44:23Z</updated>
		
		<summary type="html">&lt;p&gt;Aoineko: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''[https://sdcc.sourceforge.net SDCC]''' is the toolchain used in {{MSXGL}} to compile, assemble and link the sources files.&lt;br /&gt;
&lt;br /&gt;
Supported version:&lt;br /&gt;
* Embedded: &amp;lt;tt&amp;gt;SDCC 4.6.0&amp;lt;/tt&amp;gt;&lt;br /&gt;
* Last tested: &amp;lt;tt&amp;gt;SDCC 4.6.0&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Assembler ==&lt;br /&gt;
&lt;br /&gt;
The assembler used by SDCC, '''[https://shop-pdp.net/ashtml/asmlnk.pdf sdasz80]''', is based on ASxxxx cross assembler (ASZ80).&lt;br /&gt;
&lt;br /&gt;
sdasz80 syntax is almost standard except for:&lt;br /&gt;
* Define instructions numeral values: must be prefixed with &amp;lt;tt&amp;gt;#&amp;lt;/tt&amp;gt; character.&lt;br /&gt;
* Define directive: must be prefix with &amp;lt;tt&amp;gt;.&amp;lt;/tt&amp;gt; character.&lt;br /&gt;
* Access to IX and IY register using offset: offset have to be write before the register name into parentheses.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Standard&lt;br /&gt;
! sdasz80&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;syntaxhighlight lang=&amp;quot;z80asm&amp;quot;&amp;gt;&lt;br /&gt;
; Numeral&lt;br /&gt;
ld      a, 100&lt;br /&gt;
and     01111100b&lt;br /&gt;
ld      hl, 1234h&lt;br /&gt;
&lt;br /&gt;
; Directive&lt;br /&gt;
db      100&lt;br /&gt;
dw      1234h&lt;br /&gt;
&lt;br /&gt;
; IX/IY offset&lt;br /&gt;
ld      e, iy[0]&lt;br /&gt;
ld      d, iy[1]&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
| &amp;lt;syntaxhighlight lang=&amp;quot;z80asm&amp;quot;&amp;gt;&lt;br /&gt;
; Numeral&lt;br /&gt;
ld      a, #100&lt;br /&gt;
and     #0b01111100&lt;br /&gt;
ld      hl, #0x1234&lt;br /&gt;
&lt;br /&gt;
; Directive&lt;br /&gt;
.db     100&lt;br /&gt;
.dw     0x1234&lt;br /&gt;
&lt;br /&gt;
; IX/IY offset&lt;br /&gt;
ld      e, 0(iy)&lt;br /&gt;
ld      d, 1(iy)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Versions ==&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;SDCC 4.2.0&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
* ⭐ '''Main features:'''&lt;br /&gt;
** New calling convention (use register to pass function parameters)&lt;br /&gt;
&lt;br /&gt;
* 🧾 '''Full change-log:'''&lt;br /&gt;
** C23 &amp;lt;tt&amp;gt;memset_explicit&amp;lt;/tt&amp;gt;&lt;br /&gt;
** Support for &amp;lt;tt&amp;gt;--oldralloc&amp;lt;/tt&amp;gt; has been removed from the z80 backends.&lt;br /&gt;
** Full support for &amp;lt;tt&amp;gt;__z88dk_callee&amp;lt;/tt&amp;gt; for the z80 backends.&lt;br /&gt;
** Support for a new &amp;lt;tt&amp;gt;__sdcccall(1)&amp;lt;/tt&amp;gt; calling convention in the z80 AS NEW DEFAULT.&lt;br /&gt;
** Removed support for &amp;lt;tt&amp;gt;--profile&amp;lt;/tt&amp;gt; for z80 backends.&lt;br /&gt;
** The z80n port Z80N Core minimum version has been raised from 1.0 to 2.0.&lt;br /&gt;
** Improved rematerialization support in the z80 backends.&lt;br /&gt;
&lt;br /&gt;
* ⚠️ '''Known issues:'''&lt;br /&gt;
** None&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;SDCC 4.3.0&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
* ⭐ '''Main features:'''&lt;br /&gt;
** Support for undocumented Z80 instructions&lt;br /&gt;
&lt;br /&gt;
* 🧾 '''Full change-log:'''&lt;br /&gt;
** Added all new general mnemonics from ASxxxx 5.40 except for .bank and enabled for all ports&lt;br /&gt;
** sm83: sdasgb now can output cycles in listing and sz80 has accurate cycles for this processor except for branching&lt;br /&gt;
** struct / union parameters and return.&lt;br /&gt;
** div standard library function family.&lt;br /&gt;
** Many fixes for the type system and _Generic.&lt;br /&gt;
** Adopted more of GCC, QuickC and tinycc tests.&lt;br /&gt;
** C2X bit-precise integer types and bit-fields thereof for. C2X nullptr, char8_t, memalignment, unreachable, typeof, typeof_unqual, auto. C2X keywords bool, true, false, alignas, alignof, static_assert. C2X bit and byte utilities.&lt;br /&gt;
** C90-C17 function declarators without prototypes.&lt;br /&gt;
** C99 variably modified types.&lt;br /&gt;
** &amp;lt;tt&amp;gt;call_once&amp;lt;/tt&amp;gt;.&lt;br /&gt;
** &amp;lt;tt&amp;gt;_sdcc_external_startup&amp;lt;/tt&amp;gt; renamed to &amp;lt;tt&amp;gt;__sdcc_external_startup&amp;lt;/tt&amp;gt; and supported for all ports.&lt;br /&gt;
** makeshift support for long double as another alias for float.&lt;br /&gt;
&lt;br /&gt;
* ⚠️ '''Known issues:'''&lt;br /&gt;
** Most of the projects can increase significantly in final size.&lt;br /&gt;
** Bug with undocumented Z80 instructions generation that can generate compilation errors.&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;SDCC 4.4.0&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
* ⭐ '''Main features:'''&lt;br /&gt;
** Native support for ASCII R800, the MSX turbo R's CPU.&lt;br /&gt;
&lt;br /&gt;
* 🧾 '''Full change-log:'''&lt;br /&gt;
** Optimizations for rotations.&lt;br /&gt;
** Generalized constant propagation.&lt;br /&gt;
** New command line option &amp;lt;tt&amp;gt;--syntax-only&amp;lt;/tt&amp;gt; to only parse the input.&lt;br /&gt;
** Added C99 header &amp;lt;tt&amp;gt;inttypes.h&amp;lt;/tt&amp;gt;&lt;br /&gt;
** Added library functions imaxabs, imaxdiv, llabs, strtoimax, strtoll, strtoull, strtoumax, wcsncmp, wcstoimax, wcstol, wcstoll, wcstoul, wcstoull, wcstoumax&lt;br /&gt;
** New r800 port to better support the ASCII Corp R800 and Zilog Z280.&lt;br /&gt;
** Improved optimizations for code speed for stm8, pdk, z80 (and related).&lt;br /&gt;
&lt;br /&gt;
* ⚠️ '''Known issues:'''&lt;br /&gt;
** On Windows, win32 version just doesn't works and win64 is... absent. You can use [https://sourceforge.net/projects/sdcc/files/sdcc-win64/4.4.0/ win64 version of &amp;lt;tt&amp;gt;SDCC 4.4.0 RC3&amp;lt;/tt&amp;gt;] (same content than the official release).&lt;br /&gt;
** Some projects can increase significantly in final size.&lt;br /&gt;
** Some projects are broken when compiled with SDCC 4.4.0 (''Clock'' sample and ''Phenix Corrupta'' project).&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;SDCC 4.5.0&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
* ⭐ '''Main features:'''&lt;br /&gt;
** C feature improvement&lt;br /&gt;
** A big gain in final program size (often better than SDCC 4.2).&amp;lt;br/&amp;gt;&amp;lt;u&amp;gt;Note:&amp;lt;/u&amp;gt; It has not yet been confirmed whether this gain in size will be reflected (for better or worse) in performance.&lt;br /&gt;
&lt;br /&gt;
* 🧾 '''Full change-log:'''&lt;br /&gt;
** ISO C2y case range expressions&lt;br /&gt;
** ISO C2y _Generic selection expression with a type operand&lt;br /&gt;
** K&amp;amp;R-style function syntax (preliminarily with the semantics of non-K&amp;amp;R ISO-style functions)&lt;br /&gt;
** ISO C23 enums with user-specified underlying type&lt;br /&gt;
** struct / union in initializers&lt;br /&gt;
&lt;br /&gt;
* ⚠️ '''Known issues:'''&lt;br /&gt;
** Major code generation [https://sourceforge.net/p/sdcc/bugs/3834/ bug] in specific condition&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;SDCC 4.5.0&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
Currently recommended version for MSXgl.&lt;br /&gt;
&lt;br /&gt;
* ⭐ '''Main features:'''&lt;br /&gt;
** C feature improvement&lt;br /&gt;
** A big gain in final program size (often better than SDCC 4.2).&amp;lt;br/&amp;gt;&amp;lt;u&amp;gt;Note:&amp;lt;/u&amp;gt; It has not yet been confirmed whether this gain in size will be reflected (for better or worse) in performance.&lt;br /&gt;
&lt;br /&gt;
* 🧾 '''Full change-log:'''&lt;br /&gt;
** Support for Dynamic C calling convention&lt;br /&gt;
** Substantially improved code generation&lt;br /&gt;
** C99 compound literals&lt;br /&gt;
** realloc(ptr, 0) now follows C99 semantics instead of C90 semantics&lt;br /&gt;
** C23 compound literals with storage class specifiers&lt;br /&gt;
** C23 constexpr (mostly)&lt;br /&gt;
** C23 va_start and variadic functions&lt;br /&gt;
** C2y _Countof operator&lt;br /&gt;
** C2y octal&lt;br /&gt;
** C2y if-declaration&lt;br /&gt;
** C2y Conditional operator with omitted second operand (originally a GNU extension)&lt;br /&gt;
** C2y signed bit-precise integer type of width 1&lt;br /&gt;
** C2y bit-precise integer types as fixed underlying type for enum&lt;br /&gt;
** C2y umaxabs&lt;br /&gt;
** C2y bit utilities&lt;br /&gt;
** C2y functions uabs, ulabs, ullabs&lt;br /&gt;
** C2y containerof macro&lt;br /&gt;
** Improved diagnostics on invalid C2y (some of which was UB up to C23)&lt;br /&gt;
** Diagnostics based on [static assignment-expression] array parameter syntax&lt;br /&gt;
** Warnings for array parameters where accesses fall outside the bounds&lt;br /&gt;
** Basic parameter forward declarations (GNU extension)&lt;br /&gt;
** _Optional qualifier&lt;br /&gt;
** Plain int bit-fields are signed&lt;br /&gt;
** strsep&lt;br /&gt;
&lt;br /&gt;
* ⚠️ '''Known issues:'''&lt;br /&gt;
** None&lt;br /&gt;
&lt;br /&gt;
== Links ==&lt;br /&gt;
&lt;br /&gt;
For more information:&lt;br /&gt;
* [https://sdcc.sourceforge.net/ SDCC homepage]&lt;br /&gt;
* [https://sdcc.sourceforge.net/doc/sdccman.pdf SDCC documentation]&lt;br /&gt;
* [https://shop-pdp.net/ashtml/asmlnk.pdf ASxxxx documentation]&lt;/div&gt;</summary>
		<author><name>Aoineko</name></author>	</entry>

	<entry>
		<id>https://aoineko.org/msxgl/index.php?title=Roadmap&amp;diff=3981</id>
		<title>Roadmap</title>
		<link rel="alternate" type="text/html" href="https://aoineko.org/msxgl/index.php?title=Roadmap&amp;diff=3981"/>
				<updated>2026-06-25T09:02:40Z</updated>
		
		<summary type="html">&lt;p&gt;Aoineko: /* Build tool */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This is not really a '''Roadmap''' since I can't guarantee any delivery date, but here are the new features planned as of 2025/01/05.&lt;br /&gt;
&lt;br /&gt;
⏳: work in progress features&lt;br /&gt;
&lt;br /&gt;
== Audio ==&lt;br /&gt;
* Add support for new audio format:&lt;br /&gt;
** [https://github.com/cornelisser/TriloTracker-Re-player TriloTracker FM] replayer (and update of the new SCC replayer).&lt;br /&gt;
** [http://www.xl2s.tk/ Realfun 3] replayer.&lt;br /&gt;
** [https://hg.sr.ht/~grauw/re-play Re-Play] replayer (from Grauw).&lt;br /&gt;
** [https://github.com/artrag/voicenc_scc Voice synthesis on the ISR] replayer (from ARTRAG).&lt;br /&gt;
** [https://www.msx.org/wiki/Moonblaster Moonblaster] replayer.&lt;br /&gt;
** [https://doc1oo.github.io/LovelyComposerDocs/en/index.html Lovely Composer] [https://github.com/aburi6800/msx-PSGSoundDriver replayer].&lt;br /&gt;
** [https://msx.org/news/software/en/adx-player-ver-40-by-mstz80ax ADX replayer].&lt;br /&gt;
** KSS replayer.&lt;br /&gt;
** MGSP2 replayer.&lt;br /&gt;
** MML replayer.&lt;br /&gt;
** MIDI replayer (through PSG, MSX-Music and MSX-Audio).&lt;br /&gt;
* Add support for new chip:&lt;br /&gt;
** ⏳ MoonSound (OPL4) audio chip.&lt;br /&gt;
*** Play sound effect using PCM (?)&lt;br /&gt;
&lt;br /&gt;
== Display ==&lt;br /&gt;
* Add replayer for [http://msxbanzai.tni.nl/dev/software.html Animecha] data and/or for an original 2D animation format.&lt;br /&gt;
* Add video replayer(s) ([https://nazo.main.jp/prog/retropc/acmsxs3.html Easy SCREEN3 Animation Converter]).&lt;br /&gt;
* Add bitmap scrolling feature to {{MOD|scroll}} module.&lt;br /&gt;
* Add bitmap sprite upscsaler (cf. [https://www.youtube.com/watch?v=9ieE_HG3Bvs NOP]).&lt;br /&gt;
* ⏳ Add 3D module (generic 3d data format, transformation and rendering).&lt;br /&gt;
* ⏳ Add Raycaster module (using DDA).&lt;br /&gt;
* ⏳ Add Movie module (rewrite MGLV exporter from MSXimg and update MSX replayer)&lt;br /&gt;
* Add support for [https://msx.org/forum/msx-talk/general-discussion/undocumented-screen-mode-32x212 32x212 screen mode].&lt;br /&gt;
* Add pseudo-bitmap support for Print module for tile-based screen mode and sprite (draw on consecutive 16x16).&lt;br /&gt;
* Add loader for more common MSX picture formats (SCx, MIF, PCX, BMP, etc.).&lt;br /&gt;
* Add support for Yamaha V9938/58 copy commands.&lt;br /&gt;
* Add support for Yamaha V9990 copy commands.&lt;br /&gt;
** Improve V9990 sample to allow testing of all color mode.&lt;br /&gt;
* Add support for [https://github.com/hra1129/TangCartMSX/tree/main/RTL/tangnano20k_vdp_cartridge_rev2_step1/src/th9958/manual V9968 cartridge].&lt;br /&gt;
* Add support for MSX2's 1-color-per-line sprite feature in Pawn module.&lt;br /&gt;
&lt;br /&gt;
== Misc. ==&lt;br /&gt;
* Add support for SRAM cartridge: Game Master 2.&lt;br /&gt;
* ⏳ Add support for Network cartridge (Gr8net, DenYoNet &amp;amp; Obsonet).&lt;br /&gt;
* Add support for Network cable ([https://www.msx.org/wiki/Konami_JE-700 Konami JE-700] &amp;amp; [https://map.grauw.nl/resources/joynet/ JoyNet]).&lt;br /&gt;
* Add support for MSX turbo R specific features.&lt;br /&gt;
** Add support for R800 assembler (SDCC now support R800 natively).&lt;br /&gt;
* Compress&lt;br /&gt;
** Add support for ZX0 unpacker to VRAM&lt;br /&gt;
** Add support for LZ48 unpacker to &amp;lt;s&amp;gt;RAM and&amp;lt;/s&amp;gt; VRAM [https://github.com/EdouardBERGE/rasm/blob/master/decrunch/lz48decrunch_v006b.asm ][https://github.com/uniabis/z80depacker/blob/master/lz48decrunch_v006_180_speed.asm ]&lt;br /&gt;
* Improve Game module with an option to force 50 Hz main loop update on all machines.&lt;br /&gt;
* Add support for variable-width fonts.&lt;br /&gt;
* Add support for ISR in page 3 using IM2 (so page 0 is free to switch).&lt;br /&gt;
&lt;br /&gt;
== [[Build tool]] ==&lt;br /&gt;
* ⏳ Add native support for SDCC 4.6.0&lt;br /&gt;
* Check advantage of using C17, C23 or C2y.&lt;br /&gt;
* Check use of &amp;lt;tt&amp;gt;--const-stringlit&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;--nolabelopt&amp;lt;/tt&amp;gt; SDCC options.&lt;br /&gt;
* Add an option to compile the source files in parallel.&lt;br /&gt;
* Add IPS generator (to create a Patch for a given binary).&lt;br /&gt;
* Add build option to convert 16 KB ROM-mapper to RAM segment switch and RAM loader.&lt;br /&gt;
* Use SDCC's &amp;lt;tt&amp;gt;-M&amp;lt;/tt&amp;gt; option to generate file dependency list and allow skip old file option to check all depedecies (Make ''like'').&lt;br /&gt;
* Generate [https://sysadminmosaic.ru/en/msx/carnivore2/specification?redirect=1#rcp_file_format RCP file].&lt;br /&gt;
&lt;br /&gt;
== Optimization ==&lt;br /&gt;
''Optimize, optimize and optimize!''&lt;br /&gt;
* Rewrite update function in assembler for {{MOD|game_pawn}} and {{MOD|scroll}} modules.&lt;br /&gt;
* Create optional fast copy/fill/read functions using unrolled outi/ini for {{MOD|vdp}} module (for supported screen mode).&lt;br /&gt;
* Add assembler optimization option to the Build tool (using SDCC peep-hole and/or MDL).&lt;br /&gt;
* Continue to set the &amp;lt;tt&amp;gt;__preserves_regs&amp;lt;/tt&amp;gt; directive for all remaining assembly functions to help the compiler optimize register usage. ''(already done for VDP and V9990 modules)''&lt;br /&gt;
* Add [https://www.msxcomputermagazine.nl/mccw/92/Multiplication/en.html fast multiplication function] ([https://msx.org/forum/development/msx-development/fastest-possible-multiplication-routine?page=6])&lt;br /&gt;
&lt;br /&gt;
Want to contribute to MSXgl? Check [[Contribute|this article]].&lt;/div&gt;</summary>
		<author><name>Aoineko</name></author>	</entry>

	<entry>
		<id>https://aoineko.org/msxgl/index.php?title=Roadmap&amp;diff=3980</id>
		<title>Roadmap</title>
		<link rel="alternate" type="text/html" href="https://aoineko.org/msxgl/index.php?title=Roadmap&amp;diff=3980"/>
				<updated>2026-06-25T08:58:22Z</updated>
		
		<summary type="html">&lt;p&gt;Aoineko: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This is not really a '''Roadmap''' since I can't guarantee any delivery date, but here are the new features planned as of 2025/01/05.&lt;br /&gt;
&lt;br /&gt;
⏳: work in progress features&lt;br /&gt;
&lt;br /&gt;
== Audio ==&lt;br /&gt;
* Add support for new audio format:&lt;br /&gt;
** [https://github.com/cornelisser/TriloTracker-Re-player TriloTracker FM] replayer (and update of the new SCC replayer).&lt;br /&gt;
** [http://www.xl2s.tk/ Realfun 3] replayer.&lt;br /&gt;
** [https://hg.sr.ht/~grauw/re-play Re-Play] replayer (from Grauw).&lt;br /&gt;
** [https://github.com/artrag/voicenc_scc Voice synthesis on the ISR] replayer (from ARTRAG).&lt;br /&gt;
** [https://www.msx.org/wiki/Moonblaster Moonblaster] replayer.&lt;br /&gt;
** [https://doc1oo.github.io/LovelyComposerDocs/en/index.html Lovely Composer] [https://github.com/aburi6800/msx-PSGSoundDriver replayer].&lt;br /&gt;
** [https://msx.org/news/software/en/adx-player-ver-40-by-mstz80ax ADX replayer].&lt;br /&gt;
** KSS replayer.&lt;br /&gt;
** MGSP2 replayer.&lt;br /&gt;
** MML replayer.&lt;br /&gt;
** MIDI replayer (through PSG, MSX-Music and MSX-Audio).&lt;br /&gt;
* Add support for new chip:&lt;br /&gt;
** ⏳ MoonSound (OPL4) audio chip.&lt;br /&gt;
*** Play sound effect using PCM (?)&lt;br /&gt;
&lt;br /&gt;
== Display ==&lt;br /&gt;
* Add replayer for [http://msxbanzai.tni.nl/dev/software.html Animecha] data and/or for an original 2D animation format.&lt;br /&gt;
* Add video replayer(s) ([https://nazo.main.jp/prog/retropc/acmsxs3.html Easy SCREEN3 Animation Converter]).&lt;br /&gt;
* Add bitmap scrolling feature to {{MOD|scroll}} module.&lt;br /&gt;
* Add bitmap sprite upscsaler (cf. [https://www.youtube.com/watch?v=9ieE_HG3Bvs NOP]).&lt;br /&gt;
* ⏳ Add 3D module (generic 3d data format, transformation and rendering).&lt;br /&gt;
* ⏳ Add Raycaster module (using DDA).&lt;br /&gt;
* ⏳ Add Movie module (rewrite MGLV exporter from MSXimg and update MSX replayer)&lt;br /&gt;
* Add support for [https://msx.org/forum/msx-talk/general-discussion/undocumented-screen-mode-32x212 32x212 screen mode].&lt;br /&gt;
* Add pseudo-bitmap support for Print module for tile-based screen mode and sprite (draw on consecutive 16x16).&lt;br /&gt;
* Add loader for more common MSX picture formats (SCx, MIF, PCX, BMP, etc.).&lt;br /&gt;
* Add support for Yamaha V9938/58 copy commands.&lt;br /&gt;
* Add support for Yamaha V9990 copy commands.&lt;br /&gt;
** Improve V9990 sample to allow testing of all color mode.&lt;br /&gt;
* Add support for [https://github.com/hra1129/TangCartMSX/tree/main/RTL/tangnano20k_vdp_cartridge_rev2_step1/src/th9958/manual V9968 cartridge].&lt;br /&gt;
* Add support for MSX2's 1-color-per-line sprite feature in Pawn module.&lt;br /&gt;
&lt;br /&gt;
== Misc. ==&lt;br /&gt;
* Add support for SRAM cartridge: Game Master 2.&lt;br /&gt;
* ⏳ Add support for Network cartridge (Gr8net, DenYoNet &amp;amp; Obsonet).&lt;br /&gt;
* Add support for Network cable ([https://www.msx.org/wiki/Konami_JE-700 Konami JE-700] &amp;amp; [https://map.grauw.nl/resources/joynet/ JoyNet]).&lt;br /&gt;
* Add support for MSX turbo R specific features.&lt;br /&gt;
** Add support for R800 assembler (SDCC now support R800 natively).&lt;br /&gt;
* Compress&lt;br /&gt;
** Add support for ZX0 unpacker to VRAM&lt;br /&gt;
** Add support for LZ48 unpacker to &amp;lt;s&amp;gt;RAM and&amp;lt;/s&amp;gt; VRAM [https://github.com/EdouardBERGE/rasm/blob/master/decrunch/lz48decrunch_v006b.asm ][https://github.com/uniabis/z80depacker/blob/master/lz48decrunch_v006_180_speed.asm ]&lt;br /&gt;
* Improve Game module with an option to force 50 Hz main loop update on all machines.&lt;br /&gt;
* Add support for variable-width fonts.&lt;br /&gt;
* Add support for ISR in page 3 using IM2 (so page 0 is free to switch).&lt;br /&gt;
&lt;br /&gt;
== [[Build tool]] ==&lt;br /&gt;
* ⏳ Add native support for SDCC 4.6.0&lt;br /&gt;
* Check advantage of using C17, C23 or C2y.&lt;br /&gt;
* Check use of &amp;lt;tt&amp;gt;--const-stringlit&amp;lt;/tt&amp;gt; SDCC option.&lt;br /&gt;
* Add an option to compile the source files in parallel.&lt;br /&gt;
* Add IPS generator (to create a Patch for a given binary).&lt;br /&gt;
* Add build option to convert 16 KB ROM-mapper to RAM segment switch and RAM loader.&lt;br /&gt;
* Use SDCC's &amp;lt;tt&amp;gt;-M&amp;lt;/tt&amp;gt; option to generate file dependency list and allow skip old file option to check all depedecies (Make ''like'').&lt;br /&gt;
* Generate [https://sysadminmosaic.ru/en/msx/carnivore2/specification?redirect=1#rcp_file_format RCP file].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Optimization ==&lt;br /&gt;
''Optimize, optimize and optimize!''&lt;br /&gt;
* Rewrite update function in assembler for {{MOD|game_pawn}} and {{MOD|scroll}} modules.&lt;br /&gt;
* Create optional fast copy/fill/read functions using unrolled outi/ini for {{MOD|vdp}} module (for supported screen mode).&lt;br /&gt;
* Add assembler optimization option to the Build tool (using SDCC peep-hole and/or MDL).&lt;br /&gt;
* Continue to set the &amp;lt;tt&amp;gt;__preserves_regs&amp;lt;/tt&amp;gt; directive for all remaining assembly functions to help the compiler optimize register usage. ''(already done for VDP and V9990 modules)''&lt;br /&gt;
* Add [https://www.msxcomputermagazine.nl/mccw/92/Multiplication/en.html fast multiplication function] ([https://msx.org/forum/development/msx-development/fastest-possible-multiplication-routine?page=6])&lt;br /&gt;
&lt;br /&gt;
Want to contribute to MSXgl? Check [[Contribute|this article]].&lt;/div&gt;</summary>
		<author><name>Aoineko</name></author>	</entry>

	<entry>
		<id>https://aoineko.org/msxgl/index.php?title=Modules/arkos/Usage&amp;diff=3979</id>
		<title>Modules/arkos/Usage</title>
		<link rel="alternate" type="text/html" href="https://aoineko.org/msxgl/index.php?title=Modules/arkos/Usage&amp;diff=3979"/>
				<updated>2026-06-15T21:10:02Z</updated>
		
		<summary type="html">&lt;p&gt;Aoineko: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;⚠️ Arkos tracker working area address in RAM is hardcoded. You must manually ensure that this area does not overlap any other content in RAM. Default value is 0xF000 but can be change in library configuration (see [[#Settings]]). The memory buffer size is 275 bytes, but it is recommended to allow for a little more in case the player is updated later.&lt;br /&gt;
&lt;br /&gt;
=== Music address ===&lt;br /&gt;
Arkos music is designed to work only if played at a specific address.&lt;br /&gt;
When you export a music file from Arkos Tracker, you select this address (e.g., &amp;lt;tt&amp;gt;0xD000&amp;lt;/tt&amp;gt;).&lt;br /&gt;
{|&lt;br /&gt;
| [[image:Arkos export.png|x400px|thumb|Arkos Tracker II's AKG exporter&amp;lt;br/&amp;gt;Encode to address (bottom-left)]]&lt;br /&gt;
| [[image:Arkos3 export.png|x400px|thumb|Arkos Tracker 3's AKG exporter&amp;lt;br/&amp;gt;Encode to address (middle)]]&lt;br /&gt;
|}&lt;br /&gt;
In your program, you must ensure that the music is placed at this address to initialize the playback properly.&lt;br /&gt;
&lt;br /&gt;
There are several possible approaches:&lt;br /&gt;
* Store your music in a compressed format (Pletter, ZX0, etc.) anywhere in your program and then decompress it to the correct address in RAM when needed. In this case, you must reserve enough space in RAM to put the current music and the SFX (if needed). A possible layout maybe:&lt;br /&gt;
** Music at &amp;lt;tt&amp;gt;0xD000&amp;lt;/tt&amp;gt; (4 KB up to &amp;lt;tt&amp;gt;0xDFFF&amp;lt;/tt&amp;gt;)&lt;br /&gt;
** SFX at &amp;lt;tt&amp;gt;0xE000&amp;lt;/tt&amp;gt; (1 KB up to &amp;lt;tt&amp;gt;0xE3FF&amp;lt;/tt&amp;gt;)&lt;br /&gt;
* Put the music directly in the &amp;quot;right&amp;quot; place in your program. This can be quite complicated in C, unless you manually place the data at a given address (with the &amp;lt;tt&amp;gt;__at()&amp;lt;/tt&amp;gt; directive). This is possible in page 0 of 48 KB ROMs, for example, or more simply with mapper segments. For example, with an 8 KB mapper, you could use the last bank (&amp;lt;tt&amp;gt;0xA000&amp;lt;/tt&amp;gt;-&amp;lt;tt&amp;gt;0xBFFF&amp;lt;/tt&amp;gt;) to put your music at the beginning of the segment, so that it's readable in &amp;lt;tt&amp;gt;0xA000&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Interruption ===&lt;br /&gt;
The &amp;lt;tt&amp;gt;{{{1|AKG}}}_Decode()&amp;lt;/tt&amp;gt; function temporarily changes the call stack address (SP register value) to optimize its execution and restores the correct value at the end.&lt;br /&gt;
If the update function is called from the main loop, an interrupt may occur while the call stack address is incorrect, potentially overwriting music data and causing the game to crash.&lt;br /&gt;
&lt;br /&gt;
In such cases, a simple solution is to disable interrupts while updating the music:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot;&amp;gt;&lt;br /&gt;
DisableInterrupt();&lt;br /&gt;
AKG_Decode();&lt;br /&gt;
EnableInterrupt();&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
A better solution is to execute the music update directly from the interrupt handler. Not only does this remove the risk of an interrupt occurring in the middle of the update, but it also allows your music to play at a constant speed even if the main loop takes several frames (for example, when you load a level or unpack data).&lt;br /&gt;
&lt;br /&gt;
However, in this case, this means that all functions that change music data — notably the &amp;lt;tt&amp;gt;{{{1|AKG}}}_Play()&amp;lt;/tt&amp;gt; function — must also be called from the handler or executed with interrupts disabled.&lt;/div&gt;</summary>
		<author><name>Aoineko</name></author>	</entry>

	<entry>
		<id>https://aoineko.org/msxgl/index.php?title=Roadmap&amp;diff=3978</id>
		<title>Roadmap</title>
		<link rel="alternate" type="text/html" href="https://aoineko.org/msxgl/index.php?title=Roadmap&amp;diff=3978"/>
				<updated>2026-05-27T20:55:52Z</updated>
		
		<summary type="html">&lt;p&gt;Aoineko: /* Misc. */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This is not really a '''Roadmap''' since I can't guarantee any delivery date, but here are the new features planned as of 2025/01/05.&lt;br /&gt;
&lt;br /&gt;
⏳: work in progress features&lt;br /&gt;
&lt;br /&gt;
== Audio ==&lt;br /&gt;
* Add support for new audio format:&lt;br /&gt;
** [https://github.com/cornelisser/TriloTracker-Re-player TriloTracker FM] replayer (and update of the new SCC replayer).&lt;br /&gt;
** [http://www.xl2s.tk/ Realfun 3] replayer.&lt;br /&gt;
** [https://hg.sr.ht/~grauw/re-play Re-Play] replayer (from Grauw).&lt;br /&gt;
** [https://github.com/artrag/voicenc_scc Voice synthesis on the ISR] replayer (from ARTRAG).&lt;br /&gt;
** [https://www.msx.org/wiki/Moonblaster Moonblaster] replayer.&lt;br /&gt;
** [https://doc1oo.github.io/LovelyComposerDocs/en/index.html Lovely Composer] [https://github.com/aburi6800/msx-PSGSoundDriver replayer].&lt;br /&gt;
** [https://msx.org/news/software/en/adx-player-ver-40-by-mstz80ax ADX replayer].&lt;br /&gt;
** KSS replayer.&lt;br /&gt;
** MGSP2 replayer.&lt;br /&gt;
** MML replayer.&lt;br /&gt;
** MIDI replayer (through PSG, MSX-Music and MSX-Audio).&lt;br /&gt;
* Add support for new chip:&lt;br /&gt;
** ⏳ MoonSound (OPL4) audio chip.&lt;br /&gt;
*** Play sound effect using PCM (?)&lt;br /&gt;
&lt;br /&gt;
== Display ==&lt;br /&gt;
* Add replayer for [http://msxbanzai.tni.nl/dev/software.html Animecha] data and/or for an original 2D animation format.&lt;br /&gt;
* Add video replayer(s) ([https://nazo.main.jp/prog/retropc/acmsxs3.html Easy SCREEN3 Animation Converter]).&lt;br /&gt;
* Add bitmap scrolling feature to {{MOD|scroll}} module.&lt;br /&gt;
* Add bitmap sprite upscsaler (cf. [https://www.youtube.com/watch?v=9ieE_HG3Bvs NOP]).&lt;br /&gt;
* ⏳ Add 3D module (generic 3d data format, transformation and rendering).&lt;br /&gt;
* ⏳ Add Raycaster module (using DDA).&lt;br /&gt;
* ⏳ Add Movie module (rewrite MGLV exporter from MSXimg and update MSX replayer)&lt;br /&gt;
* Add support for [https://msx.org/forum/msx-talk/general-discussion/undocumented-screen-mode-32x212 32x212 screen mode].&lt;br /&gt;
* Add pseudo-bitmap support for Print module for tile-based screen mode and sprite (draw on consecutive 16x16).&lt;br /&gt;
* Add loader for more common MSX picture formats (SCx, MIF, PCX, BMP, etc.).&lt;br /&gt;
* Add support for Yamaha V9938/58 copy commands.&lt;br /&gt;
* Add support for Yamaha V9990 copy commands.&lt;br /&gt;
** Improve V9990 sample to allow testing of all color mode.&lt;br /&gt;
* Add support for [https://github.com/hra1129/TangCartMSX/tree/main/RTL/tangnano20k_vdp_cartridge_rev2_step1/src/th9958/manual V9968 cartridge].&lt;br /&gt;
* Add support for MSX2's 1-color-per-line sprite feature in Pawn module.&lt;br /&gt;
&lt;br /&gt;
== Misc. ==&lt;br /&gt;
* Add support for SRAM cartridge: Game Master 2.&lt;br /&gt;
* ⏳ Add support for Network cartridge (Gr8net, DenYoNet &amp;amp; Obsonet).&lt;br /&gt;
* Add support for Network cable ([https://www.msx.org/wiki/Konami_JE-700 Konami JE-700] &amp;amp; [https://map.grauw.nl/resources/joynet/ JoyNet]).&lt;br /&gt;
* Add support for MSX turbo R specific features.&lt;br /&gt;
** Add support for R800 assembler (SDCC now support R800 natively).&lt;br /&gt;
* Compress&lt;br /&gt;
** Add support for ZX0 unpacker to VRAM&lt;br /&gt;
** Add support for LZ48 unpacker to &amp;lt;s&amp;gt;RAM and&amp;lt;/s&amp;gt; VRAM [https://github.com/EdouardBERGE/rasm/blob/master/decrunch/lz48decrunch_v006b.asm ][https://github.com/uniabis/z80depacker/blob/master/lz48decrunch_v006_180_speed.asm ]&lt;br /&gt;
* Improve Game module with an option to force 50 Hz main loop update on all machines.&lt;br /&gt;
* Add support for variable-width fonts.&lt;br /&gt;
* Add support for ISR in page 3 using IM2 (so page 0 is free to switch).&lt;br /&gt;
&lt;br /&gt;
== [[Build tool]] ==&lt;br /&gt;
* ⏳ Add native support for SDCC 4.5.0 ''(done but waiting for SDCC fix release)''&lt;br /&gt;
* Add an option to compile the source files in parallel.&lt;br /&gt;
* Add IPS generator (to create a Patch for a given binary).&lt;br /&gt;
* Add build option to convert 16 KB ROM-mapper to RAM segment switch and RAM loader.&lt;br /&gt;
* Use SDCC's &amp;lt;tt&amp;gt;-M&amp;lt;/tt&amp;gt; option to generate file dependency list and allow skip old file option to check all depedecies (Make ''like'').&lt;br /&gt;
* Generate [https://sysadminmosaic.ru/en/msx/carnivore2/specification?redirect=1#rcp_file_format RCP file].&lt;br /&gt;
&lt;br /&gt;
== Optimization ==&lt;br /&gt;
''Optimize, optimize and optimize!''&lt;br /&gt;
* Rewrite update function in assembler for {{MOD|game_pawn}} and {{MOD|scroll}} modules.&lt;br /&gt;
* Create optional fast copy/fill/read functions using unrolled outi/ini for {{MOD|vdp}} module (for supported screen mode).&lt;br /&gt;
* Add assembler optimization option to the Build tool (using SDCC peep-hole and/or MDL).&lt;br /&gt;
* Continue to set the &amp;lt;tt&amp;gt;__preserves_regs&amp;lt;/tt&amp;gt; directive for all remaining assembly functions to help the compiler optimize register usage. ''(already done for VDP and V9990 modules)''&lt;br /&gt;
* Add [https://www.msxcomputermagazine.nl/mccw/92/Multiplication/en.html fast multiplication function] ([https://msx.org/forum/development/msx-development/fastest-possible-multiplication-routine?page=6])&lt;br /&gt;
&lt;br /&gt;
Want to contribute to MSXgl? Check [[Contribute|this article]].&lt;/div&gt;</summary>
		<author><name>Aoineko</name></author>	</entry>

	<entry>
		<id>https://aoineko.org/msxgl/index.php?title=Roadmap&amp;diff=3977</id>
		<title>Roadmap</title>
		<link rel="alternate" type="text/html" href="https://aoineko.org/msxgl/index.php?title=Roadmap&amp;diff=3977"/>
				<updated>2026-05-27T20:54:32Z</updated>
		
		<summary type="html">&lt;p&gt;Aoineko: /* Display */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This is not really a '''Roadmap''' since I can't guarantee any delivery date, but here are the new features planned as of 2025/01/05.&lt;br /&gt;
&lt;br /&gt;
⏳: work in progress features&lt;br /&gt;
&lt;br /&gt;
== Audio ==&lt;br /&gt;
* Add support for new audio format:&lt;br /&gt;
** [https://github.com/cornelisser/TriloTracker-Re-player TriloTracker FM] replayer (and update of the new SCC replayer).&lt;br /&gt;
** [http://www.xl2s.tk/ Realfun 3] replayer.&lt;br /&gt;
** [https://hg.sr.ht/~grauw/re-play Re-Play] replayer (from Grauw).&lt;br /&gt;
** [https://github.com/artrag/voicenc_scc Voice synthesis on the ISR] replayer (from ARTRAG).&lt;br /&gt;
** [https://www.msx.org/wiki/Moonblaster Moonblaster] replayer.&lt;br /&gt;
** [https://doc1oo.github.io/LovelyComposerDocs/en/index.html Lovely Composer] [https://github.com/aburi6800/msx-PSGSoundDriver replayer].&lt;br /&gt;
** [https://msx.org/news/software/en/adx-player-ver-40-by-mstz80ax ADX replayer].&lt;br /&gt;
** KSS replayer.&lt;br /&gt;
** MGSP2 replayer.&lt;br /&gt;
** MML replayer.&lt;br /&gt;
** MIDI replayer (through PSG, MSX-Music and MSX-Audio).&lt;br /&gt;
* Add support for new chip:&lt;br /&gt;
** ⏳ MoonSound (OPL4) audio chip.&lt;br /&gt;
*** Play sound effect using PCM (?)&lt;br /&gt;
&lt;br /&gt;
== Display ==&lt;br /&gt;
* Add replayer for [http://msxbanzai.tni.nl/dev/software.html Animecha] data and/or for an original 2D animation format.&lt;br /&gt;
* Add video replayer(s) ([https://nazo.main.jp/prog/retropc/acmsxs3.html Easy SCREEN3 Animation Converter]).&lt;br /&gt;
* Add bitmap scrolling feature to {{MOD|scroll}} module.&lt;br /&gt;
* Add bitmap sprite upscsaler (cf. [https://www.youtube.com/watch?v=9ieE_HG3Bvs NOP]).&lt;br /&gt;
* ⏳ Add 3D module (generic 3d data format, transformation and rendering).&lt;br /&gt;
* ⏳ Add Raycaster module (using DDA).&lt;br /&gt;
* ⏳ Add Movie module (rewrite MGLV exporter from MSXimg and update MSX replayer)&lt;br /&gt;
* Add support for [https://msx.org/forum/msx-talk/general-discussion/undocumented-screen-mode-32x212 32x212 screen mode].&lt;br /&gt;
* Add pseudo-bitmap support for Print module for tile-based screen mode and sprite (draw on consecutive 16x16).&lt;br /&gt;
* Add loader for more common MSX picture formats (SCx, MIF, PCX, BMP, etc.).&lt;br /&gt;
* Add support for Yamaha V9938/58 copy commands.&lt;br /&gt;
* Add support for Yamaha V9990 copy commands.&lt;br /&gt;
** Improve V9990 sample to allow testing of all color mode.&lt;br /&gt;
* Add support for [https://github.com/hra1129/TangCartMSX/tree/main/RTL/tangnano20k_vdp_cartridge_rev2_step1/src/th9958/manual V9968 cartridge].&lt;br /&gt;
* Add support for MSX2's 1-color-per-line sprite feature in Pawn module.&lt;br /&gt;
&lt;br /&gt;
== Misc. ==&lt;br /&gt;
* Add support for SRAM cartridge: Game Master 2.&lt;br /&gt;
* ⏳ Add support for Network cartridge (Gr8net, DenYoNet &amp;amp; Obsonet).&lt;br /&gt;
* Add support for Network cable ([https://www.msx.org/wiki/Konami_JE-700 Konami JE-700] &amp;amp; [https://map.grauw.nl/resources/joynet/ JoyNet]).&lt;br /&gt;
* Add support for MSX turbo R specific features.&lt;br /&gt;
** Add support for R800 assembler (SDCC now support R800 natively).&lt;br /&gt;
* Compress&lt;br /&gt;
** Add support for ZX0 unpacker to VRAM &lt;br /&gt;
** Add support for LZ48 unpacker to &amp;lt;s&amp;gt;RAM and&amp;lt;/s&amp;gt; VRAM [https://github.com/EdouardBERGE/rasm/blob/master/decrunch/lz48decrunch_v006b.asm ][https://github.com/uniabis/z80depacker/blob/master/lz48decrunch_v006_180_speed.asm ]&lt;br /&gt;
* Improve Game module with an option to force 50 Hz main loop update on all machines&lt;br /&gt;
* Add support for variable-width fonts.&lt;br /&gt;
&lt;br /&gt;
== [[Build tool]] ==&lt;br /&gt;
* ⏳ Add native support for SDCC 4.5.0 ''(done but waiting for SDCC fix release)''&lt;br /&gt;
* Add an option to compile the source files in parallel.&lt;br /&gt;
* Add IPS generator (to create a Patch for a given binary).&lt;br /&gt;
* Add build option to convert 16 KB ROM-mapper to RAM segment switch and RAM loader.&lt;br /&gt;
* Use SDCC's &amp;lt;tt&amp;gt;-M&amp;lt;/tt&amp;gt; option to generate file dependency list and allow skip old file option to check all depedecies (Make ''like'').&lt;br /&gt;
* Generate [https://sysadminmosaic.ru/en/msx/carnivore2/specification?redirect=1#rcp_file_format RCP file].&lt;br /&gt;
&lt;br /&gt;
== Optimization ==&lt;br /&gt;
''Optimize, optimize and optimize!''&lt;br /&gt;
* Rewrite update function in assembler for {{MOD|game_pawn}} and {{MOD|scroll}} modules.&lt;br /&gt;
* Create optional fast copy/fill/read functions using unrolled outi/ini for {{MOD|vdp}} module (for supported screen mode).&lt;br /&gt;
* Add assembler optimization option to the Build tool (using SDCC peep-hole and/or MDL).&lt;br /&gt;
* Continue to set the &amp;lt;tt&amp;gt;__preserves_regs&amp;lt;/tt&amp;gt; directive for all remaining assembly functions to help the compiler optimize register usage. ''(already done for VDP and V9990 modules)''&lt;br /&gt;
* Add [https://www.msxcomputermagazine.nl/mccw/92/Multiplication/en.html fast multiplication function] ([https://msx.org/forum/development/msx-development/fastest-possible-multiplication-routine?page=6])&lt;br /&gt;
&lt;br /&gt;
Want to contribute to MSXgl? Check [[Contribute|this article]].&lt;/div&gt;</summary>
		<author><name>Aoineko</name></author>	</entry>

	<entry>
		<id>https://aoineko.org/msxgl/index.php?title=Lexicon&amp;diff=3976</id>
		<title>Lexicon</title>
		<link rel="alternate" type="text/html" href="https://aoineko.org/msxgl/index.php?title=Lexicon&amp;diff=3976"/>
				<updated>2026-05-23T12:39:54Z</updated>
		
		<summary type="html">&lt;p&gt;Aoineko: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== A ==&lt;br /&gt;
&lt;br /&gt;
* '''ASCII''': A Japanese company responsible for several standards, including the MSX. It is also behind the character encoding standard (the ASCII table).&lt;br /&gt;
&lt;br /&gt;
== B ==&lt;br /&gt;
&lt;br /&gt;
* '''Bank''' (mapper): A chunk of memory (8 or 16 KB) managed by a register that allow to select what part of the mapped ROM (segment) is visible in the given bank. For 8 KB mappers, there is 2 banks per page and for 16 KB one, there is 1 bank per page1.&lt;br /&gt;
&lt;br /&gt;
* '''BIOS''': The core program found on all MSX computers that provides standard access to MSX peripherals (keyboard, display, sound, etc.). The BIOS may vary from one MSX to another, but all have a standard routine library that must function exactly the same way and be accessible at fixed addresses on page 0 (addresses 0x0000–0x3FFF).&lt;br /&gt;
&lt;br /&gt;
== C ==&lt;br /&gt;
&lt;br /&gt;
* '''CPU''': The central processor unit (CPU), is the processor that executes instructions of the program, such as arithmetic, logic, controlling, and input/output (I/O) operations. See '''Z80'''.&lt;br /&gt;
&lt;br /&gt;
== M ==&lt;br /&gt;
&lt;br /&gt;
* '''Mapper''': A device that contains one or more registers that allow to select the chunk of memory that is visible through the pages where the device is selected. These registers are generally accessible either via I/O ports, or via write access to given addresses.&lt;br /&gt;
&lt;br /&gt;
* '''Mapped-RAM''': A device with a mapper that allow to select chunk of the RAM (called 'segment') to be visible in each mapper's address blocs (called 'bank').&lt;br /&gt;
&lt;br /&gt;
* '''Mapped-ROM''': A device with a mapper that allow to select chunk of the ROM (called 'segment') to be visible in each mapper's address blocs (called 'bank').&lt;br /&gt;
&lt;br /&gt;
* '''MegaROM''': A ROM of 128 KB or more (1048576 bits, or 1 mega-bit, hence the name MegaROM). All MegaROM are Mapped-ROM.&lt;br /&gt;
&lt;br /&gt;
* '''Memory space''': The total memory address space visible by the Z80 (64 KB from 0x0000 to 0xFFFF).&lt;br /&gt;
&lt;br /&gt;
== P ==&lt;br /&gt;
&lt;br /&gt;
* '''Page''' (memory): A quarter of the memory space (16 KB). The page number is defined by the 2 higher bits of the address. MSX allow to select an given slot/subslot to be visible in each page.&lt;br /&gt;
&lt;br /&gt;
== R ==&lt;br /&gt;
&lt;br /&gt;
* '''R800''': The secondary 16-bit CPU found in the MSX Turbo R and designed by ASCII. See also '''Z80'''.&lt;br /&gt;
&lt;br /&gt;
* '''RAM''': Volatile memory that allows variable data to be stored as long as the MSX is switched on. Programmes require varying amounts of memory and therefore only run on machines with sufficient memory. MSX1 models have a minimum of 8 KB of memory, MSX2 models have 64 KB, MSX2+ models have 128 KB and MSX turbo R models have 256 KB.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== S ==&lt;br /&gt;
&lt;br /&gt;
* '''Segment''' (mapper): A chunk of mapped ROM (8 or 16 KB) that can be selected into a given bank.&lt;br /&gt;
&lt;br /&gt;
* '''PSG''': The programmable sound generator (PSG) is the MSX audio standard. All MSX computers are therefore equipped with a compatible chip, usually an AY-3-8910. It allows the generation of square waves across three channels, the application of envelopes, and the generation of noise.&lt;br /&gt;
&lt;br /&gt;
== Z80 ==&lt;br /&gt;
&lt;br /&gt;
* '''Z80''': The 8-bit CPU found in all MSX computers. See also '''R800'''.&lt;/div&gt;</summary>
		<author><name>Aoineko</name></author>	</entry>

	<entry>
		<id>https://aoineko.org/msxgl/index.php?title=Lexicon&amp;diff=3975</id>
		<title>Lexicon</title>
		<link rel="alternate" type="text/html" href="https://aoineko.org/msxgl/index.php?title=Lexicon&amp;diff=3975"/>
				<updated>2026-05-23T11:22:04Z</updated>
		
		<summary type="html">&lt;p&gt;Aoineko: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== B ==&lt;br /&gt;
&lt;br /&gt;
* '''Bank''' (mapper): A chunk of memory (8 or 16 KB) managed by a register that allow to select what part of the mapped ROM (segment) is visible in the given bank. For 8 KB mappers, there is 2 banks per page and for 16 KB one, there is 1 bank per page1.&lt;br /&gt;
&lt;br /&gt;
* '''BIOS''': The core program found on all MSX computers that provides standard access to MSX peripherals (keyboard, display, sound, etc.). The BIOS may vary from one MSX to another, but all have a standard routine library that must function exactly the same way and be accessible at fixed addresses on page 0 (addresses 0x0000–0x3FFF).&lt;br /&gt;
&lt;br /&gt;
== C ==&lt;br /&gt;
&lt;br /&gt;
* '''CPU''': The central processor unit (CPU), is the processor that executes instructions of the program, such as arithmetic, logic, controlling, and input/output (I/O) operations. See '''Z80'''.&lt;br /&gt;
&lt;br /&gt;
== M ==&lt;br /&gt;
&lt;br /&gt;
* '''Mapper''': A device that contains one or more registers that allow to select the chunk of memory that is visible through the pages where the device is selected. These registers are generally accessible either via I/O ports, or via write access to given addresses.&lt;br /&gt;
&lt;br /&gt;
* '''Mapped-RAM''': A device with a mapper that allow to select chunk of the RAM (called 'segment') to be visible in each mapper's address blocs (called 'bank').&lt;br /&gt;
&lt;br /&gt;
* '''Mapped-ROM''': A device with a mapper that allow to select chunk of the ROM (called 'segment') to be visible in each mapper's address blocs (called 'bank').&lt;br /&gt;
&lt;br /&gt;
* '''MegaROM''': A ROM of 128 KB or more (1048576 bits, or 1 mega-bit, hence the name MegaROM). All MegaROM are Mapped-ROM.&lt;br /&gt;
&lt;br /&gt;
* '''Memory space''': The total memory address space visible by the Z80 (64 KB from 0x0000 to 0xFFFF).&lt;br /&gt;
&lt;br /&gt;
== P ==&lt;br /&gt;
&lt;br /&gt;
* '''Page''' (memory): A quarter of the memory space (16 KB). The page number is defined by the 2 higher bits of the address. MSX allow to select an given slot/subslot to be visible in each page.&lt;br /&gt;
&lt;br /&gt;
== S ==&lt;br /&gt;
&lt;br /&gt;
* '''Segment''' (mapper): A chunk of mapped ROM (8 or 16 KB) that can be selected into a given bank.&lt;br /&gt;
&lt;br /&gt;
* '''PSG''': The programmable sound generator (PSG) is the MSX audio standard. All MSX computers are therefore equipped with a compatible chip, usually an AY-3-8910. It allows the generation of square waves across three channels, the application of envelopes, and the generation of noise.&lt;/div&gt;</summary>
		<author><name>Aoineko</name></author>	</entry>

	<entry>
		<id>https://aoineko.org/msxgl/index.php?title=Lexicon&amp;diff=3974</id>
		<title>Lexicon</title>
		<link rel="alternate" type="text/html" href="https://aoineko.org/msxgl/index.php?title=Lexicon&amp;diff=3974"/>
				<updated>2026-05-23T11:13:45Z</updated>
		
		<summary type="html">&lt;p&gt;Aoineko: /* M */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== B ==&lt;br /&gt;
&lt;br /&gt;
* '''Bank''' (mapper): A chunk of memory (8 or 16 KB) managed by a register that allow to select what part of the mapped ROM (segment) is visible in the given bank. For 8 KB mappers, there is 2 banks per page and for 16 KB one, there is 1 bank per page1.&lt;br /&gt;
&lt;br /&gt;
* '''BIOS''': The core program found on all MSX computers that provides standard access to MSX peripherals (keyboard, display, sound, etc.). The BIOS may vary from one MSX to another, but all have a standard routine library that must function exactly the same way and be accessible at fixed addresses on page 0 (addresses 0x0000–0x3FFF).&lt;br /&gt;
&lt;br /&gt;
== C ==&lt;br /&gt;
&lt;br /&gt;
* '''CPU''': The central processor unit, is the processor that executes instructions of the program, such as arithmetic, logic, controlling, and input/output (I/O) operations. See '''Z80'''.&lt;br /&gt;
&lt;br /&gt;
== M ==&lt;br /&gt;
&lt;br /&gt;
* '''Mapper''': A device that contains one or more registers that allow to select the chunk of memory that is visible through the pages where the device is selected. These registers are generally accessible either via I/O ports, or via write access to given addresses.&lt;br /&gt;
&lt;br /&gt;
* '''Mapped-RAM''': A device with a mapper that allow to select chunk of the RAM (called 'segment') to be visible in each mapper's address blocs (called 'bank').&lt;br /&gt;
&lt;br /&gt;
* '''Mapped-ROM''': A device with a mapper that allow to select chunk of the ROM (called 'segment') to be visible in each mapper's address blocs (called 'bank').&lt;br /&gt;
&lt;br /&gt;
* '''MegaROM''': A ROM of 128 KB or more (1048576 bits, or 1 mega-bit, hence the name MegaROM). All MegaROM are Mapped-ROM.&lt;br /&gt;
&lt;br /&gt;
* '''Memory space''': The total memory address space visible by the Z80 (64 KB from 0x0000 to 0xFFFF).&lt;br /&gt;
&lt;br /&gt;
== P ==&lt;br /&gt;
&lt;br /&gt;
* '''Page''' (memory): A quarter of the memory space (16 KB). The page number is defined by the 2 higher bits of the address. MSX allow to select an given slot/subslot to be visible in each page.&lt;br /&gt;
&lt;br /&gt;
== S ==&lt;br /&gt;
&lt;br /&gt;
* '''Segment''' (mapper): A chunk of mapped ROM (8 or 16 KB) that can be selected into a given bank.&lt;/div&gt;</summary>
		<author><name>Aoineko</name></author>	</entry>

	<entry>
		<id>https://aoineko.org/msxgl/index.php?title=Lexicon&amp;diff=3973</id>
		<title>Lexicon</title>
		<link rel="alternate" type="text/html" href="https://aoineko.org/msxgl/index.php?title=Lexicon&amp;diff=3973"/>
				<updated>2026-05-23T11:13:34Z</updated>
		
		<summary type="html">&lt;p&gt;Aoineko: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== B ==&lt;br /&gt;
&lt;br /&gt;
* '''Bank''' (mapper): A chunk of memory (8 or 16 KB) managed by a register that allow to select what part of the mapped ROM (segment) is visible in the given bank. For 8 KB mappers, there is 2 banks per page and for 16 KB one, there is 1 bank per page1.&lt;br /&gt;
&lt;br /&gt;
* '''BIOS''': The core program found on all MSX computers that provides standard access to MSX peripherals (keyboard, display, sound, etc.). The BIOS may vary from one MSX to another, but all have a standard routine library that must function exactly the same way and be accessible at fixed addresses on page 0 (addresses 0x0000–0x3FFF).&lt;br /&gt;
&lt;br /&gt;
== C ==&lt;br /&gt;
&lt;br /&gt;
* '''CPU''': The central processor unit, is the processor that executes instructions of the program, such as arithmetic, logic, controlling, and input/output (I/O) operations. See '''Z80'''.&lt;br /&gt;
&lt;br /&gt;
== M ==&lt;br /&gt;
&lt;br /&gt;
* '''Mapper''': A device that contains one or more registers that allow to select the chunk part of memory that is visible through the pages where the device is selected. These registers are generally accessible either via I/O ports, or via write access to given addresses.&lt;br /&gt;
&lt;br /&gt;
* '''Mapped-RAM''': A device with a mapper that allow to select chunk of the RAM (called 'segment') to be visible in each mapper's address blocs (called 'bank').&lt;br /&gt;
&lt;br /&gt;
* '''Mapped-ROM''': A device with a mapper that allow to select chunk of the ROM (called 'segment') to be visible in each mapper's address blocs (called 'bank').&lt;br /&gt;
&lt;br /&gt;
* '''MegaROM''': A ROM of 128 KB or more (1048576 bits, or 1 mega-bit, hence the name MegaROM). All MegaROM are Mapped-ROM.&lt;br /&gt;
&lt;br /&gt;
* '''Memory space''': The total memory address space visible by the Z80 (64 KB from 0x0000 to 0xFFFF).&lt;br /&gt;
&lt;br /&gt;
== P ==&lt;br /&gt;
&lt;br /&gt;
* '''Page''' (memory): A quarter of the memory space (16 KB). The page number is defined by the 2 higher bits of the address. MSX allow to select an given slot/subslot to be visible in each page.&lt;br /&gt;
&lt;br /&gt;
== S ==&lt;br /&gt;
&lt;br /&gt;
* '''Segment''' (mapper): A chunk of mapped ROM (8 or 16 KB) that can be selected into a given bank.&lt;/div&gt;</summary>
		<author><name>Aoineko</name></author>	</entry>

	<entry>
		<id>https://aoineko.org/msxgl/index.php?title=Lexicon&amp;diff=3972</id>
		<title>Lexicon</title>
		<link rel="alternate" type="text/html" href="https://aoineko.org/msxgl/index.php?title=Lexicon&amp;diff=3972"/>
				<updated>2026-05-23T11:12:48Z</updated>
		
		<summary type="html">&lt;p&gt;Aoineko: /* M */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== B ==&lt;br /&gt;
&lt;br /&gt;
* '''Bank''' (mapper): A chunk of memory (8 or 16 KB) managed by a register that allow to select what part of the mapped ROM (segment) is visible in the given bank. For 8 KB mappers, there is 2 banks per page and for 16 KB one, there is 1 bank per page1.&lt;br /&gt;
&lt;br /&gt;
* '''BIOS''': The core program found on all MSX computers that provides standard access to MSX peripherals (keyboard, display, sound, etc.). The BIOS may vary from one MSX to another, but all have a standard routine library that must function exactly the same way and be accessible at fixed addresses on page 0 (addresses 0x0000–0x3FFF).&lt;br /&gt;
&lt;br /&gt;
== C ==&lt;br /&gt;
&lt;br /&gt;
* '''CPU''': The central processor unit, is the processor that executes instructions of the program, such as arithmetic, logic, controlling, and input/output (I/O) operations. See '''Z80'''.&lt;br /&gt;
&lt;br /&gt;
== M ==&lt;br /&gt;
&lt;br /&gt;
* '''Mapper''': A device that contains one or more registers that allow to select the small part of a big memory space that is visible through the pages where the device is selected. These registers are generally accessible either via I/O ports, or via write access to given addresses.&lt;br /&gt;
&lt;br /&gt;
* '''Mapped-RAM''': A device with a mapper that allow to select chunk of the RAM (called 'segment') to be visible in each mapper's address blocs (called 'bank').&lt;br /&gt;
&lt;br /&gt;
* '''Mapped-ROM''': A device with a mapper that allow to select chunk of the ROM (called 'segment') to be visible in each mapper's address blocs (called 'bank').&lt;br /&gt;
&lt;br /&gt;
* '''MegaROM''': A ROM of 128 KB or more (1048576 bits, or 1 mega-bit, hence the name MegaROM). All MegaROM are Mapped-ROM.&lt;br /&gt;
&lt;br /&gt;
* '''Memory space''': The total memory address space visible by the Z80 (64 KB from 0x0000 to 0xFFFF).&lt;br /&gt;
&lt;br /&gt;
== P ==&lt;br /&gt;
&lt;br /&gt;
* '''Page''' (memory): A quarter of the memory space (16 KB). The page number is defined by the 2 higher bits of the address. MSX allow to select an given slot/subslot to be visible in each page.&lt;br /&gt;
&lt;br /&gt;
== S ==&lt;br /&gt;
&lt;br /&gt;
* '''Segment''' (mapper): A chunk of mapped ROM (8 or 16 KB) that can be selected into a given bank.&lt;/div&gt;</summary>
		<author><name>Aoineko</name></author>	</entry>

	<entry>
		<id>https://aoineko.org/msxgl/index.php?title=Lexicon&amp;diff=3971</id>
		<title>Lexicon</title>
		<link rel="alternate" type="text/html" href="https://aoineko.org/msxgl/index.php?title=Lexicon&amp;diff=3971"/>
				<updated>2026-05-23T11:11:23Z</updated>
		
		<summary type="html">&lt;p&gt;Aoineko: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== B ==&lt;br /&gt;
&lt;br /&gt;
* '''Bank''' (mapper): A chunk of memory (8 or 16 KB) managed by a register that allow to select what part of the mapped ROM (segment) is visible in the given bank. For 8 KB mappers, there is 2 banks per page and for 16 KB one, there is 1 bank per page1.&lt;br /&gt;
&lt;br /&gt;
* '''BIOS''': The core program found on all MSX computers that provides standard access to MSX peripherals (keyboard, display, sound, etc.). The BIOS may vary from one MSX to another, but all have a standard routine library that must function exactly the same way and be accessible at fixed addresses on page 0 (addresses 0x0000–0x3FFF).&lt;br /&gt;
&lt;br /&gt;
== C ==&lt;br /&gt;
&lt;br /&gt;
* '''CPU''': The central processor unit, is the processor that executes instructions of the program, such as arithmetic, logic, controlling, and input/output (I/O) operations. See '''Z80'''.&lt;br /&gt;
&lt;br /&gt;
== M ==&lt;br /&gt;
&lt;br /&gt;
* '''Mapper''': A device that contains one or more registers that allow to select the memory accessible through the pages where the device is selected. These registers are generally accessible either via I/O ports, or via write access to given addresses.&lt;br /&gt;
&lt;br /&gt;
* '''Mapped-RAM''': A device with a mapper that allow to select chunk of the RAM (called 'segment') to be visible in each mapper's address blocs (called 'bank').&lt;br /&gt;
&lt;br /&gt;
* '''Mapped-ROM''': A device with a mapper that allow to select chunk of the ROM (called 'segment') to be visible in each mapper's address blocs (called 'bank').&lt;br /&gt;
&lt;br /&gt;
* '''MegaROM''': A ROM of 128 KB or more (1048576 bits, or 1 mega-bit, hence the name MegaROM). All MegaROM are Mapped-ROM.&lt;br /&gt;
&lt;br /&gt;
* '''Memory space''': The total memory address space visible by the Z80 (64 KB from 0x0000 to 0xFFFF).&lt;br /&gt;
&lt;br /&gt;
== P ==&lt;br /&gt;
&lt;br /&gt;
* '''Page''' (memory): A quarter of the memory space (16 KB). The page number is defined by the 2 higher bits of the address. MSX allow to select an given slot/subslot to be visible in each page.&lt;br /&gt;
&lt;br /&gt;
== S ==&lt;br /&gt;
&lt;br /&gt;
* '''Segment''' (mapper): A chunk of mapped ROM (8 or 16 KB) that can be selected into a given bank.&lt;/div&gt;</summary>
		<author><name>Aoineko</name></author>	</entry>

	<entry>
		<id>https://aoineko.org/msxgl/index.php?title=Create_a_mapped_ROM&amp;diff=3970</id>
		<title>Create a mapped ROM</title>
		<link rel="alternate" type="text/html" href="https://aoineko.org/msxgl/index.php?title=Create_a_mapped_ROM&amp;diff=3970"/>
				<updated>2026-05-23T08:07:22Z</updated>
		
		<summary type="html">&lt;p&gt;Aoineko: /* Change segment visbile through bank */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;To create cartridges larger than 64 KB, {{MSXGL}} allows to use several types of mapped ROM (often called MegaROM).&lt;br /&gt;
&lt;br /&gt;
This documentation primarily explains how standard mappers work: ASCII-8, ASCII-16, Konami and Konami with SCC.&lt;br /&gt;
Most of this information also applies to the [[NEO mapper]] (NEO-8 and NEO-16), or to other new mappers (Yamanooto, Popolon SCC or ASCII16-X), but for further details, please refer to the relevant sections.&lt;br /&gt;
&lt;br /&gt;
== Principles ==&lt;br /&gt;
&lt;br /&gt;
A mapped ROM cartridge is visible to the Z80 through pages 1 and 2 of the memory space (address 4000h-7FFFh and 8000h-BFFFh).&lt;br /&gt;
This 32 KB space is divided into either 4 '''banks''' (or sub-pages) of 8 KB, or 2 banks of 16 KB.&lt;br /&gt;
This is why mappers are often categorized as 8 KB mapper and 16 KB mapper.&lt;br /&gt;
&lt;br /&gt;
ROMs using these mappers can be for example 128 KB, 256 KB, 512 KB, 1 MB, 2 MB or 4 MB in size (4 MB, only for 16 KB mapper).&lt;br /&gt;
The total content of the ROM is divided into blocks of the mapper size (8 or 16 KB). These blocks are called '''segments'''.&lt;br /&gt;
&lt;br /&gt;
The concept of using mappers is to associate a given segment with a bank to make it visible to the Z80.&lt;br /&gt;
By changing the segments visible in each bank during the course of the program, we can thus access the entire contents of the ROM.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;width:640px; border:medium solid lightblue; margin:0.5em; padding:0.5em;&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;html&amp;gt;&amp;lt;img style=&amp;quot;width:100%&amp;quot; src=&amp;quot;https://raw.githubusercontent.com/aoineko-fr/MSXgl/main/engine/doc/img/target/rom_slot_ascii8_128.png&amp;quot; /&amp;gt;&amp;lt;/html&amp;gt;&lt;br /&gt;
&lt;br /&gt;
''128 KB ROM using an 8 KB mapper (ASCII-8) in slot 1. The ROM is composed of 16 segments, visible to the Z80 through 4 banks. In the example above, segment #0 is visible in bank #0, segment #1 in bank #1, segment #4 in bank #2 and segment #12 in bank #3.''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Change segment visbile through bank ===&lt;br /&gt;
&lt;br /&gt;
To change the visible segment in a bank, you just have to write the segment number to a given address (different depending on the mappers).&lt;br /&gt;
&lt;br /&gt;
Write in a ROM, yes, you read it right!&lt;br /&gt;
&lt;br /&gt;
In fact, mapped ROMs have special mechanisms (mappers) that intercept write signals at certain addresses and use the written value to select the segment.&lt;br /&gt;
Using MSXgl, you don't need to know the addresses or write because you only need to use the &amp;lt;tt&amp;gt;SET_BANK_SEGMENT(bank, seg)&amp;lt;/tt&amp;gt; macro which takes care of associating a segment to a bank.&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
SET_BANK_SEGMENT(1, 8); // Set segment #8 visible through bank #1.&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Types of mappers ===&lt;br /&gt;
&lt;br /&gt;
The supported mappers are:&lt;br /&gt;
{{:Target/Mappers}}&lt;br /&gt;
&lt;br /&gt;
More details on the different mappers:&lt;br /&gt;
* https://www.msx.org/wiki/MegaROM_Mappers&lt;br /&gt;
* http://bifi.msxnet.org/msxnet/tech/megaroms&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;Note&amp;lt;/u&amp;gt;: &amp;quot;MegaROM&amp;quot; refers to a ROM of 128 KB or more. Even though they are not widely supported, there is nothing to prevent you from creating a 64 KB ROM using a mapper. We therefore prefer to use the term Mapped ROM here rather than MegaROM.&lt;br /&gt;
&lt;br /&gt;
== How to ==&lt;br /&gt;
&lt;br /&gt;
=== Setup ===&lt;br /&gt;
&lt;br /&gt;
First, you need to decide which mapper you want to use and what size you need.&amp;lt;br/&amp;gt;&lt;br /&gt;
If you have no idea, start with a 128 KB ROM using ASCII-8 mapper.&lt;br /&gt;
&lt;br /&gt;
The choice of ROM is made in the configuration file of the build tool (&amp;lt;tt&amp;gt;project_config.js&amp;lt;/tt&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;js&amp;quot;&amp;gt;&lt;br /&gt;
target = &amp;quot;ROM_ASCII8&amp;quot;;&lt;br /&gt;
ROMSize = 128;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
See the details of the configuration of the Build Tool: [[Targets#Mapped_ROM_program]].&lt;br /&gt;
&lt;br /&gt;
=== Example ===&lt;br /&gt;
&lt;br /&gt;
A sample program (&amp;lt;tt&amp;gt;s_mapper&amp;lt;/tt&amp;gt;) is available to demonstrate the use of ROM mappers.&lt;br /&gt;
&lt;br /&gt;
In this example, we create a 128 KB mapped ROM in ASCII-8 format (16 segments). The first 4 segments are defined in the main program (32 KB) and 2 others in separate files.&lt;br /&gt;
&lt;br /&gt;
Sample files:&lt;br /&gt;
* &amp;lt;tt&amp;gt;projects/&amp;lt;/tt&amp;gt;&lt;br /&gt;
** &amp;lt;tt&amp;gt;samples/&amp;lt;/tt&amp;gt;&lt;br /&gt;
*** &amp;lt;tt&amp;gt;[https://github.com/aoineko-fr/MSXgl/blob/main/projects/samples/s_mapper.c s_mapper.c]&amp;lt;/tt&amp;gt; (main program)&lt;br /&gt;
*** &amp;lt;tt&amp;gt;[https://github.com/aoineko-fr/MSXgl/blob/main/projects/samples/s_mapper.js s_mapper.js]&amp;lt;/tt&amp;gt; (build tool configuration)&lt;br /&gt;
*** &amp;lt;tt&amp;gt;[https://github.com/aoineko-fr/MSXgl/blob/main/projects/samples/s_mapper_s4_b2.c s_mapper_s4_b2.c]&amp;lt;/tt&amp;gt; (segment #4 C source)&lt;br /&gt;
*** &amp;lt;tt&amp;gt;[https://github.com/aoineko-fr/MSXgl/blob/main/projects/samples/s_mapper_s5_b3.asm s_mapper_s5_b3.asm]&amp;lt;/tt&amp;gt; (segment #5 assembler source)&lt;br /&gt;
&lt;br /&gt;
In the Build Tool:&lt;br /&gt;
* &amp;lt;tt&amp;gt;s_mapper.c&amp;lt;/tt&amp;gt; will be compile as a 32 KB plain ROM (which represents the first 4 segments: #0 to #3).&lt;br /&gt;
* Then, the Build Tool will search for source files for segment #4 to #15 starting with &amp;lt;tt&amp;gt;s_mapper_&amp;lt;/tt&amp;gt;. 3 files extensions are supported: &amp;lt;tt&amp;gt;.c&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;.asm&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;.s&amp;lt;/tt&amp;gt;.&lt;br /&gt;
** &amp;lt;tt&amp;gt;s_mapper_s4_b2.c&amp;lt;/tt&amp;gt; will be find, compile to be visible in bank 2 (from 0x8000) and added to link list.&lt;br /&gt;
** &amp;lt;tt&amp;gt;s_mapper_s5_b3.asm&amp;lt;/tt&amp;gt; will be find, compile to be visible in bank 3 (from 0xA000) and added to link list. Assembler segment source file must include the &amp;lt;tt&amp;gt;.area&amp;lt;/tt&amp;gt; directive with the segment name &amp;lt;tt&amp;gt;_SEG{num}&amp;lt;/tt&amp;gt; (&amp;lt;tt&amp;gt;_SEG5&amp;lt;/tt&amp;gt; here).&lt;br /&gt;
* All the source will be linked together (and symbols will be &amp;quot;resolved&amp;quot;).&lt;br /&gt;
* The final binary file will be create by [[MSXhex]], putting each segment at its final location in the ROM.&lt;br /&gt;
&lt;br /&gt;
=== Symbols ===&lt;br /&gt;
&lt;br /&gt;
Segment symbols (tables or functions name) can be accessed from any other sources.&amp;lt;br/&amp;gt;&lt;br /&gt;
No more need to know the address of a data in a segment of the mapper; it is enough to call it by its name (which also allows the C compiler to validate the data type).&amp;lt;br/&amp;gt;&lt;br /&gt;
It is therefore also much easier to accumulate data in a segment since it is only necessary to put the data one after the other; the address of the arrays being resolved at link time.&amp;lt;br/&amp;gt;&lt;br /&gt;
The switching of the segments remains the responsibility of the programmer. &lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
// File: mygame_s5_b3.c&lt;br /&gt;
// Segment #5 (bank #3)&lt;br /&gt;
&lt;br /&gt;
const u8 MyData[] = { 1, 2, 3, 4, 5, 6, 7, 8 }; &lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
// File: mygame.c&lt;br /&gt;
// Main program&lt;br /&gt;
&lt;br /&gt;
extern const u8 MyData[]; // Tell the compiler this data exists somewhere else.&lt;br /&gt;
&lt;br /&gt;
SET_BANK_SEGMENT(3, 5); // Switch segment visible through bank #3.&lt;br /&gt;
u8 s = MyData[1];&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Banked call ===&lt;br /&gt;
&lt;br /&gt;
SDCC banked calls (using the &amp;lt;tt&amp;gt;__banked&amp;lt;/tt&amp;gt; directive) can be used to call a function in a segment and have an automatic bank switching to this segment before call, and then, a restoration of the previous segment after function returns.&lt;br /&gt;
The only limitation is that SDCC only returns the segment number (and not the bank number) to the default trampoline functions.&lt;br /&gt;
So, to make it simple (and efficient), MSXgl only allow (for the moment) a switch on one of a mapped-ROM's bank.&lt;br /&gt;
* For 8 KB mapper : bank #2 (8000h-9FFFh)&lt;br /&gt;
* For 16 KB mapper : bank #1 (8000h-BFFFh)&lt;br /&gt;
To activate this feature, you need to add &amp;lt;tt&amp;gt;set BankedCall=true;&amp;lt;/tt&amp;gt; in your &amp;quot;project_config.js&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
// File: mygame_s7_b2.c&lt;br /&gt;
// Segment #7 (bank #2)&lt;br /&gt;
&lt;br /&gt;
u8 LocalFunc() { return 2; }&lt;br /&gt;
u8 BankedFunc() __banked { return LocalFunc()+1; };&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
// File: mygame.c&lt;br /&gt;
// Main program&lt;br /&gt;
&lt;br /&gt;
u8 BankedFunc() __banked; // Prototype to tell the compiler this function exists somewhere else.&lt;br /&gt;
&lt;br /&gt;
void main()&lt;br /&gt;
{&lt;br /&gt;
   BankedFunc(); // automatic switch to segment #7 then restore previous segment&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
⚠️ &amp;lt;u&amp;gt;Note&amp;lt;/u&amp;gt;: Banked functions seem simple to use at first glance, but I don't recommend using them as they make segment switching invisible and can be a source of many bugs. Making bank switches by hand has the big advantage of making them explicit in the code, so you don't lose sight of this sensitive mechanism.&lt;br /&gt;
&lt;br /&gt;
=== Raw binary data ===&lt;br /&gt;
&lt;br /&gt;
MSXgl also provides a means of adding raw binary data directly to segments. This data is not compiled (faster) and is simply added to the final ROM, automatically placing it in the right place.&lt;br /&gt;
&lt;br /&gt;
All you have to do is define the &amp;lt;tt&amp;gt;RawFiles&amp;lt;/tt&amp;gt; parameter in your project configuration (&amp;lt;tt&amp;gt;project_setting.js&amp;lt;/tt&amp;gt;) with an array of the type:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;js&amp;quot;&amp;gt;&lt;br /&gt;
//-- List of raw data files to be added to final binary (array). Each entry must be in the following format: { offset:0x0000, file:&amp;quot;myfile.bin&amp;quot; }&lt;br /&gt;
RawFiles = [&lt;br /&gt;
    { segment: 2, file: &amp;quot;content/music1.vgm&amp;quot;},&lt;br /&gt;
    { segment: 3, file: &amp;quot;content/music2.vgm&amp;quot; },&lt;br /&gt;
    { offset: 0x18000, file: &amp;quot;content/image.bin&amp;quot; },&lt;br /&gt;
    { page: 4, file: &amp;quot;content/video.bin&amp;quot; }&lt;br /&gt;
];&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The first parameter of each table entry can be any of 3 types:&lt;br /&gt;
* &amp;lt;tt&amp;gt;offset&amp;lt;/tt&amp;gt;: a 32-bit offset (decimal or hexadecimal) from the start of the ROM.&lt;br /&gt;
* &amp;lt;tt&amp;gt;segment&amp;lt;/tt&amp;gt;: segment number for mapped ROMs (Build tool use mapper's bank size to determine the final position).&lt;br /&gt;
* &amp;lt;tt&amp;gt;page&amp;lt;/tt&amp;gt;: page number (16 KB) for mapped or plain ROM.&lt;br /&gt;
&lt;br /&gt;
A header file (named &amp;lt;tt&amp;gt;myproject_rawdef.h&amp;lt;/tt&amp;gt;) with information about those raw files will be generated before compiling occurs so you can include it in your program.&lt;br /&gt;
&lt;br /&gt;
You can add several binary files to the same segment/page. In this case, data will be concatenated from the given segment/page start address. In this case, you need to use the generated header file to know where the file ends up.&lt;br /&gt;
&lt;br /&gt;
The sample &amp;lt;tt&amp;gt;s_vgm&amp;lt;/tt&amp;gt; showcase the use this option.&lt;br /&gt;
&lt;br /&gt;
=== Initial slot configuration ===&lt;br /&gt;
&lt;br /&gt;
When your &amp;lt;tt&amp;gt;main()&amp;lt;/tt&amp;gt; function start, the mapped-ROM cartridge slot is selected in pages #1 and #2 of the memory space.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;img style=&amp;quot;width:400px; margin:0.5em;&amp;quot; src=&amp;quot;https://raw.githubusercontent.com/aoineko-fr/MSXgl/main/engine/doc/img/target/rom_slot_ascii8_128.png&amp;quot; /&amp;gt;&lt;br /&gt;
&amp;lt;img style=&amp;quot;width:400px; margin:0.5em;&amp;quot; src=&amp;quot;https://raw.githubusercontent.com/aoineko-fr/MSXgl/main/engine/doc/img/target/rom_slot_ascii16_128.png&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Also, the banks are initially setup as:&lt;br /&gt;
&lt;br /&gt;
For 8 KB mappers:&lt;br /&gt;
* Bank #0 (4000h-5FFFh): Segment #0 (contain the ROM header)&lt;br /&gt;
* Bank #1 (6000h-7FFFh): Segment #1&lt;br /&gt;
* Bank #2 (8000h-9FFFh): Segment #2&lt;br /&gt;
* Bank #3 (A000h-BFFFh): Segment #3&lt;br /&gt;
&lt;br /&gt;
For 16 KB mappers:&lt;br /&gt;
* Bank #0 (4000h-7FFFh): Segment #0 (contain the ROM header)&lt;br /&gt;
* Bank #1 (8000h-BFFFh): Segment #1&lt;br /&gt;
&lt;br /&gt;
=== NEO mapper ===&lt;br /&gt;
[[NEO mapper]] works on the same principle as the legacy mappers, but has more bank switching registers (covering page 0) and registers are 16-bit instead of 8-bit.&lt;br /&gt;
&lt;br /&gt;
When your &amp;lt;tt&amp;gt;main()&amp;lt;/tt&amp;gt; function start, the mapped-ROM cartridge slot is selected in pages #0, #1 and #2 of the memory space.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;img style=&amp;quot;width:400px; margin:0.5em;&amp;quot; src=&amp;quot;https://raw.githubusercontent.com/aoineko-fr/MSXgl/main/engine/doc/mapper_neo8.png&amp;quot; /&amp;gt;&lt;br /&gt;
&amp;lt;img style=&amp;quot;width:400px; margin:0.5em;&amp;quot; src=&amp;quot;https://raw.githubusercontent.com/aoineko-fr/MSXgl/main/engine/doc/mapper_neo16.png&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Segment #4 of the NEO-8 and segment #2 of the NEO-16 have a special use: they are designed to be selected in bank #0, and the Build tool will automatically add an interrupt handling code (ISR) to them. This segment can be used to store code or data, but note that it will be accumulated from address 0x0100 (after the ISR).&lt;br /&gt;
&lt;br /&gt;
Default selected segments:&lt;br /&gt;
&lt;br /&gt;
NEO-8&lt;br /&gt;
* Bank #0 (0000h-1FFFh): Segment #4 (contain the ISR + user code/data after 0x0100)&lt;br /&gt;
* Bank #1 (2000h-3FFFh): Segment #5&lt;br /&gt;
* Bank #2 (4000h-5FFFh): Segment #0 (contain the ROM header)&lt;br /&gt;
* Bank #3 (6000h-7FFFh): Segment #1&lt;br /&gt;
* Bank #4 (8000h-9FFFh): Segment #2&lt;br /&gt;
* Bank #5 (A000h-BFFFh): Segment #3&lt;br /&gt;
&lt;br /&gt;
NEO-16&lt;br /&gt;
* Bank #0 (0000h-3FFFh): Segment #2 (contain the ISR + user code/data after 0x0100)&lt;br /&gt;
* Bank #1 (4000h-7FFFh): Segment #0 (contain the ROM header)&lt;br /&gt;
* Bank #2 (8000h-BFFFh): Segment #1&lt;br /&gt;
&lt;br /&gt;
See the [[NEO mapper|NEO mapper specifications]] for more details about the mapper.&lt;br /&gt;
&lt;br /&gt;
=== Yamanooto &amp;amp; ASCII16-X ===&lt;br /&gt;
Yamanooto and ASCII16-X are mappers that works like legacy mappers but allows more the 256 segments so they overcome their maximal size.&lt;br /&gt;
&lt;br /&gt;
Yamanoto:&lt;br /&gt;
* Banks: 4 banks of 8 KB (visible on memory pages 1 and 2)&lt;br /&gt;
* Size: up to 8 MB&lt;br /&gt;
* Support: Yamanooto and openMSX&lt;br /&gt;
&lt;br /&gt;
ASCII16-X:&lt;br /&gt;
* Banks: 2 banks of 16 KB (visible on memory pages 1 and 2)&lt;br /&gt;
* Size: up to 64 MB&lt;br /&gt;
* Support: Incomming hardware and openMSX (8 MB)&lt;br /&gt;
&lt;br /&gt;
== Advice ==&lt;br /&gt;
&lt;br /&gt;
The simplest way to start with mapped-ROM is to use a 8 KB mapper (ASCII-8 for example) and to keep the first 3 segments always visible from the first 3 banks (the initial state), and then use the last bank (#3) to switch between all other segments.&lt;br /&gt;
&lt;br /&gt;
This allows to have a 24 KB program (3 segments) always visible by the Z80 and to switch only the segments that contain the data, when needed.&lt;br /&gt;
&lt;br /&gt;
Let's say you have a 24 KB (segment #0, #1 and #2) program and 3 data segments containing: sprites (segment #4), background tiles (segment #5) and music (segment #6).&amp;lt;br/&amp;gt;&lt;br /&gt;
Your pseudo code could be something like this:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
// File: mygame.c&lt;br /&gt;
...&lt;br /&gt;
&lt;br /&gt;
// Init VRAM data&lt;br /&gt;
SET_BANK_SEGMENT(3, 4); // Segment #4 visible through bank #3&lt;br /&gt;
LoadSpriteInVRAM();&lt;br /&gt;
&lt;br /&gt;
SET_BANK_SEGMENT(3, 5); // Segment #5 visible through bank #3&lt;br /&gt;
LoadTilesInVRAM();&lt;br /&gt;
&lt;br /&gt;
...&lt;br /&gt;
&lt;br /&gt;
// Main loop&lt;br /&gt;
while(1)&lt;br /&gt;
{&lt;br /&gt;
    WaitForVSynch();&lt;br /&gt;
    SET_BANK_SEGMENT(3, 6); // Segment #6 visible through bank #3&lt;br /&gt;
    PlayMusic();&lt;br /&gt;
&lt;br /&gt;
    ...&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
To go further, the next step could be, for example, to use bank #2 (the third one) to put specific code that doesn't need to be always visible by your main program.&amp;lt;br/&amp;gt;&lt;br /&gt;
For example, the music player could be in a segment and switch to bank #2 only when you need to decode a music frame.&lt;br /&gt;
&lt;br /&gt;
=== Warning ===&lt;br /&gt;
⚠️ If your main program is larger than the size of one segment, it will span several segments. And since SDCC can add low-level functions anywhere in the space occupied by your main program, you can end up with critical functions (whose calls you don't control) ending up in a segment that you want to switch. And if you do, your program will crash.&lt;br /&gt;
For example, if you use ASCII-16 mapper format and your main program is bigger than 16 KB, part of it will ends up to segment #1 visible through bank #1. If you switch bank #1 to another segment, you will lose visibility to potentially critical functions.&lt;br /&gt;
&lt;br /&gt;
It is therefore strongly recommended that you keep the main programme below the size of the segments that you can keep always visible to the Z80: 16 KB for a 16 KB mapper, and 8, 16 or 24 KB for an 8 KB mapper (depending on whether you keep 1, 2 or 3 segments always visible).&lt;/div&gt;</summary>
		<author><name>Aoineko</name></author>	</entry>

	<entry>
		<id>https://aoineko.org/msxgl/index.php?title=Create_a_mapped_ROM&amp;diff=3969</id>
		<title>Create a mapped ROM</title>
		<link rel="alternate" type="text/html" href="https://aoineko.org/msxgl/index.php?title=Create_a_mapped_ROM&amp;diff=3969"/>
				<updated>2026-05-23T08:06:16Z</updated>
		
		<summary type="html">&lt;p&gt;Aoineko: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;To create cartridges larger than 64 KB, {{MSXGL}} allows to use several types of mapped ROM (often called MegaROM).&lt;br /&gt;
&lt;br /&gt;
This documentation primarily explains how standard mappers work: ASCII-8, ASCII-16, Konami and Konami with SCC.&lt;br /&gt;
Most of this information also applies to the [[NEO mapper]] (NEO-8 and NEO-16), or to other new mappers (Yamanooto, Popolon SCC or ASCII16-X), but for further details, please refer to the relevant sections.&lt;br /&gt;
&lt;br /&gt;
== Principles ==&lt;br /&gt;
&lt;br /&gt;
A mapped ROM cartridge is visible to the Z80 through pages 1 and 2 of the memory space (address 4000h-7FFFh and 8000h-BFFFh).&lt;br /&gt;
This 32 KB space is divided into either 4 '''banks''' (or sub-pages) of 8 KB, or 2 banks of 16 KB.&lt;br /&gt;
This is why mappers are often categorized as 8 KB mapper and 16 KB mapper.&lt;br /&gt;
&lt;br /&gt;
ROMs using these mappers can be for example 128 KB, 256 KB, 512 KB, 1 MB, 2 MB or 4 MB in size (4 MB, only for 16 KB mapper).&lt;br /&gt;
The total content of the ROM is divided into blocks of the mapper size (8 or 16 KB). These blocks are called '''segments'''.&lt;br /&gt;
&lt;br /&gt;
The concept of using mappers is to associate a given segment with a bank to make it visible to the Z80.&lt;br /&gt;
By changing the segments visible in each bank during the course of the program, we can thus access the entire contents of the ROM.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;width:640px; border:medium solid lightblue; margin:0.5em; padding:0.5em;&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;html&amp;gt;&amp;lt;img style=&amp;quot;width:100%&amp;quot; src=&amp;quot;https://raw.githubusercontent.com/aoineko-fr/MSXgl/main/engine/doc/img/target/rom_slot_ascii8_128.png&amp;quot; /&amp;gt;&amp;lt;/html&amp;gt;&lt;br /&gt;
&lt;br /&gt;
''128 KB ROM using an 8 KB mapper (ASCII-8) in slot 1. The ROM is composed of 16 segments, visible to the Z80 through 4 banks. In the example above, segment #0 is visible in bank #0, segment #1 in bank #1, segment #4 in bank #2 and segment #12 in bank #3.''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Change segment visbile through bank ===&lt;br /&gt;
&lt;br /&gt;
To change the visible segment in a bank, you just have to write the segment number to a given address (different depending on the mappers).&lt;br /&gt;
&lt;br /&gt;
Write in a ROM, yes, you read it right!&lt;br /&gt;
&lt;br /&gt;
In fact, mapped ROMs have special mechanisms (mappers) that intercept write signals at certain addresses and use the written value to select the segment.&lt;br /&gt;
Using MSXgl, you don't need to know the addresses or write because you only need to use the &amp;lt;tt&amp;gt;SET_BANK_SEGMENT(bank, seg)&amp;lt;/tt&amp;gt; macro which takes care of associating a segment to a bank.&lt;br /&gt;
&lt;br /&gt;
For example:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
SET_BANK_SEGMENT(1, 8); // Set segment #8 visible through bank #1.&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Types of mappers ===&lt;br /&gt;
&lt;br /&gt;
The supported mappers are:&lt;br /&gt;
{{:Target/Mappers}}&lt;br /&gt;
&lt;br /&gt;
More details on the different mappers:&lt;br /&gt;
* https://www.msx.org/wiki/MegaROM_Mappers&lt;br /&gt;
* http://bifi.msxnet.org/msxnet/tech/megaroms&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;Note&amp;lt;/u&amp;gt;: &amp;quot;MegaROM&amp;quot; refers to a ROM of 128 KB or more. Even though they are not widely supported, there is nothing to prevent you from creating a 64 KB ROM using a mapper. We therefore prefer to use the term Mapped ROM here rather than MegaROM.&lt;br /&gt;
&lt;br /&gt;
== How to ==&lt;br /&gt;
&lt;br /&gt;
=== Setup ===&lt;br /&gt;
&lt;br /&gt;
First, you need to decide which mapper you want to use and what size you need.&amp;lt;br/&amp;gt;&lt;br /&gt;
If you have no idea, start with a 128 KB ROM using ASCII-8 mapper.&lt;br /&gt;
&lt;br /&gt;
The choice of ROM is made in the configuration file of the build tool (&amp;lt;tt&amp;gt;project_config.js&amp;lt;/tt&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;js&amp;quot;&amp;gt;&lt;br /&gt;
target = &amp;quot;ROM_ASCII8&amp;quot;;&lt;br /&gt;
ROMSize = 128;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
See the details of the configuration of the Build Tool: [[Targets#Mapped_ROM_program]].&lt;br /&gt;
&lt;br /&gt;
=== Example ===&lt;br /&gt;
&lt;br /&gt;
A sample program (&amp;lt;tt&amp;gt;s_mapper&amp;lt;/tt&amp;gt;) is available to demonstrate the use of ROM mappers.&lt;br /&gt;
&lt;br /&gt;
In this example, we create a 128 KB mapped ROM in ASCII-8 format (16 segments). The first 4 segments are defined in the main program (32 KB) and 2 others in separate files.&lt;br /&gt;
&lt;br /&gt;
Sample files:&lt;br /&gt;
* &amp;lt;tt&amp;gt;projects/&amp;lt;/tt&amp;gt;&lt;br /&gt;
** &amp;lt;tt&amp;gt;samples/&amp;lt;/tt&amp;gt;&lt;br /&gt;
*** &amp;lt;tt&amp;gt;[https://github.com/aoineko-fr/MSXgl/blob/main/projects/samples/s_mapper.c s_mapper.c]&amp;lt;/tt&amp;gt; (main program)&lt;br /&gt;
*** &amp;lt;tt&amp;gt;[https://github.com/aoineko-fr/MSXgl/blob/main/projects/samples/s_mapper.js s_mapper.js]&amp;lt;/tt&amp;gt; (build tool configuration)&lt;br /&gt;
*** &amp;lt;tt&amp;gt;[https://github.com/aoineko-fr/MSXgl/blob/main/projects/samples/s_mapper_s4_b2.c s_mapper_s4_b2.c]&amp;lt;/tt&amp;gt; (segment #4 C source)&lt;br /&gt;
*** &amp;lt;tt&amp;gt;[https://github.com/aoineko-fr/MSXgl/blob/main/projects/samples/s_mapper_s5_b3.asm s_mapper_s5_b3.asm]&amp;lt;/tt&amp;gt; (segment #5 assembler source)&lt;br /&gt;
&lt;br /&gt;
In the Build Tool:&lt;br /&gt;
* &amp;lt;tt&amp;gt;s_mapper.c&amp;lt;/tt&amp;gt; will be compile as a 32 KB plain ROM (which represents the first 4 segments: #0 to #3).&lt;br /&gt;
* Then, the Build Tool will search for source files for segment #4 to #15 starting with &amp;lt;tt&amp;gt;s_mapper_&amp;lt;/tt&amp;gt;. 3 files extensions are supported: &amp;lt;tt&amp;gt;.c&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;.asm&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;.s&amp;lt;/tt&amp;gt;.&lt;br /&gt;
** &amp;lt;tt&amp;gt;s_mapper_s4_b2.c&amp;lt;/tt&amp;gt; will be find, compile to be visible in bank 2 (from 0x8000) and added to link list.&lt;br /&gt;
** &amp;lt;tt&amp;gt;s_mapper_s5_b3.asm&amp;lt;/tt&amp;gt; will be find, compile to be visible in bank 3 (from 0xA000) and added to link list. Assembler segment source file must include the &amp;lt;tt&amp;gt;.area&amp;lt;/tt&amp;gt; directive with the segment name &amp;lt;tt&amp;gt;_SEG{num}&amp;lt;/tt&amp;gt; (&amp;lt;tt&amp;gt;_SEG5&amp;lt;/tt&amp;gt; here).&lt;br /&gt;
* All the source will be linked together (and symbols will be &amp;quot;resolved&amp;quot;).&lt;br /&gt;
* The final binary file will be create by [[MSXhex]], putting each segment at its final location in the ROM.&lt;br /&gt;
&lt;br /&gt;
=== Symbols ===&lt;br /&gt;
&lt;br /&gt;
Segment symbols (tables or functions name) can be accessed from any other sources.&amp;lt;br/&amp;gt;&lt;br /&gt;
No more need to know the address of a data in a segment of the mapper; it is enough to call it by its name (which also allows the C compiler to validate the data type).&amp;lt;br/&amp;gt;&lt;br /&gt;
It is therefore also much easier to accumulate data in a segment since it is only necessary to put the data one after the other; the address of the arrays being resolved at link time.&amp;lt;br/&amp;gt;&lt;br /&gt;
The switching of the segments remains the responsibility of the programmer. &lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
// File: mygame_s5_b3.c&lt;br /&gt;
// Segment #5 (bank #3)&lt;br /&gt;
&lt;br /&gt;
const u8 MyData[] = { 1, 2, 3, 4, 5, 6, 7, 8 }; &lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
// File: mygame.c&lt;br /&gt;
// Main program&lt;br /&gt;
&lt;br /&gt;
extern const u8 MyData[]; // Tell the compiler this data exists somewhere else.&lt;br /&gt;
&lt;br /&gt;
SET_BANK_SEGMENT(3, 5); // Switch segment visible through bank #3.&lt;br /&gt;
u8 s = MyData[1];&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Banked call ===&lt;br /&gt;
&lt;br /&gt;
SDCC banked calls (using the &amp;lt;tt&amp;gt;__banked&amp;lt;/tt&amp;gt; directive) can be used to call a function in a segment and have an automatic bank switching to this segment before call, and then, a restoration of the previous segment after function returns.&lt;br /&gt;
The only limitation is that SDCC only returns the segment number (and not the bank number) to the default trampoline functions.&lt;br /&gt;
So, to make it simple (and efficient), MSXgl only allow (for the moment) a switch on one of a mapped-ROM's bank.&lt;br /&gt;
* For 8 KB mapper : bank #2 (8000h-9FFFh)&lt;br /&gt;
* For 16 KB mapper : bank #1 (8000h-BFFFh)&lt;br /&gt;
To activate this feature, you need to add &amp;lt;tt&amp;gt;set BankedCall=true;&amp;lt;/tt&amp;gt; in your &amp;quot;project_config.js&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
// File: mygame_s7_b2.c&lt;br /&gt;
// Segment #7 (bank #2)&lt;br /&gt;
&lt;br /&gt;
u8 LocalFunc() { return 2; }&lt;br /&gt;
u8 BankedFunc() __banked { return LocalFunc()+1; };&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
// File: mygame.c&lt;br /&gt;
// Main program&lt;br /&gt;
&lt;br /&gt;
u8 BankedFunc() __banked; // Prototype to tell the compiler this function exists somewhere else.&lt;br /&gt;
&lt;br /&gt;
void main()&lt;br /&gt;
{&lt;br /&gt;
   BankedFunc(); // automatic switch to segment #7 then restore previous segment&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
⚠️ &amp;lt;u&amp;gt;Note&amp;lt;/u&amp;gt;: Banked functions seem simple to use at first glance, but I don't recommend using them as they make segment switching invisible and can be a source of many bugs. Making bank switches by hand has the big advantage of making them explicit in the code, so you don't lose sight of this sensitive mechanism.&lt;br /&gt;
&lt;br /&gt;
=== Raw binary data ===&lt;br /&gt;
&lt;br /&gt;
MSXgl also provides a means of adding raw binary data directly to segments. This data is not compiled (faster) and is simply added to the final ROM, automatically placing it in the right place.&lt;br /&gt;
&lt;br /&gt;
All you have to do is define the &amp;lt;tt&amp;gt;RawFiles&amp;lt;/tt&amp;gt; parameter in your project configuration (&amp;lt;tt&amp;gt;project_setting.js&amp;lt;/tt&amp;gt;) with an array of the type:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;js&amp;quot;&amp;gt;&lt;br /&gt;
//-- List of raw data files to be added to final binary (array). Each entry must be in the following format: { offset:0x0000, file:&amp;quot;myfile.bin&amp;quot; }&lt;br /&gt;
RawFiles = [&lt;br /&gt;
    { segment: 2, file: &amp;quot;content/music1.vgm&amp;quot;},&lt;br /&gt;
    { segment: 3, file: &amp;quot;content/music2.vgm&amp;quot; },&lt;br /&gt;
    { offset: 0x18000, file: &amp;quot;content/image.bin&amp;quot; },&lt;br /&gt;
    { page: 4, file: &amp;quot;content/video.bin&amp;quot; }&lt;br /&gt;
];&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The first parameter of each table entry can be any of 3 types:&lt;br /&gt;
* &amp;lt;tt&amp;gt;offset&amp;lt;/tt&amp;gt;: a 32-bit offset (decimal or hexadecimal) from the start of the ROM.&lt;br /&gt;
* &amp;lt;tt&amp;gt;segment&amp;lt;/tt&amp;gt;: segment number for mapped ROMs (Build tool use mapper's bank size to determine the final position).&lt;br /&gt;
* &amp;lt;tt&amp;gt;page&amp;lt;/tt&amp;gt;: page number (16 KB) for mapped or plain ROM.&lt;br /&gt;
&lt;br /&gt;
A header file (named &amp;lt;tt&amp;gt;myproject_rawdef.h&amp;lt;/tt&amp;gt;) with information about those raw files will be generated before compiling occurs so you can include it in your program.&lt;br /&gt;
&lt;br /&gt;
You can add several binary files to the same segment/page. In this case, data will be concatenated from the given segment/page start address. In this case, you need to use the generated header file to know where the file ends up.&lt;br /&gt;
&lt;br /&gt;
The sample &amp;lt;tt&amp;gt;s_vgm&amp;lt;/tt&amp;gt; showcase the use this option.&lt;br /&gt;
&lt;br /&gt;
=== Initial slot configuration ===&lt;br /&gt;
&lt;br /&gt;
When your &amp;lt;tt&amp;gt;main()&amp;lt;/tt&amp;gt; function start, the mapped-ROM cartridge slot is selected in pages #1 and #2 of the memory space.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;img style=&amp;quot;width:400px; margin:0.5em;&amp;quot; src=&amp;quot;https://raw.githubusercontent.com/aoineko-fr/MSXgl/main/engine/doc/img/target/rom_slot_ascii8_128.png&amp;quot; /&amp;gt;&lt;br /&gt;
&amp;lt;img style=&amp;quot;width:400px; margin:0.5em;&amp;quot; src=&amp;quot;https://raw.githubusercontent.com/aoineko-fr/MSXgl/main/engine/doc/img/target/rom_slot_ascii16_128.png&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Also, the banks are initially setup as:&lt;br /&gt;
&lt;br /&gt;
For 8 KB mappers:&lt;br /&gt;
* Bank #0 (4000h-5FFFh): Segment #0 (contain the ROM header)&lt;br /&gt;
* Bank #1 (6000h-7FFFh): Segment #1&lt;br /&gt;
* Bank #2 (8000h-9FFFh): Segment #2&lt;br /&gt;
* Bank #3 (A000h-BFFFh): Segment #3&lt;br /&gt;
&lt;br /&gt;
For 16 KB mappers:&lt;br /&gt;
* Bank #0 (4000h-7FFFh): Segment #0 (contain the ROM header)&lt;br /&gt;
* Bank #1 (8000h-BFFFh): Segment #1&lt;br /&gt;
&lt;br /&gt;
=== NEO mapper ===&lt;br /&gt;
[[NEO mapper]] works on the same principle as the legacy mappers, but has more bank switching registers (covering page 0) and registers are 16-bit instead of 8-bit.&lt;br /&gt;
&lt;br /&gt;
When your &amp;lt;tt&amp;gt;main()&amp;lt;/tt&amp;gt; function start, the mapped-ROM cartridge slot is selected in pages #0, #1 and #2 of the memory space.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;img style=&amp;quot;width:400px; margin:0.5em;&amp;quot; src=&amp;quot;https://raw.githubusercontent.com/aoineko-fr/MSXgl/main/engine/doc/mapper_neo8.png&amp;quot; /&amp;gt;&lt;br /&gt;
&amp;lt;img style=&amp;quot;width:400px; margin:0.5em;&amp;quot; src=&amp;quot;https://raw.githubusercontent.com/aoineko-fr/MSXgl/main/engine/doc/mapper_neo16.png&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Segment #4 of the NEO-8 and segment #2 of the NEO-16 have a special use: they are designed to be selected in bank #0, and the Build tool will automatically add an interrupt handling code (ISR) to them. This segment can be used to store code or data, but note that it will be accumulated from address 0x0100 (after the ISR).&lt;br /&gt;
&lt;br /&gt;
Default selected segments:&lt;br /&gt;
&lt;br /&gt;
NEO-8&lt;br /&gt;
* Bank #0 (0000h-1FFFh): Segment #4 (contain the ISR + user code/data after 0x0100)&lt;br /&gt;
* Bank #1 (2000h-3FFFh): Segment #5&lt;br /&gt;
* Bank #2 (4000h-5FFFh): Segment #0 (contain the ROM header)&lt;br /&gt;
* Bank #3 (6000h-7FFFh): Segment #1&lt;br /&gt;
* Bank #4 (8000h-9FFFh): Segment #2&lt;br /&gt;
* Bank #5 (A000h-BFFFh): Segment #3&lt;br /&gt;
&lt;br /&gt;
NEO-16&lt;br /&gt;
* Bank #0 (0000h-3FFFh): Segment #2 (contain the ISR + user code/data after 0x0100)&lt;br /&gt;
* Bank #1 (4000h-7FFFh): Segment #0 (contain the ROM header)&lt;br /&gt;
* Bank #2 (8000h-BFFFh): Segment #1&lt;br /&gt;
&lt;br /&gt;
See the [[NEO mapper|NEO mapper specifications]] for more details about the mapper.&lt;br /&gt;
&lt;br /&gt;
=== Yamanooto &amp;amp; ASCII16-X ===&lt;br /&gt;
Yamanooto and ASCII16-X are mappers that works like legacy mappers but allows more the 256 segments so they overcome their maximal size.&lt;br /&gt;
&lt;br /&gt;
Yamanoto:&lt;br /&gt;
* Banks: 4 banks of 8 KB (visible on memory pages 1 and 2)&lt;br /&gt;
* Size: up to 8 MB&lt;br /&gt;
* Support: Yamanooto and openMSX&lt;br /&gt;
&lt;br /&gt;
ASCII16-X:&lt;br /&gt;
* Banks: 2 banks of 16 KB (visible on memory pages 1 and 2)&lt;br /&gt;
* Size: up to 64 MB&lt;br /&gt;
* Support: Incomming hardware and openMSX (8 MB)&lt;br /&gt;
&lt;br /&gt;
== Advice ==&lt;br /&gt;
&lt;br /&gt;
The simplest way to start with mapped-ROM is to use a 8 KB mapper (ASCII-8 for example) and to keep the first 3 segments always visible from the first 3 banks (the initial state), and then use the last bank (#3) to switch between all other segments.&lt;br /&gt;
&lt;br /&gt;
This allows to have a 24 KB program (3 segments) always visible by the Z80 and to switch only the segments that contain the data, when needed.&lt;br /&gt;
&lt;br /&gt;
Let's say you have a 24 KB (segment #0, #1 and #2) program and 3 data segments containing: sprites (segment #4), background tiles (segment #5) and music (segment #6).&amp;lt;br/&amp;gt;&lt;br /&gt;
Your pseudo code could be something like this:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
// File: mygame.c&lt;br /&gt;
...&lt;br /&gt;
&lt;br /&gt;
// Init VRAM data&lt;br /&gt;
SET_BANK_SEGMENT(3, 4); // Segment #4 visible through bank #3&lt;br /&gt;
LoadSpriteInVRAM();&lt;br /&gt;
&lt;br /&gt;
SET_BANK_SEGMENT(3, 5); // Segment #5 visible through bank #3&lt;br /&gt;
LoadTilesInVRAM();&lt;br /&gt;
&lt;br /&gt;
...&lt;br /&gt;
&lt;br /&gt;
// Main loop&lt;br /&gt;
while(1)&lt;br /&gt;
{&lt;br /&gt;
    WaitForVSynch();&lt;br /&gt;
    SET_BANK_SEGMENT(3, 6); // Segment #6 visible through bank #3&lt;br /&gt;
    PlayMusic();&lt;br /&gt;
&lt;br /&gt;
    ...&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
To go further, the next step could be, for example, to use bank #2 (the third one) to put specific code that doesn't need to be always visible by your main program.&amp;lt;br/&amp;gt;&lt;br /&gt;
For example, the music player could be in a segment and switch to bank #2 only when you need to decode a music frame.&lt;br /&gt;
&lt;br /&gt;
=== Warning ===&lt;br /&gt;
⚠️ If your main program is larger than the size of one segment, it will span several segments. And since SDCC can add low-level functions anywhere in the space occupied by your main program, you can end up with critical functions (whose calls you don't control) ending up in a segment that you want to switch. And if you do, your program will crash.&lt;br /&gt;
For example, if you use ASCII-16 mapper format and your main program is bigger than 16 KB, part of it will ends up to segment #1 visible through bank #1. If you switch bank #1 to another segment, you will lose visibility to potentially critical functions.&lt;br /&gt;
&lt;br /&gt;
It is therefore strongly recommended that you keep the main programme below the size of the segments that you can keep always visible to the Z80: 16 KB for a 16 KB mapper, and 8, 16 or 24 KB for an 8 KB mapper (depending on whether you keep 1, 2 or 3 segments always visible).&lt;/div&gt;</summary>
		<author><name>Aoineko</name></author>	</entry>

	<entry>
		<id>https://aoineko.org/msxgl/index.php?title=Create_a_mapped_ROM&amp;diff=3968</id>
		<title>Create a mapped ROM</title>
		<link rel="alternate" type="text/html" href="https://aoineko.org/msxgl/index.php?title=Create_a_mapped_ROM&amp;diff=3968"/>
				<updated>2026-05-23T07:58:16Z</updated>
		
		<summary type="html">&lt;p&gt;Aoineko: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;To create cartridges larger than 64 KB, {{MSXGL}} allows to use several types of mapped-ROM (often called MegaROM).&lt;br /&gt;
&lt;br /&gt;
This documentation primarily explains how standard mappers work: ASCII-8, ASCII-16, Konami and Konami with SCC.&lt;br /&gt;
Most of this information also applies to the [[NEO mapper]] (NEO-8 and NEO-16), or to other new mappers (Yamanooto, Popolon SCC or ASCII16-X), but for further details, please refer to the relevant sections.&lt;br /&gt;
&lt;br /&gt;
== Principles ==&lt;br /&gt;
&lt;br /&gt;
A mapped ROM is visible in pages 1 and 2 of the Z80 memory space (address 4000h-7FFFh and 8000h-BFFFh).&amp;lt;br/&amp;gt;&lt;br /&gt;
This 32 KB space is divided into either 4 '''banks''' (or sub-pages) of 8 KB or 2 banks of 16 KB.&lt;br /&gt;
This is why mappers are often categorized as 8 KB mapper and 16 KB mapper.&lt;br /&gt;
&lt;br /&gt;
ROMs using these mappers can be for example 128 KB, 256 KB, 512 KB, 1 MB, 2 MB or 4 MB in size (4 MB, only for 16 KB mapper).&amp;lt;br/&amp;gt;&lt;br /&gt;
The total content of the ROM is divided into blocks of the mapper size (8 or 16 KB). These blocks are called '''segments'''.&lt;br /&gt;
&lt;br /&gt;
The concept of using mappers is to associate a given segment with a bank to make it visible to the Z80.&amp;lt;br/&amp;gt;&lt;br /&gt;
By changing the segments visible in each bank during the course of the program, we can thus access the entire contents of the ROM.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;width:640px; border:medium solid lightblue; margin:0.5em; padding:0.5em;&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;html&amp;gt;&amp;lt;img style=&amp;quot;width:100%&amp;quot; src=&amp;quot;https://raw.githubusercontent.com/aoineko-fr/MSXgl/main/engine/doc/img/target/rom_slot_ascii8_128.png&amp;quot; /&amp;gt;&amp;lt;/html&amp;gt;&lt;br /&gt;
&lt;br /&gt;
''128 KB ROM using an 8 KB mapper (ASCII-8) in slot 1. The ROM is composed of 16 segments, visible to the Z80 through 4 banks. In the example above, segment #0 is visible in bank #0, segment #1 in bank #1, segment #4 in bank #2 and segment #12 in bank #3.''&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Change segment visbile through bank ===&lt;br /&gt;
&lt;br /&gt;
To change the visible segment in a bank, you just have to write the segment number to a given address (different depending on the mappers).&amp;lt;br/&amp;gt;&lt;br /&gt;
Write in a ROM, yes, you read it right!&lt;br /&gt;
&lt;br /&gt;
In fact, mapped ROMs have special mechanisms (mappers) that intercept write signals at certain addresses and use the written value to select the segment.&amp;lt;br/&amp;gt;&lt;br /&gt;
Using MSXgl, you don't need to know the addresses or write because you only need to use the &amp;lt;tt&amp;gt;SET_BANK_SEGMENT(bank, seg)&amp;lt;/tt&amp;gt; macro which takes care of associating a segment to a bank.&lt;br /&gt;
&lt;br /&gt;
=== Types of mappers ===&lt;br /&gt;
&lt;br /&gt;
The supported mappers are:&lt;br /&gt;
{{:Target/Mappers}}&lt;br /&gt;
&lt;br /&gt;
More details on the different mappers:&lt;br /&gt;
* https://www.msx.org/wiki/MegaROM_Mappers&lt;br /&gt;
* http://bifi.msxnet.org/msxnet/tech/megaroms&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;Note&amp;lt;/u&amp;gt;: &amp;quot;MegaROM&amp;quot; refers to a ROM of 128 KB or more. Even though they are not widely supported, there is nothing to prevent you from creating a 64 KB ROM using a mapper. We therefore prefer to use the term Mapped ROM here rather than MegaROM.&lt;br /&gt;
&lt;br /&gt;
== How to ==&lt;br /&gt;
&lt;br /&gt;
=== Setup ===&lt;br /&gt;
&lt;br /&gt;
First, you need to decide which mapper you want to use and what size you need.&amp;lt;br/&amp;gt;&lt;br /&gt;
If you have no idea, start with a 128 KB ROM using ASCII-8 mapper.&lt;br /&gt;
&lt;br /&gt;
The choice of ROM is made in the configuration file of the build tool (&amp;lt;tt&amp;gt;project_config.js&amp;lt;/tt&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;js&amp;quot;&amp;gt;&lt;br /&gt;
target = &amp;quot;ROM_ASCII8&amp;quot;;&lt;br /&gt;
ROMSize = 128;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
See the details of the configuration of the Build Tool: [[Targets#Mapped_ROM_program]].&lt;br /&gt;
&lt;br /&gt;
=== Example ===&lt;br /&gt;
&lt;br /&gt;
A sample program (&amp;lt;tt&amp;gt;s_mapper&amp;lt;/tt&amp;gt;) is available to demonstrate the use of ROM mappers.&lt;br /&gt;
&lt;br /&gt;
In this example, we create a 128 KB mapped ROM in ASCII-8 format (16 segments). The first 4 segments are defined in the main program (32 KB) and 2 others in separate files.&lt;br /&gt;
&lt;br /&gt;
Sample files:&lt;br /&gt;
* &amp;lt;tt&amp;gt;projects/&amp;lt;/tt&amp;gt;&lt;br /&gt;
** &amp;lt;tt&amp;gt;samples/&amp;lt;/tt&amp;gt;&lt;br /&gt;
*** &amp;lt;tt&amp;gt;[https://github.com/aoineko-fr/MSXgl/blob/main/projects/samples/s_mapper.c s_mapper.c]&amp;lt;/tt&amp;gt; (main program)&lt;br /&gt;
*** &amp;lt;tt&amp;gt;[https://github.com/aoineko-fr/MSXgl/blob/main/projects/samples/s_mapper.js s_mapper.js]&amp;lt;/tt&amp;gt; (build tool configuration)&lt;br /&gt;
*** &amp;lt;tt&amp;gt;[https://github.com/aoineko-fr/MSXgl/blob/main/projects/samples/s_mapper_s4_b2.c s_mapper_s4_b2.c]&amp;lt;/tt&amp;gt; (segment #4 C source)&lt;br /&gt;
*** &amp;lt;tt&amp;gt;[https://github.com/aoineko-fr/MSXgl/blob/main/projects/samples/s_mapper_s5_b3.asm s_mapper_s5_b3.asm]&amp;lt;/tt&amp;gt; (segment #5 assembler source)&lt;br /&gt;
&lt;br /&gt;
In the Build Tool:&lt;br /&gt;
* &amp;lt;tt&amp;gt;s_mapper.c&amp;lt;/tt&amp;gt; will be compile as a 32 KB plain ROM (which represents the first 4 segments: #0 to #3).&lt;br /&gt;
* Then, the Build Tool will search for source files for segment #4 to #15 starting with &amp;lt;tt&amp;gt;s_mapper_&amp;lt;/tt&amp;gt;. 3 files extensions are supported: &amp;lt;tt&amp;gt;.c&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;.asm&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;.s&amp;lt;/tt&amp;gt;.&lt;br /&gt;
** &amp;lt;tt&amp;gt;s_mapper_s4_b2.c&amp;lt;/tt&amp;gt; will be find, compile to be visible in bank 2 (from 0x8000) and added to link list.&lt;br /&gt;
** &amp;lt;tt&amp;gt;s_mapper_s5_b3.asm&amp;lt;/tt&amp;gt; will be find, compile to be visible in bank 3 (from 0xA000) and added to link list. Assembler segment source file must include the &amp;lt;tt&amp;gt;.area&amp;lt;/tt&amp;gt; directive with the segment name &amp;lt;tt&amp;gt;_SEG{num}&amp;lt;/tt&amp;gt; (&amp;lt;tt&amp;gt;_SEG5&amp;lt;/tt&amp;gt; here).&lt;br /&gt;
* All the source will be linked together (and symbols will be &amp;quot;resolved&amp;quot;).&lt;br /&gt;
* The final binary file will be create by [[MSXhex]], putting each segment at its final location in the ROM.&lt;br /&gt;
&lt;br /&gt;
=== Symbols ===&lt;br /&gt;
&lt;br /&gt;
Segment symbols (tables or functions name) can be accessed from any other sources.&amp;lt;br/&amp;gt;&lt;br /&gt;
No more need to know the address of a data in a segment of the mapper; it is enough to call it by its name (which also allows the C compiler to validate the data type).&amp;lt;br/&amp;gt;&lt;br /&gt;
It is therefore also much easier to accumulate data in a segment since it is only necessary to put the data one after the other; the address of the arrays being resolved at link time.&amp;lt;br/&amp;gt;&lt;br /&gt;
The switching of the segments remains the responsibility of the programmer. &lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
// File: mygame_s5_b3.c&lt;br /&gt;
// Segment #5 (bank #3)&lt;br /&gt;
&lt;br /&gt;
const u8 MyData[] = { 1, 2, 3, 4, 5, 6, 7, 8 }; &lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
// File: mygame.c&lt;br /&gt;
// Main program&lt;br /&gt;
&lt;br /&gt;
extern const u8 MyData[]; // Tell the compiler this data exists somewhere else.&lt;br /&gt;
&lt;br /&gt;
SET_BANK_SEGMENT(3, 5); // Switch segment visible through bank #3.&lt;br /&gt;
u8 s = MyData[1];&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Banked call ===&lt;br /&gt;
&lt;br /&gt;
SDCC banked calls (using the &amp;lt;tt&amp;gt;__banked&amp;lt;/tt&amp;gt; directive) can be used to call a function in a segment and have an automatic bank switching to this segment before call, and then, a restoration of the previous segment after function returns.&lt;br /&gt;
The only limitation is that SDCC only returns the segment number (and not the bank number) to the default trampoline functions.&lt;br /&gt;
So, to make it simple (and efficient), MSXgl only allow (for the moment) a switch on one of a mapped-ROM's bank.&lt;br /&gt;
* For 8 KB mapper : bank #2 (8000h-9FFFh)&lt;br /&gt;
* For 16 KB mapper : bank #1 (8000h-BFFFh)&lt;br /&gt;
To activate this feature, you need to add &amp;lt;tt&amp;gt;set BankedCall=true;&amp;lt;/tt&amp;gt; in your &amp;quot;project_config.js&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
// File: mygame_s7_b2.c&lt;br /&gt;
// Segment #7 (bank #2)&lt;br /&gt;
&lt;br /&gt;
u8 LocalFunc() { return 2; }&lt;br /&gt;
u8 BankedFunc() __banked { return LocalFunc()+1; };&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
// File: mygame.c&lt;br /&gt;
// Main program&lt;br /&gt;
&lt;br /&gt;
u8 BankedFunc() __banked; // Prototype to tell the compiler this function exists somewhere else.&lt;br /&gt;
&lt;br /&gt;
void main()&lt;br /&gt;
{&lt;br /&gt;
   BankedFunc(); // automatic switch to segment #7 then restore previous segment&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
⚠️ &amp;lt;u&amp;gt;Note&amp;lt;/u&amp;gt;: Banked functions seem simple to use at first glance, but I don't recommend using them as they make segment switching invisible and can be a source of many bugs. Making bank switches by hand has the big advantage of making them explicit in the code, so you don't lose sight of this sensitive mechanism.&lt;br /&gt;
&lt;br /&gt;
=== Raw binary data ===&lt;br /&gt;
&lt;br /&gt;
MSXgl also provides a means of adding raw binary data directly to segments. This data is not compiled (faster) and is simply added to the final ROM, automatically placing it in the right place.&lt;br /&gt;
&lt;br /&gt;
All you have to do is define the &amp;lt;tt&amp;gt;RawFiles&amp;lt;/tt&amp;gt; parameter in your project configuration (&amp;lt;tt&amp;gt;project_setting.js&amp;lt;/tt&amp;gt;) with an array of the type:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;js&amp;quot;&amp;gt;&lt;br /&gt;
//-- List of raw data files to be added to final binary (array). Each entry must be in the following format: { offset:0x0000, file:&amp;quot;myfile.bin&amp;quot; }&lt;br /&gt;
RawFiles = [&lt;br /&gt;
    { segment: 2, file: &amp;quot;content/music1.vgm&amp;quot;},&lt;br /&gt;
    { segment: 3, file: &amp;quot;content/music2.vgm&amp;quot; },&lt;br /&gt;
    { offset: 0x18000, file: &amp;quot;content/image.bin&amp;quot; },&lt;br /&gt;
    { page: 4, file: &amp;quot;content/video.bin&amp;quot; }&lt;br /&gt;
];&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The first parameter of each table entry can be any of 3 types:&lt;br /&gt;
* &amp;lt;tt&amp;gt;offset&amp;lt;/tt&amp;gt;: a 32-bit offset (decimal or hexadecimal) from the start of the ROM.&lt;br /&gt;
* &amp;lt;tt&amp;gt;segment&amp;lt;/tt&amp;gt;: segment number for mapped ROMs (Build tool use mapper's bank size to determine the final position).&lt;br /&gt;
* &amp;lt;tt&amp;gt;page&amp;lt;/tt&amp;gt;: page number (16 KB) for mapped or plain ROM.&lt;br /&gt;
&lt;br /&gt;
A header file (named &amp;lt;tt&amp;gt;myproject_rawdef.h&amp;lt;/tt&amp;gt;) with information about those raw files will be generated before compiling occurs so you can include it in your program.&lt;br /&gt;
&lt;br /&gt;
You can add several binary files to the same segment/page. In this case, data will be concatenated from the given segment/page start address. In this case, you need to use the generated header file to know where the file ends up.&lt;br /&gt;
&lt;br /&gt;
The sample &amp;lt;tt&amp;gt;s_vgm&amp;lt;/tt&amp;gt; showcase the use this option.&lt;br /&gt;
&lt;br /&gt;
=== Initial slot configuration ===&lt;br /&gt;
&lt;br /&gt;
When your &amp;lt;tt&amp;gt;main()&amp;lt;/tt&amp;gt; function start, the mapped-ROM cartridge slot is selected in pages #1 and #2 of the memory space.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;img style=&amp;quot;width:400px; margin:0.5em;&amp;quot; src=&amp;quot;https://raw.githubusercontent.com/aoineko-fr/MSXgl/main/engine/doc/img/target/rom_slot_ascii8_128.png&amp;quot; /&amp;gt;&lt;br /&gt;
&amp;lt;img style=&amp;quot;width:400px; margin:0.5em;&amp;quot; src=&amp;quot;https://raw.githubusercontent.com/aoineko-fr/MSXgl/main/engine/doc/img/target/rom_slot_ascii16_128.png&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Also, the banks are initially setup as:&lt;br /&gt;
&lt;br /&gt;
For 8 KB mappers:&lt;br /&gt;
* Bank #0 (4000h-5FFFh): Segment #0 (contain the ROM header)&lt;br /&gt;
* Bank #1 (6000h-7FFFh): Segment #1&lt;br /&gt;
* Bank #2 (8000h-9FFFh): Segment #2&lt;br /&gt;
* Bank #3 (A000h-BFFFh): Segment #3&lt;br /&gt;
&lt;br /&gt;
For 16 KB mappers:&lt;br /&gt;
* Bank #0 (4000h-7FFFh): Segment #0 (contain the ROM header)&lt;br /&gt;
* Bank #1 (8000h-BFFFh): Segment #1&lt;br /&gt;
&lt;br /&gt;
=== NEO mapper ===&lt;br /&gt;
[[NEO mapper]] works on the same principle as the legacy mappers, but has more bank switching registers (covering page 0) and registers are 16-bit instead of 8-bit.&lt;br /&gt;
&lt;br /&gt;
When your &amp;lt;tt&amp;gt;main()&amp;lt;/tt&amp;gt; function start, the mapped-ROM cartridge slot is selected in pages #0, #1 and #2 of the memory space.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;img style=&amp;quot;width:400px; margin:0.5em;&amp;quot; src=&amp;quot;https://raw.githubusercontent.com/aoineko-fr/MSXgl/main/engine/doc/mapper_neo8.png&amp;quot; /&amp;gt;&lt;br /&gt;
&amp;lt;img style=&amp;quot;width:400px; margin:0.5em;&amp;quot; src=&amp;quot;https://raw.githubusercontent.com/aoineko-fr/MSXgl/main/engine/doc/mapper_neo16.png&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Segment #4 of the NEO-8 and segment #2 of the NEO-16 have a special use: they are designed to be selected in bank #0, and the Build tool will automatically add an interrupt handling code (ISR) to them. This segment can be used to store code or data, but note that it will be accumulated from address 0x0100 (after the ISR).&lt;br /&gt;
&lt;br /&gt;
Default selected segments:&lt;br /&gt;
&lt;br /&gt;
NEO-8&lt;br /&gt;
* Bank #0 (0000h-1FFFh): Segment #4 (contain the ISR + user code/data after 0x0100)&lt;br /&gt;
* Bank #1 (2000h-3FFFh): Segment #5&lt;br /&gt;
* Bank #2 (4000h-5FFFh): Segment #0 (contain the ROM header)&lt;br /&gt;
* Bank #3 (6000h-7FFFh): Segment #1&lt;br /&gt;
* Bank #4 (8000h-9FFFh): Segment #2&lt;br /&gt;
* Bank #5 (A000h-BFFFh): Segment #3&lt;br /&gt;
&lt;br /&gt;
NEO-16&lt;br /&gt;
* Bank #0 (0000h-3FFFh): Segment #2 (contain the ISR + user code/data after 0x0100)&lt;br /&gt;
* Bank #1 (4000h-7FFFh): Segment #0 (contain the ROM header)&lt;br /&gt;
* Bank #2 (8000h-BFFFh): Segment #1&lt;br /&gt;
&lt;br /&gt;
See the [[NEO mapper|NEO mapper specifications]] for more details about the mapper.&lt;br /&gt;
&lt;br /&gt;
=== Yamanooto &amp;amp; ASCII16-X ===&lt;br /&gt;
Yamanooto and ASCII16-X are mappers that works like legacy mappers but allows more the 256 segments so they overcome their maximal size.&lt;br /&gt;
&lt;br /&gt;
Yamanoto:&lt;br /&gt;
* Banks: 4 banks of 8 KB (visible on memory pages 1 and 2)&lt;br /&gt;
* Size: up to 8 MB&lt;br /&gt;
* Support: Yamanooto and openMSX&lt;br /&gt;
&lt;br /&gt;
ASCII16-X:&lt;br /&gt;
* Banks: 2 banks of 16 KB (visible on memory pages 1 and 2)&lt;br /&gt;
* Size: up to 64 MB&lt;br /&gt;
* Support: Incomming hardware and openMSX (8 MB)&lt;br /&gt;
&lt;br /&gt;
== Advice ==&lt;br /&gt;
&lt;br /&gt;
The simplest way to start with mapped-ROM is to use a 8 KB mapper (ASCII-8 for example) and to keep the first 3 segments always visible from the first 3 banks (the initial state), and then use the last bank (#3) to switch between all other segments.&lt;br /&gt;
&lt;br /&gt;
This allows to have a 24 KB program (3 segments) always visible by the Z80 and to switch only the segments that contain the data, when needed.&lt;br /&gt;
&lt;br /&gt;
Let's say you have a 24 KB (segment #0, #1 and #2) program and 3 data segments containing: sprites (segment #4), background tiles (segment #5) and music (segment #6).&amp;lt;br/&amp;gt;&lt;br /&gt;
Your pseudo code could be something like this:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
// File: mygame.c&lt;br /&gt;
...&lt;br /&gt;
&lt;br /&gt;
// Init VRAM data&lt;br /&gt;
SET_BANK_SEGMENT(3, 4); // Segment #4 visible through bank #3&lt;br /&gt;
LoadSpriteInVRAM();&lt;br /&gt;
&lt;br /&gt;
SET_BANK_SEGMENT(3, 5); // Segment #5 visible through bank #3&lt;br /&gt;
LoadTilesInVRAM();&lt;br /&gt;
&lt;br /&gt;
...&lt;br /&gt;
&lt;br /&gt;
// Main loop&lt;br /&gt;
while(1)&lt;br /&gt;
{&lt;br /&gt;
    WaitForVSynch();&lt;br /&gt;
    SET_BANK_SEGMENT(3, 6); // Segment #6 visible through bank #3&lt;br /&gt;
    PlayMusic();&lt;br /&gt;
&lt;br /&gt;
    ...&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
To go further, the next step could be, for example, to use bank #2 (the third one) to put specific code that doesn't need to be always visible by your main program.&amp;lt;br/&amp;gt;&lt;br /&gt;
For example, the music player could be in a segment and switch to bank #2 only when you need to decode a music frame.&lt;br /&gt;
&lt;br /&gt;
=== Warning ===&lt;br /&gt;
⚠️ If your main program is larger than the size of one segment, it will span several segments. And since SDCC can add low-level functions anywhere in the space occupied by your main program, you can end up with critical functions (whose calls you don't control) ending up in a segment that you want to switch. And if you do, your program will crash.&lt;br /&gt;
For example, if you use ASCII-16 mapper format and your main program is bigger than 16 KB, part of it will ends up to segment #1 visible through bank #1. If you switch bank #1 to another segment, you will lose visibility to potentially critical functions.&lt;br /&gt;
&lt;br /&gt;
It is therefore strongly recommended that you keep the main programme below the size of the segments that you can keep always visible to the Z80: 16 KB for a 16 KB mapper, and 8, 16 or 24 KB for an 8 KB mapper (depending on whether you keep 1, 2 or 3 segments always visible).&lt;/div&gt;</summary>
		<author><name>Aoineko</name></author>	</entry>

	<entry>
		<id>https://aoineko.org/msxgl/index.php?title=Build_tool&amp;diff=3967</id>
		<title>Build tool</title>
		<link rel="alternate" type="text/html" href="https://aoineko.org/msxgl/index.php?title=Build_tool&amp;diff=3967"/>
				<updated>2026-05-21T07:28:06Z</updated>
		
		<summary type="html">&lt;p&gt;Aoineko: /* Localization */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;The '''Build tool''' is the {{MSXGL}} script that will create your final program for MSX.&lt;br /&gt;
&lt;br /&gt;
It is fully configurable by the user. For example, it is here that we can choose whether we want our game to be available in ROM, MSX-DOS or BASIC binary format. Or if our program should be MSX1 compatible or only MSX2+ for example.&lt;br /&gt;
&lt;br /&gt;
The Build tool is written in JavaScript and executed via Node.js. All the programs needed to run the script are available in MSXgl and the user does not need to install anything.&lt;br /&gt;
&lt;br /&gt;
Build tool is started from the project directory via a script that depends on the platform:&lt;br /&gt;
* On Windows, run &amp;lt;tt&amp;gt;build.bat&amp;lt;/tt&amp;gt;,&lt;br /&gt;
* On Linux, run &amp;lt;tt&amp;gt;./build.sh&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
See the &amp;lt;tt&amp;gt;example&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;template&amp;lt;/tt&amp;gt; project for an actual use case.&lt;br /&gt;
&lt;br /&gt;
== Configuration ==&lt;br /&gt;
&lt;br /&gt;
The Build tool configuration's parameters are defined in the '''engine''' (&amp;lt;tt&amp;gt;engine/script/js/setup_global.js&amp;lt;/tt&amp;gt;) and can be overwrite by the user at two levels:&lt;br /&gt;
* The '''default''' configuration (&amp;lt;tt&amp;gt;projects/default_config.js&amp;lt;/tt&amp;gt;), commun for all the projects.&lt;br /&gt;
* The '''project''' configuration (&amp;lt;tt&amp;gt;projects/myProject/project_config.js&amp;lt;/tt&amp;gt;), specific for a given project.&lt;br /&gt;
&lt;br /&gt;
The value of the parameters redefined in a higher level replaces that of a lower level.&lt;br /&gt;
&lt;br /&gt;
Some parameters can be overwrite as command-line parameters (see [[#Command-line overwrite|Command-line overwrite]] section).&lt;br /&gt;
&lt;br /&gt;
The order of '''priority''' is: Command-line &amp;gt; Project config &amp;gt; Default config &amp;gt; Engine config.&lt;br /&gt;
&lt;br /&gt;
== Build parameters ==&lt;br /&gt;
&lt;br /&gt;
=== Stage ===&lt;br /&gt;
The build tool is divided into several stages that you can choose to activate or deactivate at will.&lt;br /&gt;
&lt;br /&gt;
{{PARAM|DoClean|Clear all intermediate files and exit|boolean|false}}&lt;br /&gt;
&lt;br /&gt;
{{PARAM|DoCompile|Compile all the project and engine source code. Generate all REL files|boolean|true}}&lt;br /&gt;
&lt;br /&gt;
{{PARAM|DoMake|Link all the project and engine source code. Merge all REL into one IHX file|boolean|true}}&lt;br /&gt;
&lt;br /&gt;
{{PARAM|DoPackage|Generate final binary file (boolean). Binarize the IHX file|boolean|true}}&lt;br /&gt;
&lt;br /&gt;
{{PARAM|DoDeploy|Gathering of all files necessary for the program to work (boolean). Depends on the type of target|boolean|true}}&lt;br /&gt;
&lt;br /&gt;
{{PARAM|DoRun|Start the program automatically at the end of the build|boolean|false}}&lt;br /&gt;
&lt;br /&gt;
=== Path ===&lt;br /&gt;
&lt;br /&gt;
{{PARAM|ProjDir|Project directory|string|}}&lt;br /&gt;
&lt;br /&gt;
{{PARAM|OutDir|Intermediate files directory|string|`${ProjDir}out/`}}&lt;br /&gt;
&lt;br /&gt;
{{PARAM|RootDir|MSXgl root directory|string|}}&lt;br /&gt;
&lt;br /&gt;
{{PARAM|LibDir|Library directory|string|`${RootDir}engine/`}}&lt;br /&gt;
&lt;br /&gt;
{{PARAM|ToolsDir|Tools directory|string|`${RootDir}tools/`}}&lt;br /&gt;
&lt;br /&gt;
=== Tools ===&lt;br /&gt;
&lt;br /&gt;
{{PARAM|SDCCPath|Path to SDCC tools chain|string|`${ToolsDir}sdcc/`}}&lt;br /&gt;
&lt;br /&gt;
{{PARAM|Compiler|Path to the C compile program|string|`${SDCCPath}bin/sdcc`}}&lt;br /&gt;
&lt;br /&gt;
{{PARAM|Assembler|Path to the assembler program|string|`${SDCCPath}bin/sdasz80`}}&lt;br /&gt;
&lt;br /&gt;
{{PARAM|Linker|Path to the linker program|string|`${SDCCPath}bin/sdcc`}}&lt;br /&gt;
&lt;br /&gt;
{{PARAM|MakeLib|Path to the program to generate lib file|string|`${SDCCPath}bin/sdar`}}&lt;br /&gt;
&lt;br /&gt;
{{PARAM|Hex2Bin|Path to IHX to binary convertor|string|`${ToolsDir}MSXtk/bin/MSXhex`}}&lt;br /&gt;
&lt;br /&gt;
{{PARAM|MSXDOS|Path to the MSX-DOS files|string|`${ToolsDir}build/DOS/`}}&lt;br /&gt;
&lt;br /&gt;
{{PARAM|DskTool|Path to the tool to generate DSK file|string|`${ToolsDir}build/msxtar/msxtar`}}&lt;br /&gt;
&lt;br /&gt;
{{PARAM|Emulator|Path to the emulator to launch the project|string|}}&lt;br /&gt;
&lt;br /&gt;
=== Project ===&lt;br /&gt;
&lt;br /&gt;
{{PARAM|ProjName|Project name. Will be use for output filename|string|}}&lt;br /&gt;
&lt;br /&gt;
{{PARAM|ProjModules|List of project modules to build. If empty, ProjName will be added|array|}}&lt;br /&gt;
&lt;br /&gt;
{{PARAM|ProjSegments|Project segments base name. ProjName will be used if not defined|string|}}&lt;br /&gt;
&lt;br /&gt;
{{PARAM|LibModules|List of library modules to build|array|}}&lt;br /&gt;
&lt;br /&gt;
{{PARAM|AddSources|Additional sources to be compiled and linked with the project|array|}}&lt;br /&gt;
&lt;br /&gt;
{{PARAM|AddLibs|Additional extern library to be linked with the project|array|}}&lt;br /&gt;
&lt;br /&gt;
{{PARAM|Machine|Target MSX machine version|string|&amp;quot;1&amp;quot;}}&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;js&amp;quot;&amp;gt;&lt;br /&gt;
//   - 1        MSX1&lt;br /&gt;
//   - 2        MSX2&lt;br /&gt;
//   - 12       MSX1 and 2 (multi support)&lt;br /&gt;
//   - 2K       Korean MSX2 (SC9 support)&lt;br /&gt;
//   - 2P       MSX2+&lt;br /&gt;
//   - 22P      MSX2 and 2+ (multi support)&lt;br /&gt;
//   - 122P     MSX1, 2 and 2+ (multi support)&lt;br /&gt;
//   - 0        MSX0&lt;br /&gt;
//   - TR       MSX turbo R&lt;br /&gt;
//   - 3        MSX3 (reserved)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Multi support means that the application can use the features of all supported MSX generations. The user must detect the MSX version at runtime and adjust the program accordingly.&lt;br /&gt;
&lt;br /&gt;
{{PARAM|Target|Target program format|string|&amp;quot;ROM_32K&amp;quot;}}&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;js&amp;quot;&amp;gt;&lt;br /&gt;
//   - BIN_DISK         .bin    BASIC binary program (starting at 8000h) on disk&lt;br /&gt;
//   - BIN_TAPE         .bin    BASIC binary program (starting at 8000h) on tape&lt;br /&gt;
//   - BIN_USR          .bin    BASIC USR binary driver (starting at C000h)&lt;br /&gt;
//   - DOS1             .com    MSX-DOS 1 program (starting at 0100h)&lt;br /&gt;
//   - DOS2             .com    MSX-DOS 2 program (starting at 0100h)&lt;br /&gt;
//   - DOS0             .com    Direct program boot from disk (starting at 0100h)&lt;br /&gt;
//   - ROM_8K           .rom    8 KB ROM in page 1 (4000h ~ 5FFFh)&lt;br /&gt;
//   - ROM_8K_P2        .rom    8 KB ROM in page 2 (8000h ~ 9FFFh)&lt;br /&gt;
//   - ROM_16K          .rom    16 KB ROM in page 1 (4000h ~ 7FFFh)&lt;br /&gt;
//   - ROM_16K_P2       .rom    16 KB ROM in page 2 (8000h ~ BFFFh)&lt;br /&gt;
//   - ROM_32K          .rom    32 KB ROM in page 1&amp;amp;2 (4000h ~ BFFFh)&lt;br /&gt;
//   - ROM_48K          .rom    48 KB ROM in page 0-2 (0000h ~ BFFFh)&lt;br /&gt;
//   - ROM_48K_ISR      .rom    48 KB ROM in page 0-2 (0000h ~ BFFFh) with ISR replacement&lt;br /&gt;
//   - ROM_64K          .rom    64 KB ROM in page 0-3 (0000h ~ FFFFh)&lt;br /&gt;
//   - ROM_64K_ISR      .rom    64 KB ROM in page 0-3 (0000h ~ FFFFh) with ISR replacement&lt;br /&gt;
//   - ROM_ASCII8       .rom    ASCII-8: 8 KB segments for a total of 64 KB to 2 MB&lt;br /&gt;
//   - ROM_ASCII16      .rom    ASCII-16: 16 KB segments for a total of 64 KB to 4 MB&lt;br /&gt;
//   - ROM_KONAMI       .rom    Konami MegaROM (aka Konami4): 8 KB segments for a total of 64 KB to 2 MB&lt;br /&gt;
//   - ROM_KONAMI_SCC   .rom    Konami MegaROM SCC (aka Konami5): 8 KB segments for a total of 64 KB to 2 MB&lt;br /&gt;
//   - ROM_NEO8         .rom    NEO-8: 8 KB segments for a total of 1 MB to 32 MB&lt;br /&gt;
//   - ROM_NEO16        .rom    NEO-16: 16 KB segments for a total of 1 MB to 64 MB&lt;br /&gt;
//   - ROM_YAMANOOTO    .rom    Yamanooto: 8 KB segments for a total up to 8 MB&lt;br /&gt;
//   - ROM_ASCII16X     .rom    ASCII16-X: 16 KB segments for a total up to 64 MB&lt;br /&gt;
//   - RAW              .bin    Raw binary code and data to be compiled at a given address&lt;br /&gt;
//   - LIB              .lib    C library to be included in other project&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
More detail: [[Targets]]&lt;br /&gt;
&lt;br /&gt;
{{PARAM|ROMSize|ROM mapper total size in KB. Must be a multiple of 8 or 16 depending on the mapper type (from 64 to 4096)|number|128}}&lt;br /&gt;
&lt;br /&gt;
{{PARAM|ROMMainSegments|Number of segments in the main program of a mapped-ROM. 0 means 'number of segments to fill 32 KB of ROM|number|0}}&lt;br /&gt;
&lt;br /&gt;
{{PARAM|ROMSkipBoot|Check for ROM boot skipping if a given key is pressed|boolean|false}}&lt;br /&gt;
&lt;br /&gt;
{{PARAM|ROMSkipBootKey|The key to be check for ROM boot skipping. Key must be from keyboard row #7|string|&amp;quot;ESC&amp;quot;}}&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;js&amp;quot;&amp;gt;&lt;br /&gt;
//   - F4&lt;br /&gt;
//   - F5&lt;br /&gt;
//   - ESC&lt;br /&gt;
//   - TAB&lt;br /&gt;
//   - STOP&lt;br /&gt;
//   - BS&lt;br /&gt;
//   - SELECT&lt;br /&gt;
//   - RETURN&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{PARAM|ROMDelayBoot|Postpone the ROM startup to let the other ROMs initialize like Disk controller or Network cartridge|boolean|false}}&lt;br /&gt;
&lt;br /&gt;
{{PARAM|AddROMSignature|Add a ROM signature to help flasher and emulator to detect the ROM type properly|boolean|false}}&lt;br /&gt;
&lt;br /&gt;
{{PARAM|InstallRAMISR|Select RAM in slot 0 and install ISR and optional code there. For MSX with at least 64 KB of RAM|string|&amp;quot;RAM0_NONE&amp;quot;}}&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;js&amp;quot;&amp;gt;&lt;br /&gt;
//   - RAM0_NONE       Don't install anything in RAM &lt;br /&gt;
//   - RAM0_ISR        Install only ISR&lt;br /&gt;
//   - RAM0_SEGMENT    Install ISR and segment data (for mapped-ROM)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
For mode detail about usage of RAM0_SEGMENT, check [[Build tool/InstallRAMISR|this document]].&lt;br /&gt;
&lt;br /&gt;
{{PARAM|CustomISR|Type of custom ISR to install. ISR is install in RAM or ROM depending on Target and InstallRAMISR parameters|string|&amp;quot;VBLANK&amp;quot;}}&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;js&amp;quot;&amp;gt;&lt;br /&gt;
//   - NONE       No ISR&lt;br /&gt;
//   - ALL        Handle all interruptions&lt;br /&gt;
//   - VBLANK     V-blank handler&lt;br /&gt;
//   - VHBLANK    V-blank and h-blank handler (V9938 or V9958)&lt;br /&gt;
//   - V9990      V-blank, h-blank and command end handler (V9990)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Depending on the selected ISR, some functions must be provided by the user:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
// CustomISR = &amp;quot;ALL&amp;quot;&lt;br /&gt;
VDP_InterruptHandler(); // All interrupt&lt;br /&gt;
&lt;br /&gt;
// CustomISR = &amp;quot;VBLANK&amp;quot;&lt;br /&gt;
VDP_InterruptHandler(); // V-blank interrupt&lt;br /&gt;
&lt;br /&gt;
// CustomISR = &amp;quot;VHBLANK&amp;quot;&lt;br /&gt;
VDP_InterruptHandler(); // V-blank interrupt&lt;br /&gt;
VDP_HBlankHandler();    // H-blank interrupt&lt;br /&gt;
&lt;br /&gt;
// CustomISR = &amp;quot;V9990&amp;quot;&lt;br /&gt;
V9_InterruptVBlank();   // V-blank interrupt&lt;br /&gt;
V9_InterruptHBlank();   // H-blank interrupt&lt;br /&gt;
V9_InterruptCommand();  // Command end interrupt&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{PARAM|BIOSReleaseEvent|Event called before BIOS is released. For target format that switch out BIOS from page 0.|boolean|false}}&lt;br /&gt;
More detail: [[Build tool/BIOSReleaseEvent|BIOSReleaseEvent]]&lt;br /&gt;
&lt;br /&gt;
{{PARAM|CheckVersion|Add code to check MSX version at program startup. Works for ROM and BASIC program.|boolean|false}}&lt;br /&gt;
&lt;br /&gt;
{{PARAM|BankedCall|Use automatic banked call and trampoline functions (for mapped ROM)|boolean|false}}&lt;br /&gt;
&lt;br /&gt;
{{PARAM|ForceCodeAddr|Overwrite code starting address. For example. 0xE0000 for a driver in RAM|number|0}}&lt;br /&gt;
&lt;br /&gt;
{{PARAM|ForceRamAddr|Overwrite RAM starting address. For example. 0xE0000 for 8K RAM machine|number|0}}&lt;br /&gt;
&lt;br /&gt;
{{PARAM|RawFiles|List of raw data files to be added to the final binary|array|}}&lt;br /&gt;
Raw files can be added to final binary by defining 3 types of position: &amp;lt;tt&amp;gt;offset&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;segment&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;page&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;js&amp;quot;&amp;gt;&lt;br /&gt;
// Sample example&lt;br /&gt;
RawFiles = [&lt;br /&gt;
    { offset: 0x10000, file: &amp;quot;file1.bin&amp;quot; }, // Offset from final binary start&lt;br /&gt;
    { segment: 7, file: &amp;quot;file2.bin&amp;quot; },      // Segment number for mapped-ROM&lt;br /&gt;
    { page: 0, file: &amp;quot;file.bin&amp;quot; },          // Page number (16 KB) in the final binary&lt;br /&gt;
];&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;lt;u&amp;gt;Notes&amp;lt;/u&amp;gt;:&lt;br /&gt;
* If the &amp;lt;tt&amp;gt;RawFiles&amp;lt;/tt&amp;gt; table is not empty, the Build tool will generate a definition header file (&amp;lt;tt&amp;gt;myproject_rawdef.h&amp;lt;/tt&amp;gt;) with information to access the raw binary data from code.&lt;br /&gt;
* More than one file can be add to the same page or mapper segment. In this case, data will be concatenated in the table order, and definition header file (see above) is needed to know the offset (relative to page / segment) where data is located.&lt;br /&gt;
* When using page 0 (0x0000~0x3FFF), data will be placed from address 0x0100 (after the area reserved for the ISR).&lt;br /&gt;
&lt;br /&gt;
{{PARAM|DiskFiles|List of data files to copy to disk|array|}}&lt;br /&gt;
&lt;br /&gt;
{{PARAM|DiskSize|Size of the final disk (.DSK file). Can be &amp;quot;360K&amp;quot; or &amp;quot;720K&amp;quot;|string|&amp;quot;720K&amp;quot;}}&lt;br /&gt;
&lt;br /&gt;
{{PARAM|DOSParseArg|Parse MSX-DOS command-line arguments|boolean|true}}&lt;br /&gt;
&lt;br /&gt;
=== Signature ===&lt;br /&gt;
{{PARAM|AppSignature|Add application signature to binary data|boolean|false}}&lt;br /&gt;
&lt;br /&gt;
{{PARAM|AppCompany|Application company. Can be 2 character string or 16-bits integer|string/number|&amp;quot;GL&amp;quot;}}&lt;br /&gt;
&lt;br /&gt;
{{PARAM|AppID|Application ID. Can be 2 character string or 16-bits integer (0~65535)|string/number|0}}&lt;br /&gt;
&lt;br /&gt;
{{PARAM|AppExtra|Application extra data. Comma-separated bytes starting with data size|array|}}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;Note&amp;lt;/u&amp;gt;: See [[AppSignature]] and [[AppExtra]] for more details.&lt;br /&gt;
&lt;br /&gt;
=== Make ===&lt;br /&gt;
&lt;br /&gt;
{{PARAM|BuildLibrary|Force to generate MSXgl static library even if 'msxgl.lib' already exist|bolean|true}}&lt;br /&gt;
&lt;br /&gt;
{{PARAM|Debug|Prepare program for debug|boolean|false}}&lt;br /&gt;
&lt;br /&gt;
{{PARAM|DebugSymbols|Move debug symbols to deployement folder|boolean|false}}&lt;br /&gt;
&lt;br /&gt;
{{PARAM|AllowUndocumented|Allow compiler to generate undocumented Z80 instructions|boolean|true}}&lt;br /&gt;
&lt;br /&gt;
{{PARAM|AsmOptim|Assembler code optimizer ⚠️ WIP|string|&amp;quot;None&amp;quot;}}&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;js&amp;quot;&amp;gt;&lt;br /&gt;
//   - None&lt;br /&gt;
//   - Peep       SDCC peep hole otpimizer&lt;br /&gt;
//   - MDL        MDL z80 otpimizer&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{PARAM|Optim|Code optimization priority|string|&amp;quot;Speed&amp;quot;}}&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;js&amp;quot;&amp;gt;&lt;br /&gt;
//   - Default&lt;br /&gt;
//   - Speed&lt;br /&gt;
//   - Size&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{PARAM|CompileComplexity|Compile complexity. The higher the most optimized but the slowest to compile. Can be one of the predefine name or a integer value.|string/integer|&amp;quot;Default&amp;quot;}}&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;js&amp;quot;&amp;gt;&lt;br /&gt;
//   - Fast              2000&lt;br /&gt;
//   - Default           3000&lt;br /&gt;
//   - Optimized        50000&lt;br /&gt;
//   - Ultra           200000&lt;br /&gt;
//   - Insane        10000000&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{PARAM|CompileOpt|Additionnal compilation flag|string|}}&lt;br /&gt;
&lt;br /&gt;
{{PARAM|CompileSkipOld|Skip file if compiled data (REL) is newer than the source code|boolean|false}}&lt;br /&gt;
&lt;br /&gt;
{{PARAM|LinkOpt|Additionnal link options|string|}}&lt;br /&gt;
&lt;br /&gt;
{{PARAM|BuildVersion|Automatic increment of build version in a header file|boolean|false}}&lt;br /&gt;
&lt;br /&gt;
{{PARAM|PackSegments|Package all segments into a lib file to reduce the number of files to link|boolean|false}}&lt;br /&gt;
&lt;br /&gt;
{{PARAM|GenCompileDB|Generate Clang compatible Compilation database|boolean|false}}&lt;br /&gt;
&lt;br /&gt;
{{PARAM|HexBinOpt|Additionnal options of Hex to Binary convertor|string|&amp;quot;&amp;quot;}}&lt;br /&gt;
&lt;br /&gt;
{{PARAM|PreBuildScripts|Command lines to be executed before the build process|array|[]}}&lt;br /&gt;
&lt;br /&gt;
{{PARAM|PostBuildScripts|Command lines to be executed after the build process|array|[]}}&lt;br /&gt;
&lt;br /&gt;
=== Localization ===&lt;br /&gt;
&lt;br /&gt;
{{PARAM|LocFiles|List files to be localized|array|}}&lt;br /&gt;
&lt;br /&gt;
{{PARAM|LocOutput|Localization output filename|string|&amp;quot;localization.h&amp;quot;}}&lt;br /&gt;
&lt;br /&gt;
{{PARAM|LocStruct|Localization structure name|string|&amp;quot;g_LocData&amp;quot;}}&lt;br /&gt;
&lt;br /&gt;
{{PARAM|LocSplitDef|Split localization data and definitions in different files|boolean|false}}&lt;br /&gt;
&lt;br /&gt;
For example:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;js&amp;quot;&amp;gt;&lt;br /&gt;
//-- List files to be localized (array)&lt;br /&gt;
LocFiles = [ &amp;quot;translate_en.ini&amp;quot;, &amp;quot;translate_fr.ini&amp;quot;, &amp;quot;translate_ja.ini&amp;quot; ];&lt;br /&gt;
&lt;br /&gt;
//-- Localization output filename (string)&lt;br /&gt;
LocOutput = &amp;quot;data/translate.h&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
//-- Localization structure name (string)&lt;br /&gt;
LocStruct = &amp;quot;g_TransData&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
//-- Split localization data and definitions in different files (boolean)&lt;br /&gt;
LocSplitDef = true;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Build Tool ===&lt;br /&gt;
&lt;br /&gt;
{{PARAM|Verbose|Activate verbose mode and get more build information|boolean|false}}&lt;br /&gt;
&lt;br /&gt;
{{PARAM|LogStdout|Output build information to the standard console|boolean|true}}&lt;br /&gt;
&lt;br /&gt;
{{PARAM|LogFile|Output build information to a log file|boolean|false}}&lt;br /&gt;
&lt;br /&gt;
{{PARAM|LogFileName|Name of the log file|string|&amp;quot;log_YYYYMMDD_HHMMSS.txt&amp;quot;}}&lt;br /&gt;
&lt;br /&gt;
=== Analyzer ===&lt;br /&gt;
&lt;br /&gt;
{{PARAM|Analyzer|Execute compiler analyzer|boolean|true}}&lt;br /&gt;
&lt;br /&gt;
{{PARAM|AnalyzerOutput|Analyzer output selection|string|Both}}&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;js&amp;quot;&amp;gt;&lt;br /&gt;
//   - Console    Output to termial console&lt;br /&gt;
//   - File       Output to file&lt;br /&gt;
//   - Both       Output to file and termial console (default)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{PARAM|AnalyzerReport|Analyzer report elements|string|ASMCV}}&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;js&amp;quot;&amp;gt;&lt;br /&gt;
//   - [A]        Report areas&lt;br /&gt;
//   - [S]        Report segments&lt;br /&gt;
//   - [M]        Report modules&lt;br /&gt;
//   - [C]        Report code symbols&lt;br /&gt;
//   - [V]        Report variable symbols&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{PARAM|AnalyzerSort|Analyzer report sorting|string|Size}}&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;js&amp;quot;&amp;gt;&lt;br /&gt;
//   - None       No sorting (MAP file order)&lt;br /&gt;
//   - Alpha      Alphanumeric sorting&lt;br /&gt;
//   - Size       Size sorting (default)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{PARAM|AnalyzerCSV|Export analyzer data to CSV file|boolean|false}}&lt;br /&gt;
&lt;br /&gt;
{{PARAM|AnalyzerSeparator|Analyzer CSV file separator|string|&amp;quot;,&amp;quot;}}&lt;br /&gt;
&lt;br /&gt;
=== Package ===&lt;br /&gt;
&lt;br /&gt;
{{PARAM|Standalone|Should the build tool create a standalone package?|boolean|false}}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;Note&amp;lt;/u&amp;gt;: Package is created in a &amp;lt;tt&amp;gt;/package/&amp;lt;/tt&amp;gt; folder at the root of the project.&lt;br /&gt;
&lt;br /&gt;
=== Emulator ===&lt;br /&gt;
&lt;br /&gt;
==== General ====&lt;br /&gt;
{{PARAM|EmulMachine|Force the MSX version of the emulated machine|boolean|true}}&lt;br /&gt;
&lt;br /&gt;
{{PARAM|Emul60Hz|Force the emulated machine to be at 60 Hz|boolean|false}}&lt;br /&gt;
&lt;br /&gt;
{{PARAM|EmulFullScreen|Force the emulator to start in fullscreen mode|boolean|false}}&lt;br /&gt;
&lt;br /&gt;
{{PARAM|EmulMute|Disable emulator sound|boolean|false}}&lt;br /&gt;
&lt;br /&gt;
{{PARAM|EmulDebug|Start emulator debugger with program launch|boolean|false}}&lt;br /&gt;
&lt;br /&gt;
{{PARAM|EmulTurbo|Start emulator in turbo mode|boolean|false}}&lt;br /&gt;
&lt;br /&gt;
{{PARAM|EmulExtraParam|Emulator extra parameters to be add to command-line. Emulator sotfware specific|string|}}&lt;br /&gt;
&lt;br /&gt;
==== Extensions ====&lt;br /&gt;
{{PARAM|EmulSCC|Add SCC extension|boolean|false}}&lt;br /&gt;
&lt;br /&gt;
{{PARAM|EmulMSXMusic|Add MSX-Music extension|boolean|false}}&lt;br /&gt;
&lt;br /&gt;
{{PARAM|EmulMSXAudio|Add MSX-Audio extension|boolean|false}}&lt;br /&gt;
&lt;br /&gt;
{{PARAM|EmulOPL4|Add OPL4 extension|boolean|false}}&lt;br /&gt;
&lt;br /&gt;
{{PARAM|EmulPSG2|Add second PSG extension|boolean|false}}&lt;br /&gt;
&lt;br /&gt;
{{PARAM|EmulV9990|Add V9990 video-chip extension|boolean|false}}&lt;br /&gt;
&lt;br /&gt;
{{PARAM|EmulRAM|Add mapped-RAM extension|boolean|false}}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;Note&amp;lt;/u&amp;gt;: The biggest available RAM extension will be selected (4 MB if supported)&lt;br /&gt;
&lt;br /&gt;
==== Input ====&lt;br /&gt;
{{PARAM|EmulPortA|Plug a virtual device into the joystick port A|string|}}&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;js&amp;quot;&amp;gt;&lt;br /&gt;
//   - Joystick&lt;br /&gt;
//   - Mouse&lt;br /&gt;
//   - Paddle&lt;br /&gt;
//   - JoyMega&lt;br /&gt;
//   - NinjaTap&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{PARAM|EmulPortB|Plug a virtual device into the joystick port B|string|}}&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;js&amp;quot;&amp;gt;&lt;br /&gt;
//   - Joystick&lt;br /&gt;
//   - Mouse&lt;br /&gt;
//   - Paddle&lt;br /&gt;
//   - JoyMega&lt;br /&gt;
//   - NinjaTap&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Run device ====&lt;br /&gt;
{{PARAM|RunDevice|Run device like Easy-USB|string|&amp;quot;&amp;quot;}}&lt;br /&gt;
&lt;br /&gt;
{{PARAM|RunDeviceOpt|Run device option|string|&amp;quot;&amp;quot;}}&lt;br /&gt;
&lt;br /&gt;
== Command-line overwrite ==&lt;br /&gt;
&lt;br /&gt;
The followings parameters can be overwrite from command-line parameter when the Build tool script is invoked:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Overwrite&amp;lt;br/&amp;gt;syntax !! Config&amp;lt;br/&amp;gt;parameter !! Desc. !! Example&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tt&amp;gt;'''projname=&amp;lt;name&amp;gt;'''&amp;lt;/tt&amp;gt; || &amp;lt;tt&amp;gt;ProjName&amp;lt;/tt&amp;gt; || Set project name (without extension) || &amp;lt;tt&amp;gt;projname=mygame&amp;lt;/tt&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tt&amp;gt;'''target=&amp;lt;name&amp;gt;'''&amp;lt;/tt&amp;gt; || &amp;lt;tt&amp;gt;Target&amp;lt;/tt&amp;gt; || Set target name || &amp;lt;tt&amp;gt;target=DOS1&amp;lt;/tt&amp;gt; (for MSX-DOS program)&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tt&amp;gt;'''machine=&amp;lt;name&amp;gt;'''&amp;lt;/tt&amp;gt; || &amp;lt;tt&amp;gt;Machine&amp;lt;/tt&amp;gt; || Set machine name || &amp;lt;tt&amp;gt;machine=2P&amp;lt;/tt&amp;gt; (for MSX2+ machine)&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tt&amp;gt;'''romsize=&amp;lt;size&amp;gt;'''&amp;lt;/tt&amp;gt; || &amp;lt;tt&amp;gt;ROMSize&amp;lt;/tt&amp;gt; || Set ROM size (in KB) || &amp;lt;tt&amp;gt;romsize=256&amp;lt;/tt&amp;gt; (for 256 KB mapped-ROM)&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tt&amp;gt;'''delay'''&amp;lt;/tt&amp;gt; || &amp;lt;tt&amp;gt;ROMDelayBoot&amp;lt;/tt&amp;gt; || Enable ROM delay boot ||&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tt&amp;gt;'''ramisr'''&amp;lt;/tt&amp;gt; || &amp;lt;tt&amp;gt;InstallRAMISR&amp;lt;/tt&amp;gt; || Install the RAM0 interrupt service routine (&amp;lt;tt&amp;gt;InstallRAMISR=&amp;quot;RAM0_ISR&amp;quot;&amp;lt;/tt&amp;gt;) ||&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tt&amp;gt;'''ramseg'''&amp;lt;/tt&amp;gt; || &amp;lt;tt&amp;gt;InstallRAMISR&amp;lt;/tt&amp;gt; || Install the RAM0 segment (&amp;lt;tt&amp;gt;InstallRAMISR=&amp;quot;RAM0_SEGMENT&amp;quot;&amp;lt;/tt&amp;gt;) ||&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tt&amp;gt;'''clean'''&amp;lt;/tt&amp;gt; || &amp;lt;tt&amp;gt;DoClean&amp;lt;/tt&amp;gt; || Clean all generated files ||&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tt&amp;gt;'''compile'''&amp;lt;/tt&amp;gt; || &amp;lt;tt&amp;gt;DoCompile&amp;lt;/tt&amp;gt; || Compile all source files ||&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tt&amp;gt;'''make'''&amp;lt;/tt&amp;gt; || &amp;lt;tt&amp;gt;DoMake&amp;lt;/tt&amp;gt; || Link all files together ||&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tt&amp;gt;'''package'''&amp;lt;/tt&amp;gt; || &amp;lt;tt&amp;gt;DoPackage&amp;lt;/tt&amp;gt; || Convert binary into target format ||&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tt&amp;gt;'''deploy'''&amp;lt;/tt&amp;gt; || &amp;lt;tt&amp;gt;DoDeploy&amp;lt;/tt&amp;gt; || Deploy final files into separate directory ||&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tt&amp;gt;'''run'''&amp;lt;/tt&amp;gt; || &amp;lt;tt&amp;gt;DoRun&amp;lt;/tt&amp;gt; || Run the built program with the selected emulator ||&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tt&amp;gt;'''rebuild'''&amp;lt;/tt&amp;gt; || All &amp;lt;tt&amp;gt;DoXxx&amp;lt;/tt&amp;gt; || Clean all generated files, then do all steps ||&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tt&amp;gt;'''define=&amp;lt;name&amp;gt;[:value]'''&amp;lt;/tt&amp;gt; || &amp;lt;tt&amp;gt;CompileOpt&amp;lt;/tt&amp;gt; || Define a compilation symbol (can be used multiple times) || &amp;lt;tt&amp;gt;define=MYDEF:123&amp;lt;/tt&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tt&amp;gt;'''help'''&amp;lt;/tt&amp;gt; || || Display this command-line arguments list ||&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Note: For parameters that take a value, there should be no space before or after the equal sign '&amp;lt;tt&amp;gt;=&amp;lt;/tt&amp;gt;'.&lt;br /&gt;
&lt;br /&gt;
=== Example ===&lt;br /&gt;
&lt;br /&gt;
==== Set target ====&lt;br /&gt;
&lt;br /&gt;
The following command allows you to overwrite the build target from the command line.&lt;br /&gt;
E.g.: &amp;lt;tt&amp;gt;build DOS2&amp;lt;/tt&amp;gt; (MSX-DOS2 application) or &amp;lt;tt&amp;gt;build ROM_48K&amp;lt;/tt&amp;gt; (48 KB plain-ROM cartridge).&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;console&amp;quot;&amp;gt;&lt;br /&gt;
..\..\tools\build\Node\node.exe ..\..\engine\script\js\build.js target=%1&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Transfert all parameters ====&lt;br /&gt;
&lt;br /&gt;
It is recommended that you pass all command line parameters to the build script.&lt;br /&gt;
This allows you to fully configure your build sessions according to your needs.&lt;br /&gt;
Here is an example of a build.bat script:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;console&amp;quot;&amp;gt;&lt;br /&gt;
..\..\tools\build\Node\node.exe ..\..\engine\script\js\build.js %1 %2 %3 %4 %5 %6 %7 %8 %9&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Misc ==&lt;br /&gt;
&lt;br /&gt;
Previously, the Build tool was written in Windows batch format.&lt;br /&gt;
Here is a [[Batch to JS conversion guide|guide to convert the configuration files to use the new Build tool]].&lt;br /&gt;
&lt;br /&gt;
⚠️ Old batch version of the build tool is no longer supported start from MSXgl 1.0.1 version. Please update your project configuration.&lt;/div&gt;</summary>
		<author><name>Aoineko</name></author>	</entry>

	<entry>
		<id>https://aoineko.org/msxgl/index.php?title=NEO_mapper&amp;diff=3966</id>
		<title>NEO mapper</title>
		<link rel="alternate" type="text/html" href="https://aoineko.org/msxgl/index.php?title=NEO_mapper&amp;diff=3966"/>
				<updated>2026-05-17T14:19:33Z</updated>
		
		<summary type="html">&lt;p&gt;Aoineko: /* Hardware */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;div style=&amp;quot;float:right&amp;quot;&amp;gt;[[NEO mapper|EN]] | [[NEO mapper/JA|JA]]&amp;lt;/div&amp;gt;&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
== Specifications ==&lt;br /&gt;
&lt;br /&gt;
=== Principles ===&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
Like conventional mappers, the basic idea is to use data write signals to the cartridge to change mapper registers value and thus, 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 [[#Format|tables below]]).&lt;br /&gt;
Read accesses, however, work as normal accesses to the memory visible through the banks.&lt;br /&gt;
&lt;br /&gt;
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 cartridge in this new mapper format.&lt;br /&gt;
&lt;br /&gt;
Compared to conventional mappers, this proposal is based on two new main features:&lt;br /&gt;
* A 16-bit segment register,&lt;br /&gt;
* Banks covering page #0 of MSX memory space (address 0000h~3FFFh).&lt;br /&gt;
&lt;br /&gt;
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).&lt;br /&gt;
&lt;br /&gt;
For the time being, we propose to reserve the 2 most significant bits of the 16-bit bank registers for future extensions of the format (such as SRAM or sound chips support for example).&lt;br /&gt;
This leaves 14 bits to select which segment is visible in each bank, for a maximum of 16384 segments.&lt;br /&gt;
The reserved bits, must be set to 0.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
!colspan=&amp;quot;8&amp;quot;| Higher byte&lt;br /&gt;
|&lt;br /&gt;
!colspan=&amp;quot;8&amp;quot;| Lower byte &lt;br /&gt;
|-&lt;br /&gt;
! 15 || 14 || 13 || 12 || 11 || 10 || 9 || 8 &lt;br /&gt;
|&lt;br /&gt;
! 7 || 6 || 5 || 4 || 3 || 2 || 1 || 0&lt;br /&gt;
|-&lt;br /&gt;
| 0 || 0&lt;br /&gt;
|colspan=&amp;quot;6&amp;quot;| Segment MSB&lt;br /&gt;
| &lt;br /&gt;
|colspan=&amp;quot;8&amp;quot;| Segment LSB &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The maximum ROM size is therefore 128 MB (for 8 KB segments) or 256 MB (for 16 KB segments).&lt;br /&gt;
&lt;br /&gt;
=== Write Access ===&lt;br /&gt;
&lt;br /&gt;
Write access to the mapper is use to change the value of the bank switching register (where you can select the ROM segment visible through a bank).&lt;br /&gt;
Bellow is the list of the predefined segment switching addresses.&lt;br /&gt;
&lt;br /&gt;
As this new mapper uses 16-bit segment switching registers, it uses 2 bytes for the segment number to be selected in each bank.&lt;br /&gt;
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.&lt;br /&gt;
This way, the segment number can be initialized at once with the [[#Bank switching cost|Z80 instructions for 16-bit memory write access]].&lt;br /&gt;
&lt;br /&gt;
==== NEO-8 mapper ====&lt;br /&gt;
&lt;br /&gt;
* Size of a segment: 8 KB&lt;br /&gt;
* Segment switching addresses:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Bank (8kB) !! Switching address !! Initial segment&lt;br /&gt;
|-&lt;br /&gt;
| 0: 0000h~1FFFh || 5000h (mirror at 1000h, 9000h and D000h) || 0000h&lt;br /&gt;
|-&lt;br /&gt;
| 1: 2000h~3FFFh || 5800h (mirror at 1800h, 9800h and D800h) || 0000h&lt;br /&gt;
|-&lt;br /&gt;
| 2: 4000h~5FFFh || 6000h (mirror at 2000h, A000h and E000h) || 0000h&lt;br /&gt;
|-&lt;br /&gt;
| 3: 6000h~7FFFh || 6800h (mirror at 2800h, A800h and E800h) || 0000h&lt;br /&gt;
|-&lt;br /&gt;
| 4: 8000h~9FFFh || 7000h (mirror at 3000h, B000h and F000h) || 0000h&lt;br /&gt;
|-&lt;br /&gt;
| 5: A000h~BFFFh || 7800h (mirror at 3800h, B800h and F800h) || 0000h&lt;br /&gt;
|}&lt;br /&gt;
* Maximum number of segments: 16384&lt;br /&gt;
* Maximum ROM size: 128 MB&lt;br /&gt;
&lt;br /&gt;
==== NEO-16 mapper ====&lt;br /&gt;
&lt;br /&gt;
* Size of a segment: 16 KB&lt;br /&gt;
* Segment switching addresses:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Bank (16kB) !! Switching address !! Initial segment&lt;br /&gt;
|-&lt;br /&gt;
| 0: 0000h~3FFFh || 5000h (mirror at 1000h, 9000h and D000h) || 0000h&lt;br /&gt;
|-&lt;br /&gt;
| 1: 4000h~7FFFh || 6000h (mirror at 2000h, A000h and E000h) || 0000h&lt;br /&gt;
|-&lt;br /&gt;
| 2: 8000h~BFFFh || 7000h (mirror at 3000h, B000h and F000h) || 0000h&lt;br /&gt;
|}&lt;br /&gt;
* Maximum number of segments: 16384&lt;br /&gt;
* Maximum ROM size: 256 MB&lt;br /&gt;
&lt;br /&gt;
=== Read Access ===&lt;br /&gt;
When mapper is selected, read accesses to memory pages 0, 1 and 2 (addresses 0000h to BFFFh), are redirected to a given ROM segment according to the value of the bank register corresponding to the address.&lt;br /&gt;
&lt;br /&gt;
For page 3, read accesses are invalid and the value returned is undefined and should not be used. Implementations of the NEO mapper should return the value FFh if page 3 is read, but this value is not guaranteed by the mapper specifications.&lt;br /&gt;
&lt;br /&gt;
=== Detection ===&lt;br /&gt;
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:&lt;br /&gt;
* &amp;quot;&amp;lt;tt&amp;gt;ROM_NEO8&amp;lt;/tt&amp;gt;&amp;quot; for NEO-8 mapper,&lt;br /&gt;
* &amp;quot;&amp;lt;tt&amp;gt;ROM_NE16&amp;lt;/tt&amp;gt;&amp;quot; for NEO-16 mapper.&lt;br /&gt;
&lt;br /&gt;
The ROM header (starting with &amp;quot;AB&amp;quot;) must be in the first ROM segment at offset 0.&lt;br /&gt;
The signature is therefore located at offset 16 of the ROM and may be visible to the Z80 on start-up at addresses 0010h, 4010h and 8010h.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;Note&amp;lt;/u&amp;gt;: Signature characters have been carefully choosed to prevent existing ROMs to generate false positive signature (See [[ROM type signature]]).&lt;br /&gt;
&lt;br /&gt;
== Support ==&lt;br /&gt;
&lt;br /&gt;
=== Hardware ===&lt;br /&gt;
Hardware supporting NEO mapper:&lt;br /&gt;
* '''[https://www.msxpico.com/ MSX Pico]''' (normal or WiFi): Support for NEO-8 and NEO-16 mappers up to ~15 MB (firmware 1.25 or above).&lt;br /&gt;
* '''[https://www.msxpico.com/ MSX Pico+]''': Support for NEO-8 and NEO-16 mappers up to ~14 MB (firmware 2.12 or above).&lt;br /&gt;
* '''[https://github.com/cristianoag/msx-picoverse-public PicoVerse] 2040 and 2350''': Support for NEO-8 and NEO-16 mappers up to ~15 MB.&lt;br /&gt;
* '''[https://github.com/arkadiuszmakarenko/RISKYMSX RISKY MSX]''': Support for NEO-8 and NEO-16 mappers up to 256 KB.&lt;br /&gt;
* '''[https://github.com/piigaa-densetu-two-dai/MSXpi MSXπ]''': Support for NEO-16 mappers up to 16 MB&lt;br /&gt;
* '''[https://github.com/piigaa-densetu-two-dai/MSXpi_plus_v2 MSXπ Plus (V2)]''': Support for NEO-16 mappers up to 16 MB&lt;br /&gt;
&lt;br /&gt;
=== Emulator ===&lt;br /&gt;
Emulators supporting NEO mapper:&lt;br /&gt;
* {{Emulicious}} '''Emulicious''': Full support for NEO-8 and NEO-16 mappers.&lt;br /&gt;
* {{MSXEC}} '''MSXEC''': Support NEO-8 and NEO-16 mappers up to 64 MB (version 20260303 or above).&lt;br /&gt;
* {{openMSX}} '''openMSX''': Full support for NEO-8 and NEO-16 mappers (version 20.0 or above).&lt;br /&gt;
* {{WebMSX}} '''WebMSX''': Full support for NEO-8 and NEO-16 mappers (version 6.0.7 or above).&lt;br /&gt;
&lt;br /&gt;
=== MSXgl ===&lt;br /&gt;
&lt;br /&gt;
Both NEO-8 and NEO-16 mappers are supported. Use respectively &amp;lt;tt&amp;gt;ROM_NEO8&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;ROM_NEO16&amp;lt;/tt&amp;gt; as target format.&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
#define SET_BANK_SEGMENT(bank, segment) /* ... */&lt;br /&gt;
&lt;br /&gt;
// Make segment #30 visible through bank #1&lt;br /&gt;
SET_BANK_SEGMENT(1, 30);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
MSXgl initialize the banks with a unique segment each, to offer the largest possible space available to the user:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;img style=&amp;quot;width:400px; margin:0.5em;&amp;quot; src=&amp;quot;https://raw.githubusercontent.com/aoineko-fr/MSXgl/main/engine/doc/mapper_neo8.png&amp;quot; /&amp;gt;&lt;br /&gt;
&amp;lt;img style=&amp;quot;width:400px; margin:0.5em;&amp;quot; src=&amp;quot;https://raw.githubusercontent.com/aoineko-fr/MSXgl/main/engine/doc/mapper_neo16.png&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;Note&amp;lt;/u&amp;gt;: When the application start, segment at 0x4000 always point to segment 0 that include the ROM header. See [[Create a mapped ROM#NEO mapper]] for more details.&lt;br /&gt;
&lt;br /&gt;
== Appendix ==&lt;br /&gt;
&lt;br /&gt;
=== Segment switching address format ===&lt;br /&gt;
&lt;br /&gt;
From a software point of view, the segment switching address is defined as:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
!colspan=&amp;quot;17&amp;quot;| 16-bit address&lt;br /&gt;
|-&lt;br /&gt;
! 15 || 14 || 13 || 12 || 11 || 10 || 9 || 8 &lt;br /&gt;
|&lt;br /&gt;
! 7 || 6 || 5 || 4 || 3 || 2 || 1 || 0&lt;br /&gt;
|-&lt;br /&gt;
| P || P || B || B || B || x || x || x || || x || x || x || x || x || x || x || R&lt;br /&gt;
|}&lt;br /&gt;
Where:&lt;br /&gt;
* '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, but the mapper registers can only be accessed from selected pages.&lt;br /&gt;
* 'BBB' (0-7) is the bank's register to write in. All unspecified values are discarded.&lt;br /&gt;
:{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Bank !! NEO-8 !! NEO-16&lt;br /&gt;
|-&lt;br /&gt;
| 0 || 010 || 010&lt;br /&gt;
|-&lt;br /&gt;
| 1 || 011 || 100&lt;br /&gt;
|-&lt;br /&gt;
| 2 || 100 || 110&lt;br /&gt;
|-&lt;br /&gt;
| 3 || 101 || &lt;br /&gt;
|-&lt;br /&gt;
| 4 || 110 || &lt;br /&gt;
|-&lt;br /&gt;
| 5 || 111 || &lt;br /&gt;
|}&lt;br /&gt;
* 'R' (0-1) is the segment switching register's byte selector (0: less significant byte; 1: most significant byte).&lt;br /&gt;
* 'x' can be any value (generating mirroring).&lt;br /&gt;
&lt;br /&gt;
So, mirroring occurs on all addresses from the given switching address +2 to the switching address +7FEh on all even-numbered addresses. For example, 5000h is mirrored at 5002h~57FEh.&lt;br /&gt;
&lt;br /&gt;
=== Programmable processor and emulation ===&lt;br /&gt;
Here is a pseudo code in C to handle NEO mappers for programmable processor based cartridges or for emulators:&lt;br /&gt;
{|&lt;br /&gt;
|-&lt;br /&gt;
| NEO-8 mapper:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
const uint8* romData; // ROM data&lt;br /&gt;
uint16 bankValue[6]; // Bank switching register value&lt;br /&gt;
&lt;br /&gt;
// Handle device initialization&lt;br /&gt;
void NEO8_Init()&lt;br /&gt;
{&lt;br /&gt;
   for (uint8 i=0; i&amp;lt;6; i++)&lt;br /&gt;
      bankValue[i] = 0;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// Handle write access&lt;br /&gt;
void NEO8_Write(uint16 address, uint8 value)&lt;br /&gt;
{&lt;br /&gt;
   uint8 bank = ((address &amp;gt;&amp;gt; 11) &amp;amp; 0x07) - 2;&lt;br /&gt;
   if (bank &amp;gt; 5)&lt;br /&gt;
      return; // skip&lt;br /&gt;
   if (address &amp;amp; 1) // Set bank register MSB&lt;br /&gt;
      bankValue[bank] = ((value &amp;amp; 0x0F) &amp;lt;&amp;lt; 8) | (bankValue[bank] &amp;amp; 0x00FF);&lt;br /&gt;
   else // Set bank register LSB&lt;br /&gt;
      bankValue[bank] = (bankValue[bank] &amp;amp; 0xFF00) | (value);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// Handle read access&lt;br /&gt;
uint8 NEO8_Read(uint16 address)&lt;br /&gt;
{&lt;br /&gt;
   uint8 bank = address &amp;gt;&amp;gt; 13;&lt;br /&gt;
   if (bank &amp;gt; 5)&lt;br /&gt;
      return 0xFF; // skip&lt;br /&gt;
   return romData[(bankValue[bank]) &amp;lt;&amp;lt; 13 + (address &amp;amp; 0x1FFF)];&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
| NEO-16 mapper:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
const uint8* romData; // ROM data&lt;br /&gt;
uint16 bankValue[3]; // Bank switching register value&lt;br /&gt;
&lt;br /&gt;
// Handle device initialization&lt;br /&gt;
void NEO16_Init()&lt;br /&gt;
{&lt;br /&gt;
   bankValue[0] = bankValue[1] = bankValue[2] = 0;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// Handle write access&lt;br /&gt;
void NEO16_Write(uint16 address, uint8 value)&lt;br /&gt;
{&lt;br /&gt;
   uint8 bank = ((address &amp;gt;&amp;gt; 12) &amp;amp; 0x03) - 1;&lt;br /&gt;
   if (bank &amp;gt; 2)&lt;br /&gt;
      return; // skip&lt;br /&gt;
   if (address &amp;amp; 1) // Set bank register MSB&lt;br /&gt;
      bankValue[bank] = ((value &amp;amp; 0x0F) &amp;lt;&amp;lt; 8) | (bankValue[bank] &amp;amp; 0x00FF);&lt;br /&gt;
   else // Set bank register LSB&lt;br /&gt;
      bankValue[bank] = (bankValue[bank] &amp;amp; 0xFF00) | (value);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// Handle read access&lt;br /&gt;
uint8 NEO16_Read(uint16 address)&lt;br /&gt;
{&lt;br /&gt;
   uint8 bank = address &amp;gt;&amp;gt; 14;&lt;br /&gt;
   if (bank &amp;gt; 2)&lt;br /&gt;
      return 0xFF; // skip&lt;br /&gt;
   return romData[(bankValue[bank]) &amp;lt;&amp;lt; 14 + (address &amp;amp; 0x3FFF)];&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Sample program ===&lt;br /&gt;
A sample program is available for testing purpose on: https://aoineko.org/msx/targets/rom/&lt;br /&gt;
&lt;br /&gt;
It is available in various sizes:&lt;br /&gt;
* NEO-8: 256 KB to 32 MB&lt;br /&gt;
* NEO-16: 256 KB to 64 MB&lt;br /&gt;
&lt;br /&gt;
=== Bank switching cost ===&lt;br /&gt;
For a program using NEO mapper, 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.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;ini&amp;quot;&amp;gt;&lt;br /&gt;
; Direct access (22 t-states)&lt;br /&gt;
LD A,n      ;  8 t-states&lt;br /&gt;
LD (nn),A   ; 14 t-states&lt;br /&gt;
&lt;br /&gt;
; Indirect access (22 t-states)&lt;br /&gt;
LD HL,nn    ; 11 t-states&lt;br /&gt;
LD (HL),n   ; 11 t-states&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Although a program can avoid having to change the 2 bytes (16-bit) of the segment register at once, there are cases where this may be necessary. In such cases, the cost is higher, but remains reasonable.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;ini&amp;quot;&amp;gt;&lt;br /&gt;
; Direct access (28 t-states)&lt;br /&gt;
LD HL,nn    ; 11 t-states&lt;br /&gt;
LD (nn),HL  ; 17 t-states&lt;br /&gt;
&lt;br /&gt;
; Indirect access (40 t-states)&lt;br /&gt;
LD HL,nn    ; 11 t-states&lt;br /&gt;
LD (HL),n   ; 11 t-states&lt;br /&gt;
INC HL      ;  7 t-states&lt;br /&gt;
LD (HL),n   ; 11 t-states&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Logos ===&lt;br /&gt;
Here are the logos you can use to indicate that a product is compatible with the NEO mapper:&lt;br /&gt;
&lt;br /&gt;
[https://aoineko.org/msx/files/neomapper8b-logo.png &amp;lt;img style=&amp;quot;width:128px&amp;quot; src=&amp;quot;https://aoineko.org/msx/files/neomapper8b-logo.png&amp;quot; /&amp;gt;]&lt;br /&gt;
[https://aoineko.org/msx/files/neomapper8w-logo.png &amp;lt;img style=&amp;quot;width:128px&amp;quot; src=&amp;quot;https://aoineko.org/msx/files/neomapper8w-logo.png&amp;quot; /&amp;gt;]&lt;br /&gt;
[https://aoineko.org/msx/files/neomapper16b-logo.png &amp;lt;img style=&amp;quot;width:128px&amp;quot; src=&amp;quot;https://aoineko.org/msx/files/neomapper16b-logo.png&amp;quot; /&amp;gt;]&lt;br /&gt;
[https://aoineko.org/msx/files/neomapper16w-logo.png &amp;lt;img style=&amp;quot;width:128px&amp;quot; src=&amp;quot;https://aoineko.org/msx/files/neomapper16w-logo.png&amp;quot; /&amp;gt;]&lt;br /&gt;
&lt;br /&gt;
== Change log ==&lt;br /&gt;
* Version 1.0 (2024/02/12)&lt;br /&gt;
** Original version&lt;br /&gt;
* Version 1.1 (2024/02/20)&lt;br /&gt;
** Changed mappers signature to minimize the risk of an old cartridge generating a false positive and to comply to [[ROM type signature]] format.&lt;br /&gt;
** Added clarification on PP and BBB values for bank switching addresses.&lt;br /&gt;
** Added clarification for read access to the mapper and especially when try to read the page 3.&lt;br /&gt;
* Version 1.2 (2026/04/06)&lt;br /&gt;
** Added optional official logo for NEO mapper product.&lt;br /&gt;
** Added bits 12 and 13 to the register value, increasing the maximum number of segments from 4096 to 16384.&lt;br /&gt;
[[Category:Proposal]][[Category:Proposal/Mapper]]&lt;/div&gt;</summary>
		<author><name>Aoineko</name></author>	</entry>

	<entry>
		<id>https://aoineko.org/msxgl/index.php?title=NEO_mapper&amp;diff=3965</id>
		<title>NEO mapper</title>
		<link rel="alternate" type="text/html" href="https://aoineko.org/msxgl/index.php?title=NEO_mapper&amp;diff=3965"/>
				<updated>2026-05-17T14:17:45Z</updated>
		
		<summary type="html">&lt;p&gt;Aoineko: /* Hardware */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;div style=&amp;quot;float:right&amp;quot;&amp;gt;[[NEO mapper|EN]] | [[NEO mapper/JA|JA]]&amp;lt;/div&amp;gt;&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
== Specifications ==&lt;br /&gt;
&lt;br /&gt;
=== Principles ===&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
Like conventional mappers, the basic idea is to use data write signals to the cartridge to change mapper registers value and thus, 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 [[#Format|tables below]]).&lt;br /&gt;
Read accesses, however, work as normal accesses to the memory visible through the banks.&lt;br /&gt;
&lt;br /&gt;
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 cartridge in this new mapper format.&lt;br /&gt;
&lt;br /&gt;
Compared to conventional mappers, this proposal is based on two new main features:&lt;br /&gt;
* A 16-bit segment register,&lt;br /&gt;
* Banks covering page #0 of MSX memory space (address 0000h~3FFFh).&lt;br /&gt;
&lt;br /&gt;
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).&lt;br /&gt;
&lt;br /&gt;
For the time being, we propose to reserve the 2 most significant bits of the 16-bit bank registers for future extensions of the format (such as SRAM or sound chips support for example).&lt;br /&gt;
This leaves 14 bits to select which segment is visible in each bank, for a maximum of 16384 segments.&lt;br /&gt;
The reserved bits, must be set to 0.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
!colspan=&amp;quot;8&amp;quot;| Higher byte&lt;br /&gt;
|&lt;br /&gt;
!colspan=&amp;quot;8&amp;quot;| Lower byte &lt;br /&gt;
|-&lt;br /&gt;
! 15 || 14 || 13 || 12 || 11 || 10 || 9 || 8 &lt;br /&gt;
|&lt;br /&gt;
! 7 || 6 || 5 || 4 || 3 || 2 || 1 || 0&lt;br /&gt;
|-&lt;br /&gt;
| 0 || 0&lt;br /&gt;
|colspan=&amp;quot;6&amp;quot;| Segment MSB&lt;br /&gt;
| &lt;br /&gt;
|colspan=&amp;quot;8&amp;quot;| Segment LSB &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The maximum ROM size is therefore 128 MB (for 8 KB segments) or 256 MB (for 16 KB segments).&lt;br /&gt;
&lt;br /&gt;
=== Write Access ===&lt;br /&gt;
&lt;br /&gt;
Write access to the mapper is use to change the value of the bank switching register (where you can select the ROM segment visible through a bank).&lt;br /&gt;
Bellow is the list of the predefined segment switching addresses.&lt;br /&gt;
&lt;br /&gt;
As this new mapper uses 16-bit segment switching registers, it uses 2 bytes for the segment number to be selected in each bank.&lt;br /&gt;
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.&lt;br /&gt;
This way, the segment number can be initialized at once with the [[#Bank switching cost|Z80 instructions for 16-bit memory write access]].&lt;br /&gt;
&lt;br /&gt;
==== NEO-8 mapper ====&lt;br /&gt;
&lt;br /&gt;
* Size of a segment: 8 KB&lt;br /&gt;
* Segment switching addresses:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Bank (8kB) !! Switching address !! Initial segment&lt;br /&gt;
|-&lt;br /&gt;
| 0: 0000h~1FFFh || 5000h (mirror at 1000h, 9000h and D000h) || 0000h&lt;br /&gt;
|-&lt;br /&gt;
| 1: 2000h~3FFFh || 5800h (mirror at 1800h, 9800h and D800h) || 0000h&lt;br /&gt;
|-&lt;br /&gt;
| 2: 4000h~5FFFh || 6000h (mirror at 2000h, A000h and E000h) || 0000h&lt;br /&gt;
|-&lt;br /&gt;
| 3: 6000h~7FFFh || 6800h (mirror at 2800h, A800h and E800h) || 0000h&lt;br /&gt;
|-&lt;br /&gt;
| 4: 8000h~9FFFh || 7000h (mirror at 3000h, B000h and F000h) || 0000h&lt;br /&gt;
|-&lt;br /&gt;
| 5: A000h~BFFFh || 7800h (mirror at 3800h, B800h and F800h) || 0000h&lt;br /&gt;
|}&lt;br /&gt;
* Maximum number of segments: 16384&lt;br /&gt;
* Maximum ROM size: 128 MB&lt;br /&gt;
&lt;br /&gt;
==== NEO-16 mapper ====&lt;br /&gt;
&lt;br /&gt;
* Size of a segment: 16 KB&lt;br /&gt;
* Segment switching addresses:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Bank (16kB) !! Switching address !! Initial segment&lt;br /&gt;
|-&lt;br /&gt;
| 0: 0000h~3FFFh || 5000h (mirror at 1000h, 9000h and D000h) || 0000h&lt;br /&gt;
|-&lt;br /&gt;
| 1: 4000h~7FFFh || 6000h (mirror at 2000h, A000h and E000h) || 0000h&lt;br /&gt;
|-&lt;br /&gt;
| 2: 8000h~BFFFh || 7000h (mirror at 3000h, B000h and F000h) || 0000h&lt;br /&gt;
|}&lt;br /&gt;
* Maximum number of segments: 16384&lt;br /&gt;
* Maximum ROM size: 256 MB&lt;br /&gt;
&lt;br /&gt;
=== Read Access ===&lt;br /&gt;
When mapper is selected, read accesses to memory pages 0, 1 and 2 (addresses 0000h to BFFFh), are redirected to a given ROM segment according to the value of the bank register corresponding to the address.&lt;br /&gt;
&lt;br /&gt;
For page 3, read accesses are invalid and the value returned is undefined and should not be used. Implementations of the NEO mapper should return the value FFh if page 3 is read, but this value is not guaranteed by the mapper specifications.&lt;br /&gt;
&lt;br /&gt;
=== Detection ===&lt;br /&gt;
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:&lt;br /&gt;
* &amp;quot;&amp;lt;tt&amp;gt;ROM_NEO8&amp;lt;/tt&amp;gt;&amp;quot; for NEO-8 mapper,&lt;br /&gt;
* &amp;quot;&amp;lt;tt&amp;gt;ROM_NE16&amp;lt;/tt&amp;gt;&amp;quot; for NEO-16 mapper.&lt;br /&gt;
&lt;br /&gt;
The ROM header (starting with &amp;quot;AB&amp;quot;) must be in the first ROM segment at offset 0.&lt;br /&gt;
The signature is therefore located at offset 16 of the ROM and may be visible to the Z80 on start-up at addresses 0010h, 4010h and 8010h.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;Note&amp;lt;/u&amp;gt;: Signature characters have been carefully choosed to prevent existing ROMs to generate false positive signature (See [[ROM type signature]]).&lt;br /&gt;
&lt;br /&gt;
== Support ==&lt;br /&gt;
&lt;br /&gt;
=== Hardware ===&lt;br /&gt;
Hardware supporting NEO mapper:&lt;br /&gt;
* '''[https://www.msxpico.com/ MSX Pico]''' (normal or WiFi): Support for NEO-8 and NEO-16 mappers up to ~15 MB (firmware 1.25 or above).&lt;br /&gt;
* '''[https://www.msxpico.com/ MSX Pico+]''': Support for NEO-8 and NEO-16 mappers up to ~14 MB (firmware 2.12 or above).&lt;br /&gt;
* '''[https://github.com/cristianoag/msx-picoverse-public PicoVerse] 2040 and 2350''': Support for NEO-8 and NEO-16 mappers up to ~15 MB.&lt;br /&gt;
* '''[https://github.com/arkadiuszmakarenko/RISKYMSX RISKY MSX]''': Support for NEO-8 and NEO-16 mappers up to 256 KB.&lt;br /&gt;
* '''[https://github.com/piigaa-densetu-two-dai/MSXpi MSXπ]''': Support for NEO-16 mappers up to 16 MB&lt;br /&gt;
* '''[https://github.com/piigaa-densetu-two-dai/MSXpi_plus_v2 MSXπ✨V2]''': Support for NEO-16 mappers up to 16 MB&lt;br /&gt;
&lt;br /&gt;
=== Emulator ===&lt;br /&gt;
Emulators supporting NEO mapper:&lt;br /&gt;
* {{Emulicious}} '''Emulicious''': Full support for NEO-8 and NEO-16 mappers.&lt;br /&gt;
* {{MSXEC}} '''MSXEC''': Support NEO-8 and NEO-16 mappers up to 64 MB (version 20260303 or above).&lt;br /&gt;
* {{openMSX}} '''openMSX''': Full support for NEO-8 and NEO-16 mappers (version 20.0 or above).&lt;br /&gt;
* {{WebMSX}} '''WebMSX''': Full support for NEO-8 and NEO-16 mappers (version 6.0.7 or above).&lt;br /&gt;
&lt;br /&gt;
=== MSXgl ===&lt;br /&gt;
&lt;br /&gt;
Both NEO-8 and NEO-16 mappers are supported. Use respectively &amp;lt;tt&amp;gt;ROM_NEO8&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;ROM_NEO16&amp;lt;/tt&amp;gt; as target format.&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
#define SET_BANK_SEGMENT(bank, segment) /* ... */&lt;br /&gt;
&lt;br /&gt;
// Make segment #30 visible through bank #1&lt;br /&gt;
SET_BANK_SEGMENT(1, 30);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
MSXgl initialize the banks with a unique segment each, to offer the largest possible space available to the user:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;img style=&amp;quot;width:400px; margin:0.5em;&amp;quot; src=&amp;quot;https://raw.githubusercontent.com/aoineko-fr/MSXgl/main/engine/doc/mapper_neo8.png&amp;quot; /&amp;gt;&lt;br /&gt;
&amp;lt;img style=&amp;quot;width:400px; margin:0.5em;&amp;quot; src=&amp;quot;https://raw.githubusercontent.com/aoineko-fr/MSXgl/main/engine/doc/mapper_neo16.png&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;Note&amp;lt;/u&amp;gt;: When the application start, segment at 0x4000 always point to segment 0 that include the ROM header. See [[Create a mapped ROM#NEO mapper]] for more details.&lt;br /&gt;
&lt;br /&gt;
== Appendix ==&lt;br /&gt;
&lt;br /&gt;
=== Segment switching address format ===&lt;br /&gt;
&lt;br /&gt;
From a software point of view, the segment switching address is defined as:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
!colspan=&amp;quot;17&amp;quot;| 16-bit address&lt;br /&gt;
|-&lt;br /&gt;
! 15 || 14 || 13 || 12 || 11 || 10 || 9 || 8 &lt;br /&gt;
|&lt;br /&gt;
! 7 || 6 || 5 || 4 || 3 || 2 || 1 || 0&lt;br /&gt;
|-&lt;br /&gt;
| P || P || B || B || B || x || x || x || || x || x || x || x || x || x || x || R&lt;br /&gt;
|}&lt;br /&gt;
Where:&lt;br /&gt;
* '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, but the mapper registers can only be accessed from selected pages.&lt;br /&gt;
* 'BBB' (0-7) is the bank's register to write in. All unspecified values are discarded.&lt;br /&gt;
:{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Bank !! NEO-8 !! NEO-16&lt;br /&gt;
|-&lt;br /&gt;
| 0 || 010 || 010&lt;br /&gt;
|-&lt;br /&gt;
| 1 || 011 || 100&lt;br /&gt;
|-&lt;br /&gt;
| 2 || 100 || 110&lt;br /&gt;
|-&lt;br /&gt;
| 3 || 101 || &lt;br /&gt;
|-&lt;br /&gt;
| 4 || 110 || &lt;br /&gt;
|-&lt;br /&gt;
| 5 || 111 || &lt;br /&gt;
|}&lt;br /&gt;
* 'R' (0-1) is the segment switching register's byte selector (0: less significant byte; 1: most significant byte).&lt;br /&gt;
* 'x' can be any value (generating mirroring).&lt;br /&gt;
&lt;br /&gt;
So, mirroring occurs on all addresses from the given switching address +2 to the switching address +7FEh on all even-numbered addresses. For example, 5000h is mirrored at 5002h~57FEh.&lt;br /&gt;
&lt;br /&gt;
=== Programmable processor and emulation ===&lt;br /&gt;
Here is a pseudo code in C to handle NEO mappers for programmable processor based cartridges or for emulators:&lt;br /&gt;
{|&lt;br /&gt;
|-&lt;br /&gt;
| NEO-8 mapper:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
const uint8* romData; // ROM data&lt;br /&gt;
uint16 bankValue[6]; // Bank switching register value&lt;br /&gt;
&lt;br /&gt;
// Handle device initialization&lt;br /&gt;
void NEO8_Init()&lt;br /&gt;
{&lt;br /&gt;
   for (uint8 i=0; i&amp;lt;6; i++)&lt;br /&gt;
      bankValue[i] = 0;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// Handle write access&lt;br /&gt;
void NEO8_Write(uint16 address, uint8 value)&lt;br /&gt;
{&lt;br /&gt;
   uint8 bank = ((address &amp;gt;&amp;gt; 11) &amp;amp; 0x07) - 2;&lt;br /&gt;
   if (bank &amp;gt; 5)&lt;br /&gt;
      return; // skip&lt;br /&gt;
   if (address &amp;amp; 1) // Set bank register MSB&lt;br /&gt;
      bankValue[bank] = ((value &amp;amp; 0x0F) &amp;lt;&amp;lt; 8) | (bankValue[bank] &amp;amp; 0x00FF);&lt;br /&gt;
   else // Set bank register LSB&lt;br /&gt;
      bankValue[bank] = (bankValue[bank] &amp;amp; 0xFF00) | (value);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// Handle read access&lt;br /&gt;
uint8 NEO8_Read(uint16 address)&lt;br /&gt;
{&lt;br /&gt;
   uint8 bank = address &amp;gt;&amp;gt; 13;&lt;br /&gt;
   if (bank &amp;gt; 5)&lt;br /&gt;
      return 0xFF; // skip&lt;br /&gt;
   return romData[(bankValue[bank]) &amp;lt;&amp;lt; 13 + (address &amp;amp; 0x1FFF)];&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
| NEO-16 mapper:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
const uint8* romData; // ROM data&lt;br /&gt;
uint16 bankValue[3]; // Bank switching register value&lt;br /&gt;
&lt;br /&gt;
// Handle device initialization&lt;br /&gt;
void NEO16_Init()&lt;br /&gt;
{&lt;br /&gt;
   bankValue[0] = bankValue[1] = bankValue[2] = 0;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// Handle write access&lt;br /&gt;
void NEO16_Write(uint16 address, uint8 value)&lt;br /&gt;
{&lt;br /&gt;
   uint8 bank = ((address &amp;gt;&amp;gt; 12) &amp;amp; 0x03) - 1;&lt;br /&gt;
   if (bank &amp;gt; 2)&lt;br /&gt;
      return; // skip&lt;br /&gt;
   if (address &amp;amp; 1) // Set bank register MSB&lt;br /&gt;
      bankValue[bank] = ((value &amp;amp; 0x0F) &amp;lt;&amp;lt; 8) | (bankValue[bank] &amp;amp; 0x00FF);&lt;br /&gt;
   else // Set bank register LSB&lt;br /&gt;
      bankValue[bank] = (bankValue[bank] &amp;amp; 0xFF00) | (value);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// Handle read access&lt;br /&gt;
uint8 NEO16_Read(uint16 address)&lt;br /&gt;
{&lt;br /&gt;
   uint8 bank = address &amp;gt;&amp;gt; 14;&lt;br /&gt;
   if (bank &amp;gt; 2)&lt;br /&gt;
      return 0xFF; // skip&lt;br /&gt;
   return romData[(bankValue[bank]) &amp;lt;&amp;lt; 14 + (address &amp;amp; 0x3FFF)];&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Sample program ===&lt;br /&gt;
A sample program is available for testing purpose on: https://aoineko.org/msx/targets/rom/&lt;br /&gt;
&lt;br /&gt;
It is available in various sizes:&lt;br /&gt;
* NEO-8: 256 KB to 32 MB&lt;br /&gt;
* NEO-16: 256 KB to 64 MB&lt;br /&gt;
&lt;br /&gt;
=== Bank switching cost ===&lt;br /&gt;
For a program using NEO mapper, 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.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;ini&amp;quot;&amp;gt;&lt;br /&gt;
; Direct access (22 t-states)&lt;br /&gt;
LD A,n      ;  8 t-states&lt;br /&gt;
LD (nn),A   ; 14 t-states&lt;br /&gt;
&lt;br /&gt;
; Indirect access (22 t-states)&lt;br /&gt;
LD HL,nn    ; 11 t-states&lt;br /&gt;
LD (HL),n   ; 11 t-states&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Although a program can avoid having to change the 2 bytes (16-bit) of the segment register at once, there are cases where this may be necessary. In such cases, the cost is higher, but remains reasonable.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;ini&amp;quot;&amp;gt;&lt;br /&gt;
; Direct access (28 t-states)&lt;br /&gt;
LD HL,nn    ; 11 t-states&lt;br /&gt;
LD (nn),HL  ; 17 t-states&lt;br /&gt;
&lt;br /&gt;
; Indirect access (40 t-states)&lt;br /&gt;
LD HL,nn    ; 11 t-states&lt;br /&gt;
LD (HL),n   ; 11 t-states&lt;br /&gt;
INC HL      ;  7 t-states&lt;br /&gt;
LD (HL),n   ; 11 t-states&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Logos ===&lt;br /&gt;
Here are the logos you can use to indicate that a product is compatible with the NEO mapper:&lt;br /&gt;
&lt;br /&gt;
[https://aoineko.org/msx/files/neomapper8b-logo.png &amp;lt;img style=&amp;quot;width:128px&amp;quot; src=&amp;quot;https://aoineko.org/msx/files/neomapper8b-logo.png&amp;quot; /&amp;gt;]&lt;br /&gt;
[https://aoineko.org/msx/files/neomapper8w-logo.png &amp;lt;img style=&amp;quot;width:128px&amp;quot; src=&amp;quot;https://aoineko.org/msx/files/neomapper8w-logo.png&amp;quot; /&amp;gt;]&lt;br /&gt;
[https://aoineko.org/msx/files/neomapper16b-logo.png &amp;lt;img style=&amp;quot;width:128px&amp;quot; src=&amp;quot;https://aoineko.org/msx/files/neomapper16b-logo.png&amp;quot; /&amp;gt;]&lt;br /&gt;
[https://aoineko.org/msx/files/neomapper16w-logo.png &amp;lt;img style=&amp;quot;width:128px&amp;quot; src=&amp;quot;https://aoineko.org/msx/files/neomapper16w-logo.png&amp;quot; /&amp;gt;]&lt;br /&gt;
&lt;br /&gt;
== Change log ==&lt;br /&gt;
* Version 1.0 (2024/02/12)&lt;br /&gt;
** Original version&lt;br /&gt;
* Version 1.1 (2024/02/20)&lt;br /&gt;
** Changed mappers signature to minimize the risk of an old cartridge generating a false positive and to comply to [[ROM type signature]] format.&lt;br /&gt;
** Added clarification on PP and BBB values for bank switching addresses.&lt;br /&gt;
** Added clarification for read access to the mapper and especially when try to read the page 3.&lt;br /&gt;
* Version 1.2 (2026/04/06)&lt;br /&gt;
** Added optional official logo for NEO mapper product.&lt;br /&gt;
** Added bits 12 and 13 to the register value, increasing the maximum number of segments from 4096 to 16384.&lt;br /&gt;
[[Category:Proposal]][[Category:Proposal/Mapper]]&lt;/div&gt;</summary>
		<author><name>Aoineko</name></author>	</entry>

	<entry>
		<id>https://aoineko.org/msxgl/index.php?title=Template:JOYMEGA&amp;diff=3964</id>
		<title>Template:JOYMEGA</title>
		<link rel="alternate" type="text/html" href="https://aoineko.org/msxgl/index.php?title=Template:JOYMEGA&amp;diff=3964"/>
				<updated>2026-05-14T20:24:00Z</updated>
		
		<summary type="html">&lt;p&gt;Aoineko: Created page with &amp;quot;{{LOGO|logo_joymega.png|JoyMega adapter|ext}}&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{LOGO|logo_joymega.png|JoyMega adapter|ext}}&lt;/div&gt;</summary>
		<author><name>Aoineko</name></author>	</entry>

	<entry>
		<id>https://aoineko.org/msxgl/index.php?title=Samples&amp;diff=3963</id>
		<title>Samples</title>
		<link rel="alternate" type="text/html" href="https://aoineko.org/msxgl/index.php?title=Samples&amp;diff=3963"/>
				<updated>2026-05-14T19:46:26Z</updated>
		
		<summary type="html">&lt;p&gt;Aoineko: /* lVGM */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Here is a list of sample programs included with '''MSXgl''' to illustrate how to use the library’s various features and functions.&lt;br /&gt;
To test a sample program, follow these steps:&lt;br /&gt;
# Open a command-line interface in the &amp;lt;tt&amp;gt;MSXgl/projects/samples/&amp;lt;/tt&amp;gt; directory.&lt;br /&gt;
# Run one of the following commands, depending on your operating system:&lt;br /&gt;
#* &amp;lt;tt&amp;gt;build.bat s_game&amp;lt;/tt&amp;gt; (Windows) &lt;br /&gt;
#* &amp;lt;tt&amp;gt;./build.sh s_game&amp;lt;/tt&amp;gt; (Linux &amp;amp; macOS)&lt;br /&gt;
&lt;br /&gt;
Replace &amp;lt;tt&amp;gt;s_game&amp;lt;/tt&amp;gt; with the name of the sample you wish to test (there’s no need to include the &amp;lt;tt&amp;gt;.c&amp;lt;/tt&amp;gt; file extension).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;Note:&amp;lt;/u&amp;gt; Sample programs use a configuration system that overwrites the default project settings (&amp;lt;tt&amp;gt;project_config.js&amp;lt;/tt&amp;gt;) with a sample-specific configuration file (e.g., &amp;lt;tt&amp;gt;s_game.js&amp;lt;/tt&amp;gt;). This approach allows multiple projects to coexist in the same directory without conflicts.&lt;br /&gt;
&lt;br /&gt;
For standalone projects, this step is unnecessary. To learn how to set up your own project from scratch, see [[Create my first program|this guide]].&lt;br /&gt;
&lt;br /&gt;
== Core ==&lt;br /&gt;
&lt;br /&gt;
=== Hello World ===&lt;br /&gt;
{{SAMPLE_BOX&lt;br /&gt;
|name=Hello&lt;br /&gt;
|desc=Program showing the minimal code needed to display a &amp;quot;Hello World!&amp;quot; text.&lt;br /&gt;
|module1=&lt;br /&gt;
|module2=&lt;br /&gt;
|module3=&lt;br /&gt;
|module4=&lt;br /&gt;
|module5=&lt;br /&gt;
|file=s_hello.c&lt;br /&gt;
|machine=MSX1&lt;br /&gt;
|target=ROM_32K&lt;br /&gt;
|ext=&lt;br /&gt;
|state=FUNCTIONAL&lt;br /&gt;
|img=raw.githubusercontent.com/aoineko-fr/MSXgl/main/engine/doc/img/sample_hello.jpg&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
=== BIOS ===&lt;br /&gt;
{{SAMPLE_BOX&lt;br /&gt;
|name=BIOS&lt;br /&gt;
|desc=Program showing the use of default BIOS functions.&lt;br /&gt;
|module1=bios&lt;br /&gt;
|module2=&lt;br /&gt;
|module3=&lt;br /&gt;
|module4=&lt;br /&gt;
|module5=&lt;br /&gt;
|file=s_bios.c&lt;br /&gt;
|machine=MSX1&lt;br /&gt;
|target=ROM_32K&lt;br /&gt;
|ext=&lt;br /&gt;
|state=FUNCTIONAL&lt;br /&gt;
|img=raw.githubusercontent.com/aoineko-fr/MSXgl/main/engine/doc/img/sample_bios.jpg&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
=== Clock ===&lt;br /&gt;
{{SAMPLE_BOX&lt;br /&gt;
|name=Clock&lt;br /&gt;
|desc=Program showing the use of the MSX2's Real Time Clock (Ricoh RP-5C01) to get current time and save/load data from CMOS memory.&lt;br /&gt;
|module1=clock&lt;br /&gt;
|module2=&lt;br /&gt;
|module3=&lt;br /&gt;
|module4=&lt;br /&gt;
|module5=&lt;br /&gt;
|file=s_clock.c&lt;br /&gt;
|machine=MSX2&lt;br /&gt;
|target=ROM_32K&lt;br /&gt;
|ext=&lt;br /&gt;
|state=FUNCTIONAL&lt;br /&gt;
|img=raw.githubusercontent.com/aoineko-fr/MSXgl/main/engine/doc/img/sample_clock.jpg&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
=== PSG ===&lt;br /&gt;
{{SAMPLE_BOX&lt;br /&gt;
|name=PSG&lt;br /&gt;
|desc=Program showing the use of direct control over PSG sound chip.&lt;br /&gt;
|module1=psg&lt;br /&gt;
|module2=&lt;br /&gt;
|module3=&lt;br /&gt;
|module4=&lt;br /&gt;
|module5=&lt;br /&gt;
|file=s_psg.c&lt;br /&gt;
|machine=MSX1&lt;br /&gt;
|target=ROM_32K&lt;br /&gt;
|ext=&lt;br /&gt;
|state=FUNCTIONAL&lt;br /&gt;
|img=raw.githubusercontent.com/aoineko-fr/MSXgl/main/engine/doc/img/sample_psg.jpg&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
=== System ===&lt;br /&gt;
{{SAMPLE_BOX&lt;br /&gt;
|name=System&lt;br /&gt;
|desc=Program showing the retrieval of system information.&lt;br /&gt;
|module1=&lt;br /&gt;
|module2=&lt;br /&gt;
|module3=&lt;br /&gt;
|module4=&lt;br /&gt;
|module5=&lt;br /&gt;
|file=s_sys.c&lt;br /&gt;
|machine=MSX1&lt;br /&gt;
|target=ROM_32K&lt;br /&gt;
|ext=&lt;br /&gt;
|state=FUNCTIONAL&lt;br /&gt;
|img=raw.githubusercontent.com/aoineko-fr/MSXgl/main/engine/doc/img/sample_sys.jpg&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
== Render ==&lt;br /&gt;
&lt;br /&gt;
=== Draw ===&lt;br /&gt;
{{SAMPLE_BOX&lt;br /&gt;
|name=Draw&lt;br /&gt;
|desc=Program showing the use of Draw module with the MSX2 bitmap screen modes.&lt;br /&gt;
|module1=vdp&lt;br /&gt;
|module2=draw&lt;br /&gt;
|module3=&lt;br /&gt;
|module4=&lt;br /&gt;
|module5=&lt;br /&gt;
|file=s_draw.c&lt;br /&gt;
|machine=MSX2&lt;br /&gt;
|target=ROM_32K&lt;br /&gt;
|ext=&lt;br /&gt;
|state=FUNCTIONAL&lt;br /&gt;
|img=raw.githubusercontent.com/aoineko-fr/MSXgl/main/engine/doc/img/sample_draw.jpg&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
=== Graph Mode 3 ===&lt;br /&gt;
{{SAMPLE_BOX&lt;br /&gt;
|name=Graph Mode 3&lt;br /&gt;
|desc=Program showing the use of Screen 4 (aka Graph mode 3) with various configuration (including unofficial MSX configurations like &amp;quot;Screen 1.5&amp;quot;).&lt;br /&gt;
|module1=vdp&lt;br /&gt;
|module2=&lt;br /&gt;
|module3=&lt;br /&gt;
|module4=&lt;br /&gt;
|module5=&lt;br /&gt;
|file=s_gm3.c&lt;br /&gt;
|machine=MSX2&lt;br /&gt;
|target=ROM_32K&lt;br /&gt;
|ext=&lt;br /&gt;
|state=FUNCTIONAL&lt;br /&gt;
|img=raw.githubusercontent.com/aoineko-fr/MSXgl/main/engine/doc/img/sample_gm3_2.png&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
=== Print ===&lt;br /&gt;
{{SAMPLE_BOX&lt;br /&gt;
|name=Print&lt;br /&gt;
|desc=Program showing the use of graphical print features (bitmap, sprite, effects, etc.).&lt;br /&gt;
|module1=print&lt;br /&gt;
|module2=&lt;br /&gt;
|module3=&lt;br /&gt;
|module4=&lt;br /&gt;
|module5=&lt;br /&gt;
|file=s_print.c&lt;br /&gt;
|machine=MSX2&lt;br /&gt;
|target=ROM_32K&lt;br /&gt;
|ext=&lt;br /&gt;
|state=FUNCTIONAL&lt;br /&gt;
|img=raw.githubusercontent.com/aoineko-fr/MSXgl/main/engine/doc/img/sample_print.jpg&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
=== Scrolling ===&lt;br /&gt;
{{SAMPLE_BOX&lt;br /&gt;
|name=Scrolling&lt;br /&gt;
|desc=Program showing the use of multi-directionnal tile-based scrolling and screen adjust register for smooth scrolling.&lt;br /&gt;
|module1=vdp&lt;br /&gt;
|module2=scroll&lt;br /&gt;
|module3=&lt;br /&gt;
|module4=&lt;br /&gt;
|module5=&lt;br /&gt;
|file=s_scroll.c&lt;br /&gt;
|machine=MSX2&lt;br /&gt;
|target=ROM_32K&lt;br /&gt;
|ext=&lt;br /&gt;
|state=FUNCTIONAL&lt;br /&gt;
|img=raw.githubusercontent.com/aoineko-fr/MSXgl/main/engine/doc/img/sample_scroll.png&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
=== Sprite Mode 1 ===&lt;br /&gt;
{{SAMPLE_BOX&lt;br /&gt;
|name=Sprite&lt;br /&gt;
|desc=Program showing the use of sprite mode 1 and a Sprite Attribute Table flip method to reduce sprite disappearance.&lt;br /&gt;
|module1=vdp&lt;br /&gt;
|module2=&lt;br /&gt;
|module3=&lt;br /&gt;
|module4=&lt;br /&gt;
|module5=&lt;br /&gt;
|file=s_sm1.c&lt;br /&gt;
|machine=MSX1&lt;br /&gt;
|target=ROM_32K&lt;br /&gt;
|ext=&lt;br /&gt;
|state=FUNCTIONAL&lt;br /&gt;
|img=raw.githubusercontent.com/aoineko-fr/MSXgl/main/engine/doc/img/sample_sm1.jpg&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
=== Sprite Mode 2 ===&lt;br /&gt;
{{SAMPLE_BOX&lt;br /&gt;
|name=Sprite&lt;br /&gt;
|desc=Program demonstrating the use of sprite mode 2 (including multi-colors) and split screen using the horizontal interrupt to modify VDP parameters during screen rendering.&lt;br /&gt;
|module1=vdp&lt;br /&gt;
|module2=&lt;br /&gt;
|module3=&lt;br /&gt;
|module4=&lt;br /&gt;
|module5=&lt;br /&gt;
|file=s_sprite.c&lt;br /&gt;
|machine=MSX2&lt;br /&gt;
|target=ROM_32K&lt;br /&gt;
|ext=&lt;br /&gt;
|state=FUNCTIONAL&lt;br /&gt;
|img=raw.githubusercontent.com/aoineko-fr/MSXgl/main/engine/doc/img/sample_sprite.jpg&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
=== Sprite FX ===&lt;br /&gt;
{{SAMPLE_BOX&lt;br /&gt;
|name=Sprite FX&lt;br /&gt;
|desc=Program showing the use of Sprite Tool module to modify sprite data (support Cropping, Flipping, Asking and Rotating).&lt;br /&gt;
|module1=sprite_fx&lt;br /&gt;
|module2=&lt;br /&gt;
|module3=&lt;br /&gt;
|module4=&lt;br /&gt;
|module5=&lt;br /&gt;
|file=s_sprtfx.c&lt;br /&gt;
|machine=MSX2&lt;br /&gt;
|target=ROM_32K&lt;br /&gt;
|ext=&lt;br /&gt;
|state=FUNCTIONAL&lt;br /&gt;
|img=raw.githubusercontent.com/aoineko-fr/MSXgl/main/engine/doc/img/sample_sprttool.gif&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
=== Software Sprite ===&lt;br /&gt;
{{SAMPLE_BOX&lt;br /&gt;
|name=Software Sprite&lt;br /&gt;
|desc=Program showing the use of software sprite for all bitmap modes using VDP commands.&lt;br /&gt;
|module1=vdp&lt;br /&gt;
|module2=&lt;br /&gt;
|module3=&lt;br /&gt;
|module4=&lt;br /&gt;
|module5=&lt;br /&gt;
|file=s_swsprt.c&lt;br /&gt;
|machine=MSX2&lt;br /&gt;
|target=ROM_32K&lt;br /&gt;
|ext=&lt;br /&gt;
|state=FUNCTIONAL&lt;br /&gt;
|img=raw.githubusercontent.com/aoineko-fr/MSXgl/main/engine/doc/img/sample_swsprt.png&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
=== Software Tile ===&lt;br /&gt;
{{SAMPLE_BOX&lt;br /&gt;
|name=Software Tile&lt;br /&gt;
|desc=Program showing the use of software tile mode for MSX2 bitmap modes (only Screen 5 &amp;amp; 8 has been tested).&lt;br /&gt;
|module1=vdp&lt;br /&gt;
|module2=&lt;br /&gt;
|module3=&lt;br /&gt;
|module4=&lt;br /&gt;
|module5=&lt;br /&gt;
|file=s_swtile.c&lt;br /&gt;
|machine=MSX2&lt;br /&gt;
|target=ROM_32K&lt;br /&gt;
|ext=&lt;br /&gt;
|state=FUNCTIONAL&lt;br /&gt;
|img=raw.githubusercontent.com/aoineko-fr/MSXgl/main/engine/doc/img/sample_swtile.png&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
=== Text ===&lt;br /&gt;
{{SAMPLE_BOX&lt;br /&gt;
|name=Text&lt;br /&gt;
|desc=Program showing the use of print module with text modes (all MSX1 and MSX2 text/tiled mode).&lt;br /&gt;
|module1=print&lt;br /&gt;
|module2=&lt;br /&gt;
|module3=&lt;br /&gt;
|module4=&lt;br /&gt;
|module5=&lt;br /&gt;
|file=s_text.c&lt;br /&gt;
|machine=MSX12&lt;br /&gt;
|target=ROM_32K&lt;br /&gt;
|ext=&lt;br /&gt;
|state=FUNCTIONAL&lt;br /&gt;
|img=raw.githubusercontent.com/aoineko-fr/MSXgl/main/engine/doc/img/sample_text.jpg&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
=== VDP Command ===&lt;br /&gt;
{{SAMPLE_BOX&lt;br /&gt;
|name=VDP&lt;br /&gt;
|desc=Program showing the use of VDP command to draw several effect in all bitmap modes.&lt;br /&gt;
|module1=vdp&lt;br /&gt;
|module2=&lt;br /&gt;
|module3=&lt;br /&gt;
|module4=&lt;br /&gt;
|module5=&lt;br /&gt;
|file=s_vdpcmd.c&lt;br /&gt;
|machine=MSX2&lt;br /&gt;
|target=ROM_32K&lt;br /&gt;
|ext=&lt;br /&gt;
|state=FUNCTIONAL&lt;br /&gt;
|img=raw.githubusercontent.com/aoineko-fr/MSXgl/main/engine/doc/img/sample_vdpcmd.jpg&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
== Target format ==&lt;br /&gt;
&lt;br /&gt;
=== Boot Disk ===&lt;br /&gt;
{{SAMPLE_BOX&lt;br /&gt;
|name=Boot Disk&lt;br /&gt;
|desc=Program showing the use boot disk target format. The program will be start from disk without going through MSX-DOS but allow to use BDOS function.&lt;br /&gt;
|module1=dos&lt;br /&gt;
|module2=&lt;br /&gt;
|module3=&lt;br /&gt;
|module4=&lt;br /&gt;
|module5=&lt;br /&gt;
|file=s_dos0.c&lt;br /&gt;
|machine=MSX2&lt;br /&gt;
|target=DOS0&lt;br /&gt;
|ext=&lt;br /&gt;
|state=PARTIAL&lt;br /&gt;
|img=&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
=== MSX-DOS ===&lt;br /&gt;
{{SAMPLE_BOX&lt;br /&gt;
|name=MSX-DOS&lt;br /&gt;
|desc=Program showing the use of MSX-DOS 1 routines to load and display image from file.&lt;br /&gt;
|module1=dos&lt;br /&gt;
|module2=&lt;br /&gt;
|module3=&lt;br /&gt;
|module4=&lt;br /&gt;
|module5=&lt;br /&gt;
|file=s_dos.c&lt;br /&gt;
|machine=MSX22+&lt;br /&gt;
|target=DOS1&lt;br /&gt;
|ext=&lt;br /&gt;
|state=FUNCTIONAL&lt;br /&gt;
|img=raw.githubusercontent.com/aoineko-fr/MSXgl/refs/heads/main/engine/doc/img/project/s_dos.png&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
=== MSX-DOS 2 ===&lt;br /&gt;
{{SAMPLE_BOX&lt;br /&gt;
|name=MSX-DOS 2&lt;br /&gt;
|desc=Program showing the use of various MSX-DOS 2 routines to load and display image, get disk information or handle mapped memory.&lt;br /&gt;
|module1=dos&lt;br /&gt;
|module2=dos_mapper&lt;br /&gt;
|module3=&lt;br /&gt;
|module4=&lt;br /&gt;
|module5=&lt;br /&gt;
|file=s_dos2.c&lt;br /&gt;
|machine=MSX2&lt;br /&gt;
|target=DOS2&lt;br /&gt;
|ext=&lt;br /&gt;
|state=FUNCTIONAL&lt;br /&gt;
|img=raw.githubusercontent.com/aoineko-fr/MSXgl/refs/heads/main/engine/doc/img/project/s_dos2.png&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
=== Mapped ROM ===&lt;br /&gt;
{{SAMPLE_BOX&lt;br /&gt;
|name=Mapped ROM&lt;br /&gt;
|desc=Program showing usage of mapped ROM and segments switching.&lt;br /&gt;
|module1=&lt;br /&gt;
|module2=&lt;br /&gt;
|module3=&lt;br /&gt;
|module4=&lt;br /&gt;
|module5=&lt;br /&gt;
|file=s_mapper.c&lt;br /&gt;
|machine=MSX1&lt;br /&gt;
|target=ROM_ASCII8_128K&lt;br /&gt;
|ext=&lt;br /&gt;
|state=FUNCTIONAL&lt;br /&gt;
|img=&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
=== NEO mapper ===&lt;br /&gt;
{{SAMPLE_BOX&lt;br /&gt;
|name=NEO mapper&lt;br /&gt;
|desc=Program showing usage of NEO-8 mapped ROM and segments switching.&lt;br /&gt;
|module1=&lt;br /&gt;
|module2=&lt;br /&gt;
|module3=&lt;br /&gt;
|module4=&lt;br /&gt;
|module5=&lt;br /&gt;
|file=s_neomap.c&lt;br /&gt;
|machine=MSX1&lt;br /&gt;
|target=ROM_NEO8_8M&lt;br /&gt;
|ext=&lt;br /&gt;
|state=FUNCTIONAL&lt;br /&gt;
|img=raw.githubusercontent.com/aoineko-fr/MSXgl/refs/heads/main/engine/doc/img/project/s_neomap.png&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
== Utilities ==&lt;br /&gt;
&lt;br /&gt;
=== BASIC USR ===&lt;br /&gt;
{{SAMPLE_BOX&lt;br /&gt;
|name=BASIC USR&lt;br /&gt;
|desc=Program showing the creation of binary to be load and used from BASIC.&lt;br /&gt;
|module1=basic_usr&lt;br /&gt;
|module2=&lt;br /&gt;
|module3=&lt;br /&gt;
|module4=&lt;br /&gt;
|module5=&lt;br /&gt;
|file=s_usr.c&lt;br /&gt;
|machine=MSX1&lt;br /&gt;
|target=BIN_USR&lt;br /&gt;
|ext={{NINJATAP}}&lt;br /&gt;
|state=FUNCTIONAL&lt;br /&gt;
|img=raw.githubusercontent.com/aoineko-fr/MSXgl/refs/heads/main/engine/doc/img/project/s_usr.png&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
=== Compressor ===&lt;br /&gt;
{{SAMPLE_BOX&lt;br /&gt;
|name=Compressor&lt;br /&gt;
|desc=Program showing the use of several compression algorithms (RLEp, Bitbuster 1 &amp;amp; 2, ZX0 and Pletter).&lt;br /&gt;
|module1=compress/bitbuster&lt;br /&gt;
|module2=compress/bitbuster2&lt;br /&gt;
|module3=compress/lz48&lt;br /&gt;
|module4=compress/pletter&lt;br /&gt;
|module5=compress/zx0&lt;br /&gt;
|file=s_zip.c&lt;br /&gt;
|machine=MSX2&lt;br /&gt;
|target=DOS1&lt;br /&gt;
|ext=&lt;br /&gt;
|state=FUNCTIONAL&lt;br /&gt;
|img=raw.githubusercontent.com/aoineko-fr/MSXgl/refs/heads/main/engine/doc/img/project/s_zip.png&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
=== Driver ===&lt;br /&gt;
{{SAMPLE_BOX&lt;br /&gt;
|name=Driver&lt;br /&gt;
|desc=Program showing the creation of the driver, a code designed to be placed in memory and executed from a main program. Used in [[#MSX-DOS 2]] sample.&lt;br /&gt;
|module1=&lt;br /&gt;
|module2=&lt;br /&gt;
|module3=&lt;br /&gt;
|module4=&lt;br /&gt;
|module5=&lt;br /&gt;
|file=s_drv.c&lt;br /&gt;
|machine=MSX1&lt;br /&gt;
|target=RAW&lt;br /&gt;
|ext=&lt;br /&gt;
|state=FUNCTIONAL&lt;br /&gt;
|img=raw.githubusercontent.com/aoineko-fr/MSXgl/refs/heads/main/engine/doc/img/project/s_drv.png&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
=== Encryption ===&lt;br /&gt;
{{SAMPLE_BOX&lt;br /&gt;
|name=Encryption&lt;br /&gt;
|desc=Program showing the use of an encoding system to encrypt data. Useful for creating backup codes, for example.&lt;br /&gt;
|module1=crypt&lt;br /&gt;
|module2=&lt;br /&gt;
|module3=&lt;br /&gt;
|module4=&lt;br /&gt;
|module5=&lt;br /&gt;
|file=s_crypt.c&lt;br /&gt;
|machine=MSX1&lt;br /&gt;
|target=ROM_32K&lt;br /&gt;
|ext=&lt;br /&gt;
|state=FUNCTIONAL&lt;br /&gt;
|img=raw.githubusercontent.com/aoineko-fr/MSXgl/refs/heads/main/engine/doc/img/project/s_crypt.png&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
=== Game ===&lt;br /&gt;
{{SAMPLE_BOX&lt;br /&gt;
|name=Game&lt;br /&gt;
|desc=Program showing the use of Game state and Game pawn modules. The Game state module offers state management while Game pawn allows to manage characters (display, animation, movement, collision, etc.) &lt;br /&gt;
|module1=game/state&lt;br /&gt;
|module2=game/pawn&lt;br /&gt;
|module3=&lt;br /&gt;
|module4=&lt;br /&gt;
|module5=&lt;br /&gt;
|file=s_game.c&lt;br /&gt;
|machine=MSX1&lt;br /&gt;
|target=ROM_32K&lt;br /&gt;
|ext=&lt;br /&gt;
|state=FUNCTIONAL&lt;br /&gt;
|img=raw.githubusercontent.com/aoineko-fr/MSXgl/main/engine/doc/img/sample_game.png&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
=== Localize ===&lt;br /&gt;
{{SAMPLE_BOX&lt;br /&gt;
|name=Localize&lt;br /&gt;
|desc=Demonstration of the localization management module with support for multiple languages and management of different character sets.&lt;br /&gt;
|module1=localize&lt;br /&gt;
|module2=&lt;br /&gt;
|module3=&lt;br /&gt;
|module4=&lt;br /&gt;
|module5=&lt;br /&gt;
|file=s_loc.c&lt;br /&gt;
|machine=MSX1&lt;br /&gt;
|target=ROM_32K&lt;br /&gt;
|ext=&lt;br /&gt;
|state=FUNCTIONAL&lt;br /&gt;
|img=raw.githubusercontent.com/aoineko-fr/MSXgl/main/engine/doc/img/sample_loc.png&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
=== Math ===&lt;br /&gt;
{{SAMPLE_BOX&lt;br /&gt;
|name=Math&lt;br /&gt;
|desc=Program showing the use of mathematics pre-computed tables, pseudo-random generator and quick-computation functions.&lt;br /&gt;
|module1=math&lt;br /&gt;
|module2=&lt;br /&gt;
|module3=&lt;br /&gt;
|module4=&lt;br /&gt;
|module5=&lt;br /&gt;
|file=s_math.c&lt;br /&gt;
|machine=MSX2&lt;br /&gt;
|target=ROM_32K&lt;br /&gt;
|ext=&lt;br /&gt;
|state=FUNCTIONAL&lt;br /&gt;
|img=raw.githubusercontent.com/aoineko-fr/MSXgl/main/engine/doc/img/sample_math.jpg&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
=== Menu ===&lt;br /&gt;
{{SAMPLE_BOX&lt;br /&gt;
|name=Menu&lt;br /&gt;
|desc=Program showing the use of Menu module.&lt;br /&gt;
|module1=game/menu&lt;br /&gt;
|module2=&lt;br /&gt;
|module3=&lt;br /&gt;
|module4=&lt;br /&gt;
|module5=&lt;br /&gt;
|file=s_menu.c&lt;br /&gt;
|machine=MSX1&lt;br /&gt;
|target=ROM_32K&lt;br /&gt;
|ext=&lt;br /&gt;
|state=PARTIAL&lt;br /&gt;
|img=raw.githubusercontent.com/aoineko-fr/MSXgl/refs/heads/main/engine/doc/img/project/s_menu.png&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
=== QR Code ===&lt;br /&gt;
{{SAMPLE_BOX&lt;br /&gt;
|name=QR Code&lt;br /&gt;
|desc=Program showing the use of QR Code module.&lt;br /&gt;
|module1=tool/qrcode&lt;br /&gt;
|module2=&lt;br /&gt;
|module3=&lt;br /&gt;
|module4=&lt;br /&gt;
|module5=&lt;br /&gt;
|file=s_qrcode.c&lt;br /&gt;
|machine=MSX2&lt;br /&gt;
|target=ROM_32K&lt;br /&gt;
|ext=&lt;br /&gt;
|state=FUNCTIONAL&lt;br /&gt;
|img=raw.githubusercontent.com/aoineko-fr/MSXgl/refs/heads/main/engine/doc/img/project/s_qrcode.png&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
=== QR Code Tiny ===&lt;br /&gt;
{{SAMPLE_BOX&lt;br /&gt;
|name=QR Code&lt;br /&gt;
|desc=Program showing the use of QR Code Tiny module (version optimized for fixed size).&lt;br /&gt;
|module1=tool/qrcode_tiny&lt;br /&gt;
|module2=&lt;br /&gt;
|module3=&lt;br /&gt;
|module4=&lt;br /&gt;
|module5=&lt;br /&gt;
|file=s_qrtiny.c&lt;br /&gt;
|machine=MSX2&lt;br /&gt;
|target=ROM_32K&lt;br /&gt;
|ext=&lt;br /&gt;
|state=FUNCTIONAL&lt;br /&gt;
|img=raw.githubusercontent.com/aoineko-fr/MSXgl/refs/heads/main/engine/doc/img/project/s_qrtiny.png&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
=== Save ===&lt;br /&gt;
{{SAMPLE_BOX&lt;br /&gt;
|name=Save&lt;br /&gt;
|desc=Program showing the use of data save from cartridge (supporting floppy disk and PAC cartridge).&lt;br /&gt;
|module1=tool/disk_save&lt;br /&gt;
|module2=device/pac&lt;br /&gt;
|module3=&lt;br /&gt;
|module4=&lt;br /&gt;
|module5=&lt;br /&gt;
|file=s_save.c&lt;br /&gt;
|machine=MSX1&lt;br /&gt;
|target=ROM_32K&lt;br /&gt;
|ext=&lt;br /&gt;
|state=FUNCTIONAL&lt;br /&gt;
|img=raw.githubusercontent.com/aoineko-fr/MSXgl/refs/heads/main/engine/doc/img/project/s_save.png&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
=== WaveGame ===&lt;br /&gt;
{{SAMPLE_BOX&lt;br /&gt;
|name=WaveGame&lt;br /&gt;
|desc=Program demonstrate the use WaveGame feature for the Pico+ cartridge.&lt;br /&gt;
|module1=device/wavegame&lt;br /&gt;
|module2=&lt;br /&gt;
|module3=&lt;br /&gt;
|module4=&lt;br /&gt;
|module5=&lt;br /&gt;
|file=s_wavegm.c&lt;br /&gt;
|machine=MSX1&lt;br /&gt;
|target=ROM_32K&lt;br /&gt;
|ext=&lt;br /&gt;
|state=FUNCTIONAL&lt;br /&gt;
|img=raw.githubusercontent.com/aoineko-fr/MSXgl/refs/heads/main/engine/doc/img/project/s_wavegm.png&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
== Devices ==&lt;br /&gt;
&lt;br /&gt;
=== Joystick ===&lt;br /&gt;
{{SAMPLE_BOX&lt;br /&gt;
|name=Joystick&lt;br /&gt;
|desc=Program showing the use of joystick and input manager.&lt;br /&gt;
|module1=input&lt;br /&gt;
|module2=input_manager&lt;br /&gt;
|module3=&lt;br /&gt;
|module4=&lt;br /&gt;
|module5=&lt;br /&gt;
|file=s_joystk.c&lt;br /&gt;
|machine=MSX1&lt;br /&gt;
|target=ROM_32K&lt;br /&gt;
|ext=&lt;br /&gt;
|state=FUNCTIONAL&lt;br /&gt;
|img=raw.githubusercontent.com/aoineko-fr/MSXgl/main/engine/doc/img/sample_joystick.jpg&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
=== Keyboard ===&lt;br /&gt;
{{SAMPLE_BOX&lt;br /&gt;
|name=Keyboard&lt;br /&gt;
|desc=Program showing the use of keyboard and input manager.&lt;br /&gt;
|module1=input&lt;br /&gt;
|module2=input_manager&lt;br /&gt;
|module3=&lt;br /&gt;
|module4=&lt;br /&gt;
|module5=&lt;br /&gt;
|file=s_keybrd.c&lt;br /&gt;
|machine=MSX1&lt;br /&gt;
|target=ROM_32K&lt;br /&gt;
|ext=&lt;br /&gt;
|state=FUNCTIONAL&lt;br /&gt;
|img=raw.githubusercontent.com/aoineko-fr/MSXgl/main/engine/doc/img/sample_keyboard.jpg&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
=== Mouse ===&lt;br /&gt;
{{SAMPLE_BOX&lt;br /&gt;
|name=Mouse&lt;br /&gt;
|desc=Program showing the use of mouse device and universal port (joystick port) device detection.&lt;br /&gt;
|module1=input&lt;br /&gt;
|module2=&lt;br /&gt;
|module3=&lt;br /&gt;
|module4=&lt;br /&gt;
|module5=&lt;br /&gt;
|file=s_mouse.c&lt;br /&gt;
|machine=MSX1&lt;br /&gt;
|target=ROM_32K&lt;br /&gt;
|ext=&lt;br /&gt;
|state=FUNCTIONAL&lt;br /&gt;
|img=raw.githubusercontent.com/aoineko-fr/MSXgl/refs/heads/main/engine/doc/img/project/s_mouse.png&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
=== Ninja Tap ===&lt;br /&gt;
{{SAMPLE_BOX&lt;br /&gt;
|name=Ninja Tap&lt;br /&gt;
|desc=Program showing the use of NinjaTap device to connect up to 8 joysticks on one MSX machine.&lt;br /&gt;
|module1=device/ninjatap&lt;br /&gt;
|module2=&lt;br /&gt;
|module3=&lt;br /&gt;
|module4=&lt;br /&gt;
|module5=&lt;br /&gt;
|file=s_ntap.c&lt;br /&gt;
|machine=MSX1&lt;br /&gt;
|target=ROM_32K&lt;br /&gt;
|ext={{NINJATAP}}&lt;br /&gt;
|state=FUNCTIONAL&lt;br /&gt;
|img=raw.githubusercontent.com/aoineko-fr/MSXgl/main/engine/doc/img/sample_ntap.png&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
=== JoyMega ===&lt;br /&gt;
{{SAMPLE_BOX&lt;br /&gt;
|name=JoyMega&lt;br /&gt;
|desc=Program showing the use of JoyMega adapter to use 8 buttons Megadrive joystick on MSX.&lt;br /&gt;
|module1=device/joymega&lt;br /&gt;
|module2=device/msx-hid&lt;br /&gt;
|module3=&lt;br /&gt;
|module4=&lt;br /&gt;
|module5=&lt;br /&gt;
|file=s_jmega.c&lt;br /&gt;
|machine=MSX1&lt;br /&gt;
|target=ROM_32K&lt;br /&gt;
|ext={{JOYMEGA}}&lt;br /&gt;
|state=FUNCTIONAL&lt;br /&gt;
|img=raw.githubusercontent.com/aoineko-fr/MSXgl/refs/heads/main/engine/doc/img/project/s_jmega.png&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
=== Lightgun ===&lt;br /&gt;
{{SAMPLE_BOX&lt;br /&gt;
|name=Lightgun&lt;br /&gt;
|desc=Program showing the use of 'ASCII Plus-X Terminator' and 'MHT Gun-Stick' lightguns on MSX.&lt;br /&gt;
|module1=device/lightgun&lt;br /&gt;
|module2=&lt;br /&gt;
|module3=&lt;br /&gt;
|module4=&lt;br /&gt;
|module5=&lt;br /&gt;
|file=s_lgun.c&lt;br /&gt;
|machine=MSX1&lt;br /&gt;
|target=ROM_32K&lt;br /&gt;
|ext=&lt;br /&gt;
|state=PARTIAL&lt;br /&gt;
|img=&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
=== ObsoNET ===&lt;br /&gt;
{{SAMPLE_BOX&lt;br /&gt;
|name=ObsoNET&lt;br /&gt;
|desc=Program showing the use of ObsoNET cartridge using network stack.&lt;br /&gt;
|module1=network/obsonet&lt;br /&gt;
|module2=&lt;br /&gt;
|module3=&lt;br /&gt;
|module4=&lt;br /&gt;
|module5=&lt;br /&gt;
|file=s_onet.c&lt;br /&gt;
|machine=MSX1&lt;br /&gt;
|target=ROM_16K&lt;br /&gt;
|ext=OBSONET&lt;br /&gt;
|state=WIP&lt;br /&gt;
|img=&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
=== PAC ===&lt;br /&gt;
{{SAMPLE_BOX&lt;br /&gt;
|name=PAC&lt;br /&gt;
|desc=Program showing the use of PAC or FM-PAC to load/save data into SRAM.&lt;br /&gt;
|module1=device/pac&lt;br /&gt;
|module2=&lt;br /&gt;
|module3=&lt;br /&gt;
|module4=&lt;br /&gt;
|module5=&lt;br /&gt;
|file=s_pac.c&lt;br /&gt;
|machine=MSX1&lt;br /&gt;
|target=ROM_32K&lt;br /&gt;
|ext={{PAC}}&lt;br /&gt;
|state=FUNCTIONAL&lt;br /&gt;
|img=raw.githubusercontent.com/aoineko-fr/MSXgl/main/engine/doc/img/sample_pac.png&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
=== Paddle ===&lt;br /&gt;
{{SAMPLE_BOX&lt;br /&gt;
|name=Paddle&lt;br /&gt;
|desc=Program showing the use of Arkanoid Vaus Paddle module.&lt;br /&gt;
|module1=device/paddle&lt;br /&gt;
|module2=&lt;br /&gt;
|module3=&lt;br /&gt;
|module4=&lt;br /&gt;
|module5=&lt;br /&gt;
|file=s_paddle.c&lt;br /&gt;
|machine=MSX1&lt;br /&gt;
|target=ROM_48K_ISR&lt;br /&gt;
|ext=PADDLE&lt;br /&gt;
|state=FUNCTIONAL&lt;br /&gt;
|img=raw.githubusercontent.com/aoineko-fr/MSXgl/refs/heads/main/engine/doc/img/project/s_paddle.png&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
=== V9990 ===&lt;br /&gt;
{{SAMPLE_BOX&lt;br /&gt;
|name=V9990&lt;br /&gt;
|desc=Program showing the use of Yamaha V9990 based video cartridge.&lt;br /&gt;
|module1=v9990&lt;br /&gt;
|module2=&lt;br /&gt;
|module3=&lt;br /&gt;
|module4=&lt;br /&gt;
|module5=&lt;br /&gt;
|file=s_v9990.c&lt;br /&gt;
|machine=MSX1&lt;br /&gt;
|target=ROM_32K&lt;br /&gt;
|ext={{V9990}}&lt;br /&gt;
|state=FUNCTIONAL&lt;br /&gt;
|img=raw.githubusercontent.com/aoineko-fr/MSXgl/main/engine/doc/img/sample_v9990.png&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
== Audio Format ==&lt;br /&gt;
&lt;br /&gt;
=== Arkos ===&lt;br /&gt;
{{SAMPLE_BOX&lt;br /&gt;
|name=Arkos&lt;br /&gt;
|desc=Program to demonstrate the use of the different Arkos Tracker (AT2 and AT3) music replayers.&lt;br /&gt;
|module1=arkos/akg_player&lt;br /&gt;
|module2=arkos/akm_player&lt;br /&gt;
|module3=arkos/aky_player&lt;br /&gt;
|module4=&lt;br /&gt;
|module5=&lt;br /&gt;
|file=s_arkos.c&lt;br /&gt;
|machine=MSX1&lt;br /&gt;
|target=ROM_ASCII8_128K&lt;br /&gt;
|ext=&lt;br /&gt;
|state=FUNCTIONAL&lt;br /&gt;
|img=raw.githubusercontent.com/aoineko-fr/MSXgl/main/engine/doc/img/sample_arkos.png&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
=== ayFX ===&lt;br /&gt;
{{SAMPLE_BOX&lt;br /&gt;
|name=ayFX&lt;br /&gt;
|desc=Program showing the use of ayFX sound effect replayer (both using a bank or a single sound file).&lt;br /&gt;
|module1=ayfx/ayfx_player&lt;br /&gt;
|module2=&lt;br /&gt;
|module3=&lt;br /&gt;
|module4=&lt;br /&gt;
|module5=&lt;br /&gt;
|file=s_ayfx.c&lt;br /&gt;
|machine=MSX2&lt;br /&gt;
|target=ROM_32K&lt;br /&gt;
|ext=&lt;br /&gt;
|state=FUNCTIONAL&lt;br /&gt;
|img=raw.githubusercontent.com/aoineko-fr/MSXgl/main/engine/doc/img/sample_ayfx.jpg&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
=== lVGM ===&lt;br /&gt;
{{SAMPLE_BOX&lt;br /&gt;
|name=Light VGM&lt;br /&gt;
|desc=Program showing the use of light-VGM's replayer (PSG).&lt;br /&gt;
|module1=vgm/lvgm_player&lt;br /&gt;
|module2=dos_mapper&lt;br /&gt;
|module3=&lt;br /&gt;
|module4=&lt;br /&gt;
|module5=&lt;br /&gt;
|file=s_lvgm.c&lt;br /&gt;
|machine=MSX1&lt;br /&gt;
|target=DOS2&lt;br /&gt;
|ext={{SCC}} {{MSXMUSIC}} {{MSXAUDIO}}&lt;br /&gt;
|state=FUNCTIONAL&lt;br /&gt;
|img=raw.githubusercontent.com/aoineko-fr/MSXgl/refs/heads/main/engine/doc/img/project/s_lvgm.png&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
=== NDP ===&lt;br /&gt;
{{SAMPLE_BOX&lt;br /&gt;
|name=NDP&lt;br /&gt;
|desc=Program showing the use of NDP replayer (PSG).&lt;br /&gt;
|module1=ndp/ndp_player&lt;br /&gt;
|module2=&lt;br /&gt;
|module3=&lt;br /&gt;
|module4=&lt;br /&gt;
|module5=&lt;br /&gt;
|file=s_ndp.c&lt;br /&gt;
|machine=MSX1&lt;br /&gt;
|target=ROM_32K&lt;br /&gt;
|ext=&lt;br /&gt;
|state=FUNCTIONAL&lt;br /&gt;
|img=raw.githubusercontent.com/aoineko-fr/MSXgl/refs/heads/main/engine/doc/img/project/s_ndp.png&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
=== PCM-Encoder ===&lt;br /&gt;
{{SAMPLE_BOX&lt;br /&gt;
|name=PCM Encoder&lt;br /&gt;
|desc=Program showing the use of the PCM Encoder's replayer (aka. ''Crystal clean PCM 8bit samples on the poor PSG'').&lt;br /&gt;
|module1=pcm/pcmenc&lt;br /&gt;
|module2=&lt;br /&gt;
|module3=&lt;br /&gt;
|module4=&lt;br /&gt;
|module5=&lt;br /&gt;
|file=s_pcmenc.c&lt;br /&gt;
|machine=MSX1&lt;br /&gt;
|target=ROM_32K&lt;br /&gt;
|ext=&lt;br /&gt;
|state=FUNCTIONAL&lt;br /&gt;
|img=raw.githubusercontent.com/aoineko-fr/MSXgl/main/engine/doc/img/sample_pcm.jpg&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
=== PCM Play ===&lt;br /&gt;
{{SAMPLE_BOX&lt;br /&gt;
|name=PCM Play&lt;br /&gt;
|desc=Program showing the use of the PCM Play's replayer.&lt;br /&gt;
|module1=pcm/pcmplay&lt;br /&gt;
|module2=&lt;br /&gt;
|module3=&lt;br /&gt;
|module4=&lt;br /&gt;
|module5=&lt;br /&gt;
|file=s_pcmplay.c&lt;br /&gt;
|machine=MSX1&lt;br /&gt;
|target=ROM_32K&lt;br /&gt;
|ext=&lt;br /&gt;
|state=FUNCTIONAL&lt;br /&gt;
|img=raw.githubusercontent.com/aoineko-fr/MSXgl/refs/heads/main/engine/doc/img/project/s_pcmplay.png&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
=== PT3 ===&lt;br /&gt;
{{SAMPLE_BOX&lt;br /&gt;
|name=PT3&lt;br /&gt;
|desc=Program showing the use of Vortex Tracker II's replayer.&lt;br /&gt;
|module1=pt3/pt3_player&lt;br /&gt;
|module2=&lt;br /&gt;
|module3=&lt;br /&gt;
|module4=&lt;br /&gt;
|module5=&lt;br /&gt;
|file=s_pt3.c&lt;br /&gt;
|machine=MSX2&lt;br /&gt;
|target=ROM_32K&lt;br /&gt;
|ext=&lt;br /&gt;
|state=FUNCTIONAL&lt;br /&gt;
|img=raw.githubusercontent.com/aoineko-fr/MSXgl/main/engine/doc/img/sample_pt3.jpg&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
=== Trilo Tracker SCC ===&lt;br /&gt;
{{SAMPLE_BOX&lt;br /&gt;
|name=Trilo Tracker SCC&lt;br /&gt;
|desc=Program showing the use of Trilo Tracker SCC's replayer.&lt;br /&gt;
|module1=trilo/trilo_scc_player&lt;br /&gt;
|module2=&lt;br /&gt;
|module3=&lt;br /&gt;
|module4=&lt;br /&gt;
|module5=&lt;br /&gt;
|file=s_trilo.c&lt;br /&gt;
|machine=MSX1&lt;br /&gt;
|target=ROM_KONAMI_SCC_128K&lt;br /&gt;
|ext=&lt;br /&gt;
|state=FUNCTIONAL&lt;br /&gt;
|img=raw.githubusercontent.com/aoineko-fr/MSXgl/refs/heads/main/engine/doc/img/project/s_trilo.png&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
=== VGM ===&lt;br /&gt;
{{SAMPLE_BOX&lt;br /&gt;
|name=VGM&lt;br /&gt;
|desc=Program showing the use of VGM's replayer (PSG, SCC, MSX-Music, MSX-Audio).&lt;br /&gt;
|module1=vgm/vgm_player&lt;br /&gt;
|module2=&lt;br /&gt;
|module3=&lt;br /&gt;
|module4=&lt;br /&gt;
|module5=&lt;br /&gt;
|file=s_vgm.c&lt;br /&gt;
|machine=MSX1&lt;br /&gt;
|target=ROM_ASCII16_256K&lt;br /&gt;
|ext={{SCC}} {{MSXMUSIC}} {{MSXAUDIO}}&lt;br /&gt;
|state=FUNCTIONAL&lt;br /&gt;
|img=raw.githubusercontent.com/aoineko-fr/MSXgl/main/engine/doc/img/sample_vgm.jpg&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
=== WYZ ===&lt;br /&gt;
{{SAMPLE_BOX&lt;br /&gt;
|name=WYZ&lt;br /&gt;
|desc=Program showing the use of WYZ Tracker's replayer (version 0.3).&lt;br /&gt;
|module1=wyz/wyz_player&lt;br /&gt;
|module2=&lt;br /&gt;
|module3=&lt;br /&gt;
|module4=&lt;br /&gt;
|module5=&lt;br /&gt;
|file=s_wyz.c&lt;br /&gt;
|machine=MSX1&lt;br /&gt;
|target=ROM_32K&lt;br /&gt;
|ext=&lt;br /&gt;
|state=FUNCTIONAL&lt;br /&gt;
|img=raw.githubusercontent.com/aoineko-fr/MSXgl/main/engine/doc/img/sample_wyz.png&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
=== WYZ2 ===&lt;br /&gt;
{{SAMPLE_BOX&lt;br /&gt;
|name=WYZ2&lt;br /&gt;
|desc=Program showing the use of WYZ Tracker's replayer (version 0.3 47d).&lt;br /&gt;
|module1=wyz/wyz_player2&lt;br /&gt;
|module2=&lt;br /&gt;
|module3=&lt;br /&gt;
|module4=&lt;br /&gt;
|module5=&lt;br /&gt;
|file=s_wyz2.c&lt;br /&gt;
|machine=MSX1&lt;br /&gt;
|target=ROM_32K&lt;br /&gt;
|ext=&lt;br /&gt;
|state=FUNCTIONAL&lt;br /&gt;
|img=raw.githubusercontent.com/aoineko-fr/MSXgl/refs/heads/main/engine/doc/img/project/s_wyz2.png&lt;br /&gt;
}}&lt;/div&gt;</summary>
		<author><name>Aoineko</name></author>	</entry>

	<entry>
		<id>https://aoineko.org/msxgl/index.php?title=Template:MSXAUDIO&amp;diff=3962</id>
		<title>Template:MSXAUDIO</title>
		<link rel="alternate" type="text/html" href="https://aoineko.org/msxgl/index.php?title=Template:MSXAUDIO&amp;diff=3962"/>
				<updated>2026-05-14T19:45:15Z</updated>
		
		<summary type="html">&lt;p&gt;Aoineko: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{LOGO|logo_msx-audio.png|MSX-Audio|ext}}&lt;/div&gt;</summary>
		<author><name>Aoineko</name></author>	</entry>

	<entry>
		<id>https://aoineko.org/msxgl/index.php?title=Template:MSXAUDIO&amp;diff=3961</id>
		<title>Template:MSXAUDIO</title>
		<link rel="alternate" type="text/html" href="https://aoineko.org/msxgl/index.php?title=Template:MSXAUDIO&amp;diff=3961"/>
				<updated>2026-05-14T19:43:30Z</updated>
		
		<summary type="html">&lt;p&gt;Aoineko: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{LOGO|logo_msx-audio.png|MSX-Audio|Ext}}&lt;/div&gt;</summary>
		<author><name>Aoineko</name></author>	</entry>

	<entry>
		<id>https://aoineko.org/msxgl/index.php?title=Template:RAW&amp;diff=3960</id>
		<title>Template:RAW</title>
		<link rel="alternate" type="text/html" href="https://aoineko.org/msxgl/index.php?title=Template:RAW&amp;diff=3960"/>
				<updated>2026-05-14T19:43:08Z</updated>
		
		<summary type="html">&lt;p&gt;Aoineko: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{LOGO|logo_bin.png|Raw binary code}}&lt;/div&gt;</summary>
		<author><name>Aoineko</name></author>	</entry>

	</feed>