<?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-05-03T09:16:17Z</updated>
		<subtitle>User contributions</subtitle>
		<generator>MediaWiki 1.30.2</generator>

	<entry>
		<id>https://aoineko.org/msxgl/index.php?title=Roadmap&amp;diff=3864</id>
		<title>Roadmap</title>
		<link rel="alternate" type="text/html" href="https://aoineko.org/msxgl/index.php?title=Roadmap&amp;diff=3864"/>
				<updated>2026-05-01T20:51:09Z</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 1-color-per-line MSX 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=Roadmap&amp;diff=3863</id>
		<title>Roadmap</title>
		<link rel="alternate" type="text/html" href="https://aoineko.org/msxgl/index.php?title=Roadmap&amp;diff=3863"/>
				<updated>2026-05-01T20:50:39Z</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 1-color-per-line MSX 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;
* Add option in MSXhex to display occupation of each 16K page for plain ROM (as for mapped ROM segments)&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=3862</id>
		<title>Roadmap</title>
		<link rel="alternate" type="text/html" href="https://aoineko.org/msxgl/index.php?title=Roadmap&amp;diff=3862"/>
				<updated>2026-05-01T16:56:08Z</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 1-color-per-line MSX 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;
* Add option in MSXhex to display occupation of each 16K page for plain ROM (as for mapped ROM segments)&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=3861</id>
		<title>Roadmap</title>
		<link rel="alternate" type="text/html" href="https://aoineko.org/msxgl/index.php?title=Roadmap&amp;diff=3861"/>
				<updated>2026-05-01T14:25:57Z</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 1-color-per-line MSX 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;
* Add option in MSXhex to display occupation of each 16K page for plain ROM (as for mapped ROM segments)&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=Build_tool/BIOSReleaseEvent&amp;diff=3860</id>
		<title>Build tool/BIOSReleaseEvent</title>
		<link rel="alternate" type="text/html" href="https://aoineko.org/msxgl/index.php?title=Build_tool/BIOSReleaseEvent&amp;diff=3860"/>
				<updated>2026-05-01T09:52:19Z</updated>
		
		<summary type="html">&lt;p&gt;Aoineko: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Build tool]] option '''BIOSReleaseEvent''' is used to add a callback function to be called just before BIOS is switched out from page 0. It allows you to have an initialization code that runs while the BIOS is still accessible at page 0. For example, to detect the presence of an MSX-Music device using the BIOS routines for cross-slot reading.&lt;br /&gt;
&lt;br /&gt;
This applies to [[target]] formats that place the '''ROM on page 0''' (ROM_48K_ISR, ROM_64K_ISR, ROM_NEO8, and ROM_NEO16), as well as ROM formats that place '''RAM on page 0''' (via the [[Build_tool/InstallRAMISR|InstallRAMISR]] option).&lt;br /&gt;
&lt;br /&gt;
== Usage ==&lt;br /&gt;
To use this option, you must provide a function that will be called by the boot process just before the BIOS is removed from page 0 (to make room for the cartridge or memory).&lt;br /&gt;
&lt;br /&gt;
Function prototype:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;void BIOS_OnRelease();&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Call context ==&lt;br /&gt;
&lt;br /&gt;
You must be fully aware of the program's initialization context at the time the BIOS_OnRelease callback function is executed. This context depends on the type of target format.&lt;br /&gt;
&lt;br /&gt;
=== ROM in page 0 ===&lt;br /&gt;
* Only page 1 of memory space points to the program in ROM&lt;br /&gt;
* The mapper has not yet been initialized;&lt;br /&gt;
** the selected segments are those selected by default by the hardware at the physical level (see https://www.msx.org/wiki/MegaROM_Mappers);&lt;br /&gt;
** mapper initialization will take place immediately after the return from the BIOS_OnRelease function and will overwrite any changes made in the callback;&lt;br /&gt;
* The global variables have not been initialized yet (so you can't use those variables because their value is undefined and any change in the callback will be overwrite later during the boot process)&lt;br /&gt;
* The &amp;lt;tt&amp;gt;main()&amp;lt;/tt&amp;gt; function has not yet been called (so no program-specific initialization has taken place yet)&lt;br /&gt;
&lt;br /&gt;
=== RAM in page 0 ===&lt;br /&gt;
* Pages 1 and 2 of memory point to the program in ROM&lt;br /&gt;
* The mapper has not yet been initialized;&lt;br /&gt;
** the selected segments are those selected by default by the hardware at the physical level (see https://www.msx.org/wiki/MegaROM_Mappers);&lt;br /&gt;
** mapper initialization will take place immediately after the return from the BIOS_OnRelease function and will overwrite any changes made in the callback;&lt;br /&gt;
* The global variables have not been initialized yet (so you can't use those variables because their value is undefined and any change in the callback will be overwrite later during the boot process)&lt;br /&gt;
* The &amp;lt;tt&amp;gt;main()&amp;lt;/tt&amp;gt; function has not yet been called (so no program-specific initialization has taken place yet)&lt;br /&gt;
&lt;br /&gt;
=== Notes ===&lt;br /&gt;
You must therefore ensure that the code you call within the callback function only calls functions that are visible to the Z80 in the given context:&lt;br /&gt;
* Within the first 16 KB for Konami, ASCII-16, and NEO-16 mappers, and plain-ROM.&lt;br /&gt;
* Within the first 8 KB for ASCII-8 and NEO-8 mappers.&lt;br /&gt;
&lt;br /&gt;
As a reminder, the order of the module array (&amp;lt;tt&amp;gt;LibModules&amp;lt;/tt&amp;gt;) in your program determines the location of each module in the final binary.&lt;br /&gt;
&lt;br /&gt;
For example, if you want to call the MSX-Music detection function from the BIOS_OnRelease() callback, placing the &amp;lt;tt&amp;gt;msx-music&amp;lt;/tt&amp;gt; module first in the list ensures that it appears at the beginning of the ROM.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
bool g_UseFM; // Used in BIOS_OnRelease (can't be initalized here)&lt;br /&gt;
&lt;br /&gt;
//-----------------------------------------------------------------------------&lt;br /&gt;
// Event called before BIOS is released&lt;br /&gt;
void BIOS_OnRelease()&lt;br /&gt;
{&lt;br /&gt;
	g_UseFM = (MSXMusic_Initialize() != MSXMUSIC_NOTFOUND);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;/div&gt;</summary>
		<author><name>Aoineko</name></author>	</entry>

	<entry>
		<id>https://aoineko.org/msxgl/index.php?title=Build_tool/BIOSReleaseEvent&amp;diff=3859</id>
		<title>Build tool/BIOSReleaseEvent</title>
		<link rel="alternate" type="text/html" href="https://aoineko.org/msxgl/index.php?title=Build_tool/BIOSReleaseEvent&amp;diff=3859"/>
				<updated>2026-04-26T09:25:33Z</updated>
		
		<summary type="html">&lt;p&gt;Aoineko: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Build tool]] option '''BIOSReleaseEvent''' is used to add a callback function to be called just before BIOS is switched out from page 0. It allows you to have an initialization code that runs while the BIOS is still accessible at page 0. For example, to detect the presence of an MSX-Music device using the BIOS routines for cross-slot reading.&lt;br /&gt;
&lt;br /&gt;
This applies to [[target]] formats that place the '''ROM on page 0''' (ROM_48K_ISR, ROM_64K_ISR, ROM_NEO8, and ROM_NEO16), as well as ROM formats that place '''RAM on page 0''' (via the [[Build_tool/InstallRAMISR|InstallRAMISR]] option).&lt;br /&gt;
&lt;br /&gt;
== Usage ==&lt;br /&gt;
To use this option, you must provide a function that will be called by the boot process just before the BIOS is removed from page 0 (to make room for the cartridge or memory).&lt;br /&gt;
&lt;br /&gt;
Function prototype:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;void BIOS_OnRelease();&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Call context ==&lt;br /&gt;
&lt;br /&gt;
You must be fully aware of the program's initialization context at the time the BIOS_OnRelease callback function is executed. This context depends on the type of target format.&lt;br /&gt;
&lt;br /&gt;
=== ROM in page 0 ===&lt;br /&gt;
* Only page 1 of memory space points to the program in ROM&lt;br /&gt;
* The mapper has not yet been initialized;&lt;br /&gt;
** the selected segments are those selected by default by the hardware at the physical level (see https://www.msx.org/wiki/MegaROM_Mappers);&lt;br /&gt;
** mapper initialization will take place immediately after the return from the BIOS_OnRelease function and will overwrite any changes made in the callback;&lt;br /&gt;
* The global variables have not been initialized yet (so you can't use those variables because their value is undefined and any change in the callback will be overwrite later during the boot process)&lt;br /&gt;
* The &amp;lt;tt&amp;gt;main()&amp;lt;/tt&amp;gt; function has not yet been called (so no program-specific initialization has taken place yet)&lt;br /&gt;
&lt;br /&gt;
=== RAM in page 0 ===&lt;br /&gt;
* Pages 1 and 2 of memory point to the program in ROM&lt;br /&gt;
* The mapper has been initialized (see [[Create_a_mapped_ROM#Initial_slot_configuration|Initial slot configuration]])&lt;br /&gt;
* The global variables have been initialized (so they have their predefined values)&lt;br /&gt;
* The &amp;lt;tt&amp;gt;main()&amp;lt;/tt&amp;gt; function has not yet been called (so no program-specific initialization has taken place yet)&lt;br /&gt;
&lt;br /&gt;
=== Notes ===&lt;br /&gt;
You must therefore ensure that the code you call within the callback function only calls functions that are visible to the Z80 in the given context:&lt;br /&gt;
* Within the first 16 KB for Konami, ASCII-16, and NEO-16 mappers, and plain-ROM.&lt;br /&gt;
* Within the first 8 KB for ASCII-8 and NEO-8 mappers.&lt;br /&gt;
&lt;br /&gt;
As a reminder, the order of the module array (&amp;lt;tt&amp;gt;LibModules&amp;lt;/tt&amp;gt;) in your program determines the location of each module in the final binary.&lt;br /&gt;
&lt;br /&gt;
For example, if you want to call the MSX-Music detection function from the BIOS_OnRelease() callback, placing the &amp;lt;tt&amp;gt;msx-music&amp;lt;/tt&amp;gt; module first in the list ensures that it appears at the beginning of the ROM.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
bool g_UseFM; // Used in BIOS_OnRelease (can't be initalized here)&lt;br /&gt;
&lt;br /&gt;
//-----------------------------------------------------------------------------&lt;br /&gt;
// Event called before BIOS is released&lt;br /&gt;
void BIOS_OnRelease()&lt;br /&gt;
{&lt;br /&gt;
	g_UseFM = (MSXMusic_Initialize() != MSXMUSIC_NOTFOUND);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;/div&gt;</summary>
		<author><name>Aoineko</name></author>	</entry>

	<entry>
		<id>https://aoineko.org/msxgl/index.php?title=Build_tool/BIOSReleaseEvent&amp;diff=3858</id>
		<title>Build tool/BIOSReleaseEvent</title>
		<link rel="alternate" type="text/html" href="https://aoineko.org/msxgl/index.php?title=Build_tool/BIOSReleaseEvent&amp;diff=3858"/>
				<updated>2026-04-26T09:24:11Z</updated>
		
		<summary type="html">&lt;p&gt;Aoineko: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Build tool]] option '''BIOSReleaseEvent''' is used to add a callback function to be called just before BIOS is switched out from page 0. It allows you to have an initialization code that runs while the BIOS is still accessible at page 0. For example, to detect the presence of an MSX-Music device using the BIOS routines for cross-slot reading.&lt;br /&gt;
&lt;br /&gt;
This applies to [[target]] formats that place the '''ROM on page 0''' (ROM_48K_ISR, ROM_64K_ISR, ROM_NEO8, and ROM_NEO16), as well as ROM formats that place '''RAM on page 0''' (via the [[Build_tool/InstallRAMISR|InstallRAMISR]] option).&lt;br /&gt;
&lt;br /&gt;
== Usage ==&lt;br /&gt;
To use this option, you must provide a function that will be called by the boot process just before the BIOS is removed from page 0 (to make room for the cartridge or memory).&lt;br /&gt;
&lt;br /&gt;
Function prototype:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;void BIOS_OnRelease();&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Call context ==&lt;br /&gt;
&lt;br /&gt;
You must be fully aware of the program's initialization context at the time the BIOS_OnRelease callback function is executed. This context depends on the type of target format.&lt;br /&gt;
&lt;br /&gt;
=== ROM in page 0 ===&lt;br /&gt;
* The global variables have not been initialized yet (so you can't use those variables because their value is undefined and any change in the callback will be overwrite later during the boot process)&lt;br /&gt;
* The mapper has not yet been initialized;&lt;br /&gt;
** the selected segments are those selected by default by the hardware at the physical level (see https://www.msx.org/wiki/MegaROM_Mappers);&lt;br /&gt;
** mapper initialization will take place immediately after the return from the BIOS_OnRelease function and will overwrite any changes made in the callback;&lt;br /&gt;
* Only page 1 of memory space points to the program in ROM&lt;br /&gt;
* The &amp;lt;tt&amp;gt;main()&amp;lt;/tt&amp;gt; function has not yet been called (so no program-specific initialization has taken place yet)&lt;br /&gt;
&lt;br /&gt;
=== RAM in page 0 ===&lt;br /&gt;
* The global variables have been initialized (so they have their predefined values)&lt;br /&gt;
* The mapper has been initialized (see [[Create_a_mapped_ROM#Initial_slot_configuration|Initial slot configuration]])&lt;br /&gt;
* Pages 1 and 2 of memory point to the program in ROM&lt;br /&gt;
* The &amp;lt;tt&amp;gt;main()&amp;lt;/tt&amp;gt; function has not yet been called (so no program-specific initialization has taken place yet)&lt;br /&gt;
&lt;br /&gt;
=== Notes ===&lt;br /&gt;
You must therefore ensure that the code you call within the callback function only calls functions that are visible to the Z80 in the given context:&lt;br /&gt;
* Within the first 16 KB for Konami, ASCII-16, and NEO-16 mappers, and plain-ROM.&lt;br /&gt;
* Within the first 8 KB for ASCII-8 and NEO-8 mappers.&lt;br /&gt;
&lt;br /&gt;
As a reminder, the order of the module array (&amp;lt;tt&amp;gt;LibModules&amp;lt;/tt&amp;gt;) in your program determines the location of each module in the final binary.&lt;br /&gt;
&lt;br /&gt;
For example, if you want to call the MSX-Music detection function from the BIOS_OnRelease() callback, placing the &amp;lt;tt&amp;gt;msx-music&amp;lt;/tt&amp;gt; module first in the list ensures that it appears at the beginning of the ROM.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
bool g_UseFM; // Used in BIOS_OnRelease (can't be initalized here)&lt;br /&gt;
&lt;br /&gt;
//-----------------------------------------------------------------------------&lt;br /&gt;
// Event called before BIOS is released&lt;br /&gt;
void BIOS_OnRelease()&lt;br /&gt;
{&lt;br /&gt;
	g_UseFM = (MSXMusic_Initialize() != MSXMUSIC_NOTFOUND);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;/div&gt;</summary>
		<author><name>Aoineko</name></author>	</entry>

	<entry>
		<id>https://aoineko.org/msxgl/index.php?title=Build_tool/BIOSReleaseEvent&amp;diff=3857</id>
		<title>Build tool/BIOSReleaseEvent</title>
		<link rel="alternate" type="text/html" href="https://aoineko.org/msxgl/index.php?title=Build_tool/BIOSReleaseEvent&amp;diff=3857"/>
				<updated>2026-04-26T09:23:24Z</updated>
		
		<summary type="html">&lt;p&gt;Aoineko: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Build tool]] option '''BIOSReleaseEvent''' is used to add a callback function to be called just before BIOS is switched out from page 0. It allows you to have an initialization code that runs while the BIOS is still accessible at page 0. For example, to detect the presence of an MSX-Music device using the BIOS routines for cross-slot reading.&lt;br /&gt;
&lt;br /&gt;
This applies to [[target]] formats that place the ROM on page 0 (ROM_48K_ISR, ROM_64K_ISR, ROM_NEO8, and ROM_NEO16), as well as ROM formats that place RAM on page 0 (via the [[Build_tool/InstallRAMISR|InstallRAMISR]] option).&lt;br /&gt;
&lt;br /&gt;
== Usage ==&lt;br /&gt;
To use this option, you must provide a function that will be called by the boot process just before the BIOS is removed from page 0 (to make room for the cartridge or memory).&lt;br /&gt;
&lt;br /&gt;
Function prototype:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;void BIOS_OnRelease();&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Call context ==&lt;br /&gt;
&lt;br /&gt;
You must be fully aware of the program's initialization context at the time the BIOS_OnRelease callback function is executed. This context depends on the type of target format.&lt;br /&gt;
&lt;br /&gt;
=== ROM in page 0 ===&lt;br /&gt;
* The global variables have not been initialized yet (so you can't use those variables because their value is undefined and any change in the callback will be overwrite later during the boot process)&lt;br /&gt;
* The mapper has not yet been initialized;&lt;br /&gt;
** the selected segments are those selected by default by the hardware at the physical level (see https://www.msx.org/wiki/MegaROM_Mappers);&lt;br /&gt;
** mapper initialization will take place immediately after the return from the BIOS_OnRelease function and will overwrite any changes made in the callback;&lt;br /&gt;
* Only page 1 of memory space points to the program in ROM&lt;br /&gt;
* The &amp;lt;tt&amp;gt;main()&amp;lt;/tt&amp;gt; function has not yet been called (so no program-specific initialization has taken place yet)&lt;br /&gt;
&lt;br /&gt;
=== RAM in page 0 ===&lt;br /&gt;
* The global variables have been initialized (so they have their predefined values)&lt;br /&gt;
* The mapper has been initialized (see [[Create_a_mapped_ROM#Initial_slot_configuration|Initial slot configuration]])&lt;br /&gt;
* Pages 1 and 2 of memory point to the program in ROM&lt;br /&gt;
* The &amp;lt;tt&amp;gt;main()&amp;lt;/tt&amp;gt; function has not yet been called (so no program-specific initialization has taken place yet)&lt;br /&gt;
&lt;br /&gt;
=== Notes ===&lt;br /&gt;
You must therefore ensure that the code you call within the callback function only calls functions that are visible to the Z80 in the given context:&lt;br /&gt;
* Within the first 16 KB for Konami, ASCII-16, and NEO-16 mappers, and plain-ROM.&lt;br /&gt;
* Within the first 8 KB for ASCII-8 and NEO-8 mappers.&lt;br /&gt;
&lt;br /&gt;
As a reminder, the order of the module array (&amp;lt;tt&amp;gt;LibModules&amp;lt;/tt&amp;gt;) in your program determines the location of each module in the final binary.&lt;br /&gt;
&lt;br /&gt;
For example, if you want to call the MSX-Music detection function from the BIOS_OnRelease() callback, placing the &amp;lt;tt&amp;gt;msx-music&amp;lt;/tt&amp;gt; module first in the list ensures that it appears at the beginning of the ROM.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
bool g_UseFM; // Used in BIOS_OnRelease (can't be initalized here)&lt;br /&gt;
&lt;br /&gt;
//-----------------------------------------------------------------------------&lt;br /&gt;
// Event called before BIOS is released&lt;br /&gt;
void BIOS_OnRelease()&lt;br /&gt;
{&lt;br /&gt;
	g_UseFM = (MSXMusic_Initialize() != MSXMUSIC_NOTFOUND);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;/div&gt;</summary>
		<author><name>Aoineko</name></author>	</entry>

	<entry>
		<id>https://aoineko.org/msxgl/index.php?title=Pixel_Phenix&amp;diff=3856</id>
		<title>Pixel Phenix</title>
		<link rel="alternate" type="text/html" href="https://aoineko.org/msxgl/index.php?title=Pixel_Phenix&amp;diff=3856"/>
				<updated>2026-04-23T21:17:06Z</updated>
		
		<summary type="html">&lt;p&gt;Aoineko: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;img src=&amp;quot;https://raw.githubusercontent.com/aoineko-fr/MSXgl/refs/heads/main/engine/doc/img/phenix.png&amp;quot; style=&amp;quot;width:192px; image-rendering:pixelated; float:right;&amp;quot; /&amp;gt;&lt;br /&gt;
'''Pixel Phenix''' is an MSX video game creation group whose objectives are:&lt;br /&gt;
* Create a high-quality gaming experience:&lt;br /&gt;
** Precise, fluid and responsive gameplay,&lt;br /&gt;
** High-quality graphics that take advantage of the machine's capabilities,&lt;br /&gt;
** Immersive storytelling (when applicable).&lt;br /&gt;
* Ensure a polished finalization:&lt;br /&gt;
** In-depth playtesting of the game,&lt;br /&gt;
** Debugging to remove known issues and instabilities.&lt;br /&gt;
* Make the best use of the hardware capabilities and available features (MSX1 game with MSX2 enhancement for example).&lt;br /&gt;
* Maintain maximum compatibility (if MSX1 is enough for the game concept, go for it).&lt;br /&gt;
&lt;br /&gt;
== Members ==&lt;br /&gt;
* Guillaume &amp;quot;Aoineko&amp;quot;&lt;br /&gt;
* Ludo &amp;quot;GFX&amp;quot;&lt;br /&gt;
&lt;br /&gt;
== Games ==&lt;br /&gt;
* '''''Crawlers''''' [PH-001] (2023)&lt;br /&gt;
* '''''Room 5''''' (2025, in association with [https://mo5.com MO5.com])&lt;br /&gt;
* '''''Peng Pong''''' [PH-003] (2025)&lt;br /&gt;
* '''''Soul Trapped''''' (2026, in association with [https://caspercroes.itch.io Casper Croes])&lt;br /&gt;
* '''''Wizzl''''' [PH-004] (WIP)&lt;br /&gt;
* '''''Final Smash''''' [PH-002] (WIP)&lt;/div&gt;</summary>
		<author><name>Aoineko</name></author>	</entry>

	<entry>
		<id>https://aoineko.org/msxgl/index.php?title=Pixel_Phenix&amp;diff=3855</id>
		<title>Pixel Phenix</title>
		<link rel="alternate" type="text/html" href="https://aoineko.org/msxgl/index.php?title=Pixel_Phenix&amp;diff=3855"/>
				<updated>2026-04-23T21:16:31Z</updated>
		
		<summary type="html">&lt;p&gt;Aoineko: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;img src=&amp;quot;https://raw.githubusercontent.com/aoineko-fr/MSXgl/refs/heads/main/engine/doc/img/phenix.png&amp;quot; style=&amp;quot;width:192px; image-rendering:pixelated; float:right;&amp;quot; /&amp;gt;&lt;br /&gt;
'''Pixel Phenix''' is an MSX video game creation group whose objectives are:&lt;br /&gt;
* Create a high-quality gaming experience:&lt;br /&gt;
** Precise, fluid and responsive gameplay,&lt;br /&gt;
** High-quality graphics that take advantage of the machine's capabilities,&lt;br /&gt;
** Immersive storytelling (where applicable).&lt;br /&gt;
* Ensure a polished finalization:&lt;br /&gt;
** In-depth playtesting of the game,&lt;br /&gt;
** Debugging to remove known issues and instabilities.&lt;br /&gt;
* Make the best use of the hardware capabilities and available features (MSX1 game with MSX2 enhancement for example).&lt;br /&gt;
* Maintain maximum compatibility (if MSX1 is enough for the game concept, go for it).&lt;br /&gt;
&lt;br /&gt;
== Members ==&lt;br /&gt;
* Guillaume &amp;quot;Aoineko&amp;quot;&lt;br /&gt;
* Ludo &amp;quot;GFX&amp;quot;&lt;br /&gt;
&lt;br /&gt;
== Games ==&lt;br /&gt;
* '''''Crawlers''''' [PH-001] (2023)&lt;br /&gt;
* '''''Room 5''''' (2025, in association with [https://mo5.com MO5.com])&lt;br /&gt;
* '''''Peng Pong''''' [PH-003] (2025)&lt;br /&gt;
* '''''Soul Trapped''''' (2026, in association with [https://caspercroes.itch.io Casper Croes])&lt;br /&gt;
* '''''Wizzl''''' [PH-004] (WIP)&lt;br /&gt;
* '''''Final Smash''''' [PH-002] (WIP)&lt;/div&gt;</summary>
		<author><name>Aoineko</name></author>	</entry>

	<entry>
		<id>https://aoineko.org/msxgl/index.php?title=Pixel_Phenix&amp;diff=3854</id>
		<title>Pixel Phenix</title>
		<link rel="alternate" type="text/html" href="https://aoineko.org/msxgl/index.php?title=Pixel_Phenix&amp;diff=3854"/>
				<updated>2026-04-23T21:15:16Z</updated>
		
		<summary type="html">&lt;p&gt;Aoineko: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;img src=&amp;quot;https://raw.githubusercontent.com/aoineko-fr/MSXgl/refs/heads/main/engine/doc/img/phenix.png&amp;quot; style=&amp;quot;width:192px; image-rendering:pixelated; float:right;&amp;quot; /&amp;gt;&lt;br /&gt;
'''Pixel Phenix''' is an MSX video game creation group whose objectives are:&lt;br /&gt;
* Create a high-quality gaming experience:&lt;br /&gt;
** Precise, fluid and responsive gameplay,&lt;br /&gt;
** High-quality graphics that take advantage of the machine's capabilities,&lt;br /&gt;
** Immersive storytelling (where applicable).&lt;br /&gt;
* Ensure a polished finalization:&lt;br /&gt;
** In-depth playtesting of the game,&lt;br /&gt;
** Debugging to remove known issues and instabilities.&lt;br /&gt;
* Make the best use of the hardware capabilities and available features (MSX1 game with MSX2 enhancement for example).&lt;br /&gt;
* Maintain maximum compatibility (if MSX1 is enough for the game concept, go for it).&lt;br /&gt;
&lt;br /&gt;
== Members ==&lt;br /&gt;
* Guillaume &amp;quot;Aoineko&amp;quot;&lt;br /&gt;
* Ludo &amp;quot;GFX&amp;quot;&lt;br /&gt;
&lt;br /&gt;
== Games ==&lt;br /&gt;
* '''''Crawlers''''' [PH-001] (2023)&lt;br /&gt;
* '''''Room 5''''' (2025, in association with [https://mo5.com MO5.com])&lt;br /&gt;
* '''''Peng Pong''''' [PH-003] (2025)&lt;br /&gt;
* '''''Soul Trapped''''' (2026, in association with Casper Croes)&lt;br /&gt;
* '''''Wizzl''''' [PH-004] (WIP)&lt;br /&gt;
* '''''Final Smash''''' [PH-002] (WIP)&lt;/div&gt;</summary>
		<author><name>Aoineko</name></author>	</entry>

	<entry>
		<id>https://aoineko.org/msxgl/index.php?title=Build_tool/BIOSReleaseEvent&amp;diff=3853</id>
		<title>Build tool/BIOSReleaseEvent</title>
		<link rel="alternate" type="text/html" href="https://aoineko.org/msxgl/index.php?title=Build_tool/BIOSReleaseEvent&amp;diff=3853"/>
				<updated>2026-04-23T20:15:58Z</updated>
		
		<summary type="html">&lt;p&gt;Aoineko: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Build tool]] option '''BIOSReleaseEvent''' is used to add a callback function to be called just before BIOS is switched out from page 0. It allows you to have an initialization code that runs while the BIOS is still accessible at page 0. For example, to detect the presence of an MSX-Music device using the BIOS routines for cross-slot reading.&lt;br /&gt;
&lt;br /&gt;
This applies to [[target]] formats that place the ROM on page 0 (ROM_48K_ISR, ROM_64K_ISR, ROM_NEO8, and ROM_NEO16), as well as ROM formats that place RAM on page 0 (via the [[Build_tool/InstallRAMISR|InstallRAMISR]] option).&lt;br /&gt;
&lt;br /&gt;
== Usage ==&lt;br /&gt;
To use this option, you must provide a function that will be called by the boot process just before the BIOS is removed from page 0 (to make room for the cartridge or memory).&lt;br /&gt;
&lt;br /&gt;
Function prototype:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;void BIOS_OnRelease();&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Call context ==&lt;br /&gt;
&lt;br /&gt;
You must be fully aware of the program's initialization context at the time the BIOS_OnRelease callback function is executed. This context depends on the type of target format.&lt;br /&gt;
&lt;br /&gt;
=== ROM in page 0 ===&lt;br /&gt;
* The global variables have not been initialized yet (so you can't use those variables because their value is undefined and any change in the callback will be overwrite later during the boot process)&lt;br /&gt;
* The &amp;lt;tt&amp;gt;main()&amp;lt;/tt&amp;gt; function has not yet been called (so no program-specific initialization has taken place yet)&lt;br /&gt;
* The mapper has not yet been initialized;&lt;br /&gt;
** the selected segments are those selected by default by the hardware at the physical level (see https://www.msx.org/wiki/MegaROM_Mappers);&lt;br /&gt;
** mapper initialization will take place immediately after the return from the BIOS_OnRelease function and will overwrite any changes made in the callback;&lt;br /&gt;
* Only page 1 of memory space points to the program in ROM&lt;br /&gt;
&lt;br /&gt;
=== RAM in page 0 ===&lt;br /&gt;
* The global variables have been initialized (so they have their predefined values)&lt;br /&gt;
* The &amp;lt;tt&amp;gt;main()&amp;lt;/tt&amp;gt; function has not yet been called (so no program-specific initialization has taken place yet)&lt;br /&gt;
* The mapper has been initialized (see [[Create_a_mapped_ROM#Initial_slot_configuration|Initial slot configuration]])&lt;br /&gt;
* Pages 1 and 2 of memory point to the program in ROM&lt;br /&gt;
&lt;br /&gt;
=== Notes ===&lt;br /&gt;
You must therefore ensure that the code you call within the callback function only calls functions that are visible to the Z80 in the given context:&lt;br /&gt;
* Within the first 16 KB for Konami, ASCII-16, and NEO-16 mappers, and plain-ROM.&lt;br /&gt;
* Within the first 8 KB for ASCII-8 and NEO-8 mappers.&lt;br /&gt;
&lt;br /&gt;
As a reminder, the order of the module array (&amp;lt;tt&amp;gt;LibModules&amp;lt;/tt&amp;gt;) in your program determines the location of each module in the final binary.&lt;br /&gt;
&lt;br /&gt;
For example, if you want to call the MSX-Music detection function from the BIOS_OnRelease() callback, placing the &amp;lt;tt&amp;gt;msx-music&amp;lt;/tt&amp;gt; module first in the list ensures that it appears at the beginning of the ROM.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
bool g_UseFM; // Used in BIOS_OnRelease (can't be initalized here)&lt;br /&gt;
&lt;br /&gt;
//-----------------------------------------------------------------------------&lt;br /&gt;
// Event called before BIOS is released&lt;br /&gt;
void BIOS_OnRelease()&lt;br /&gt;
{&lt;br /&gt;
	g_UseFM = (MSXMusic_Initialize() != MSXMUSIC_NOTFOUND);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;/div&gt;</summary>
		<author><name>Aoineko</name></author>	</entry>

	<entry>
		<id>https://aoineko.org/msxgl/index.php?title=Build_tool/BIOSReleaseEvent&amp;diff=3852</id>
		<title>Build tool/BIOSReleaseEvent</title>
		<link rel="alternate" type="text/html" href="https://aoineko.org/msxgl/index.php?title=Build_tool/BIOSReleaseEvent&amp;diff=3852"/>
				<updated>2026-04-23T20:13:14Z</updated>
		
		<summary type="html">&lt;p&gt;Aoineko: /* Call context */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Build tool]] option '''BIOSReleaseEvent''' is used to add a callback function to be called just before BIOS is switched out from page 0. It allows you to have an initialization code that runs while the BIOS is still accessible at page 0. For example, to detect the presence of an MSX-Music device using the BIOS routines for cross-slot reading.&lt;br /&gt;
&lt;br /&gt;
This applies to [[target]] formats that place the ROM on page 0 (ROM_48K_ISR, ROM_64K_ISR, ROM_NEO8, and ROM_NEO16), as well as ROM formats that place RAM on page 0 (via the [[Build_tool/InstallRAMISR|InstallRAMISR]] option).&lt;br /&gt;
&lt;br /&gt;
== Usage ==&lt;br /&gt;
To use this option, you must provide a function that will be called by the boot process just before the BIOS is removed from page 0 (to make room for the cartridge or memory).&lt;br /&gt;
&lt;br /&gt;
Function prototype:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;void BIOS_OnRelease();&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Call context ==&lt;br /&gt;
&lt;br /&gt;
You must be fully aware of the program's initialization context at the time the BIOS_OnRelease callback function is executed. This context depends on the type of target format.&lt;br /&gt;
&lt;br /&gt;
=== ROM in page 0 ===&lt;br /&gt;
* The global variables have not been initialized yet (so you can't use those variables because their value is undefined and any change in the callback will be overwrite later during the boot process)&lt;br /&gt;
* The &amp;lt;tt&amp;gt;main()&amp;lt;/tt&amp;gt; function has not yet been called (so no program-specific initialization has taken place yet)&lt;br /&gt;
* The mapper has not yet been initialized;&lt;br /&gt;
** the selected segments are those selected by default by the hardware at the physical level (see https://www.msx.org/wiki/MegaROM_Mappers);&lt;br /&gt;
** mapper initialization will take place immediately after the return from the BIOS_OnRelease function and will overwrite any changes made in the callback;&lt;br /&gt;
* Only page 1 of memory space points to the program in ROM&lt;br /&gt;
&lt;br /&gt;
=== RAM in page 0 ===&lt;br /&gt;
* The global variables have been initialized (so they have their predefined values)&lt;br /&gt;
* The &amp;lt;tt&amp;gt;main()&amp;lt;/tt&amp;gt; function has not yet been called (so no program-specific initialization has taken place yet)&lt;br /&gt;
* The mapper has been initialized (see [[Create_a_mapped_ROM#Initial_slot_configuration|Initial slot configuration]])&lt;br /&gt;
* Pages 1 and 2 of memory point to the program in ROM&lt;br /&gt;
&lt;br /&gt;
=== Notes ===&lt;br /&gt;
You must therefore ensure that the code you call within the callback function only calls functions that are visible to the Z80 in the given context:&lt;br /&gt;
* Within the first 16 KB for Konami, ASCII-16, and NEO-16 mappers, and plain-ROM.&lt;br /&gt;
* Within the first 8 KB for ASCII-8 and NEO-8 mappers.&lt;br /&gt;
&lt;br /&gt;
As a reminder, the order of the module array (&amp;lt;tt&amp;gt;LibModules&amp;lt;/tt&amp;gt;) in your program determines the location of each module in the final binary.&lt;br /&gt;
&lt;br /&gt;
For example, if you want to call the MSX-Music detection function from the BIOS_OnRelease() callback, placing the &amp;lt;tt&amp;gt;msx-music&amp;lt;/tt&amp;gt; module first in the list ensures that it appears at the beginning of the ROM.&lt;/div&gt;</summary>
		<author><name>Aoineko</name></author>	</entry>

	<entry>
		<id>https://aoineko.org/msxgl/index.php?title=Build_tool/BIOSReleaseEvent&amp;diff=3851</id>
		<title>Build tool/BIOSReleaseEvent</title>
		<link rel="alternate" type="text/html" href="https://aoineko.org/msxgl/index.php?title=Build_tool/BIOSReleaseEvent&amp;diff=3851"/>
				<updated>2026-04-23T20:12:53Z</updated>
		
		<summary type="html">&lt;p&gt;Aoineko: /* ROM in page 0 */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Build tool]] option '''BIOSReleaseEvent''' is used to add a callback function to be called just before BIOS is switched out from page 0. It allows you to have an initialization code that runs while the BIOS is still accessible at page 0. For example, to detect the presence of an MSX-Music device using the BIOS routines for cross-slot reading.&lt;br /&gt;
&lt;br /&gt;
This applies to [[target]] formats that place the ROM on page 0 (ROM_48K_ISR, ROM_64K_ISR, ROM_NEO8, and ROM_NEO16), as well as ROM formats that place RAM on page 0 (via the [[Build_tool/InstallRAMISR|InstallRAMISR]] option).&lt;br /&gt;
&lt;br /&gt;
== Usage ==&lt;br /&gt;
To use this option, you must provide a function that will be called by the boot process just before the BIOS is removed from page 0 (to make room for the cartridge or memory).&lt;br /&gt;
&lt;br /&gt;
Function prototype:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;void BIOS_OnRelease();&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Call context ==&lt;br /&gt;
&lt;br /&gt;
You must be fully aware of the program's initialization context at the time the BIOS_OnRelease callback function is executed. This context depends on the type of target format.&lt;br /&gt;
&lt;br /&gt;
=== ROM in page 0 ===&lt;br /&gt;
* The global variables have not been initialized yet (so you can't use those variables because their value is undefined and any change in the callback will be overwrite later during the boot process)&lt;br /&gt;
* The main() function has not yet been called (so no program-specific initialization has taken place yet)&lt;br /&gt;
* The mapper has not yet been initialized;&lt;br /&gt;
** the selected segments are those selected by default by the hardware at the physical level (see https://www.msx.org/wiki/MegaROM_Mappers);&lt;br /&gt;
** mapper initialization will take place immediately after the return from the BIOS_OnRelease function and will overwrite any changes made in the callback;&lt;br /&gt;
* Only page 1 of memory space points to the program in ROM&lt;br /&gt;
&lt;br /&gt;
=== RAM in page 0 ===&lt;br /&gt;
* The global variables have been initialized (so they have their predefined values)&lt;br /&gt;
* The main() function has not yet been called (so no program-specific initialization has taken place yet)&lt;br /&gt;
* The mapper has been initialized (see [[Create_a_mapped_ROM#Initial_slot_configuration|Initial slot configuration]])&lt;br /&gt;
* Pages 1 and 2 of memory point to the program in ROM&lt;br /&gt;
&lt;br /&gt;
=== Notes ===&lt;br /&gt;
You must therefore ensure that the code you call within the callback function only calls functions that are visible to the Z80 in the given context:&lt;br /&gt;
* Within the first 16 KB for Konami, ASCII-16, and NEO-16 mappers, and plain-ROM.&lt;br /&gt;
* Within the first 8 KB for ASCII-8 and NEO-8 mappers.&lt;br /&gt;
&lt;br /&gt;
As a reminder, the order of the module array (&amp;lt;tt&amp;gt;LibModules&amp;lt;/tt&amp;gt;) in your program determines the location of each module in the final binary.&lt;br /&gt;
&lt;br /&gt;
For example, if you want to call the MSX-Music detection function from the BIOS_OnRelease() callback, placing the &amp;lt;tt&amp;gt;msx-music&amp;lt;/tt&amp;gt; module first in the list ensures that it appears at the beginning of the ROM.&lt;/div&gt;</summary>
		<author><name>Aoineko</name></author>	</entry>

	<entry>
		<id>https://aoineko.org/msxgl/index.php?title=Build_tool/BIOSReleaseEvent&amp;diff=3850</id>
		<title>Build tool/BIOSReleaseEvent</title>
		<link rel="alternate" type="text/html" href="https://aoineko.org/msxgl/index.php?title=Build_tool/BIOSReleaseEvent&amp;diff=3850"/>
				<updated>2026-04-23T20:10:19Z</updated>
		
		<summary type="html">&lt;p&gt;Aoineko: /* Usage */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Build tool]] option '''BIOSReleaseEvent''' is used to add a callback function to be called just before BIOS is switched out from page 0. It allows you to have an initialization code that runs while the BIOS is still accessible at page 0. For example, to detect the presence of an MSX-Music device using the BIOS routines for cross-slot reading.&lt;br /&gt;
&lt;br /&gt;
This applies to [[target]] formats that place the ROM on page 0 (ROM_48K_ISR, ROM_64K_ISR, ROM_NEO8, and ROM_NEO16), as well as ROM formats that place RAM on page 0 (via the [[Build_tool/InstallRAMISR|InstallRAMISR]] option).&lt;br /&gt;
&lt;br /&gt;
== Usage ==&lt;br /&gt;
To use this option, you must provide a function that will be called by the boot process just before the BIOS is removed from page 0 (to make room for the cartridge or memory).&lt;br /&gt;
&lt;br /&gt;
Function prototype:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;void BIOS_OnRelease();&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Call context ==&lt;br /&gt;
&lt;br /&gt;
You must be fully aware of the program's initialization context at the time the BIOS_OnRelease callback function is executed. This context depends on the type of target format.&lt;br /&gt;
&lt;br /&gt;
=== ROM in page 0 ===&lt;br /&gt;
* The global variables have been initialized (so they have their predefined values)&lt;br /&gt;
* The main() function has not yet been called (so no program-specific initialization has taken place yet)&lt;br /&gt;
* The mapper has not yet been initialized;&lt;br /&gt;
** the selected segments are those selected by default by the hardware at the physical level (see https://www.msx.org/wiki/MegaROM_Mappers);&lt;br /&gt;
** mapper initialization will take place immediately after the return from the BIOS_OnRelease function and will overwrite any changes made in the callback;&lt;br /&gt;
* Only page 1 of memory space points to the program in ROM&lt;br /&gt;
&lt;br /&gt;
=== RAM in page 0 ===&lt;br /&gt;
* The global variables have been initialized (so they have their predefined values)&lt;br /&gt;
* The main() function has not yet been called (so no program-specific initialization has taken place yet)&lt;br /&gt;
* The mapper has been initialized (see [[Create_a_mapped_ROM#Initial_slot_configuration|Initial slot configuration]])&lt;br /&gt;
* Pages 1 and 2 of memory point to the program in ROM&lt;br /&gt;
&lt;br /&gt;
=== Notes ===&lt;br /&gt;
You must therefore ensure that the code you call within the callback function only calls functions that are visible to the Z80 in the given context:&lt;br /&gt;
* Within the first 16 KB for Konami, ASCII-16, and NEO-16 mappers, and plain-ROM.&lt;br /&gt;
* Within the first 8 KB for ASCII-8 and NEO-8 mappers.&lt;br /&gt;
&lt;br /&gt;
As a reminder, the order of the module array (&amp;lt;tt&amp;gt;LibModules&amp;lt;/tt&amp;gt;) in your program determines the location of each module in the final binary.&lt;br /&gt;
&lt;br /&gt;
For example, if you want to call the MSX-Music detection function from the BIOS_OnRelease() callback, placing the &amp;lt;tt&amp;gt;msx-music&amp;lt;/tt&amp;gt; module first in the list ensures that it appears at the beginning of the ROM.&lt;/div&gt;</summary>
		<author><name>Aoineko</name></author>	</entry>

	<entry>
		<id>https://aoineko.org/msxgl/index.php?title=Build_tool/BIOSReleaseEvent&amp;diff=3849</id>
		<title>Build tool/BIOSReleaseEvent</title>
		<link rel="alternate" type="text/html" href="https://aoineko.org/msxgl/index.php?title=Build_tool/BIOSReleaseEvent&amp;diff=3849"/>
				<updated>2026-04-19T11:07:13Z</updated>
		
		<summary type="html">&lt;p&gt;Aoineko: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Build tool]] option '''BIOSReleaseEvent''' is used to add a callback function to be called just before BIOS is switched out from page 0. It allows you to have an initialization code that runs while the BIOS is still accessible at page 0. For example, to detect the presence of an MSX-Music device using the BIOS routines for cross-slot reading.&lt;br /&gt;
&lt;br /&gt;
This applies to [[target]] formats that place the ROM on page 0 (ROM_48K_ISR, ROM_64K_ISR, ROM_NEO8, and ROM_NEO16), as well as ROM formats that place RAM on page 0 (via the [[Build_tool/InstallRAMISR|InstallRAMISR]] option).&lt;br /&gt;
&lt;br /&gt;
== Usage ==&lt;br /&gt;
To use this option, the user must provide a function that will be called by the boot process just before the BIOS is removed from page 0 (to make room for the cartridge or memory).&lt;br /&gt;
&lt;br /&gt;
Function prototype:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;void BIOS_OnRelease();&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Call context ==&lt;br /&gt;
&lt;br /&gt;
You must be fully aware of the program's initialization context at the time the BIOS_OnRelease callback function is executed. This context depends on the type of target format.&lt;br /&gt;
&lt;br /&gt;
=== ROM in page 0 ===&lt;br /&gt;
* The global variables have been initialized (so they have their predefined values)&lt;br /&gt;
* The main() function has not yet been called (so no program-specific initialization has taken place yet)&lt;br /&gt;
* The mapper has not yet been initialized;&lt;br /&gt;
** the selected segments are those selected by default by the hardware at the physical level (see https://www.msx.org/wiki/MegaROM_Mappers);&lt;br /&gt;
** mapper initialization will take place immediately after the return from the BIOS_OnRelease function and will overwrite any changes made in the callback;&lt;br /&gt;
* Only page 1 of memory space points to the program in ROM&lt;br /&gt;
&lt;br /&gt;
=== RAM in page 0 ===&lt;br /&gt;
* The global variables have been initialized (so they have their predefined values)&lt;br /&gt;
* The main() function has not yet been called (so no program-specific initialization has taken place yet)&lt;br /&gt;
* The mapper has been initialized (see [[Create_a_mapped_ROM#Initial_slot_configuration|Initial slot configuration]])&lt;br /&gt;
* Pages 1 and 2 of memory point to the program in ROM&lt;br /&gt;
&lt;br /&gt;
=== Notes ===&lt;br /&gt;
You must therefore ensure that the code you call within the callback function only calls functions that are visible to the Z80 in the given context:&lt;br /&gt;
* Within the first 16 KB for Konami, ASCII-16, and NEO-16 mappers, and plain-ROM.&lt;br /&gt;
* Within the first 8 KB for ASCII-8 and NEO-8 mappers.&lt;br /&gt;
&lt;br /&gt;
As a reminder, the order of the module array (&amp;lt;tt&amp;gt;LibModules&amp;lt;/tt&amp;gt;) in your program determines the location of each module in the final binary.&lt;br /&gt;
&lt;br /&gt;
For example, if you want to call the MSX-Music detection function from the BIOS_OnRelease() callback, placing the &amp;lt;tt&amp;gt;msx-music&amp;lt;/tt&amp;gt; module first in the list ensures that it appears at the beginning of the ROM.&lt;/div&gt;</summary>
		<author><name>Aoineko</name></author>	</entry>

	<entry>
		<id>https://aoineko.org/msxgl/index.php?title=Build_tool/BIOSReleaseEvent&amp;diff=3848</id>
		<title>Build tool/BIOSReleaseEvent</title>
		<link rel="alternate" type="text/html" href="https://aoineko.org/msxgl/index.php?title=Build_tool/BIOSReleaseEvent&amp;diff=3848"/>
				<updated>2026-04-19T11:06:59Z</updated>
		
		<summary type="html">&lt;p&gt;Aoineko: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Build tool]] option '''BIOSReleaseEvent''' is used to add a callback function to be called just before BIOS is switched out from page 0. It allows you to have an initialization code that runs while the BIOS is still accessible at page 0. For example, to detect the presence of an MSX-Music device using the BIOS routines for cross-slot reading.&lt;br /&gt;
&lt;br /&gt;
This applies to [[target]] formats that place the ROM on page 0 (ROM_48K_ISR, ROM_64K_ISR, ROM_NEO8, and ROM_NEO16), as well as ROM formats that place RAM on page 0 (via the [[Build_tool/InstallRAMISR|InstallRAMISR]] option).&lt;br /&gt;
&lt;br /&gt;
== Usage ==&lt;br /&gt;
To use this option, the user must provide a function that will be called by the boot process just before the BIOS is removed from page 0 (to make room for the cartridge or memory).&lt;br /&gt;
&lt;br /&gt;
Function prototype:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;void BIOS_OnRelease();&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Call context ==&lt;br /&gt;
&lt;br /&gt;
You must be fully aware of the program's initialization context at the time the BIOS_OnRelease callback function is executed. This context depends on the type of target format.&lt;br /&gt;
&lt;br /&gt;
=== ROM in page 0 ===&lt;br /&gt;
* The global variables have been initialized (so they have their predefined values)&lt;br /&gt;
* The main() function has not yet been called (so no program-specific initialization has taken place yet)&lt;br /&gt;
* The mapper has not yet been initialized;&lt;br /&gt;
** the selected segments are those selected by default by the hardware at the physical level (see https://www.msx.org/wiki/MegaROM_Mappers);&lt;br /&gt;
** mapper initialization will take place immediately after the return from the BIOS_OnRelease function and will overwrite any changes made in the callback;&lt;br /&gt;
* Only page 1 of memory space points to the program in ROM&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== RAM in page 0 ===&lt;br /&gt;
* The global variables have been initialized (so they have their predefined values)&lt;br /&gt;
* The main() function has not yet been called (so no program-specific initialization has taken place yet)&lt;br /&gt;
* The mapper has been initialized (see [[Create_a_mapped_ROM#Initial_slot_configuration|Initial slot configuration]])&lt;br /&gt;
* Pages 1 and 2 of memory point to the program in ROM&lt;br /&gt;
&lt;br /&gt;
=== Notes ===&lt;br /&gt;
You must therefore ensure that the code you call within the callback function only calls functions that are visible to the Z80 in the given context:&lt;br /&gt;
* Within the first 16 KB for Konami, ASCII-16, and NEO-16 mappers, and plain-ROM.&lt;br /&gt;
* Within the first 8 KB for ASCII-8 and NEO-8 mappers.&lt;br /&gt;
&lt;br /&gt;
As a reminder, the order of the module array (&amp;lt;tt&amp;gt;LibModules&amp;lt;/tt&amp;gt;) in your program determines the location of each module in the final binary.&lt;br /&gt;
&lt;br /&gt;
For example, if you want to call the MSX-Music detection function from the BIOS_OnRelease() callback, placing the &amp;lt;tt&amp;gt;msx-music&amp;lt;/tt&amp;gt; module first in the list ensures that it appears at the beginning of the ROM.&lt;/div&gt;</summary>
		<author><name>Aoineko</name></author>	</entry>

	<entry>
		<id>https://aoineko.org/msxgl/index.php?title=Build_tool/BIOSReleaseEvent&amp;diff=3847</id>
		<title>Build tool/BIOSReleaseEvent</title>
		<link rel="alternate" type="text/html" href="https://aoineko.org/msxgl/index.php?title=Build_tool/BIOSReleaseEvent&amp;diff=3847"/>
				<updated>2026-04-19T10:58:36Z</updated>
		
		<summary type="html">&lt;p&gt;Aoineko: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Build tool]] option '''BIOSReleaseEvent''' is used to add a callback function to be called just before BIOS is switched out from page 0. It allows you to have an initialization code that runs while the BIOS is still accessible at page 0. For example, to detect the presence of an MSX-Music device using the BIOS routines for cross-slot reading.&lt;br /&gt;
&lt;br /&gt;
This applies to [[target]] formats that place the ROM on page 0 (ROM_48K_ISR, ROM_64K_ISR, ROM_NEO8, and ROM_NEO16), as well as ROM formats that place RAM on page 0 (via the [[Build_tool/InstallRAMISR|InstallRAMISR]] option).&lt;br /&gt;
&lt;br /&gt;
== Usage ==&lt;br /&gt;
To use this option, the user must provide a function that will be called by the boot process just before the BIOS is removed from page 0 (to make room for the cartridge or memory).&lt;br /&gt;
&lt;br /&gt;
Function prototype:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;void BIOS_OnRelease();&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Call Context ==&lt;br /&gt;
&lt;br /&gt;
You must be fully aware of the program's initialization context at the time the BIOS_OnRelease callback function is executed. This context depends on the type of target format.&lt;br /&gt;
&lt;br /&gt;
=== ROM in page 0 ===&lt;br /&gt;
* The global variables have been initialized (so they have their predefined values)&lt;br /&gt;
* The main() function has not yet been called (so no program-specific initialization has taken place yet)&lt;br /&gt;
* The mapper has not yet been initialized;&lt;br /&gt;
** the selected segments are those selected by default by the hardware at the physical level (see https://www.msx.org/wiki/MegaROM_Mappers);&lt;br /&gt;
** mapper initialization will take place immediately after the return from the BIOS_OnRelease function and will overwrite any changes made in the callback;&lt;br /&gt;
* Only page 1 of memory space points to the program in ROM&lt;br /&gt;
&lt;br /&gt;
=== RAM in page 0 ===&lt;br /&gt;
* The global variables have been initialized (so they have their predefined values)&lt;br /&gt;
* The main() function has not yet been called (so no program-specific initialization has taken place yet)&lt;br /&gt;
* The mapper has been initialized (see [[Create_a_mapped_ROM#Initial_slot_configuration|Initial slot configuration]])&lt;br /&gt;
* Pages 1 and 2 of memory point to the program in ROM&lt;/div&gt;</summary>
		<author><name>Aoineko</name></author>	</entry>

	<entry>
		<id>https://aoineko.org/msxgl/index.php?title=Build_tool/BIOSReleaseEvent&amp;diff=3846</id>
		<title>Build tool/BIOSReleaseEvent</title>
		<link rel="alternate" type="text/html" href="https://aoineko.org/msxgl/index.php?title=Build_tool/BIOSReleaseEvent&amp;diff=3846"/>
				<updated>2026-04-19T10:58:04Z</updated>
		
		<summary type="html">&lt;p&gt;Aoineko: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Build tool]] option '''BIOSReleaseEvent''' is used to add a callback function to be called just before BIOS is switched out from page 0. It allows you to have an initialization code that runs while the BIOS is still accessible at page 0. For example, to detect the presence of an MSX-Music device using the BIOS routines for cross-slot reading.&lt;br /&gt;
&lt;br /&gt;
This applies to [[target]] formats that place the ROM on page 0 (ROM_48K_ISR, ROM_64K_ISR, ROM_NEO8, and ROM_NEO16), as well as ROM formats that place RAM on page 0 (via the [[Build_tool/InstallRAMISR|InstallRAMISR]] option).&lt;br /&gt;
&lt;br /&gt;
== Usage ==&lt;br /&gt;
To use this option, the user must provide a function that will be called by the boot process just before the BIOS is removed from page 0 (to make room for the cartridge or memory).&lt;br /&gt;
&lt;br /&gt;
Function prototype:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;void BIOS_OnRelease();&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Call Context ==&lt;br /&gt;
&lt;br /&gt;
You must be fully aware of the program's initialization context at the time the BIOS_OnRelease callback function is executed. This context depends on the type of target format.&lt;br /&gt;
&lt;br /&gt;
=== ROM in page 0 ===&lt;br /&gt;
The global variables have been initialized (so they have their predefined values)&lt;br /&gt;
The main() function has not yet been called (so no program-specific initialization has taken place yet)&lt;br /&gt;
The mapper has not yet been initialized;&lt;br /&gt;
the selected segments are those selected by default by the hardware at the physical level (see https://www.msx.org/wiki/MegaROM_Mappers);&lt;br /&gt;
mapper initialization will take place immediately after the return from the BIOS_OnRelease function and will overwrite any changes made in the callback;&lt;br /&gt;
Only page 1 of memory space points to the program in ROM&lt;br /&gt;
&lt;br /&gt;
=== RAM in page 0 ===&lt;br /&gt;
The global variables have been initialized (so they have their predefined values)&lt;br /&gt;
The main() function has not yet been called (so no program-specific initialization has taken place yet)&lt;br /&gt;
The mapper has been initialized (see [[Create_a_mapped_ROM#Initial_slot_configuration|Initial slot configuration]])&lt;br /&gt;
Pages 1 and 2 of memory point to the program in ROM&lt;/div&gt;</summary>
		<author><name>Aoineko</name></author>	</entry>

	<entry>
		<id>https://aoineko.org/msxgl/index.php?title=Build_tool/BIOSReleaseEvent&amp;diff=3845</id>
		<title>Build tool/BIOSReleaseEvent</title>
		<link rel="alternate" type="text/html" href="https://aoineko.org/msxgl/index.php?title=Build_tool/BIOSReleaseEvent&amp;diff=3845"/>
				<updated>2026-04-19T10:17:44Z</updated>
		
		<summary type="html">&lt;p&gt;Aoineko: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Build tool]] option '''BIOSReleaseEvent''' is used to add a callback function to be called just before BIOS is switched out from page 0. It allows you to have an initialization code that runs while the BIOS is still accessible at page 0. For example, to detect the presence of an MSX-Music device using the BIOS routines for cross-slot reading.&lt;br /&gt;
&lt;br /&gt;
This applies to [[target]] formats that place the ROM on page 0 (ROM_48K_ISR, ROM_64K_ISR, ROM_NEO8, and ROM_NEO16), as well as ROM formats that place RAM on page 0 (via the [[Build_tool/InstallRAMISR|InstallRAMISR]] option).&lt;br /&gt;
&lt;br /&gt;
== Usage ==&lt;br /&gt;
To use this option, the user must provide a function that will be called by the boot process just before the BIOS is removed from page 0 (to make room for the cartridge or memory).&lt;br /&gt;
&lt;br /&gt;
Function prototype:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;void BIOS_OnRelease();&amp;lt;/syntaxhighlight&amp;gt;&lt;/div&gt;</summary>
		<author><name>Aoineko</name></author>	</entry>

	<entry>
		<id>https://aoineko.org/msxgl/index.php?title=Build_tool/BIOSReleaseEvent&amp;diff=3844</id>
		<title>Build tool/BIOSReleaseEvent</title>
		<link rel="alternate" type="text/html" href="https://aoineko.org/msxgl/index.php?title=Build_tool/BIOSReleaseEvent&amp;diff=3844"/>
				<updated>2026-04-19T10:17:28Z</updated>
		
		<summary type="html">&lt;p&gt;Aoineko: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Build tool]] option '''BIOSReleaseEvent''' is used to add a callback function to be called just before BIOS is switched out from page 0. It allows you to have an initialization code that runs while the BIOS is still accessible at page 0. For example, to detect the presence of an MSX-Music device using the BIOS routines for cross-slot reading.&lt;br /&gt;
&lt;br /&gt;
This applies to [[target]] formats that place the ROM on page 0 (ROM_48K_ISR, ROM_64K_ISR, ROM_NEO8, and ROM_NEO16), as well as ROM formats that place RAM on page 0 (via the [[Build_tool/InstallRAMISR|InstallRAMISR]] option).&lt;br /&gt;
&lt;br /&gt;
To use this option, the user must provide a function that will be called by the boot process just before the BIOS is removed from page 0 (to make room for the cartridge or memory).&lt;br /&gt;
&lt;br /&gt;
Function prototype:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;void BIOS_OnRelease();&amp;lt;/syntaxhighlight&amp;gt;&lt;/div&gt;</summary>
		<author><name>Aoineko</name></author>	</entry>

	<entry>
		<id>https://aoineko.org/msxgl/index.php?title=Build_tool/BIOSReleaseEvent&amp;diff=3843</id>
		<title>Build tool/BIOSReleaseEvent</title>
		<link rel="alternate" type="text/html" href="https://aoineko.org/msxgl/index.php?title=Build_tool/BIOSReleaseEvent&amp;diff=3843"/>
				<updated>2026-04-19T10:11:27Z</updated>
		
		<summary type="html">&lt;p&gt;Aoineko: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Build tool]] option '''BIOSReleaseEvent''' is used to add a callback function to be called just before BIOS is switched out from page 0.&lt;br /&gt;
&lt;br /&gt;
This applies to [[target]] formats that place the ROM on page 0 (ROM_48K_ISR, ROM_64K_ISR, ROM_NEO8, and ROM_NEO16), as well as ROM formats that place RAM on page 0 (via the [[Build_tool/InstallRAMISR|InstallRAMISR]] option).&lt;/div&gt;</summary>
		<author><name>Aoineko</name></author>	</entry>

	<entry>
		<id>https://aoineko.org/msxgl/index.php?title=Build_tool/BIOSReleaseEvent&amp;diff=3842</id>
		<title>Build tool/BIOSReleaseEvent</title>
		<link rel="alternate" type="text/html" href="https://aoineko.org/msxgl/index.php?title=Build_tool/BIOSReleaseEvent&amp;diff=3842"/>
				<updated>2026-04-19T10:11:18Z</updated>
		
		<summary type="html">&lt;p&gt;Aoineko: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Build tool]] option '''BIOSReleaseEvent''' is used to add a callback function to be called just before BIOS is switched out from page 0. This applies to [[target]] formats that place the ROM on page 0 (ROM_48K_ISR, ROM_64K_ISR, ROM_NEO8, and ROM_NEO16), as well as ROM formats that place RAM on page 0 (via the [[Build_tool/InstallRAMISR|InstallRAMISR]] option).&lt;/div&gt;</summary>
		<author><name>Aoineko</name></author>	</entry>

	<entry>
		<id>https://aoineko.org/msxgl/index.php?title=Build_tool&amp;diff=3841</id>
		<title>Build tool</title>
		<link rel="alternate" type="text/html" href="https://aoineko.org/msxgl/index.php?title=Build_tool&amp;diff=3841"/>
				<updated>2026-04-19T08:18:02Z</updated>
		
		<summary type="html">&lt;p&gt;Aoineko: /* Project */&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 socalization 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 socalization 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=Build_tool/BIOSReleaseEvent&amp;diff=3840</id>
		<title>Build tool/BIOSReleaseEvent</title>
		<link rel="alternate" type="text/html" href="https://aoineko.org/msxgl/index.php?title=Build_tool/BIOSReleaseEvent&amp;diff=3840"/>
				<updated>2026-04-18T17:54:12Z</updated>
		
		<summary type="html">&lt;p&gt;Aoineko: Created page with &amp;quot;Build tool option '''BIOSReleaseEvent''' is used to add a callback function to be called just before BIOS is switch out from page 0.&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Build tool]] option '''BIOSReleaseEvent''' is used to add a callback function to be called just before BIOS is switch out from page 0.&lt;/div&gt;</summary>
		<author><name>Aoineko</name></author>	</entry>

	<entry>
		<id>https://aoineko.org/msxgl/index.php?title=Build_tool&amp;diff=3839</id>
		<title>Build tool</title>
		<link rel="alternate" type="text/html" href="https://aoineko.org/msxgl/index.php?title=Build_tool&amp;diff=3839"/>
				<updated>2026-04-18T17:53:08Z</updated>
		
		<summary type="html">&lt;p&gt;Aoineko: /* Project */&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]]&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 socalization 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 socalization 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=Build_tool&amp;diff=3838</id>
		<title>Build tool</title>
		<link rel="alternate" type="text/html" href="https://aoineko.org/msxgl/index.php?title=Build_tool&amp;diff=3838"/>
				<updated>2026-04-18T17:52:21Z</updated>
		
		<summary type="html">&lt;p&gt;Aoineko: /* Project */&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]]&lt;br /&gt;
&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 socalization 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 socalization 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=AppSignature&amp;diff=3837</id>
		<title>AppSignature</title>
		<link rel="alternate" type="text/html" href="https://aoineko.org/msxgl/index.php?title=AppSignature&amp;diff=3837"/>
				<updated>2026-04-18T11:21:33Z</updated>
		
		<summary type="html">&lt;p&gt;Aoineko: /* Creator ID */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This [[Build tool]] option allow to add an '''application signature''' to binary data (right after the header).&lt;br /&gt;
&lt;br /&gt;
The MSXgl signature format is directly inspired by the meta-data used by '''Konami''' to identify their cartridges and add cross-games options.&lt;br /&gt;
&lt;br /&gt;
== Definition ==&lt;br /&gt;
&lt;br /&gt;
Application's signature is 4 bytes long and composed of:&lt;br /&gt;
* &amp;lt;tt&amp;gt;AppCompany&amp;lt;/tt&amp;gt;: 2 bytes for the creator ID ([[#Creator ID|reserve yours!]]),&lt;br /&gt;
* &amp;lt;tt&amp;gt;AppID&amp;lt;/tt&amp;gt;: 2 bytes for the product ID (the numbering of the applications is up to each creator).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;js&amp;quot;&amp;gt;&lt;br /&gt;
//-- Add application signature to binary data (boolean)&lt;br /&gt;
AppSignature = true;&lt;br /&gt;
&lt;br /&gt;
//-- Application creator ID. Can be 2 character string or 16-bits integer (0~65535)&lt;br /&gt;
AppCompany = &amp;quot;GL&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
//-- Application product ID. Can be 2 character string or 16-bits integer (0~65535)&lt;br /&gt;
AppID = 0;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If 2-character string is recommended for creator ID and integer for product ID, in fact, both of those parameters can be any of:&lt;br /&gt;
* 2-character string (&amp;lt;tt&amp;gt;&amp;quot;MX&amp;quot;&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;&amp;quot;a7&amp;quot;&amp;lt;/tt&amp;gt; for example),&lt;br /&gt;
* 16-bits decimal unsigned number (&amp;lt;tt&amp;gt;12345&amp;lt;/tt&amp;gt; for example),&lt;br /&gt;
* 16-bits hexadecimal number starting with &amp;lt;tt&amp;gt;0x&amp;lt;/tt&amp;gt; (&amp;lt;tt&amp;gt;0x0750&amp;lt;/tt&amp;gt; for example).&lt;br /&gt;
&lt;br /&gt;
For example, the header first 2 words of Konami's ''Penguin Adventure'' are &amp;lt;tt&amp;gt;&amp;quot;CD&amp;quot;, 0x4307&amp;lt;/tt&amp;gt;. &amp;lt;tt&amp;gt;&amp;quot;CD&amp;quot;&amp;lt;/tt&amp;gt; is one of the signature used by Konami to mark there ROM (see next section) and &amp;lt;tt&amp;gt;0x4307&amp;lt;/tt&amp;gt; show in binary viewer the number 0743... the serial number of ''Penguin Adventure'' (RC743).&lt;br /&gt;
&lt;br /&gt;
You can also add extra data using [[AppExtra]] option. {{WIP}}&lt;br /&gt;
&lt;br /&gt;
== Programming ==&lt;br /&gt;
If &amp;lt;tt&amp;gt;AppSignature&amp;lt;/tt&amp;gt; is set to TRUE in Build tool configuration, then &amp;lt;tt&amp;gt;APPSIGN&amp;lt;/tt&amp;gt; is defined in your C program.&lt;br /&gt;
&lt;br /&gt;
Application signature is put just after the binary header:&lt;br /&gt;
* At ROM header address +0x0010 (should be 0x4010 or 0x8010),&lt;br /&gt;
* At Basic binary header address +0x0007 (should be 0x8007),&lt;br /&gt;
* At DOS binary start address +0x0002 (should be 0x0102).&lt;br /&gt;
&lt;br /&gt;
Define an external variable as &amp;lt;tt&amp;gt;g_AppSignature&amp;lt;/tt&amp;gt; if you need to access the data from your program.&lt;br /&gt;
It can be defined in several ways depending on your needs. For example:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
extern const u16 g_AppSignature[2];&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
extern const u8 g_AppSignature[4];&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Keep in mind than MSX store data as Less significant byte first (Little endian).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;Note&amp;lt;/u&amp;gt;: For ROM targets, if a [[ROM type signature]] is present at offset +0010h, then the application signature is placed just after (header +0x0018)&lt;br /&gt;
&lt;br /&gt;
== Creator ID ==&lt;br /&gt;
Some creators' ID are already reserved:&lt;br /&gt;
{| class=&amp;quot;wikitable sortable&amp;quot;&lt;br /&gt;
! ID !! Rel !! Creator's name&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tt&amp;gt;0x00??&amp;lt;/tt&amp;gt; || ➖ || ''Reserved''&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tt&amp;gt;&amp;quot;2N&amp;quot;&amp;lt;/tt&amp;gt; || ✔️ || 2NICE&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tt&amp;gt;&amp;quot;AB&amp;quot;&amp;lt;/tt&amp;gt; || ✔️ || Konami (''Boxing'' and ''Football'')&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tt&amp;gt;&amp;quot;AM&amp;quot;&amp;lt;/tt&amp;gt; || ✔️ || Associazione MSX Italia&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tt&amp;gt;&amp;quot;AG&amp;quot;&amp;lt;/tt&amp;gt; ||  || Antxiko Gorjon&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tt&amp;gt;&amp;quot;B5&amp;quot;&amp;lt;/tt&amp;gt; || ✔️ || Bik5 (J. Bikker)&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tt&amp;gt;&amp;quot;CC&amp;quot;&amp;lt;/tt&amp;gt; || ✔️ || Casper Croes&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tt&amp;gt;&amp;quot;CD&amp;quot;&amp;lt;/tt&amp;gt; || ✔️ || Konami (many games)&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tt&amp;gt;&amp;quot;CL&amp;quot;&amp;lt;/tt&amp;gt; ||  || Chien Loco&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tt&amp;gt;&amp;quot;EF&amp;quot;&amp;lt;/tt&amp;gt; || ✔️ || Konami (''Pennant Race'' and ''Knightmare 3'')&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tt&amp;gt;&amp;quot;FD&amp;quot;&amp;lt;/tt&amp;gt; || ✔️ || FutureDisk&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tt&amp;gt;&amp;quot;FP&amp;quot;&amp;lt;/tt&amp;gt; || ✔️ || Fausto &lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tt&amp;gt;&amp;quot;JP&amp;quot;&amp;lt;/tt&amp;gt; ||  || Johan de Punder &lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tt&amp;gt;&amp;quot;GH&amp;quot;&amp;lt;/tt&amp;gt; || ➖ || ''Reserved''&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tt&amp;gt;&amp;quot;GL&amp;quot;&amp;lt;/tt&amp;gt; || ✔️ || MSXgl (samples)&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tt&amp;gt;&amp;quot;H_&amp;quot;&amp;lt;/tt&amp;gt; ||  || Peruho&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tt&amp;gt;&amp;quot;HN&amp;quot;&amp;lt;/tt&amp;gt; ||  || Hando&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tt&amp;gt;&amp;quot;MO&amp;quot;&amp;lt;/tt&amp;gt; || ✔️ || MO5.com&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tt&amp;gt;&amp;quot;NB&amp;quot;&amp;lt;/tt&amp;gt; || ✔️ || Nicola &amp;quot;8bit&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tt&amp;gt;&amp;quot;PH&amp;quot;&amp;lt;/tt&amp;gt; || ✔️ || Pixel Phenix&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tt&amp;gt;&amp;quot;PP&amp;quot;&amp;lt;/tt&amp;gt; || ✔️ || Pixel Phenix (obsolete)&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tt&amp;gt;&amp;quot;RC&amp;quot;&amp;lt;/tt&amp;gt; || ➖ || ''Reserved''&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tt&amp;gt;&amp;quot;RG&amp;quot;&amp;lt;/tt&amp;gt; || ✔️ || Rutagames (Diogo Patrão)&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tt&amp;gt;&amp;quot;RO&amp;quot;&amp;lt;/tt&amp;gt; || ➖ || ''Reserved for [[ROM type signature]]''&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tt&amp;gt;&amp;quot;RS&amp;quot;&amp;lt;/tt&amp;gt; || ✔️ || RoboSoft&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tt&amp;gt;&amp;quot;TL&amp;quot;&amp;lt;/tt&amp;gt; ||  || Tele-Line&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tt&amp;gt;&amp;quot;TT&amp;quot;&amp;lt;/tt&amp;gt; || ✔️ || Thomas ‘Totta’ Lundgren&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tt&amp;gt;&amp;quot;YZ&amp;quot;&amp;lt;/tt&amp;gt; || ✔️ || Konami (''Game Master 2)''&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tt&amp;gt;&amp;quot;WD&amp;quot;&amp;lt;/tt&amp;gt; ||  || Wim Dewijngaert&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tt&amp;gt;&amp;quot;ZR&amp;quot;&amp;lt;/tt&amp;gt; ||  || Zdrmonster Productions&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tt&amp;gt;&amp;quot;XX&amp;quot;&amp;lt;/tt&amp;gt; || ➖ || ''Reserved''&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tt&amp;gt;0xFF??&amp;lt;/tt&amp;gt; || ➖ || ''Reserved''&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Note:&lt;br /&gt;
* Come on the MSXgl's [https://discord.gg/pMeadGfv8E Discord Server] to reserve your own creator ID.&lt;br /&gt;
* Creator ID are only definitively assigned when an application is published with this code.&lt;br /&gt;
&lt;br /&gt;
== Known signed applications ==&lt;br /&gt;
List of released applications that contain compatible signature.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable sortable&amp;quot;&lt;br /&gt;
! C !! App !! Author !! Application&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tt&amp;gt;&amp;quot;B5&amp;quot;&amp;lt;/tt&amp;gt; || &amp;lt;tt&amp;gt;&amp;quot;EM&amp;quot;&amp;lt;/tt&amp;gt; || Bik5 (J. Bikker) || ''Eggy's Maze''&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tt&amp;gt;&amp;quot;B5&amp;quot;&amp;lt;/tt&amp;gt; || &amp;lt;tt&amp;gt;&amp;quot;R3&amp;quot;&amp;lt;/tt&amp;gt; || Bik5 (J. Bikker) || ''DELTA''&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tt&amp;gt;&amp;quot;CC&amp;quot;&amp;lt;/tt&amp;gt; || &amp;lt;tt&amp;gt;&amp;quot;PC&amp;quot;&amp;lt;/tt&amp;gt; || Casper Croes || ''Phenix Corrupta''&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tt&amp;gt;&amp;quot;CC&amp;quot;&amp;lt;/tt&amp;gt; || &amp;lt;tt&amp;gt;&amp;quot;TR&amp;quot;&amp;lt;/tt&amp;gt; || Casper Croes || ''Soul Trapped''&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tt&amp;gt;&amp;quot;FD&amp;quot;&amp;lt;/tt&amp;gt; || &amp;lt;tt&amp;gt;&amp;quot;LW&amp;quot;&amp;lt;/tt&amp;gt; || FutureDisk || ''A Lone Wolf''&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tt&amp;gt;&amp;quot;FP&amp;quot;&amp;lt;/tt&amp;gt; || &amp;lt;tt&amp;gt;&amp;quot;EX&amp;quot;&amp;lt;/tt&amp;gt; || Fausto Pracek || ''Sam.Pr Explore''&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tt&amp;gt;&amp;quot;FP&amp;quot;&amp;lt;/tt&amp;gt; || &amp;lt;tt&amp;gt;&amp;quot;MW&amp;quot;&amp;lt;/tt&amp;gt; || Fausto Pracek || ''Martian War''&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tt&amp;gt;&amp;quot;FP&amp;quot;&amp;lt;/tt&amp;gt; || &amp;lt;tt&amp;gt;&amp;quot;SL&amp;quot;&amp;lt;/tt&amp;gt; || Fausto Pracek || ''Soccer League''&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tt&amp;gt;&amp;quot;FP&amp;quot;&amp;lt;/tt&amp;gt; || &amp;lt;tt&amp;gt;&amp;quot;SP&amp;quot;&amp;lt;/tt&amp;gt; || Fausto Pracek || ''Sam.Pr''&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tt&amp;gt;&amp;quot;NB&amp;quot;&amp;lt;/tt&amp;gt; || &amp;lt;tt&amp;gt;&amp;quot;TC&amp;quot;&amp;lt;/tt&amp;gt; || Nicola &amp;quot;8bit&amp;quot; || ''The New Castle''&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tt&amp;gt;&amp;quot;PP&amp;quot;&amp;lt;/tt&amp;gt; || &amp;lt;tt&amp;gt;&amp;quot;CR&amp;quot;&amp;lt;/tt&amp;gt; || Pixel Phenix || ''Crawlers (MSXdev'23)''&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tt&amp;gt;&amp;quot;PH&amp;quot;&amp;lt;/tt&amp;gt; || &amp;lt;tt&amp;gt;001&amp;lt;/tt&amp;gt; || Pixel Phenix || ''Crawlers (cartridge)''&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tt&amp;gt;&amp;quot;PH&amp;quot;&amp;lt;/tt&amp;gt; || &amp;lt;tt&amp;gt;003&amp;lt;/tt&amp;gt; || Pixel Phenix || ''Peng Pong''&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tt&amp;gt;&amp;quot;RG&amp;quot;&amp;lt;/tt&amp;gt; || &amp;lt;tt&amp;gt;&amp;quot;TM&amp;quot;&amp;lt;/tt&amp;gt; || Rutagames || ''TerMSX Multi''&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tt&amp;gt;&amp;quot;RS&amp;quot;&amp;lt;/tt&amp;gt; || &amp;lt;tt&amp;gt;&amp;quot;P9&amp;quot;&amp;lt;/tt&amp;gt; || RoboSoft || ''Planet X9''&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tt&amp;gt;&amp;quot;RS&amp;quot;&amp;lt;/tt&amp;gt; || &amp;lt;tt&amp;gt;&amp;quot;PE&amp;quot;&amp;lt;/tt&amp;gt; || RoboSoft || ''Attack of the Petscii Robots''&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tt&amp;gt;&amp;quot;TT&amp;quot;&amp;lt;/tt&amp;gt; || &amp;lt;tt&amp;gt;&amp;quot;TP&amp;quot;&amp;lt;/tt&amp;gt; || Thomas ‘Totta’ Lundgren || ''Tetpuz''&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tt&amp;gt;&amp;quot;TT&amp;quot;&amp;lt;/tt&amp;gt; || &amp;lt;tt&amp;gt;&amp;quot;DL&amp;quot;&amp;lt;/tt&amp;gt; || Thomas ‘Totta’ Lundgren || ''Doomlings''&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tt&amp;gt;&amp;quot;MO&amp;quot;&amp;lt;/tt&amp;gt; || &amp;lt;tt&amp;gt;&amp;quot;R5&amp;quot;&amp;lt;/tt&amp;gt; || MO5.com || ''Room 5''&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tt&amp;gt;&amp;quot;GL&amp;quot;&amp;lt;/tt&amp;gt; || &amp;lt;tt&amp;gt;?&amp;lt;/tt&amp;gt; || MSXgl || (samples)&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tt&amp;gt;&amp;quot;AB&amp;quot;&amp;lt;/tt&amp;gt; || &amp;lt;tt&amp;gt;?&amp;lt;/tt&amp;gt; || Konami || (''Boxing'' and ''Football'')&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tt&amp;gt;&amp;quot;CD&amp;quot;&amp;lt;/tt&amp;gt; || &amp;lt;tt&amp;gt;?&amp;lt;/tt&amp;gt; || Konami || (many games)&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tt&amp;gt;&amp;quot;EF&amp;quot;&amp;lt;/tt&amp;gt; || &amp;lt;tt&amp;gt;?&amp;lt;/tt&amp;gt; || Konami || (''Pennant Race'' and ''Knightmare 3'')&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tt&amp;gt;&amp;quot;YZ&amp;quot;&amp;lt;/tt&amp;gt; || &amp;lt;tt&amp;gt;?&amp;lt;/tt&amp;gt; || Konami || (''Game Master 2)''&lt;br /&gt;
|}&lt;/div&gt;</summary>
		<author><name>Aoineko</name></author>	</entry>

	<entry>
		<id>https://aoineko.org/msxgl/index.php?title=NEO_mapper/Extension&amp;diff=3836</id>
		<title>NEO mapper/Extension</title>
		<link rel="alternate" type="text/html" href="https://aoineko.org/msxgl/index.php?title=NEO_mapper/Extension&amp;diff=3836"/>
				<updated>2026-04-13T21:34:17Z</updated>
		
		<summary type="html">&lt;p&gt;Aoineko: /* 0x05: Activate device */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{WARNING|This page is still in the proposal stage and should not yet be considered an official specification.}}&lt;br /&gt;
&lt;br /&gt;
Proposal for an extension to the [[NEO mapper]] format.&lt;br /&gt;
&lt;br /&gt;
== Specifications ==&lt;br /&gt;
&lt;br /&gt;
=== Principles ===&lt;br /&gt;
&lt;br /&gt;
Any write operation to the NEO mapper with data bit 7 set to 1 and address bit 0 set to 1 is considered an access to extended features. In that case, the mapper bank register is not modified.&lt;br /&gt;
&lt;br /&gt;
All other write operations should be considered normal access to the mapper's bank register.&lt;br /&gt;
&lt;br /&gt;
The data contains:&lt;br /&gt;
* The number of an extended function in the mapper&lt;br /&gt;
* A bit indicating whether the function should be enabled or disabled&lt;br /&gt;
&lt;br /&gt;
The address contains an 8-bit parameter to be passed to the function.&lt;br /&gt;
{|&lt;br /&gt;
|-&lt;br /&gt;
|&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ ADDRESS&lt;br /&gt;
|-&lt;br /&gt;
! 15 || 14 || 13 || 12 || 11 || 10 || 9 || 8 || 7 || 6 || 5 || 4 || 3 || 2 || 1 || 0&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#BBB;&amp;quot; colspan=&amp;quot;2&amp;quot;| Page&lt;br /&gt;
|style=&amp;quot;background-color:#BBB;&amp;quot; colspan=&amp;quot;3&amp;quot;| Bank&lt;br /&gt;
|style=&amp;quot;background-color:#BBB;&amp;quot;| 0&lt;br /&gt;
|style=&amp;quot;background-color:#BBB;&amp;quot;| 0&lt;br /&gt;
|style=&amp;quot;background-color:#AAF;&amp;quot; colspan=&amp;quot;8&amp;quot;| Parameter&lt;br /&gt;
|style=&amp;quot;background-color:#FAA;&amp;quot;| 1&lt;br /&gt;
|}&lt;br /&gt;
|&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ DATA&lt;br /&gt;
|-&lt;br /&gt;
! 7 || 6 || 5 || 4 || 3 || 2 || 1 || 0&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FAA;&amp;quot;| 1&lt;br /&gt;
|style=&amp;quot;background-color:#AAF;&amp;quot;| A&lt;br /&gt;
|style=&amp;quot;background-color:#BBB;&amp;quot;| 0&lt;br /&gt;
|style=&amp;quot;background-color:#AAF;&amp;quot; colspan=&amp;quot;5&amp;quot;| Function&lt;br /&gt;
|}&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Functions ===&lt;br /&gt;
==== 0x00: Cartridge information ====&lt;br /&gt;
When activated, any read access to the given bank will return the cartridge information (8 KB, mirrored on NEO-16).&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ PARAMETER&lt;br /&gt;
|-&lt;br /&gt;
! 8 || 7 || 6 || 5 || 4 || 3 || 2 || 1&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#BBB;&amp;quot;| 0&lt;br /&gt;
|style=&amp;quot;background-color:#BBB;&amp;quot;| 0&lt;br /&gt;
|style=&amp;quot;background-color:#BBB;&amp;quot;| 0&lt;br /&gt;
|style=&amp;quot;background-color:#BBB;&amp;quot;| 0&lt;br /&gt;
|style=&amp;quot;background-color:#BBB;&amp;quot;| 0&lt;br /&gt;
|style=&amp;quot;background-color:#AAF;&amp;quot; colspan=&amp;quot;5&amp;quot;| ROM Bank&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Examples:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Action || Pseudo-code&lt;br /&gt;
|-&lt;br /&gt;
| Activate information in bank 2 of NEO-16 || &amp;lt;tt&amp;gt;[0x7005] = 0xC0&amp;lt;/tt&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Read information (offset +5) from bank 2 of NEO-16 || &amp;lt;tt&amp;gt;BankSize = [0x8005]&amp;lt;/tt&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Disactivate information in bank 2 of NEO-16 || &amp;lt;tt&amp;gt;[0x7005] = 0x80&amp;lt;/tt&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== 0x01: Cartridge configuration ====&lt;br /&gt;
&lt;br /&gt;
==== 0x04: Activate SRAM/FRAM ====&lt;br /&gt;
When activated, any read/write access to the specified bank (defined in the parameter) is redirected to the selected segment of the SRAM/FRAM.&lt;br /&gt;
&lt;br /&gt;
SRAM/FRAM is accessed through 8 KB segments (on the NEO-16, the segment is mirrored).&lt;br /&gt;
&lt;br /&gt;
Up to 16 segments can be accessed, for a total capacity of 128 KB.&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ PARAMETER&lt;br /&gt;
|-&lt;br /&gt;
! 8 || 7 || 6 || 5 || 4 || 3 || 2 || 1&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#AAF;&amp;quot; colspan=&amp;quot;4&amp;quot;| RAM Segment&lt;br /&gt;
|style=&amp;quot;background-color:#BBB;&amp;quot;| 0&lt;br /&gt;
|style=&amp;quot;background-color:#AAF;&amp;quot; colspan=&amp;quot;5&amp;quot;| ROM Bank&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== 0x05: Activate device ====&lt;br /&gt;
Activate or disactivate the given device.&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ PARAMETER&lt;br /&gt;
|-&lt;br /&gt;
! 8 || 7 || 6 || 5 || 4 || 3 || 2 || 1&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#BBB;&amp;quot;| 0&lt;br /&gt;
|style=&amp;quot;background-color:#BBB;&amp;quot;| 0&lt;br /&gt;
|style=&amp;quot;background-color:#BBB;&amp;quot;| 0&lt;br /&gt;
|style=&amp;quot;background-color:#AAF;&amp;quot; colspan=&amp;quot;5&amp;quot;| Device ID&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Devices:&lt;br /&gt;
* &amp;lt;tt&amp;gt;00&amp;lt;/tt&amp;gt;: MSX-Music (OPLL)&lt;br /&gt;
* &amp;lt;tt&amp;gt;01&amp;lt;/tt&amp;gt;: MSX-Audio&lt;br /&gt;
* &amp;lt;tt&amp;gt;02&amp;lt;/tt&amp;gt;: SCC&lt;br /&gt;
* &amp;lt;tt&amp;gt;03&amp;lt;/tt&amp;gt;: SCC+&lt;br /&gt;
* &amp;lt;tt&amp;gt;04&amp;lt;/tt&amp;gt;: 2nd PSG (port 10h)&lt;br /&gt;
* &amp;lt;tt&amp;gt;05&amp;lt;/tt&amp;gt;: Darky (2 x ePSG)&lt;br /&gt;
* &amp;lt;tt&amp;gt;06&amp;lt;/tt&amp;gt;: Darky Jr. (2 x PSG)&lt;br /&gt;
* &amp;lt;tt&amp;gt;08&amp;lt;/tt&amp;gt;: OPM (SFK-01, SFG-01 et SFG-05 ver.1)&lt;br /&gt;
* &amp;lt;tt&amp;gt;09&amp;lt;/tt&amp;gt;: OPP (SFG-05 ver.2)&lt;br /&gt;
* &amp;lt;tt&amp;gt;12&amp;lt;/tt&amp;gt;: OPL4&lt;br /&gt;
* &amp;lt;tt&amp;gt;15&amp;lt;/tt&amp;gt;: SAM2695&lt;br /&gt;
&lt;br /&gt;
== Appendix ==&lt;br /&gt;
=== Programmable processor and emulation ===&lt;br /&gt;
Here is a pseudo code in C to handle NEO mappers extension for programmable processor based cartridges or for emulators:&lt;br /&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;
// Extended function prototypes&lt;br /&gt;
typedef void (*funcEnable_t)(bool, uint8);&lt;br /&gt;
typedef void (*funcWrite_t)(uint16, uint8);&lt;br /&gt;
typedef uint8 (*funcRead_t)(uint16);&lt;br /&gt;
// Extended functions table&lt;br /&gt;
funcEnable_t funcEnableTable[32];&lt;br /&gt;
funcWrite_t funcWriteTable[3];&lt;br /&gt;
funcRead_t funcReadTable[3];&lt;br /&gt;
&lt;br /&gt;
// Handle device initialization&lt;br /&gt;
void NEO16_Init()&lt;br /&gt;
{&lt;br /&gt;
	for (uint8 i = 0; i &amp;lt; 3; i++)&lt;br /&gt;
	{&lt;br /&gt;
		bankValue[i] = 0x0000;&lt;br /&gt;
		funcWriteTable[i] = NULL;&lt;br /&gt;
		funcReadTable[i] = NULL;		&lt;br /&gt;
	}&lt;br /&gt;
	for (uint8 i = 0; i &amp;lt; 32; i++)&lt;br /&gt;
		funcEnableTable[i] = NULL;&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; // Get the corresponding bank number&lt;br /&gt;
	if (bank &amp;gt; 2)&lt;br /&gt;
		return; // skip&lt;br /&gt;
&lt;br /&gt;
	if (funcWriteTable[bank] != NULL) // Check for bank write callback&lt;br /&gt;
	{&lt;br /&gt;
		funcWriteTable[bank](address, value);&lt;br /&gt;
	}&lt;br /&gt;
	else if ((address &amp;amp; 0x0001) &amp;amp;&amp;amp; (value &amp;amp; 0x80)) // Handle extended function&lt;br /&gt;
	{&lt;br /&gt;
		uint8 funcId = value &amp;amp; 0x3F; // Get function ID&lt;br /&gt;
		if (funcEnableTable[funcId] != NULL)&lt;br /&gt;
			funcEnableTable[funcId](value &amp;amp; 0x40, (address &amp;gt;&amp;gt; 1) &amp;amp; 0xFF); // Execute function specific code&lt;br /&gt;
	}&lt;br /&gt;
	else // Write to the given bank register&lt;br /&gt;
	{&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;
&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; // Get the corresponding bank number&lt;br /&gt;
	if (bank &amp;gt; 2)&lt;br /&gt;
		return 0xFF; // skip&lt;br /&gt;
&lt;br /&gt;
	if (funcReadTable[bank] != NULL) // Check for bank read callback&lt;br /&gt;
		return funcReadTable[bank](address);&lt;br /&gt;
	else&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;
=== Extension example ===&lt;br /&gt;
Here is a pseudo code in C to handle a SRAM extension for NEO mapper:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
uint8 sramSeg; // Current SRAM segment [0:15]&lt;br /&gt;
uint8 sramBank; // Current bank where SRAM is selected (0xFF if not selected)&lt;br /&gt;
uint8* sramData; // SRAM data (hardware specific)&lt;br /&gt;
&lt;br /&gt;
// Write to SRAM&lt;br /&gt;
void SRAM_Write(uint16 address, uint8 value)&lt;br /&gt;
{&lt;br /&gt;
	sramData[(sramSeg * 0x2000) + (address &amp;amp; 0x1FFF)] = value; // &lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// Read from SRAM&lt;br /&gt;
uint8 SRAM_Read(uint16 address)&lt;br /&gt;
{&lt;br /&gt;
	return sramData[(sramSeg * 0x2000) + (address &amp;amp; 0x1FFF)];	&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// Enable/disable SRAM feature&lt;br /&gt;
void SRAM_Enable(bool enable, uint8 param)&lt;br /&gt;
{&lt;br /&gt;
	if (sramBank != 0xFF) // Disable previous SRAM registration&lt;br /&gt;
	{&lt;br /&gt;
		if (funcWriteTable[sramBank] == SRAM_Write)&lt;br /&gt;
			funcWriteTable[sramBank] = NULL;&lt;br /&gt;
		if (funcReadTable[sramBank] == SRAM_Read)&lt;br /&gt;
			funcReadTable[sramBank] = NULL;&lt;br /&gt;
		sramBank = 0xFF;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	if (enable) // Enable a SRAM segment in the given bank&lt;br /&gt;
	{&lt;br /&gt;
		uint8 bank = param &amp;amp; 0x07; // Get bank number&lt;br /&gt;
		if (bank &amp;gt; 2)&lt;br /&gt;
			return; // skip (for NEO-16)&lt;br /&gt;
&lt;br /&gt;
		sramSeg = (param &amp;gt;&amp;gt; 4) &amp;amp; 0x0F; // SRAM segment number&lt;br /&gt;
		sramBank = bank;&lt;br /&gt;
		funcWriteTable[sramBank] = SRAM_Write; // Register SRAM callbacks&lt;br /&gt;
		funcReadTable[sramBank] = SRAM_Read;&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// Initialize SRAM feature&lt;br /&gt;
void SRAM_Init()&lt;br /&gt;
{&lt;br /&gt;
	sramBank = 0xFF;&lt;br /&gt;
	funcEnableTable[0x04] = SRAM_Enable; // Register to function 0x04 (SRAM/FRAM feature)&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Then, you just need to call &amp;lt;tt&amp;gt;SRAM_Init()&amp;lt;/tt&amp;gt; from &amp;lt;tt&amp;gt;NEO16_Init()&amp;lt;/tt&amp;gt; to register the extended feature.&lt;/div&gt;</summary>
		<author><name>Aoineko</name></author>	</entry>

	<entry>
		<id>https://aoineko.org/msxgl/index.php?title=NEO_mapper/Extension&amp;diff=3835</id>
		<title>NEO mapper/Extension</title>
		<link rel="alternate" type="text/html" href="https://aoineko.org/msxgl/index.php?title=NEO_mapper/Extension&amp;diff=3835"/>
				<updated>2026-04-13T21:32:59Z</updated>
		
		<summary type="html">&lt;p&gt;Aoineko: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{WARNING|This page is still in the proposal stage and should not yet be considered an official specification.}}&lt;br /&gt;
&lt;br /&gt;
Proposal for an extension to the [[NEO mapper]] format.&lt;br /&gt;
&lt;br /&gt;
== Specifications ==&lt;br /&gt;
&lt;br /&gt;
=== Principles ===&lt;br /&gt;
&lt;br /&gt;
Any write operation to the NEO mapper with data bit 7 set to 1 and address bit 0 set to 1 is considered an access to extended features. In that case, the mapper bank register is not modified.&lt;br /&gt;
&lt;br /&gt;
All other write operations should be considered normal access to the mapper's bank register.&lt;br /&gt;
&lt;br /&gt;
The data contains:&lt;br /&gt;
* The number of an extended function in the mapper&lt;br /&gt;
* A bit indicating whether the function should be enabled or disabled&lt;br /&gt;
&lt;br /&gt;
The address contains an 8-bit parameter to be passed to the function.&lt;br /&gt;
{|&lt;br /&gt;
|-&lt;br /&gt;
|&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ ADDRESS&lt;br /&gt;
|-&lt;br /&gt;
! 15 || 14 || 13 || 12 || 11 || 10 || 9 || 8 || 7 || 6 || 5 || 4 || 3 || 2 || 1 || 0&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#BBB;&amp;quot; colspan=&amp;quot;2&amp;quot;| Page&lt;br /&gt;
|style=&amp;quot;background-color:#BBB;&amp;quot; colspan=&amp;quot;3&amp;quot;| Bank&lt;br /&gt;
|style=&amp;quot;background-color:#BBB;&amp;quot;| 0&lt;br /&gt;
|style=&amp;quot;background-color:#BBB;&amp;quot;| 0&lt;br /&gt;
|style=&amp;quot;background-color:#AAF;&amp;quot; colspan=&amp;quot;8&amp;quot;| Parameter&lt;br /&gt;
|style=&amp;quot;background-color:#FAA;&amp;quot;| 1&lt;br /&gt;
|}&lt;br /&gt;
|&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ DATA&lt;br /&gt;
|-&lt;br /&gt;
! 7 || 6 || 5 || 4 || 3 || 2 || 1 || 0&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FAA;&amp;quot;| 1&lt;br /&gt;
|style=&amp;quot;background-color:#AAF;&amp;quot;| A&lt;br /&gt;
|style=&amp;quot;background-color:#BBB;&amp;quot;| 0&lt;br /&gt;
|style=&amp;quot;background-color:#AAF;&amp;quot; colspan=&amp;quot;5&amp;quot;| Function&lt;br /&gt;
|}&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Functions ===&lt;br /&gt;
==== 0x00: Cartridge information ====&lt;br /&gt;
When activated, any read access to the given bank will return the cartridge information (8 KB, mirrored on NEO-16).&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ PARAMETER&lt;br /&gt;
|-&lt;br /&gt;
! 8 || 7 || 6 || 5 || 4 || 3 || 2 || 1&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#BBB;&amp;quot;| 0&lt;br /&gt;
|style=&amp;quot;background-color:#BBB;&amp;quot;| 0&lt;br /&gt;
|style=&amp;quot;background-color:#BBB;&amp;quot;| 0&lt;br /&gt;
|style=&amp;quot;background-color:#BBB;&amp;quot;| 0&lt;br /&gt;
|style=&amp;quot;background-color:#BBB;&amp;quot;| 0&lt;br /&gt;
|style=&amp;quot;background-color:#AAF;&amp;quot; colspan=&amp;quot;5&amp;quot;| ROM Bank&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Examples:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Action || Pseudo-code&lt;br /&gt;
|-&lt;br /&gt;
| Activate information in bank 2 of NEO-16 || &amp;lt;tt&amp;gt;[0x7005] = 0xC0&amp;lt;/tt&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Read information (offset +5) from bank 2 of NEO-16 || &amp;lt;tt&amp;gt;BankSize = [0x8005]&amp;lt;/tt&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Disactivate information in bank 2 of NEO-16 || &amp;lt;tt&amp;gt;[0x7005] = 0x80&amp;lt;/tt&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== 0x01: Cartridge configuration ====&lt;br /&gt;
&lt;br /&gt;
==== 0x04: Activate SRAM/FRAM ====&lt;br /&gt;
When activated, any read/write access to the specified bank (defined in the parameter) is redirected to the selected segment of the SRAM/FRAM.&lt;br /&gt;
&lt;br /&gt;
SRAM/FRAM is accessed through 8 KB segments (on the NEO-16, the segment is mirrored).&lt;br /&gt;
&lt;br /&gt;
Up to 16 segments can be accessed, for a total capacity of 128 KB.&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ PARAMETER&lt;br /&gt;
|-&lt;br /&gt;
! 8 || 7 || 6 || 5 || 4 || 3 || 2 || 1&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#AAF;&amp;quot; colspan=&amp;quot;4&amp;quot;| RAM Segment&lt;br /&gt;
|style=&amp;quot;background-color:#BBB;&amp;quot;| 0&lt;br /&gt;
|style=&amp;quot;background-color:#AAF;&amp;quot; colspan=&amp;quot;5&amp;quot;| ROM Bank&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== 0x05: Activate device ====&lt;br /&gt;
Activate or disactivate the given device.&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ PARAMETER&lt;br /&gt;
|-&lt;br /&gt;
! 8 || 7 || 6 || 5 || 4 || 3 || 2 || 1&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#BBB;&amp;quot;| 0&lt;br /&gt;
|style=&amp;quot;background-color:#BBB;&amp;quot;| 0&lt;br /&gt;
|style=&amp;quot;background-color:#BBB;&amp;quot;| 0&lt;br /&gt;
|style=&amp;quot;background-color:#AAF;&amp;quot; colspan=&amp;quot;5&amp;quot;| Device&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Devices:&lt;br /&gt;
* &amp;lt;tt&amp;gt;00&amp;lt;/tt&amp;gt;: MSX-Music (OPLL)&lt;br /&gt;
* &amp;lt;tt&amp;gt;01&amp;lt;/tt&amp;gt;: MSX-Audio&lt;br /&gt;
* &amp;lt;tt&amp;gt;02&amp;lt;/tt&amp;gt;: SCC&lt;br /&gt;
* &amp;lt;tt&amp;gt;03&amp;lt;/tt&amp;gt;: SCC+&lt;br /&gt;
* &amp;lt;tt&amp;gt;04&amp;lt;/tt&amp;gt;: 2nd PSG (port 10h)&lt;br /&gt;
* &amp;lt;tt&amp;gt;05&amp;lt;/tt&amp;gt;: Darky (2 x ePSG)&lt;br /&gt;
* &amp;lt;tt&amp;gt;06&amp;lt;/tt&amp;gt;: Darky Jr. (2 x PSG)&lt;br /&gt;
* &amp;lt;tt&amp;gt;08&amp;lt;/tt&amp;gt;: OPM (SFK-01, SFG-01 et SFG-05 ver.1)&lt;br /&gt;
* &amp;lt;tt&amp;gt;09&amp;lt;/tt&amp;gt;: OPP (SFG-05 ver.2)&lt;br /&gt;
* &amp;lt;tt&amp;gt;12&amp;lt;/tt&amp;gt;: OPL4&lt;br /&gt;
* &amp;lt;tt&amp;gt;15&amp;lt;/tt&amp;gt;: SAM2695&lt;br /&gt;
&lt;br /&gt;
== Appendix ==&lt;br /&gt;
=== Programmable processor and emulation ===&lt;br /&gt;
Here is a pseudo code in C to handle NEO mappers extension for programmable processor based cartridges or for emulators:&lt;br /&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;
// Extended function prototypes&lt;br /&gt;
typedef void (*funcEnable_t)(bool, uint8);&lt;br /&gt;
typedef void (*funcWrite_t)(uint16, uint8);&lt;br /&gt;
typedef uint8 (*funcRead_t)(uint16);&lt;br /&gt;
// Extended functions table&lt;br /&gt;
funcEnable_t funcEnableTable[32];&lt;br /&gt;
funcWrite_t funcWriteTable[3];&lt;br /&gt;
funcRead_t funcReadTable[3];&lt;br /&gt;
&lt;br /&gt;
// Handle device initialization&lt;br /&gt;
void NEO16_Init()&lt;br /&gt;
{&lt;br /&gt;
	for (uint8 i = 0; i &amp;lt; 3; i++)&lt;br /&gt;
	{&lt;br /&gt;
		bankValue[i] = 0x0000;&lt;br /&gt;
		funcWriteTable[i] = NULL;&lt;br /&gt;
		funcReadTable[i] = NULL;		&lt;br /&gt;
	}&lt;br /&gt;
	for (uint8 i = 0; i &amp;lt; 32; i++)&lt;br /&gt;
		funcEnableTable[i] = NULL;&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; // Get the corresponding bank number&lt;br /&gt;
	if (bank &amp;gt; 2)&lt;br /&gt;
		return; // skip&lt;br /&gt;
&lt;br /&gt;
	if (funcWriteTable[bank] != NULL) // Check for bank write callback&lt;br /&gt;
	{&lt;br /&gt;
		funcWriteTable[bank](address, value);&lt;br /&gt;
	}&lt;br /&gt;
	else if ((address &amp;amp; 0x0001) &amp;amp;&amp;amp; (value &amp;amp; 0x80)) // Handle extended function&lt;br /&gt;
	{&lt;br /&gt;
		uint8 funcId = value &amp;amp; 0x3F; // Get function ID&lt;br /&gt;
		if (funcEnableTable[funcId] != NULL)&lt;br /&gt;
			funcEnableTable[funcId](value &amp;amp; 0x40, (address &amp;gt;&amp;gt; 1) &amp;amp; 0xFF); // Execute function specific code&lt;br /&gt;
	}&lt;br /&gt;
	else // Write to the given bank register&lt;br /&gt;
	{&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;
&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; // Get the corresponding bank number&lt;br /&gt;
	if (bank &amp;gt; 2)&lt;br /&gt;
		return 0xFF; // skip&lt;br /&gt;
&lt;br /&gt;
	if (funcReadTable[bank] != NULL) // Check for bank read callback&lt;br /&gt;
		return funcReadTable[bank](address);&lt;br /&gt;
	else&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;
=== Extension example ===&lt;br /&gt;
Here is a pseudo code in C to handle a SRAM extension for NEO mapper:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
uint8 sramSeg; // Current SRAM segment [0:15]&lt;br /&gt;
uint8 sramBank; // Current bank where SRAM is selected (0xFF if not selected)&lt;br /&gt;
uint8* sramData; // SRAM data (hardware specific)&lt;br /&gt;
&lt;br /&gt;
// Write to SRAM&lt;br /&gt;
void SRAM_Write(uint16 address, uint8 value)&lt;br /&gt;
{&lt;br /&gt;
	sramData[(sramSeg * 0x2000) + (address &amp;amp; 0x1FFF)] = value; // &lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// Read from SRAM&lt;br /&gt;
uint8 SRAM_Read(uint16 address)&lt;br /&gt;
{&lt;br /&gt;
	return sramData[(sramSeg * 0x2000) + (address &amp;amp; 0x1FFF)];	&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// Enable/disable SRAM feature&lt;br /&gt;
void SRAM_Enable(bool enable, uint8 param)&lt;br /&gt;
{&lt;br /&gt;
	if (sramBank != 0xFF) // Disable previous SRAM registration&lt;br /&gt;
	{&lt;br /&gt;
		if (funcWriteTable[sramBank] == SRAM_Write)&lt;br /&gt;
			funcWriteTable[sramBank] = NULL;&lt;br /&gt;
		if (funcReadTable[sramBank] == SRAM_Read)&lt;br /&gt;
			funcReadTable[sramBank] = NULL;&lt;br /&gt;
		sramBank = 0xFF;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	if (enable) // Enable a SRAM segment in the given bank&lt;br /&gt;
	{&lt;br /&gt;
		uint8 bank = param &amp;amp; 0x07; // Get bank number&lt;br /&gt;
		if (bank &amp;gt; 2)&lt;br /&gt;
			return; // skip (for NEO-16)&lt;br /&gt;
&lt;br /&gt;
		sramSeg = (param &amp;gt;&amp;gt; 4) &amp;amp; 0x0F; // SRAM segment number&lt;br /&gt;
		sramBank = bank;&lt;br /&gt;
		funcWriteTable[sramBank] = SRAM_Write; // Register SRAM callbacks&lt;br /&gt;
		funcReadTable[sramBank] = SRAM_Read;&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// Initialize SRAM feature&lt;br /&gt;
void SRAM_Init()&lt;br /&gt;
{&lt;br /&gt;
	sramBank = 0xFF;&lt;br /&gt;
	funcEnableTable[0x04] = SRAM_Enable; // Register to function 0x04 (SRAM/FRAM feature)&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Then, you just need to call &amp;lt;tt&amp;gt;SRAM_Init()&amp;lt;/tt&amp;gt; from &amp;lt;tt&amp;gt;NEO16_Init()&amp;lt;/tt&amp;gt; to register the extended feature.&lt;/div&gt;</summary>
		<author><name>Aoineko</name></author>	</entry>

	<entry>
		<id>https://aoineko.org/msxgl/index.php?title=NEO_mapper/Extension&amp;diff=3834</id>
		<title>NEO mapper/Extension</title>
		<link rel="alternate" type="text/html" href="https://aoineko.org/msxgl/index.php?title=NEO_mapper/Extension&amp;diff=3834"/>
				<updated>2026-04-13T21:26:50Z</updated>
		
		<summary type="html">&lt;p&gt;Aoineko: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{WARNING|This page is still in the proposal stage and should not yet be considered an official specification.}}&lt;br /&gt;
&lt;br /&gt;
Proposal for an extension to the [[NEO mapper]] format.&lt;br /&gt;
&lt;br /&gt;
== Specifications ==&lt;br /&gt;
&lt;br /&gt;
=== Principles ===&lt;br /&gt;
&lt;br /&gt;
Any write operation to the NEO mapper with data bit 7 set to 1 and address bit 0 set to 1 is considered an access to extended features. In that case, the mapper bank register is not modified.&lt;br /&gt;
&lt;br /&gt;
All other write operations should be considered normal access to the mapper's bank register.&lt;br /&gt;
&lt;br /&gt;
The data contains:&lt;br /&gt;
* The number of an extended function in the mapper&lt;br /&gt;
* A bit indicating whether the function should be enabled or disabled&lt;br /&gt;
&lt;br /&gt;
The address contains an 8-bit parameter to be passed to the function.&lt;br /&gt;
{|&lt;br /&gt;
|-&lt;br /&gt;
|&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ ADDRESS&lt;br /&gt;
|-&lt;br /&gt;
! 15 || 14 || 13 || 12 || 11 || 10 || 9 || 8 || 7 || 6 || 5 || 4 || 3 || 2 || 1 || 0&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#BBB;&amp;quot; colspan=&amp;quot;2&amp;quot;| Page&lt;br /&gt;
|style=&amp;quot;background-color:#BBB;&amp;quot; colspan=&amp;quot;3&amp;quot;| Bank&lt;br /&gt;
|style=&amp;quot;background-color:#BBB;&amp;quot;| 0&lt;br /&gt;
|style=&amp;quot;background-color:#BBB;&amp;quot;| 0&lt;br /&gt;
|style=&amp;quot;background-color:#AAF;&amp;quot; colspan=&amp;quot;8&amp;quot;| Parameter&lt;br /&gt;
|style=&amp;quot;background-color:#FAA;&amp;quot;| 1&lt;br /&gt;
|}&lt;br /&gt;
|&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ DATA&lt;br /&gt;
|-&lt;br /&gt;
! 7 || 6 || 5 || 4 || 3 || 2 || 1 || 0&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FAA;&amp;quot;| 1&lt;br /&gt;
|style=&amp;quot;background-color:#AAF;&amp;quot;| A&lt;br /&gt;
|style=&amp;quot;background-color:#BBB;&amp;quot;| 0&lt;br /&gt;
|style=&amp;quot;background-color:#AAF;&amp;quot; colspan=&amp;quot;5&amp;quot;| Function&lt;br /&gt;
|}&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Functions ===&lt;br /&gt;
==== 0x00: Cartridge information ====&lt;br /&gt;
When activated, any read access to the given bank will return the cartridge information (8 KB, mirrored on NEO-16).&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ PARAMETER&lt;br /&gt;
|-&lt;br /&gt;
! 8 || 7 || 6 || 5 || 4 || 3 || 2 || 1&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#BBB;&amp;quot;| 0&lt;br /&gt;
|style=&amp;quot;background-color:#BBB;&amp;quot;| 0&lt;br /&gt;
|style=&amp;quot;background-color:#BBB;&amp;quot;| 0&lt;br /&gt;
|style=&amp;quot;background-color:#BBB;&amp;quot;| 0&lt;br /&gt;
|style=&amp;quot;background-color:#BBB;&amp;quot;| 0&lt;br /&gt;
|style=&amp;quot;background-color:#AAF;&amp;quot; colspan=&amp;quot;5&amp;quot;| ROM Bank&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Examples:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Action || Pseudo-code&lt;br /&gt;
|-&lt;br /&gt;
| Activate information in bank 2 of NEO-16 || &amp;lt;tt&amp;gt;[0x7005] = 0xC0&amp;lt;/tt&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Read information (offset +5) from bank 2 of NEO-16 || &amp;lt;tt&amp;gt;BankSize = [0x8005]&amp;lt;/tt&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Disactivate information in bank 2 of NEO-16 || &amp;lt;tt&amp;gt;[0x7005] = 0x80&amp;lt;/tt&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== 0x01: Cartridge configuration ====&lt;br /&gt;
&lt;br /&gt;
==== 0x04: Activate SRAM/FRAM ====&lt;br /&gt;
When activated, any read/write access to the specified bank (defined in the parameter) is redirected to the selected segment of the SRAM/FRAM.&lt;br /&gt;
&lt;br /&gt;
SRAM/FRAM is accessed through 8 KB segments (on the NEO-16, the segment is mirrored).&lt;br /&gt;
&lt;br /&gt;
Up to 16 segments can be accessed, for a total capacity of 128 KB.&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ PARAMETER&lt;br /&gt;
|-&lt;br /&gt;
! 8 || 7 || 6 || 5 || 4 || 3 || 2 || 1&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#AAF;&amp;quot; colspan=&amp;quot;4&amp;quot;| RAM Segment&lt;br /&gt;
|style=&amp;quot;background-color:#BBB;&amp;quot;| 0&lt;br /&gt;
|style=&amp;quot;background-color:#AAF;&amp;quot; colspan=&amp;quot;5&amp;quot;| ROM Bank&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== 0x05: Activate device ====&lt;br /&gt;
Activate or disactivate the given device.&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ PARAMETER&lt;br /&gt;
|-&lt;br /&gt;
! 8 || 7 || 6 || 5 || 4 || 3 || 2 || 1&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#BBB;&amp;quot;| 0&lt;br /&gt;
|style=&amp;quot;background-color:#BBB;&amp;quot;| 0&lt;br /&gt;
|style=&amp;quot;background-color:#BBB;&amp;quot;| 0&lt;br /&gt;
|style=&amp;quot;background-color:#AAF;&amp;quot; colspan=&amp;quot;5&amp;quot;| Device&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Devices:&lt;br /&gt;
* &amp;lt;tt&amp;gt;00&amp;lt;/tt&amp;gt;: MSX-Music (OPLL)&lt;br /&gt;
* &amp;lt;tt&amp;gt;01&amp;lt;/tt&amp;gt;: MSX-Audio&lt;br /&gt;
* &amp;lt;tt&amp;gt;02&amp;lt;/tt&amp;gt;: SCC&lt;br /&gt;
* &amp;lt;tt&amp;gt;03&amp;lt;/tt&amp;gt;: SCC+&lt;br /&gt;
* &amp;lt;tt&amp;gt;04&amp;lt;/tt&amp;gt;: 2nd PSG (port 10h)&lt;br /&gt;
* &amp;lt;tt&amp;gt;05&amp;lt;/tt&amp;gt;: Darky (2 x ePSG)&lt;br /&gt;
* &amp;lt;tt&amp;gt;06&amp;lt;/tt&amp;gt;: Darky Jr. (2 x PSG)&lt;br /&gt;
* &amp;lt;tt&amp;gt;08&amp;lt;/tt&amp;gt;: OPM (SFK-01, SFG-01 et SFG-05 ver.1)&lt;br /&gt;
* &amp;lt;tt&amp;gt;09&amp;lt;/tt&amp;gt;: OPP (SFG-05 ver.2)&lt;br /&gt;
* &amp;lt;tt&amp;gt;12&amp;lt;/tt&amp;gt;: OPL4&lt;br /&gt;
* &amp;lt;tt&amp;gt;15&amp;lt;/tt&amp;gt;: SAM2695&lt;br /&gt;
&lt;br /&gt;
== Appendix ==&lt;br /&gt;
=== Programmable processor and emulation ===&lt;br /&gt;
Here is a pseudo code in C to handle NEO mappers extension for programmable processor based cartridges or for emulators:&lt;br /&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;
// Extended function prototypes&lt;br /&gt;
typedef void (*funcEnable_t)(bool, uint8);&lt;br /&gt;
typedef void (*funcWrite_t)(uint16, uint8);&lt;br /&gt;
typedef uint8 (*funcRead_t)(uint16);&lt;br /&gt;
// Extended functions table&lt;br /&gt;
funcEnable_t funcEnableTable[32];&lt;br /&gt;
funcWrite_t funcWriteTable[3];&lt;br /&gt;
funcRead_t funcReadTable[3];&lt;br /&gt;
&lt;br /&gt;
// Handle device initialization&lt;br /&gt;
void NEO16_Init()&lt;br /&gt;
{&lt;br /&gt;
	for (uint8 i = 0; i &amp;lt; 3; i++)&lt;br /&gt;
	{&lt;br /&gt;
		bankValue[i] = 0x0000;&lt;br /&gt;
		funcWriteTable[i] = NULL;&lt;br /&gt;
		funcReadTable[i] = NULL;		&lt;br /&gt;
	}&lt;br /&gt;
	for (uint8 i = 0; i &amp;lt; 32; i++)&lt;br /&gt;
		funcEnableTable[i] = NULL;&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; // Get the corresponding bank number&lt;br /&gt;
	if (bank &amp;gt; 2)&lt;br /&gt;
		return; // skip&lt;br /&gt;
&lt;br /&gt;
	if (funcWriteTable[bank] != NULL) // Check for bank write callback&lt;br /&gt;
	{&lt;br /&gt;
		funcWriteTable[bank](address, value);&lt;br /&gt;
	}&lt;br /&gt;
	else if ((address &amp;amp; 0x0001) &amp;amp;&amp;amp; (value &amp;amp; 0x80)) // Handle extended function&lt;br /&gt;
	{&lt;br /&gt;
		uint8 funcId = value &amp;amp; 0x3F; // Get function ID&lt;br /&gt;
		if (funcEnableTable[funcId] != NULL)&lt;br /&gt;
			funcEnableTable[funcId](value &amp;amp; 0x40, (address &amp;gt;&amp;gt; 1) &amp;amp; 0xFF); // Execute function specific code&lt;br /&gt;
	}&lt;br /&gt;
	else // Write to the given bank register&lt;br /&gt;
	{&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;
&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; // Get the corresponding bank number&lt;br /&gt;
	if (bank &amp;gt; 2)&lt;br /&gt;
		return 0xFF; // skip&lt;br /&gt;
&lt;br /&gt;
	if (funcReadTable[bank] != NULL) // Check for bank read callback&lt;br /&gt;
		return funcReadTable[bank](address);&lt;br /&gt;
	else&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;
=== Extension example ===&lt;br /&gt;
Here is a pseudo code in C to handle a SRAM extension for NEO mapper:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
uint8 sramSeg; // Current SRAM segment [0:15]&lt;br /&gt;
uint8 sramBank; // Current bank where SRAM is selected (0xFF if not selected)&lt;br /&gt;
uint8* sramData; // SRAM data (hardware specific)&lt;br /&gt;
&lt;br /&gt;
// Write to SRAM&lt;br /&gt;
void SRAM_Write(uint16 address, uint8 value)&lt;br /&gt;
{&lt;br /&gt;
	sramData[(sramSeg * 0x2000) + (address &amp;amp; 0x1FFF)] = value; // &lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// Read from SRAM&lt;br /&gt;
uint8 SRAM_Read(uint16 address)&lt;br /&gt;
{&lt;br /&gt;
	return sramData[(sramSeg * 0x2000) + (address &amp;amp; 0x1FFF)];	&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// Enable/disable SRAM feature&lt;br /&gt;
void SRAM_Enable(bool enable, uint8 param)&lt;br /&gt;
{&lt;br /&gt;
	if (sramBank != 0xFF) // Disable previous SRAM registration&lt;br /&gt;
	{&lt;br /&gt;
		if (funcWriteTable[sramBank] == SRAM_Write)&lt;br /&gt;
			funcWriteTable[sramBank] = NULL;&lt;br /&gt;
		if (funcReadTable[sramBank] == SRAM_Read)&lt;br /&gt;
			funcReadTable[sramBank] = NULL;&lt;br /&gt;
		sramBank = 0xFF;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	if (enable) // Enable a SRAM segment in the given bank&lt;br /&gt;
	{&lt;br /&gt;
		uint8 bank = param &amp;amp; 0x07; // Get bank number&lt;br /&gt;
		if (bank &amp;gt; 2)&lt;br /&gt;
			return; // skip (for NEO-16)&lt;br /&gt;
&lt;br /&gt;
		sramSeg = (param &amp;gt;&amp;gt; 4) &amp;amp; 0x0F; // SRAM segment number&lt;br /&gt;
		sramBank = bank;&lt;br /&gt;
		funcWriteTable[sramBank] = SRAM_Write; // Register SRAM callbacks&lt;br /&gt;
		funcReadTable[sramBank] = SRAM_Read;&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// Initialize SRAM feature&lt;br /&gt;
void SRAM_Init()&lt;br /&gt;
{&lt;br /&gt;
	sramBank = 0xFF;&lt;br /&gt;
	funcEnableTable[0x04] = SRAM_Enable; // Register to function 0x04 (SRAM/FRAM feature)&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Then, you just need to call &amp;lt;tt&amp;gt;SRAM_Init()&amp;lt;/tt&amp;gt; from &amp;lt;tt&amp;gt;NEO16_Init()&amp;lt;/tt&amp;gt; to register the feature.&lt;/div&gt;</summary>
		<author><name>Aoineko</name></author>	</entry>

	<entry>
		<id>https://aoineko.org/msxgl/index.php?title=NEO_mapper/Extension&amp;diff=3833</id>
		<title>NEO mapper/Extension</title>
		<link rel="alternate" type="text/html" href="https://aoineko.org/msxgl/index.php?title=NEO_mapper/Extension&amp;diff=3833"/>
				<updated>2026-04-13T21:26:10Z</updated>
		
		<summary type="html">&lt;p&gt;Aoineko: /* Extension example */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{WARNING|This page is still in the proposal stage and should not yet be considered an official specification.}}&lt;br /&gt;
&lt;br /&gt;
Proposal for an extension to the [[NEO mapper]] format.&lt;br /&gt;
&lt;br /&gt;
== Specifications ==&lt;br /&gt;
&lt;br /&gt;
=== Principles ===&lt;br /&gt;
&lt;br /&gt;
Any write operation to the NEO mapper with data bit 7 set to 1 and address bit 0 set to 1 is considered an access to extended features. In that case, the mapper bank register is not modified.&lt;br /&gt;
&lt;br /&gt;
All other write operations should be considered normal access to the mapper's bank register.&lt;br /&gt;
&lt;br /&gt;
The data contains:&lt;br /&gt;
* The number of an extended function in the mapper&lt;br /&gt;
* A bit indicating whether the function should be enabled or disabled&lt;br /&gt;
&lt;br /&gt;
The address contains an 8-bit parameter to be passed to the function.&lt;br /&gt;
{|&lt;br /&gt;
|-&lt;br /&gt;
|&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ ADDRESS&lt;br /&gt;
|-&lt;br /&gt;
! 15 || 14 || 13 || 12 || 11 || 10 || 9 || 8 || 7 || 6 || 5 || 4 || 3 || 2 || 1 || 0&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#BBB;&amp;quot; colspan=&amp;quot;2&amp;quot;| Page&lt;br /&gt;
|style=&amp;quot;background-color:#BBB;&amp;quot; colspan=&amp;quot;3&amp;quot;| Bank&lt;br /&gt;
|style=&amp;quot;background-color:#BBB;&amp;quot;| 0&lt;br /&gt;
|style=&amp;quot;background-color:#BBB;&amp;quot;| 0&lt;br /&gt;
|style=&amp;quot;background-color:#AAF;&amp;quot; colspan=&amp;quot;8&amp;quot;| Parameter&lt;br /&gt;
|style=&amp;quot;background-color:#FAA;&amp;quot;| 1&lt;br /&gt;
|}&lt;br /&gt;
|&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ DATA&lt;br /&gt;
|-&lt;br /&gt;
! 7 || 6 || 5 || 4 || 3 || 2 || 1 || 0&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FAA;&amp;quot;| 1&lt;br /&gt;
|style=&amp;quot;background-color:#AAF;&amp;quot;| A&lt;br /&gt;
|style=&amp;quot;background-color:#BBB;&amp;quot;| 0&lt;br /&gt;
|style=&amp;quot;background-color:#AAF;&amp;quot; colspan=&amp;quot;5&amp;quot;| Function&lt;br /&gt;
|}&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Functions ===&lt;br /&gt;
==== 0x00: Cartridge information ====&lt;br /&gt;
When activated, any read access to the given bank will return the cartridge information (8 KB, mirrored on NEO-16).&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ PARAMETER&lt;br /&gt;
|-&lt;br /&gt;
! 8 || 7 || 6 || 5 || 4 || 3 || 2 || 1&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#BBB;&amp;quot;| 0&lt;br /&gt;
|style=&amp;quot;background-color:#BBB;&amp;quot;| 0&lt;br /&gt;
|style=&amp;quot;background-color:#BBB;&amp;quot;| 0&lt;br /&gt;
|style=&amp;quot;background-color:#BBB;&amp;quot;| 0&lt;br /&gt;
|style=&amp;quot;background-color:#BBB;&amp;quot;| 0&lt;br /&gt;
|style=&amp;quot;background-color:#AAF;&amp;quot; colspan=&amp;quot;5&amp;quot;| ROM Bank&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Examples:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Action || Pseudo-code&lt;br /&gt;
|-&lt;br /&gt;
| Activate information in bank 2 of NEO-16 || &amp;lt;tt&amp;gt;[0x7005] = 0xC0&amp;lt;/tt&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Read information (offset +5) from bank 2 of NEO-16 || &amp;lt;tt&amp;gt;BankSize = [0x8005]&amp;lt;/tt&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Disactivate information in bank 2 of NEO-16 || &amp;lt;tt&amp;gt;[0x7005] = 0x80&amp;lt;/tt&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== 0x01: Cartridge configuration ====&lt;br /&gt;
&lt;br /&gt;
==== 0x04: Activate SRAM/FRAM ====&lt;br /&gt;
When activated, any read/write access to the specified bank (defined in the parameter) is redirected to the selected segment of the SRAM/FRAM.&lt;br /&gt;
&lt;br /&gt;
SRAM/FRAM is accessed through 8 KB segments (on the NEO-16, the segment is mirrored).&lt;br /&gt;
&lt;br /&gt;
Up to 16 segments can be accessed, for a total capacity of 128 KB.&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ PARAMETER&lt;br /&gt;
|-&lt;br /&gt;
! 8 || 7 || 6 || 5 || 4 || 3 || 2 || 1&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#AAF;&amp;quot; colspan=&amp;quot;4&amp;quot;| RAM Segment&lt;br /&gt;
|style=&amp;quot;background-color:#BBB;&amp;quot;| 0&lt;br /&gt;
|style=&amp;quot;background-color:#AAF;&amp;quot; colspan=&amp;quot;5&amp;quot;| ROM Bank&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== 0x05: Activate device ====&lt;br /&gt;
Activate or disactivate the given device.&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ PARAMETER&lt;br /&gt;
|-&lt;br /&gt;
! 8 || 7 || 6 || 5 || 4 || 3 || 2 || 1&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#BBB;&amp;quot;| 0&lt;br /&gt;
|style=&amp;quot;background-color:#BBB;&amp;quot;| 0&lt;br /&gt;
|style=&amp;quot;background-color:#BBB;&amp;quot;| 0&lt;br /&gt;
|style=&amp;quot;background-color:#AAF;&amp;quot; colspan=&amp;quot;5&amp;quot;| Device&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Devices:&lt;br /&gt;
* &amp;lt;tt&amp;gt;00&amp;lt;/tt&amp;gt;: MSX-Music (OPLL)&lt;br /&gt;
* &amp;lt;tt&amp;gt;01&amp;lt;/tt&amp;gt;: MSX-Audio&lt;br /&gt;
* &amp;lt;tt&amp;gt;02&amp;lt;/tt&amp;gt;: SCC&lt;br /&gt;
* &amp;lt;tt&amp;gt;03&amp;lt;/tt&amp;gt;: SCC+&lt;br /&gt;
* &amp;lt;tt&amp;gt;04&amp;lt;/tt&amp;gt;: 2nd PSG (port 10h)&lt;br /&gt;
* &amp;lt;tt&amp;gt;05&amp;lt;/tt&amp;gt;: Darky (2 x ePSG)&lt;br /&gt;
* &amp;lt;tt&amp;gt;06&amp;lt;/tt&amp;gt;: Darky Jr. (2 x PSG)&lt;br /&gt;
* &amp;lt;tt&amp;gt;08&amp;lt;/tt&amp;gt;: OPM (SFK-01, SFG-01 et SFG-05 ver.1)&lt;br /&gt;
* &amp;lt;tt&amp;gt;09&amp;lt;/tt&amp;gt;: OPP (SFG-05 ver.2)&lt;br /&gt;
* &amp;lt;tt&amp;gt;12&amp;lt;/tt&amp;gt;: OPL4&lt;br /&gt;
* &amp;lt;tt&amp;gt;15&amp;lt;/tt&amp;gt;: SAM2695&lt;br /&gt;
&lt;br /&gt;
== Appendix ==&lt;br /&gt;
=== Programmable processor and emulation ===&lt;br /&gt;
Here is a pseudo code in C to handle NEO mappers extension for programmable processor based cartridges or for emulators:&lt;br /&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;
// Extended function prototypes&lt;br /&gt;
typedef void (*funcEnable_t)(bool, uint8);&lt;br /&gt;
typedef void (*funcWrite_t)(uint16, uint8);&lt;br /&gt;
typedef uint8 (*funcRead_t)(uint16);&lt;br /&gt;
// Extended functions table&lt;br /&gt;
funcEnable_t funcEnableTable[32];&lt;br /&gt;
funcWrite_t funcWriteTable[3];&lt;br /&gt;
funcRead_t funcReadTable[3];&lt;br /&gt;
&lt;br /&gt;
// Handle device initialization&lt;br /&gt;
void NEO16_Init()&lt;br /&gt;
{&lt;br /&gt;
	for (uint8 i = 0; i &amp;lt; 3; i++)&lt;br /&gt;
	{&lt;br /&gt;
		bankValue[i] = 0x0000;&lt;br /&gt;
		funcWriteTable[i] = NULL;&lt;br /&gt;
		funcReadTable[i] = NULL;		&lt;br /&gt;
	}&lt;br /&gt;
	for (uint8 i = 0; i &amp;lt; 32; i++)&lt;br /&gt;
		funcEnableTable[i] = NULL;&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; // Get the corresponding bank number&lt;br /&gt;
	if (bank &amp;gt; 2)&lt;br /&gt;
		return; // skip&lt;br /&gt;
&lt;br /&gt;
	if (funcWriteTable[bank] != NULL) // Check for bank write callback&lt;br /&gt;
	{&lt;br /&gt;
		funcWriteTable[bank](address, value);&lt;br /&gt;
	}&lt;br /&gt;
	else if ((address &amp;amp; 0x0001) &amp;amp;&amp;amp; (value &amp;amp; 0x80)) // Handle extended function&lt;br /&gt;
	{&lt;br /&gt;
		uint8 funcId = value &amp;amp; 0x3F; // Get function ID&lt;br /&gt;
		if (funcEnableTable[funcId] != NULL)&lt;br /&gt;
			funcEnableTable[funcId](value &amp;amp; 0x40, (address &amp;gt;&amp;gt; 1) &amp;amp; 0xFF); // Execute function specific code&lt;br /&gt;
	}&lt;br /&gt;
	else // Write to the given bank register&lt;br /&gt;
	{&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;
&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; // Get the corresponding bank number&lt;br /&gt;
	if (bank &amp;gt; 2)&lt;br /&gt;
		return 0xFF; // skip&lt;br /&gt;
&lt;br /&gt;
	if (funcReadTable[bank] != NULL) // Check for bank read callback&lt;br /&gt;
		return funcReadTable[bank](address);&lt;br /&gt;
	else&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;
=== Extension example ===&lt;br /&gt;
Here is a pseudo code in C to handle a SRAM extension for NEO mapper:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
uint8 sramSeg; // Current SRAM segment [0:15]&lt;br /&gt;
uint8 sramBank; // Current bank where SRAM is selected (0xFF if not selected)&lt;br /&gt;
uint8* sramData; // SRAM data (hardware specific)&lt;br /&gt;
&lt;br /&gt;
// Write to SRAM&lt;br /&gt;
void SRAM_Write(uint16 address, uint8 value)&lt;br /&gt;
{&lt;br /&gt;
	sramData[(sramSeg * 0x2000) + (address &amp;amp; 0x1FFF)] = value; // &lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// Read from SRAM&lt;br /&gt;
uint8 SRAM_Read(uint16 address)&lt;br /&gt;
{&lt;br /&gt;
	return sramData[(sramSeg * 0x2000) + (address &amp;amp; 0x1FFF)];	&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// Enable/disable SRAM feature&lt;br /&gt;
void SRAM_Enable(bool enable, uint8 param)&lt;br /&gt;
{&lt;br /&gt;
	if (sramBank != 0xFF) // Disable previous SRAM registration&lt;br /&gt;
	{&lt;br /&gt;
		if (funcWriteTable[sramBank] == SRAM_Write)&lt;br /&gt;
			funcWriteTable[sramBank] = NULL;&lt;br /&gt;
		if (funcReadTable[sramBank] == SRAM_Read)&lt;br /&gt;
			funcReadTable[sramBank] = NULL;&lt;br /&gt;
		sramBank = 0xFF;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	if (enable) // Enable a SRAM segment in the given bank&lt;br /&gt;
	{&lt;br /&gt;
		uint8 bank = param &amp;amp; 0x07; // Get bank number&lt;br /&gt;
		if (bank &amp;gt; 2)&lt;br /&gt;
			return; // skip (for NEO-16)&lt;br /&gt;
&lt;br /&gt;
		sramSeg = (param &amp;gt;&amp;gt; 4) &amp;amp; 0x0F; // SRAM segment number&lt;br /&gt;
		sramBank = bank;&lt;br /&gt;
		funcWriteTable[sramBank] = SRAM_Write; // Register SRAM callbacks&lt;br /&gt;
		funcReadTable[sramBank] = SRAM_Read;&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// Initialize SRAM feature&lt;br /&gt;
void SRAM_Init()&lt;br /&gt;
{&lt;br /&gt;
	sramBank = 0xFF;&lt;br /&gt;
	funcTab[0x04] = SRAM_Enable; // Register to function 0x04 (SRAM/FRAM feature)&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Then, you just need to call &amp;lt;tt&amp;gt;SRAM_Init()&amp;lt;/tt&amp;gt; from &amp;lt;tt&amp;gt;NEO16_Init()&amp;lt;/tt&amp;gt; to register the feature.&lt;/div&gt;</summary>
		<author><name>Aoineko</name></author>	</entry>

	<entry>
		<id>https://aoineko.org/msxgl/index.php?title=NEO_mapper/Extension&amp;diff=3832</id>
		<title>NEO mapper/Extension</title>
		<link rel="alternate" type="text/html" href="https://aoineko.org/msxgl/index.php?title=NEO_mapper/Extension&amp;diff=3832"/>
				<updated>2026-04-13T21:23:56Z</updated>
		
		<summary type="html">&lt;p&gt;Aoineko: /* Programmable processor and emulation */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{WARNING|This page is still in the proposal stage and should not yet be considered an official specification.}}&lt;br /&gt;
&lt;br /&gt;
Proposal for an extension to the [[NEO mapper]] format.&lt;br /&gt;
&lt;br /&gt;
== Specifications ==&lt;br /&gt;
&lt;br /&gt;
=== Principles ===&lt;br /&gt;
&lt;br /&gt;
Any write operation to the NEO mapper with data bit 7 set to 1 and address bit 0 set to 1 is considered an access to extended features. In that case, the mapper bank register is not modified.&lt;br /&gt;
&lt;br /&gt;
All other write operations should be considered normal access to the mapper's bank register.&lt;br /&gt;
&lt;br /&gt;
The data contains:&lt;br /&gt;
* The number of an extended function in the mapper&lt;br /&gt;
* A bit indicating whether the function should be enabled or disabled&lt;br /&gt;
&lt;br /&gt;
The address contains an 8-bit parameter to be passed to the function.&lt;br /&gt;
{|&lt;br /&gt;
|-&lt;br /&gt;
|&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ ADDRESS&lt;br /&gt;
|-&lt;br /&gt;
! 15 || 14 || 13 || 12 || 11 || 10 || 9 || 8 || 7 || 6 || 5 || 4 || 3 || 2 || 1 || 0&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#BBB;&amp;quot; colspan=&amp;quot;2&amp;quot;| Page&lt;br /&gt;
|style=&amp;quot;background-color:#BBB;&amp;quot; colspan=&amp;quot;3&amp;quot;| Bank&lt;br /&gt;
|style=&amp;quot;background-color:#BBB;&amp;quot;| 0&lt;br /&gt;
|style=&amp;quot;background-color:#BBB;&amp;quot;| 0&lt;br /&gt;
|style=&amp;quot;background-color:#AAF;&amp;quot; colspan=&amp;quot;8&amp;quot;| Parameter&lt;br /&gt;
|style=&amp;quot;background-color:#FAA;&amp;quot;| 1&lt;br /&gt;
|}&lt;br /&gt;
|&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ DATA&lt;br /&gt;
|-&lt;br /&gt;
! 7 || 6 || 5 || 4 || 3 || 2 || 1 || 0&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FAA;&amp;quot;| 1&lt;br /&gt;
|style=&amp;quot;background-color:#AAF;&amp;quot;| A&lt;br /&gt;
|style=&amp;quot;background-color:#BBB;&amp;quot;| 0&lt;br /&gt;
|style=&amp;quot;background-color:#AAF;&amp;quot; colspan=&amp;quot;5&amp;quot;| Function&lt;br /&gt;
|}&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Functions ===&lt;br /&gt;
==== 0x00: Cartridge information ====&lt;br /&gt;
When activated, any read access to the given bank will return the cartridge information (8 KB, mirrored on NEO-16).&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ PARAMETER&lt;br /&gt;
|-&lt;br /&gt;
! 8 || 7 || 6 || 5 || 4 || 3 || 2 || 1&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#BBB;&amp;quot;| 0&lt;br /&gt;
|style=&amp;quot;background-color:#BBB;&amp;quot;| 0&lt;br /&gt;
|style=&amp;quot;background-color:#BBB;&amp;quot;| 0&lt;br /&gt;
|style=&amp;quot;background-color:#BBB;&amp;quot;| 0&lt;br /&gt;
|style=&amp;quot;background-color:#BBB;&amp;quot;| 0&lt;br /&gt;
|style=&amp;quot;background-color:#AAF;&amp;quot; colspan=&amp;quot;5&amp;quot;| ROM Bank&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Examples:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Action || Pseudo-code&lt;br /&gt;
|-&lt;br /&gt;
| Activate information in bank 2 of NEO-16 || &amp;lt;tt&amp;gt;[0x7005] = 0xC0&amp;lt;/tt&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Read information (offset +5) from bank 2 of NEO-16 || &amp;lt;tt&amp;gt;BankSize = [0x8005]&amp;lt;/tt&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Disactivate information in bank 2 of NEO-16 || &amp;lt;tt&amp;gt;[0x7005] = 0x80&amp;lt;/tt&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== 0x01: Cartridge configuration ====&lt;br /&gt;
&lt;br /&gt;
==== 0x04: Activate SRAM/FRAM ====&lt;br /&gt;
When activated, any read/write access to the specified bank (defined in the parameter) is redirected to the selected segment of the SRAM/FRAM.&lt;br /&gt;
&lt;br /&gt;
SRAM/FRAM is accessed through 8 KB segments (on the NEO-16, the segment is mirrored).&lt;br /&gt;
&lt;br /&gt;
Up to 16 segments can be accessed, for a total capacity of 128 KB.&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ PARAMETER&lt;br /&gt;
|-&lt;br /&gt;
! 8 || 7 || 6 || 5 || 4 || 3 || 2 || 1&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#AAF;&amp;quot; colspan=&amp;quot;4&amp;quot;| RAM Segment&lt;br /&gt;
|style=&amp;quot;background-color:#BBB;&amp;quot;| 0&lt;br /&gt;
|style=&amp;quot;background-color:#AAF;&amp;quot; colspan=&amp;quot;5&amp;quot;| ROM Bank&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== 0x05: Activate device ====&lt;br /&gt;
Activate or disactivate the given device.&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ PARAMETER&lt;br /&gt;
|-&lt;br /&gt;
! 8 || 7 || 6 || 5 || 4 || 3 || 2 || 1&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#BBB;&amp;quot;| 0&lt;br /&gt;
|style=&amp;quot;background-color:#BBB;&amp;quot;| 0&lt;br /&gt;
|style=&amp;quot;background-color:#BBB;&amp;quot;| 0&lt;br /&gt;
|style=&amp;quot;background-color:#AAF;&amp;quot; colspan=&amp;quot;5&amp;quot;| Device&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Devices:&lt;br /&gt;
* &amp;lt;tt&amp;gt;00&amp;lt;/tt&amp;gt;: MSX-Music (OPLL)&lt;br /&gt;
* &amp;lt;tt&amp;gt;01&amp;lt;/tt&amp;gt;: MSX-Audio&lt;br /&gt;
* &amp;lt;tt&amp;gt;02&amp;lt;/tt&amp;gt;: SCC&lt;br /&gt;
* &amp;lt;tt&amp;gt;03&amp;lt;/tt&amp;gt;: SCC+&lt;br /&gt;
* &amp;lt;tt&amp;gt;04&amp;lt;/tt&amp;gt;: 2nd PSG (port 10h)&lt;br /&gt;
* &amp;lt;tt&amp;gt;05&amp;lt;/tt&amp;gt;: Darky (2 x ePSG)&lt;br /&gt;
* &amp;lt;tt&amp;gt;06&amp;lt;/tt&amp;gt;: Darky Jr. (2 x PSG)&lt;br /&gt;
* &amp;lt;tt&amp;gt;08&amp;lt;/tt&amp;gt;: OPM (SFK-01, SFG-01 et SFG-05 ver.1)&lt;br /&gt;
* &amp;lt;tt&amp;gt;09&amp;lt;/tt&amp;gt;: OPP (SFG-05 ver.2)&lt;br /&gt;
* &amp;lt;tt&amp;gt;12&amp;lt;/tt&amp;gt;: OPL4&lt;br /&gt;
* &amp;lt;tt&amp;gt;15&amp;lt;/tt&amp;gt;: SAM2695&lt;br /&gt;
&lt;br /&gt;
== Appendix ==&lt;br /&gt;
=== Programmable processor and emulation ===&lt;br /&gt;
Here is a pseudo code in C to handle NEO mappers extension for programmable processor based cartridges or for emulators:&lt;br /&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;
// Extended function prototypes&lt;br /&gt;
typedef void (*funcEnable_t)(bool, uint8);&lt;br /&gt;
typedef void (*funcWrite_t)(uint16, uint8);&lt;br /&gt;
typedef uint8 (*funcRead_t)(uint16);&lt;br /&gt;
// Extended functions table&lt;br /&gt;
funcEnable_t funcEnableTable[32];&lt;br /&gt;
funcWrite_t funcWriteTable[3];&lt;br /&gt;
funcRead_t funcReadTable[3];&lt;br /&gt;
&lt;br /&gt;
// Handle device initialization&lt;br /&gt;
void NEO16_Init()&lt;br /&gt;
{&lt;br /&gt;
	for (uint8 i = 0; i &amp;lt; 3; i++)&lt;br /&gt;
	{&lt;br /&gt;
		bankValue[i] = 0x0000;&lt;br /&gt;
		funcWriteTable[i] = NULL;&lt;br /&gt;
		funcReadTable[i] = NULL;		&lt;br /&gt;
	}&lt;br /&gt;
	for (uint8 i = 0; i &amp;lt; 32; i++)&lt;br /&gt;
		funcEnableTable[i] = NULL;&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; // Get the corresponding bank number&lt;br /&gt;
	if (bank &amp;gt; 2)&lt;br /&gt;
		return; // skip&lt;br /&gt;
&lt;br /&gt;
	if (funcWriteTable[bank] != NULL) // Check for bank write callback&lt;br /&gt;
	{&lt;br /&gt;
		funcWriteTable[bank](address, value);&lt;br /&gt;
	}&lt;br /&gt;
	else if ((address &amp;amp; 0x0001) &amp;amp;&amp;amp; (value &amp;amp; 0x80)) // Handle extended function&lt;br /&gt;
	{&lt;br /&gt;
		uint8 funcId = value &amp;amp; 0x3F; // Get function ID&lt;br /&gt;
		if (funcEnableTable[funcId] != NULL)&lt;br /&gt;
			funcEnableTable[funcId](value &amp;amp; 0x40, (address &amp;gt;&amp;gt; 1) &amp;amp; 0xFF); // Execute function specific code&lt;br /&gt;
	}&lt;br /&gt;
	else // Write to the given bank register&lt;br /&gt;
	{&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;
&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; // Get the corresponding bank number&lt;br /&gt;
	if (bank &amp;gt; 2)&lt;br /&gt;
		return 0xFF; // skip&lt;br /&gt;
&lt;br /&gt;
	if (funcReadTable[bank] != NULL) // Check for bank read callback&lt;br /&gt;
		return funcReadTable[bank](address);&lt;br /&gt;
	else&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;
=== Extension example ===&lt;br /&gt;
Here is a pseudo code in C to handle a SRAM extension for NEO mapper:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
uint8 sramSeg; // Current SRAM segment [0:15]&lt;br /&gt;
uint8 sramBank; // Current bank where SRAM is selected (0xFF if not selected)&lt;br /&gt;
uint8* sramData; // SRAM data (hardware specific)&lt;br /&gt;
&lt;br /&gt;
// Write to SRAM&lt;br /&gt;
void SRAM_Write(uint16 address, uint8 value)&lt;br /&gt;
{&lt;br /&gt;
	sramData[(sramSeg * 0x2000) + (address &amp;amp; 0x1FFF)] = value; // &lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// Read from SRAM&lt;br /&gt;
uint8 SRAM_read(uint16 address)&lt;br /&gt;
{&lt;br /&gt;
	return sramData[(sramSeg * 0x2000) + (address &amp;amp; 0x1FFF)];	&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// Enable/disable SRAM feature&lt;br /&gt;
void SRAM_Enable(bool enable, uint8 param)&lt;br /&gt;
{&lt;br /&gt;
	if (sramBank != 0xFF) // Disable previous SRAM registration&lt;br /&gt;
	{&lt;br /&gt;
		if (funcWriteTable[sramBank] == SRAM_Write)&lt;br /&gt;
			funcWriteTable[sramBank] = NULL;&lt;br /&gt;
		if (funcReadTable[sramBank] == SRAM_Read)&lt;br /&gt;
			funcReadTable[sramBank] = NULL;&lt;br /&gt;
		sramBank = 0xFF;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	if (enable) // Enable a SRAM segment in the given bank&lt;br /&gt;
	{&lt;br /&gt;
		uint8 bank = param &amp;amp; 0x07; // Get bank number&lt;br /&gt;
		if (bank &amp;gt; 2)&lt;br /&gt;
			return; // skip (for NEO-16)&lt;br /&gt;
&lt;br /&gt;
		sramSeg = (param &amp;gt;&amp;gt; 4) &amp;amp; 0x0F; // SRAM segment number&lt;br /&gt;
		sramBank = bank;&lt;br /&gt;
		funcWriteTable[sramBank] = SRAM_Write; // Register SRAM callbacks&lt;br /&gt;
		funcReadTable[sramBank] = SRAM_Read;&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// Initialize SRAM feature&lt;br /&gt;
void SRAM_Init()&lt;br /&gt;
{&lt;br /&gt;
	sramBank = 0xFF;&lt;br /&gt;
	funcTab[0x04] = SRAM_Init; // Register to function 0x04 (SRAM/FRAM feature)&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Then, you just need to call &amp;lt;tt&amp;gt;SRAM_Init()&amp;lt;/tt&amp;gt; from &amp;lt;tt&amp;gt;NEO16_Init()&amp;lt;/tt&amp;gt; to register the feature.&lt;/div&gt;</summary>
		<author><name>Aoineko</name></author>	</entry>

	<entry>
		<id>https://aoineko.org/msxgl/index.php?title=NEO_mapper/Extension&amp;diff=3831</id>
		<title>NEO mapper/Extension</title>
		<link rel="alternate" type="text/html" href="https://aoineko.org/msxgl/index.php?title=NEO_mapper/Extension&amp;diff=3831"/>
				<updated>2026-04-13T21:12:03Z</updated>
		
		<summary type="html">&lt;p&gt;Aoineko: /* 0x04: Activate SRAM/FRAM */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{WARNING|This page is still in the proposal stage and should not yet be considered an official specification.}}&lt;br /&gt;
&lt;br /&gt;
Proposal for an extension to the [[NEO mapper]] format.&lt;br /&gt;
&lt;br /&gt;
== Specifications ==&lt;br /&gt;
&lt;br /&gt;
=== Principles ===&lt;br /&gt;
&lt;br /&gt;
Any write operation to the NEO mapper with data bit 7 set to 1 and address bit 0 set to 1 is considered an access to extended features. In that case, the mapper bank register is not modified.&lt;br /&gt;
&lt;br /&gt;
All other write operations should be considered normal access to the mapper's bank register.&lt;br /&gt;
&lt;br /&gt;
The data contains:&lt;br /&gt;
* The number of an extended function in the mapper&lt;br /&gt;
* A bit indicating whether the function should be enabled or disabled&lt;br /&gt;
&lt;br /&gt;
The address contains an 8-bit parameter to be passed to the function.&lt;br /&gt;
{|&lt;br /&gt;
|-&lt;br /&gt;
|&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ ADDRESS&lt;br /&gt;
|-&lt;br /&gt;
! 15 || 14 || 13 || 12 || 11 || 10 || 9 || 8 || 7 || 6 || 5 || 4 || 3 || 2 || 1 || 0&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#BBB;&amp;quot; colspan=&amp;quot;2&amp;quot;| Page&lt;br /&gt;
|style=&amp;quot;background-color:#BBB;&amp;quot; colspan=&amp;quot;3&amp;quot;| Bank&lt;br /&gt;
|style=&amp;quot;background-color:#BBB;&amp;quot;| 0&lt;br /&gt;
|style=&amp;quot;background-color:#BBB;&amp;quot;| 0&lt;br /&gt;
|style=&amp;quot;background-color:#AAF;&amp;quot; colspan=&amp;quot;8&amp;quot;| Parameter&lt;br /&gt;
|style=&amp;quot;background-color:#FAA;&amp;quot;| 1&lt;br /&gt;
|}&lt;br /&gt;
|&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ DATA&lt;br /&gt;
|-&lt;br /&gt;
! 7 || 6 || 5 || 4 || 3 || 2 || 1 || 0&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FAA;&amp;quot;| 1&lt;br /&gt;
|style=&amp;quot;background-color:#AAF;&amp;quot;| A&lt;br /&gt;
|style=&amp;quot;background-color:#BBB;&amp;quot;| 0&lt;br /&gt;
|style=&amp;quot;background-color:#AAF;&amp;quot; colspan=&amp;quot;5&amp;quot;| Function&lt;br /&gt;
|}&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Functions ===&lt;br /&gt;
==== 0x00: Cartridge information ====&lt;br /&gt;
When activated, any read access to the given bank will return the cartridge information (8 KB, mirrored on NEO-16).&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ PARAMETER&lt;br /&gt;
|-&lt;br /&gt;
! 8 || 7 || 6 || 5 || 4 || 3 || 2 || 1&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#BBB;&amp;quot;| 0&lt;br /&gt;
|style=&amp;quot;background-color:#BBB;&amp;quot;| 0&lt;br /&gt;
|style=&amp;quot;background-color:#BBB;&amp;quot;| 0&lt;br /&gt;
|style=&amp;quot;background-color:#BBB;&amp;quot;| 0&lt;br /&gt;
|style=&amp;quot;background-color:#BBB;&amp;quot;| 0&lt;br /&gt;
|style=&amp;quot;background-color:#AAF;&amp;quot; colspan=&amp;quot;5&amp;quot;| ROM Bank&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Examples:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Action || Pseudo-code&lt;br /&gt;
|-&lt;br /&gt;
| Activate information in bank 2 of NEO-16 || &amp;lt;tt&amp;gt;[0x7005] = 0xC0&amp;lt;/tt&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Read information (offset +5) from bank 2 of NEO-16 || &amp;lt;tt&amp;gt;BankSize = [0x8005]&amp;lt;/tt&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Disactivate information in bank 2 of NEO-16 || &amp;lt;tt&amp;gt;[0x7005] = 0x80&amp;lt;/tt&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== 0x01: Cartridge configuration ====&lt;br /&gt;
&lt;br /&gt;
==== 0x04: Activate SRAM/FRAM ====&lt;br /&gt;
When activated, any read/write access to the specified bank (defined in the parameter) is redirected to the selected segment of the SRAM/FRAM.&lt;br /&gt;
&lt;br /&gt;
SRAM/FRAM is accessed through 8 KB segments (on the NEO-16, the segment is mirrored).&lt;br /&gt;
&lt;br /&gt;
Up to 16 segments can be accessed, for a total capacity of 128 KB.&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ PARAMETER&lt;br /&gt;
|-&lt;br /&gt;
! 8 || 7 || 6 || 5 || 4 || 3 || 2 || 1&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#AAF;&amp;quot; colspan=&amp;quot;4&amp;quot;| RAM Segment&lt;br /&gt;
|style=&amp;quot;background-color:#BBB;&amp;quot;| 0&lt;br /&gt;
|style=&amp;quot;background-color:#AAF;&amp;quot; colspan=&amp;quot;5&amp;quot;| ROM Bank&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== 0x05: Activate device ====&lt;br /&gt;
Activate or disactivate the given device.&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ PARAMETER&lt;br /&gt;
|-&lt;br /&gt;
! 8 || 7 || 6 || 5 || 4 || 3 || 2 || 1&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#BBB;&amp;quot;| 0&lt;br /&gt;
|style=&amp;quot;background-color:#BBB;&amp;quot;| 0&lt;br /&gt;
|style=&amp;quot;background-color:#BBB;&amp;quot;| 0&lt;br /&gt;
|style=&amp;quot;background-color:#AAF;&amp;quot; colspan=&amp;quot;5&amp;quot;| Device&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Devices:&lt;br /&gt;
* &amp;lt;tt&amp;gt;00&amp;lt;/tt&amp;gt;: MSX-Music (OPLL)&lt;br /&gt;
* &amp;lt;tt&amp;gt;01&amp;lt;/tt&amp;gt;: MSX-Audio&lt;br /&gt;
* &amp;lt;tt&amp;gt;02&amp;lt;/tt&amp;gt;: SCC&lt;br /&gt;
* &amp;lt;tt&amp;gt;03&amp;lt;/tt&amp;gt;: SCC+&lt;br /&gt;
* &amp;lt;tt&amp;gt;04&amp;lt;/tt&amp;gt;: 2nd PSG (port 10h)&lt;br /&gt;
* &amp;lt;tt&amp;gt;05&amp;lt;/tt&amp;gt;: Darky (2 x ePSG)&lt;br /&gt;
* &amp;lt;tt&amp;gt;06&amp;lt;/tt&amp;gt;: Darky Jr. (2 x PSG)&lt;br /&gt;
* &amp;lt;tt&amp;gt;08&amp;lt;/tt&amp;gt;: OPM (SFK-01, SFG-01 et SFG-05 ver.1)&lt;br /&gt;
* &amp;lt;tt&amp;gt;09&amp;lt;/tt&amp;gt;: OPP (SFG-05 ver.2)&lt;br /&gt;
* &amp;lt;tt&amp;gt;12&amp;lt;/tt&amp;gt;: OPL4&lt;br /&gt;
* &amp;lt;tt&amp;gt;15&amp;lt;/tt&amp;gt;: SAM2695&lt;br /&gt;
&lt;br /&gt;
== Appendix ==&lt;br /&gt;
=== Programmable processor and emulation ===&lt;br /&gt;
Here is a pseudo code in C to handle NEO mappers extension for programmable processor based cartridges or for emulators:&lt;br /&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;
// Extended function prototypes&lt;br /&gt;
typedef void (*funcEnable_t)(bool, uint8);&lt;br /&gt;
typedef void (*funcWrite_t)(uint16, uint8);&lt;br /&gt;
typedef uint8 (*funcRead_t)(uint16);&lt;br /&gt;
// Extended functions table&lt;br /&gt;
funcEnable_t funcEnableTable[32];&lt;br /&gt;
funcWrite_t funcWriteTable[3];&lt;br /&gt;
funcRead_t funcReadTable[3];&lt;br /&gt;
&lt;br /&gt;
// Handle device initialization&lt;br /&gt;
void NEO16_Init()&lt;br /&gt;
{&lt;br /&gt;
	for (uint8 i = 0; i &amp;lt; 3; i++)&lt;br /&gt;
	{&lt;br /&gt;
		bankValue[i] = 0x0000;&lt;br /&gt;
		funcWriteTable[i] = NULL;&lt;br /&gt;
		funcReadTable[i] = NULL;		&lt;br /&gt;
	}&lt;br /&gt;
	for (uint8 i = 0; i &amp;lt; 32; i++)&lt;br /&gt;
		funcTab[i] = NULL;&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; // Get the corresponding bank number&lt;br /&gt;
	if (bank &amp;gt; 2)&lt;br /&gt;
		return; // skip&lt;br /&gt;
&lt;br /&gt;
	if (funcWriteTable[bank] != NULL) // Check for bank write callback&lt;br /&gt;
	{&lt;br /&gt;
		funcWriteTable[bank](address, value);&lt;br /&gt;
	}&lt;br /&gt;
	else if ((address &amp;amp; 0x0001) &amp;amp;&amp;amp; (value &amp;amp; 0x80)) // Handle extended function&lt;br /&gt;
	{&lt;br /&gt;
		uint8 funcId = value &amp;amp; 0x3F; // Get function ID&lt;br /&gt;
		if (funcEnableTable[funcId] != NULL)&lt;br /&gt;
			funcEnableTable[funcId](value &amp;amp; 0x40, (address &amp;gt;&amp;gt; 1) &amp;amp; 0xFF); // Execute function specific code&lt;br /&gt;
	}&lt;br /&gt;
	else // Write to the given bank register&lt;br /&gt;
	{&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;
&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; // Get the corresponding bank number&lt;br /&gt;
	if (bank &amp;gt; 2)&lt;br /&gt;
		return 0xFF; // skip&lt;br /&gt;
&lt;br /&gt;
	if (funcReadTable[bank] != NULL) // Check for bank read callback&lt;br /&gt;
		return funcReadTable[bank](address);&lt;br /&gt;
	else&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;
=== Extension example ===&lt;br /&gt;
Here is a pseudo code in C to handle a SRAM extension for NEO mapper:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
uint8 sramSeg; // Current SRAM segment [0:15]&lt;br /&gt;
uint8 sramBank; // Current bank where SRAM is selected (0xFF if not selected)&lt;br /&gt;
uint8* sramData; // SRAM data (hardware specific)&lt;br /&gt;
&lt;br /&gt;
// Write to SRAM&lt;br /&gt;
void SRAM_Write(uint16 address, uint8 value)&lt;br /&gt;
{&lt;br /&gt;
	sramData[(sramSeg * 0x2000) + (address &amp;amp; 0x1FFF)] = value; // &lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// Read from SRAM&lt;br /&gt;
uint8 SRAM_read(uint16 address)&lt;br /&gt;
{&lt;br /&gt;
	return sramData[(sramSeg * 0x2000) + (address &amp;amp; 0x1FFF)];	&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// Enable/disable SRAM feature&lt;br /&gt;
void SRAM_Enable(bool enable, uint8 param)&lt;br /&gt;
{&lt;br /&gt;
	if (sramBank != 0xFF) // Disable previous SRAM registration&lt;br /&gt;
	{&lt;br /&gt;
		if (funcWriteTable[sramBank] == SRAM_Write)&lt;br /&gt;
			funcWriteTable[sramBank] = NULL;&lt;br /&gt;
		if (funcReadTable[sramBank] == SRAM_Read)&lt;br /&gt;
			funcReadTable[sramBank] = NULL;&lt;br /&gt;
		sramBank = 0xFF;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	if (enable) // Enable a SRAM segment in the given bank&lt;br /&gt;
	{&lt;br /&gt;
		uint8 bank = param &amp;amp; 0x07; // Get bank number&lt;br /&gt;
		if (bank &amp;gt; 2)&lt;br /&gt;
			return; // skip (for NEO-16)&lt;br /&gt;
&lt;br /&gt;
		sramSeg = (param &amp;gt;&amp;gt; 4) &amp;amp; 0x0F; // SRAM segment number&lt;br /&gt;
		sramBank = bank;&lt;br /&gt;
		funcWriteTable[sramBank] = SRAM_Write; // Register SRAM callbacks&lt;br /&gt;
		funcReadTable[sramBank] = SRAM_Read;&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// Initialize SRAM feature&lt;br /&gt;
void SRAM_Init()&lt;br /&gt;
{&lt;br /&gt;
	sramBank = 0xFF;&lt;br /&gt;
	funcTab[0x04] = SRAM_Init; // Register to function 0x04 (SRAM/FRAM feature)&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Then, you just need to call &amp;lt;tt&amp;gt;SRAM_Init()&amp;lt;/tt&amp;gt; from &amp;lt;tt&amp;gt;NEO16_Init()&amp;lt;/tt&amp;gt; to register the feature.&lt;/div&gt;</summary>
		<author><name>Aoineko</name></author>	</entry>

	<entry>
		<id>https://aoineko.org/msxgl/index.php?title=NEO_mapper/Extension&amp;diff=3830</id>
		<title>NEO mapper/Extension</title>
		<link rel="alternate" type="text/html" href="https://aoineko.org/msxgl/index.php?title=NEO_mapper/Extension&amp;diff=3830"/>
				<updated>2026-04-13T21:11:51Z</updated>
		
		<summary type="html">&lt;p&gt;Aoineko: /* 0x00: Cartridge information */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{WARNING|This page is still in the proposal stage and should not yet be considered an official specification.}}&lt;br /&gt;
&lt;br /&gt;
Proposal for an extension to the [[NEO mapper]] format.&lt;br /&gt;
&lt;br /&gt;
== Specifications ==&lt;br /&gt;
&lt;br /&gt;
=== Principles ===&lt;br /&gt;
&lt;br /&gt;
Any write operation to the NEO mapper with data bit 7 set to 1 and address bit 0 set to 1 is considered an access to extended features. In that case, the mapper bank register is not modified.&lt;br /&gt;
&lt;br /&gt;
All other write operations should be considered normal access to the mapper's bank register.&lt;br /&gt;
&lt;br /&gt;
The data contains:&lt;br /&gt;
* The number of an extended function in the mapper&lt;br /&gt;
* A bit indicating whether the function should be enabled or disabled&lt;br /&gt;
&lt;br /&gt;
The address contains an 8-bit parameter to be passed to the function.&lt;br /&gt;
{|&lt;br /&gt;
|-&lt;br /&gt;
|&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ ADDRESS&lt;br /&gt;
|-&lt;br /&gt;
! 15 || 14 || 13 || 12 || 11 || 10 || 9 || 8 || 7 || 6 || 5 || 4 || 3 || 2 || 1 || 0&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#BBB;&amp;quot; colspan=&amp;quot;2&amp;quot;| Page&lt;br /&gt;
|style=&amp;quot;background-color:#BBB;&amp;quot; colspan=&amp;quot;3&amp;quot;| Bank&lt;br /&gt;
|style=&amp;quot;background-color:#BBB;&amp;quot;| 0&lt;br /&gt;
|style=&amp;quot;background-color:#BBB;&amp;quot;| 0&lt;br /&gt;
|style=&amp;quot;background-color:#AAF;&amp;quot; colspan=&amp;quot;8&amp;quot;| Parameter&lt;br /&gt;
|style=&amp;quot;background-color:#FAA;&amp;quot;| 1&lt;br /&gt;
|}&lt;br /&gt;
|&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ DATA&lt;br /&gt;
|-&lt;br /&gt;
! 7 || 6 || 5 || 4 || 3 || 2 || 1 || 0&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FAA;&amp;quot;| 1&lt;br /&gt;
|style=&amp;quot;background-color:#AAF;&amp;quot;| A&lt;br /&gt;
|style=&amp;quot;background-color:#BBB;&amp;quot;| 0&lt;br /&gt;
|style=&amp;quot;background-color:#AAF;&amp;quot; colspan=&amp;quot;5&amp;quot;| Function&lt;br /&gt;
|}&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Functions ===&lt;br /&gt;
==== 0x00: Cartridge information ====&lt;br /&gt;
When activated, any read access to the given bank will return the cartridge information (8 KB, mirrored on NEO-16).&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ PARAMETER&lt;br /&gt;
|-&lt;br /&gt;
! 8 || 7 || 6 || 5 || 4 || 3 || 2 || 1&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#BBB;&amp;quot;| 0&lt;br /&gt;
|style=&amp;quot;background-color:#BBB;&amp;quot;| 0&lt;br /&gt;
|style=&amp;quot;background-color:#BBB;&amp;quot;| 0&lt;br /&gt;
|style=&amp;quot;background-color:#BBB;&amp;quot;| 0&lt;br /&gt;
|style=&amp;quot;background-color:#BBB;&amp;quot;| 0&lt;br /&gt;
|style=&amp;quot;background-color:#AAF;&amp;quot; colspan=&amp;quot;5&amp;quot;| ROM Bank&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Examples:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Action || Pseudo-code&lt;br /&gt;
|-&lt;br /&gt;
| Activate information in bank 2 of NEO-16 || &amp;lt;tt&amp;gt;[0x7005] = 0xC0&amp;lt;/tt&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Read information (offset +5) from bank 2 of NEO-16 || &amp;lt;tt&amp;gt;BankSize = [0x8005]&amp;lt;/tt&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Disactivate information in bank 2 of NEO-16 || &amp;lt;tt&amp;gt;[0x7005] = 0x80&amp;lt;/tt&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== 0x01: Cartridge configuration ====&lt;br /&gt;
&lt;br /&gt;
==== 0x04: Activate SRAM/FRAM ====&lt;br /&gt;
When activated, any read/write access to the specified bank (defined in the parameter) is redirected to the selected segment of the SRAM/FRAM.&lt;br /&gt;
&lt;br /&gt;
SRAM/FRAM is accessed through 8 KB segments (on the NEO-16, the segment is mirrored).&lt;br /&gt;
&lt;br /&gt;
Up to 16 segments can be accessed, for a total capacity of 128 KB.&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ PARAMETER&lt;br /&gt;
|-&lt;br /&gt;
! 8 || 7 || 6 || 5 || 4 || 3 || 2 || 1&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#AAF;&amp;quot; colspan=&amp;quot;4&amp;quot;| Segment&lt;br /&gt;
|style=&amp;quot;background-color:#BBB;&amp;quot;| 0&lt;br /&gt;
|style=&amp;quot;background-color:#AAF;&amp;quot; colspan=&amp;quot;5&amp;quot;| Bank&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== 0x05: Activate device ====&lt;br /&gt;
Activate or disactivate the given device.&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ PARAMETER&lt;br /&gt;
|-&lt;br /&gt;
! 8 || 7 || 6 || 5 || 4 || 3 || 2 || 1&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#BBB;&amp;quot;| 0&lt;br /&gt;
|style=&amp;quot;background-color:#BBB;&amp;quot;| 0&lt;br /&gt;
|style=&amp;quot;background-color:#BBB;&amp;quot;| 0&lt;br /&gt;
|style=&amp;quot;background-color:#AAF;&amp;quot; colspan=&amp;quot;5&amp;quot;| Device&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Devices:&lt;br /&gt;
* &amp;lt;tt&amp;gt;00&amp;lt;/tt&amp;gt;: MSX-Music (OPLL)&lt;br /&gt;
* &amp;lt;tt&amp;gt;01&amp;lt;/tt&amp;gt;: MSX-Audio&lt;br /&gt;
* &amp;lt;tt&amp;gt;02&amp;lt;/tt&amp;gt;: SCC&lt;br /&gt;
* &amp;lt;tt&amp;gt;03&amp;lt;/tt&amp;gt;: SCC+&lt;br /&gt;
* &amp;lt;tt&amp;gt;04&amp;lt;/tt&amp;gt;: 2nd PSG (port 10h)&lt;br /&gt;
* &amp;lt;tt&amp;gt;05&amp;lt;/tt&amp;gt;: Darky (2 x ePSG)&lt;br /&gt;
* &amp;lt;tt&amp;gt;06&amp;lt;/tt&amp;gt;: Darky Jr. (2 x PSG)&lt;br /&gt;
* &amp;lt;tt&amp;gt;08&amp;lt;/tt&amp;gt;: OPM (SFK-01, SFG-01 et SFG-05 ver.1)&lt;br /&gt;
* &amp;lt;tt&amp;gt;09&amp;lt;/tt&amp;gt;: OPP (SFG-05 ver.2)&lt;br /&gt;
* &amp;lt;tt&amp;gt;12&amp;lt;/tt&amp;gt;: OPL4&lt;br /&gt;
* &amp;lt;tt&amp;gt;15&amp;lt;/tt&amp;gt;: SAM2695&lt;br /&gt;
&lt;br /&gt;
== Appendix ==&lt;br /&gt;
=== Programmable processor and emulation ===&lt;br /&gt;
Here is a pseudo code in C to handle NEO mappers extension for programmable processor based cartridges or for emulators:&lt;br /&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;
// Extended function prototypes&lt;br /&gt;
typedef void (*funcEnable_t)(bool, uint8);&lt;br /&gt;
typedef void (*funcWrite_t)(uint16, uint8);&lt;br /&gt;
typedef uint8 (*funcRead_t)(uint16);&lt;br /&gt;
// Extended functions table&lt;br /&gt;
funcEnable_t funcEnableTable[32];&lt;br /&gt;
funcWrite_t funcWriteTable[3];&lt;br /&gt;
funcRead_t funcReadTable[3];&lt;br /&gt;
&lt;br /&gt;
// Handle device initialization&lt;br /&gt;
void NEO16_Init()&lt;br /&gt;
{&lt;br /&gt;
	for (uint8 i = 0; i &amp;lt; 3; i++)&lt;br /&gt;
	{&lt;br /&gt;
		bankValue[i] = 0x0000;&lt;br /&gt;
		funcWriteTable[i] = NULL;&lt;br /&gt;
		funcReadTable[i] = NULL;		&lt;br /&gt;
	}&lt;br /&gt;
	for (uint8 i = 0; i &amp;lt; 32; i++)&lt;br /&gt;
		funcTab[i] = NULL;&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; // Get the corresponding bank number&lt;br /&gt;
	if (bank &amp;gt; 2)&lt;br /&gt;
		return; // skip&lt;br /&gt;
&lt;br /&gt;
	if (funcWriteTable[bank] != NULL) // Check for bank write callback&lt;br /&gt;
	{&lt;br /&gt;
		funcWriteTable[bank](address, value);&lt;br /&gt;
	}&lt;br /&gt;
	else if ((address &amp;amp; 0x0001) &amp;amp;&amp;amp; (value &amp;amp; 0x80)) // Handle extended function&lt;br /&gt;
	{&lt;br /&gt;
		uint8 funcId = value &amp;amp; 0x3F; // Get function ID&lt;br /&gt;
		if (funcEnableTable[funcId] != NULL)&lt;br /&gt;
			funcEnableTable[funcId](value &amp;amp; 0x40, (address &amp;gt;&amp;gt; 1) &amp;amp; 0xFF); // Execute function specific code&lt;br /&gt;
	}&lt;br /&gt;
	else // Write to the given bank register&lt;br /&gt;
	{&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;
&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; // Get the corresponding bank number&lt;br /&gt;
	if (bank &amp;gt; 2)&lt;br /&gt;
		return 0xFF; // skip&lt;br /&gt;
&lt;br /&gt;
	if (funcReadTable[bank] != NULL) // Check for bank read callback&lt;br /&gt;
		return funcReadTable[bank](address);&lt;br /&gt;
	else&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;
=== Extension example ===&lt;br /&gt;
Here is a pseudo code in C to handle a SRAM extension for NEO mapper:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
uint8 sramSeg; // Current SRAM segment [0:15]&lt;br /&gt;
uint8 sramBank; // Current bank where SRAM is selected (0xFF if not selected)&lt;br /&gt;
uint8* sramData; // SRAM data (hardware specific)&lt;br /&gt;
&lt;br /&gt;
// Write to SRAM&lt;br /&gt;
void SRAM_Write(uint16 address, uint8 value)&lt;br /&gt;
{&lt;br /&gt;
	sramData[(sramSeg * 0x2000) + (address &amp;amp; 0x1FFF)] = value; // &lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// Read from SRAM&lt;br /&gt;
uint8 SRAM_read(uint16 address)&lt;br /&gt;
{&lt;br /&gt;
	return sramData[(sramSeg * 0x2000) + (address &amp;amp; 0x1FFF)];	&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// Enable/disable SRAM feature&lt;br /&gt;
void SRAM_Enable(bool enable, uint8 param)&lt;br /&gt;
{&lt;br /&gt;
	if (sramBank != 0xFF) // Disable previous SRAM registration&lt;br /&gt;
	{&lt;br /&gt;
		if (funcWriteTable[sramBank] == SRAM_Write)&lt;br /&gt;
			funcWriteTable[sramBank] = NULL;&lt;br /&gt;
		if (funcReadTable[sramBank] == SRAM_Read)&lt;br /&gt;
			funcReadTable[sramBank] = NULL;&lt;br /&gt;
		sramBank = 0xFF;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	if (enable) // Enable a SRAM segment in the given bank&lt;br /&gt;
	{&lt;br /&gt;
		uint8 bank = param &amp;amp; 0x07; // Get bank number&lt;br /&gt;
		if (bank &amp;gt; 2)&lt;br /&gt;
			return; // skip (for NEO-16)&lt;br /&gt;
&lt;br /&gt;
		sramSeg = (param &amp;gt;&amp;gt; 4) &amp;amp; 0x0F; // SRAM segment number&lt;br /&gt;
		sramBank = bank;&lt;br /&gt;
		funcWriteTable[sramBank] = SRAM_Write; // Register SRAM callbacks&lt;br /&gt;
		funcReadTable[sramBank] = SRAM_Read;&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// Initialize SRAM feature&lt;br /&gt;
void SRAM_Init()&lt;br /&gt;
{&lt;br /&gt;
	sramBank = 0xFF;&lt;br /&gt;
	funcTab[0x04] = SRAM_Init; // Register to function 0x04 (SRAM/FRAM feature)&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Then, you just need to call &amp;lt;tt&amp;gt;SRAM_Init()&amp;lt;/tt&amp;gt; from &amp;lt;tt&amp;gt;NEO16_Init()&amp;lt;/tt&amp;gt; to register the feature.&lt;/div&gt;</summary>
		<author><name>Aoineko</name></author>	</entry>

	<entry>
		<id>https://aoineko.org/msxgl/index.php?title=NEO_mapper&amp;diff=3829</id>
		<title>NEO mapper</title>
		<link rel="alternate" type="text/html" href="https://aoineko.org/msxgl/index.php?title=NEO_mapper&amp;diff=3829"/>
				<updated>2026-04-13T21:05:19Z</updated>
		
		<summary type="html">&lt;p&gt;Aoineko: &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;
* '''Mega-USB 512''': ''WIP hardware...''&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=3828</id>
		<title>NEO mapper</title>
		<link rel="alternate" type="text/html" href="https://aoineko.org/msxgl/index.php?title=NEO_mapper&amp;diff=3828"/>
				<updated>2026-04-13T21:04:14Z</updated>
		
		<summary type="html">&lt;p&gt;Aoineko: &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;
* '''Mega-USB 512''': ''WIP hardware...''&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 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/Extension&amp;diff=3827</id>
		<title>NEO mapper/Extension</title>
		<link rel="alternate" type="text/html" href="https://aoineko.org/msxgl/index.php?title=NEO_mapper/Extension&amp;diff=3827"/>
				<updated>2026-04-13T20:54:53Z</updated>
		
		<summary type="html">&lt;p&gt;Aoineko: /* 0x00: Cartridge information */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{WARNING|This page is still in the proposal stage and should not yet be considered an official specification.}}&lt;br /&gt;
&lt;br /&gt;
Proposal for an extension to the [[NEO mapper]] format.&lt;br /&gt;
&lt;br /&gt;
== Specifications ==&lt;br /&gt;
&lt;br /&gt;
=== Principles ===&lt;br /&gt;
&lt;br /&gt;
Any write operation to the NEO mapper with data bit 7 set to 1 and address bit 0 set to 1 is considered an access to extended features. In that case, the mapper bank register is not modified.&lt;br /&gt;
&lt;br /&gt;
All other write operations should be considered normal access to the mapper's bank register.&lt;br /&gt;
&lt;br /&gt;
The data contains:&lt;br /&gt;
* The number of an extended function in the mapper&lt;br /&gt;
* A bit indicating whether the function should be enabled or disabled&lt;br /&gt;
&lt;br /&gt;
The address contains an 8-bit parameter to be passed to the function.&lt;br /&gt;
{|&lt;br /&gt;
|-&lt;br /&gt;
|&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ ADDRESS&lt;br /&gt;
|-&lt;br /&gt;
! 15 || 14 || 13 || 12 || 11 || 10 || 9 || 8 || 7 || 6 || 5 || 4 || 3 || 2 || 1 || 0&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#BBB;&amp;quot; colspan=&amp;quot;2&amp;quot;| Page&lt;br /&gt;
|style=&amp;quot;background-color:#BBB;&amp;quot; colspan=&amp;quot;3&amp;quot;| Bank&lt;br /&gt;
|style=&amp;quot;background-color:#BBB;&amp;quot;| 0&lt;br /&gt;
|style=&amp;quot;background-color:#BBB;&amp;quot;| 0&lt;br /&gt;
|style=&amp;quot;background-color:#AAF;&amp;quot; colspan=&amp;quot;8&amp;quot;| Parameter&lt;br /&gt;
|style=&amp;quot;background-color:#FAA;&amp;quot;| 1&lt;br /&gt;
|}&lt;br /&gt;
|&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ DATA&lt;br /&gt;
|-&lt;br /&gt;
! 7 || 6 || 5 || 4 || 3 || 2 || 1 || 0&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FAA;&amp;quot;| 1&lt;br /&gt;
|style=&amp;quot;background-color:#AAF;&amp;quot;| A&lt;br /&gt;
|style=&amp;quot;background-color:#BBB;&amp;quot;| 0&lt;br /&gt;
|style=&amp;quot;background-color:#AAF;&amp;quot; colspan=&amp;quot;5&amp;quot;| Function&lt;br /&gt;
|}&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Functions ===&lt;br /&gt;
==== 0x00: Cartridge information ====&lt;br /&gt;
When activated, any read access to the given bank will return the cartridge information (8 KB, mirrored on NEO-16).&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ PARAMETER&lt;br /&gt;
|-&lt;br /&gt;
! 8 || 7 || 6 || 5 || 4 || 3 || 2 || 1&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#BBB;&amp;quot;| 0&lt;br /&gt;
|style=&amp;quot;background-color:#BBB;&amp;quot;| 0&lt;br /&gt;
|style=&amp;quot;background-color:#BBB;&amp;quot;| 0&lt;br /&gt;
|style=&amp;quot;background-color:#BBB;&amp;quot;| 0&lt;br /&gt;
|style=&amp;quot;background-color:#BBB;&amp;quot;| 0&lt;br /&gt;
|style=&amp;quot;background-color:#AAF;&amp;quot; colspan=&amp;quot;5&amp;quot;| Bank&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Examples:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Action || Pseudo-code&lt;br /&gt;
|-&lt;br /&gt;
| Activate information in bank 2 of NEO-16 || &amp;lt;tt&amp;gt;[0x7005] = 0xC0&amp;lt;/tt&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Read information (offset +5) from bank 2 of NEO-16 || &amp;lt;tt&amp;gt;BankSize = [0x8005]&amp;lt;/tt&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Disactivate information in bank 2 of NEO-16 || &amp;lt;tt&amp;gt;[0x7005] = 0x80&amp;lt;/tt&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== 0x01: Cartridge configuration ====&lt;br /&gt;
&lt;br /&gt;
==== 0x04: Activate SRAM/FRAM ====&lt;br /&gt;
When activated, any read/write access to the specified bank (defined in the parameter) is redirected to the selected segment of the SRAM/FRAM.&lt;br /&gt;
&lt;br /&gt;
SRAM/FRAM is accessed through 8 KB segments (on the NEO-16, the segment is mirrored).&lt;br /&gt;
&lt;br /&gt;
Up to 16 segments can be accessed, for a total capacity of 128 KB.&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ PARAMETER&lt;br /&gt;
|-&lt;br /&gt;
! 8 || 7 || 6 || 5 || 4 || 3 || 2 || 1&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#AAF;&amp;quot; colspan=&amp;quot;4&amp;quot;| Segment&lt;br /&gt;
|style=&amp;quot;background-color:#BBB;&amp;quot;| 0&lt;br /&gt;
|style=&amp;quot;background-color:#AAF;&amp;quot; colspan=&amp;quot;5&amp;quot;| Bank&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== 0x05: Activate device ====&lt;br /&gt;
Activate or disactivate the given device.&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ PARAMETER&lt;br /&gt;
|-&lt;br /&gt;
! 8 || 7 || 6 || 5 || 4 || 3 || 2 || 1&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#BBB;&amp;quot;| 0&lt;br /&gt;
|style=&amp;quot;background-color:#BBB;&amp;quot;| 0&lt;br /&gt;
|style=&amp;quot;background-color:#BBB;&amp;quot;| 0&lt;br /&gt;
|style=&amp;quot;background-color:#AAF;&amp;quot; colspan=&amp;quot;5&amp;quot;| Device&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Devices:&lt;br /&gt;
* &amp;lt;tt&amp;gt;00&amp;lt;/tt&amp;gt;: MSX-Music (OPLL)&lt;br /&gt;
* &amp;lt;tt&amp;gt;01&amp;lt;/tt&amp;gt;: MSX-Audio&lt;br /&gt;
* &amp;lt;tt&amp;gt;02&amp;lt;/tt&amp;gt;: SCC&lt;br /&gt;
* &amp;lt;tt&amp;gt;03&amp;lt;/tt&amp;gt;: SCC+&lt;br /&gt;
* &amp;lt;tt&amp;gt;04&amp;lt;/tt&amp;gt;: 2nd PSG (port 10h)&lt;br /&gt;
* &amp;lt;tt&amp;gt;05&amp;lt;/tt&amp;gt;: Darky (2 x ePSG)&lt;br /&gt;
* &amp;lt;tt&amp;gt;06&amp;lt;/tt&amp;gt;: Darky Jr. (2 x PSG)&lt;br /&gt;
* &amp;lt;tt&amp;gt;08&amp;lt;/tt&amp;gt;: OPM (SFK-01, SFG-01 et SFG-05 ver.1)&lt;br /&gt;
* &amp;lt;tt&amp;gt;09&amp;lt;/tt&amp;gt;: OPP (SFG-05 ver.2)&lt;br /&gt;
* &amp;lt;tt&amp;gt;12&amp;lt;/tt&amp;gt;: OPL4&lt;br /&gt;
* &amp;lt;tt&amp;gt;15&amp;lt;/tt&amp;gt;: SAM2695&lt;br /&gt;
&lt;br /&gt;
== Appendix ==&lt;br /&gt;
=== Programmable processor and emulation ===&lt;br /&gt;
Here is a pseudo code in C to handle NEO mappers extension for programmable processor based cartridges or for emulators:&lt;br /&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;
// Extended function prototypes&lt;br /&gt;
typedef void (*funcEnable_t)(bool, uint8);&lt;br /&gt;
typedef void (*funcWrite_t)(uint16, uint8);&lt;br /&gt;
typedef uint8 (*funcRead_t)(uint16);&lt;br /&gt;
// Extended functions table&lt;br /&gt;
funcEnable_t funcEnableTable[32];&lt;br /&gt;
funcWrite_t funcWriteTable[3];&lt;br /&gt;
funcRead_t funcReadTable[3];&lt;br /&gt;
&lt;br /&gt;
// Handle device initialization&lt;br /&gt;
void NEO16_Init()&lt;br /&gt;
{&lt;br /&gt;
	for (uint8 i = 0; i &amp;lt; 3; i++)&lt;br /&gt;
	{&lt;br /&gt;
		bankValue[i] = 0x0000;&lt;br /&gt;
		funcWriteTable[i] = NULL;&lt;br /&gt;
		funcReadTable[i] = NULL;		&lt;br /&gt;
	}&lt;br /&gt;
	for (uint8 i = 0; i &amp;lt; 32; i++)&lt;br /&gt;
		funcTab[i] = NULL;&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; // Get the corresponding bank number&lt;br /&gt;
	if (bank &amp;gt; 2)&lt;br /&gt;
		return; // skip&lt;br /&gt;
&lt;br /&gt;
	if (funcWriteTable[bank] != NULL) // Check for bank write callback&lt;br /&gt;
	{&lt;br /&gt;
		funcWriteTable[bank](address, value);&lt;br /&gt;
	}&lt;br /&gt;
	else if ((address &amp;amp; 0x0001) &amp;amp;&amp;amp; (value &amp;amp; 0x80)) // Handle extended function&lt;br /&gt;
	{&lt;br /&gt;
		uint8 funcId = value &amp;amp; 0x3F; // Get function ID&lt;br /&gt;
		if (funcEnableTable[funcId] != NULL)&lt;br /&gt;
			funcEnableTable[funcId](value &amp;amp; 0x40, (address &amp;gt;&amp;gt; 1) &amp;amp; 0xFF); // Execute function specific code&lt;br /&gt;
	}&lt;br /&gt;
	else // Write to the given bank register&lt;br /&gt;
	{&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;
&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; // Get the corresponding bank number&lt;br /&gt;
	if (bank &amp;gt; 2)&lt;br /&gt;
		return 0xFF; // skip&lt;br /&gt;
&lt;br /&gt;
	if (funcReadTable[bank] != NULL) // Check for bank read callback&lt;br /&gt;
		return funcReadTable[bank](address);&lt;br /&gt;
	else&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;
=== Extension example ===&lt;br /&gt;
Here is a pseudo code in C to handle a SRAM extension for NEO mapper:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
uint8 sramSeg; // Current SRAM segment [0:15]&lt;br /&gt;
uint8 sramBank; // Current bank where SRAM is selected (0xFF if not selected)&lt;br /&gt;
uint8* sramData; // SRAM data (hardware specific)&lt;br /&gt;
&lt;br /&gt;
// Write to SRAM&lt;br /&gt;
void SRAM_Write(uint16 address, uint8 value)&lt;br /&gt;
{&lt;br /&gt;
	sramData[(sramSeg * 0x2000) + (address &amp;amp; 0x1FFF)] = value; // &lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// Read from SRAM&lt;br /&gt;
uint8 SRAM_read(uint16 address)&lt;br /&gt;
{&lt;br /&gt;
	return sramData[(sramSeg * 0x2000) + (address &amp;amp; 0x1FFF)];	&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// Enable/disable SRAM feature&lt;br /&gt;
void SRAM_Enable(bool enable, uint8 param)&lt;br /&gt;
{&lt;br /&gt;
	if (sramBank != 0xFF) // Disable previous SRAM registration&lt;br /&gt;
	{&lt;br /&gt;
		if (funcWriteTable[sramBank] == SRAM_Write)&lt;br /&gt;
			funcWriteTable[sramBank] = NULL;&lt;br /&gt;
		if (funcReadTable[sramBank] == SRAM_Read)&lt;br /&gt;
			funcReadTable[sramBank] = NULL;&lt;br /&gt;
		sramBank = 0xFF;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	if (enable) // Enable a SRAM segment in the given bank&lt;br /&gt;
	{&lt;br /&gt;
		uint8 bank = param &amp;amp; 0x07; // Get bank number&lt;br /&gt;
		if (bank &amp;gt; 2)&lt;br /&gt;
			return; // skip (for NEO-16)&lt;br /&gt;
&lt;br /&gt;
		sramSeg = (param &amp;gt;&amp;gt; 4) &amp;amp; 0x0F; // SRAM segment number&lt;br /&gt;
		sramBank = bank;&lt;br /&gt;
		funcWriteTable[sramBank] = SRAM_Write; // Register SRAM callbacks&lt;br /&gt;
		funcReadTable[sramBank] = SRAM_Read;&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// Initialize SRAM feature&lt;br /&gt;
void SRAM_Init()&lt;br /&gt;
{&lt;br /&gt;
	sramBank = 0xFF;&lt;br /&gt;
	funcTab[0x04] = SRAM_Init; // Register to function 0x04 (SRAM/FRAM feature)&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Then, you just need to call &amp;lt;tt&amp;gt;SRAM_Init()&amp;lt;/tt&amp;gt; from &amp;lt;tt&amp;gt;NEO16_Init()&amp;lt;/tt&amp;gt; to register the feature.&lt;/div&gt;</summary>
		<author><name>Aoineko</name></author>	</entry>

	<entry>
		<id>https://aoineko.org/msxgl/index.php?title=NEO_mapper/Extension&amp;diff=3826</id>
		<title>NEO mapper/Extension</title>
		<link rel="alternate" type="text/html" href="https://aoineko.org/msxgl/index.php?title=NEO_mapper/Extension&amp;diff=3826"/>
				<updated>2026-04-13T20:53:53Z</updated>
		
		<summary type="html">&lt;p&gt;Aoineko: /* 0x00: Cartridge information */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{WARNING|This page is still in the proposal stage and should not yet be considered an official specification.}}&lt;br /&gt;
&lt;br /&gt;
Proposal for an extension to the [[NEO mapper]] format.&lt;br /&gt;
&lt;br /&gt;
== Specifications ==&lt;br /&gt;
&lt;br /&gt;
=== Principles ===&lt;br /&gt;
&lt;br /&gt;
Any write operation to the NEO mapper with data bit 7 set to 1 and address bit 0 set to 1 is considered an access to extended features. In that case, the mapper bank register is not modified.&lt;br /&gt;
&lt;br /&gt;
All other write operations should be considered normal access to the mapper's bank register.&lt;br /&gt;
&lt;br /&gt;
The data contains:&lt;br /&gt;
* The number of an extended function in the mapper&lt;br /&gt;
* A bit indicating whether the function should be enabled or disabled&lt;br /&gt;
&lt;br /&gt;
The address contains an 8-bit parameter to be passed to the function.&lt;br /&gt;
{|&lt;br /&gt;
|-&lt;br /&gt;
|&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ ADDRESS&lt;br /&gt;
|-&lt;br /&gt;
! 15 || 14 || 13 || 12 || 11 || 10 || 9 || 8 || 7 || 6 || 5 || 4 || 3 || 2 || 1 || 0&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#BBB;&amp;quot; colspan=&amp;quot;2&amp;quot;| Page&lt;br /&gt;
|style=&amp;quot;background-color:#BBB;&amp;quot; colspan=&amp;quot;3&amp;quot;| Bank&lt;br /&gt;
|style=&amp;quot;background-color:#BBB;&amp;quot;| 0&lt;br /&gt;
|style=&amp;quot;background-color:#BBB;&amp;quot;| 0&lt;br /&gt;
|style=&amp;quot;background-color:#AAF;&amp;quot; colspan=&amp;quot;8&amp;quot;| Parameter&lt;br /&gt;
|style=&amp;quot;background-color:#FAA;&amp;quot;| 1&lt;br /&gt;
|}&lt;br /&gt;
|&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ DATA&lt;br /&gt;
|-&lt;br /&gt;
! 7 || 6 || 5 || 4 || 3 || 2 || 1 || 0&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FAA;&amp;quot;| 1&lt;br /&gt;
|style=&amp;quot;background-color:#AAF;&amp;quot;| A&lt;br /&gt;
|style=&amp;quot;background-color:#BBB;&amp;quot;| 0&lt;br /&gt;
|style=&amp;quot;background-color:#AAF;&amp;quot; colspan=&amp;quot;5&amp;quot;| Function&lt;br /&gt;
|}&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Functions ===&lt;br /&gt;
==== 0x00: Cartridge information ====&lt;br /&gt;
When activated, any read access to the given bank will return the cartridge information (8 KB, mirrored on NEO-16).&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ PARAMETER&lt;br /&gt;
|-&lt;br /&gt;
! 8 || 7 || 6 || 5 || 4 || 3 || 2 || 1&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#BBB;&amp;quot;| 0&lt;br /&gt;
|style=&amp;quot;background-color:#BBB;&amp;quot;| 0&lt;br /&gt;
|style=&amp;quot;background-color:#BBB;&amp;quot;| 0&lt;br /&gt;
|style=&amp;quot;background-color:#BBB;&amp;quot;| 0&lt;br /&gt;
|style=&amp;quot;background-color:#BBB;&amp;quot;| 0&lt;br /&gt;
|style=&amp;quot;background-color:#AAF;&amp;quot; colspan=&amp;quot;5&amp;quot;| Bank&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Examples:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Action || Pseudo-code&lt;br /&gt;
|-&lt;br /&gt;
| Activate information in bank 2 of NEO-16 || &amp;lt;tt&amp;gt;[0x7005] = 0xC0&amp;lt;/tt&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Read information from bank 2 of NEO-16 || &amp;lt;tt&amp;gt;BankSize = [0x8005]&amp;lt;/tt&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Disactivate information in bank 2 of NEO-16 || &amp;lt;tt&amp;gt;[0x7005] = 0x80&amp;lt;/tt&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== 0x01: Cartridge configuration ====&lt;br /&gt;
&lt;br /&gt;
==== 0x04: Activate SRAM/FRAM ====&lt;br /&gt;
When activated, any read/write access to the specified bank (defined in the parameter) is redirected to the selected segment of the SRAM/FRAM.&lt;br /&gt;
&lt;br /&gt;
SRAM/FRAM is accessed through 8 KB segments (on the NEO-16, the segment is mirrored).&lt;br /&gt;
&lt;br /&gt;
Up to 16 segments can be accessed, for a total capacity of 128 KB.&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ PARAMETER&lt;br /&gt;
|-&lt;br /&gt;
! 8 || 7 || 6 || 5 || 4 || 3 || 2 || 1&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#AAF;&amp;quot; colspan=&amp;quot;4&amp;quot;| Segment&lt;br /&gt;
|style=&amp;quot;background-color:#BBB;&amp;quot;| 0&lt;br /&gt;
|style=&amp;quot;background-color:#AAF;&amp;quot; colspan=&amp;quot;5&amp;quot;| Bank&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== 0x05: Activate device ====&lt;br /&gt;
Activate or disactivate the given device.&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ PARAMETER&lt;br /&gt;
|-&lt;br /&gt;
! 8 || 7 || 6 || 5 || 4 || 3 || 2 || 1&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#BBB;&amp;quot;| 0&lt;br /&gt;
|style=&amp;quot;background-color:#BBB;&amp;quot;| 0&lt;br /&gt;
|style=&amp;quot;background-color:#BBB;&amp;quot;| 0&lt;br /&gt;
|style=&amp;quot;background-color:#AAF;&amp;quot; colspan=&amp;quot;5&amp;quot;| Device&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Devices:&lt;br /&gt;
* &amp;lt;tt&amp;gt;00&amp;lt;/tt&amp;gt;: MSX-Music (OPLL)&lt;br /&gt;
* &amp;lt;tt&amp;gt;01&amp;lt;/tt&amp;gt;: MSX-Audio&lt;br /&gt;
* &amp;lt;tt&amp;gt;02&amp;lt;/tt&amp;gt;: SCC&lt;br /&gt;
* &amp;lt;tt&amp;gt;03&amp;lt;/tt&amp;gt;: SCC+&lt;br /&gt;
* &amp;lt;tt&amp;gt;04&amp;lt;/tt&amp;gt;: 2nd PSG (port 10h)&lt;br /&gt;
* &amp;lt;tt&amp;gt;05&amp;lt;/tt&amp;gt;: Darky (2 x ePSG)&lt;br /&gt;
* &amp;lt;tt&amp;gt;06&amp;lt;/tt&amp;gt;: Darky Jr. (2 x PSG)&lt;br /&gt;
* &amp;lt;tt&amp;gt;08&amp;lt;/tt&amp;gt;: OPM (SFK-01, SFG-01 et SFG-05 ver.1)&lt;br /&gt;
* &amp;lt;tt&amp;gt;09&amp;lt;/tt&amp;gt;: OPP (SFG-05 ver.2)&lt;br /&gt;
* &amp;lt;tt&amp;gt;12&amp;lt;/tt&amp;gt;: OPL4&lt;br /&gt;
* &amp;lt;tt&amp;gt;15&amp;lt;/tt&amp;gt;: SAM2695&lt;br /&gt;
&lt;br /&gt;
== Appendix ==&lt;br /&gt;
=== Programmable processor and emulation ===&lt;br /&gt;
Here is a pseudo code in C to handle NEO mappers extension for programmable processor based cartridges or for emulators:&lt;br /&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;
// Extended function prototypes&lt;br /&gt;
typedef void (*funcEnable_t)(bool, uint8);&lt;br /&gt;
typedef void (*funcWrite_t)(uint16, uint8);&lt;br /&gt;
typedef uint8 (*funcRead_t)(uint16);&lt;br /&gt;
// Extended functions table&lt;br /&gt;
funcEnable_t funcEnableTable[32];&lt;br /&gt;
funcWrite_t funcWriteTable[3];&lt;br /&gt;
funcRead_t funcReadTable[3];&lt;br /&gt;
&lt;br /&gt;
// Handle device initialization&lt;br /&gt;
void NEO16_Init()&lt;br /&gt;
{&lt;br /&gt;
	for (uint8 i = 0; i &amp;lt; 3; i++)&lt;br /&gt;
	{&lt;br /&gt;
		bankValue[i] = 0x0000;&lt;br /&gt;
		funcWriteTable[i] = NULL;&lt;br /&gt;
		funcReadTable[i] = NULL;		&lt;br /&gt;
	}&lt;br /&gt;
	for (uint8 i = 0; i &amp;lt; 32; i++)&lt;br /&gt;
		funcTab[i] = NULL;&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; // Get the corresponding bank number&lt;br /&gt;
	if (bank &amp;gt; 2)&lt;br /&gt;
		return; // skip&lt;br /&gt;
&lt;br /&gt;
	if (funcWriteTable[bank] != NULL) // Check for bank write callback&lt;br /&gt;
	{&lt;br /&gt;
		funcWriteTable[bank](address, value);&lt;br /&gt;
	}&lt;br /&gt;
	else if ((address &amp;amp; 0x0001) &amp;amp;&amp;amp; (value &amp;amp; 0x80)) // Handle extended function&lt;br /&gt;
	{&lt;br /&gt;
		uint8 funcId = value &amp;amp; 0x3F; // Get function ID&lt;br /&gt;
		if (funcEnableTable[funcId] != NULL)&lt;br /&gt;
			funcEnableTable[funcId](value &amp;amp; 0x40, (address &amp;gt;&amp;gt; 1) &amp;amp; 0xFF); // Execute function specific code&lt;br /&gt;
	}&lt;br /&gt;
	else // Write to the given bank register&lt;br /&gt;
	{&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;
&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; // Get the corresponding bank number&lt;br /&gt;
	if (bank &amp;gt; 2)&lt;br /&gt;
		return 0xFF; // skip&lt;br /&gt;
&lt;br /&gt;
	if (funcReadTable[bank] != NULL) // Check for bank read callback&lt;br /&gt;
		return funcReadTable[bank](address);&lt;br /&gt;
	else&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;
=== Extension example ===&lt;br /&gt;
Here is a pseudo code in C to handle a SRAM extension for NEO mapper:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
uint8 sramSeg; // Current SRAM segment [0:15]&lt;br /&gt;
uint8 sramBank; // Current bank where SRAM is selected (0xFF if not selected)&lt;br /&gt;
uint8* sramData; // SRAM data (hardware specific)&lt;br /&gt;
&lt;br /&gt;
// Write to SRAM&lt;br /&gt;
void SRAM_Write(uint16 address, uint8 value)&lt;br /&gt;
{&lt;br /&gt;
	sramData[(sramSeg * 0x2000) + (address &amp;amp; 0x1FFF)] = value; // &lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// Read from SRAM&lt;br /&gt;
uint8 SRAM_read(uint16 address)&lt;br /&gt;
{&lt;br /&gt;
	return sramData[(sramSeg * 0x2000) + (address &amp;amp; 0x1FFF)];	&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// Enable/disable SRAM feature&lt;br /&gt;
void SRAM_Enable(bool enable, uint8 param)&lt;br /&gt;
{&lt;br /&gt;
	if (sramBank != 0xFF) // Disable previous SRAM registration&lt;br /&gt;
	{&lt;br /&gt;
		if (funcWriteTable[sramBank] == SRAM_Write)&lt;br /&gt;
			funcWriteTable[sramBank] = NULL;&lt;br /&gt;
		if (funcReadTable[sramBank] == SRAM_Read)&lt;br /&gt;
			funcReadTable[sramBank] = NULL;&lt;br /&gt;
		sramBank = 0xFF;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	if (enable) // Enable a SRAM segment in the given bank&lt;br /&gt;
	{&lt;br /&gt;
		uint8 bank = param &amp;amp; 0x07; // Get bank number&lt;br /&gt;
		if (bank &amp;gt; 2)&lt;br /&gt;
			return; // skip (for NEO-16)&lt;br /&gt;
&lt;br /&gt;
		sramSeg = (param &amp;gt;&amp;gt; 4) &amp;amp; 0x0F; // SRAM segment number&lt;br /&gt;
		sramBank = bank;&lt;br /&gt;
		funcWriteTable[sramBank] = SRAM_Write; // Register SRAM callbacks&lt;br /&gt;
		funcReadTable[sramBank] = SRAM_Read;&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// Initialize SRAM feature&lt;br /&gt;
void SRAM_Init()&lt;br /&gt;
{&lt;br /&gt;
	sramBank = 0xFF;&lt;br /&gt;
	funcTab[0x04] = SRAM_Init; // Register to function 0x04 (SRAM/FRAM feature)&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Then, you just need to call &amp;lt;tt&amp;gt;SRAM_Init()&amp;lt;/tt&amp;gt; from &amp;lt;tt&amp;gt;NEO16_Init()&amp;lt;/tt&amp;gt; to register the feature.&lt;/div&gt;</summary>
		<author><name>Aoineko</name></author>	</entry>

	<entry>
		<id>https://aoineko.org/msxgl/index.php?title=NEO_mapper/Extension&amp;diff=3825</id>
		<title>NEO mapper/Extension</title>
		<link rel="alternate" type="text/html" href="https://aoineko.org/msxgl/index.php?title=NEO_mapper/Extension&amp;diff=3825"/>
				<updated>2026-04-13T20:22:32Z</updated>
		
		<summary type="html">&lt;p&gt;Aoineko: /* 0x00: Cartridge information */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{WARNING|This page is still in the proposal stage and should not yet be considered an official specification.}}&lt;br /&gt;
&lt;br /&gt;
Proposal for an extension to the [[NEO mapper]] format.&lt;br /&gt;
&lt;br /&gt;
== Specifications ==&lt;br /&gt;
&lt;br /&gt;
=== Principles ===&lt;br /&gt;
&lt;br /&gt;
Any write operation to the NEO mapper with data bit 7 set to 1 and address bit 0 set to 1 is considered an access to extended features. In that case, the mapper bank register is not modified.&lt;br /&gt;
&lt;br /&gt;
All other write operations should be considered normal access to the mapper's bank register.&lt;br /&gt;
&lt;br /&gt;
The data contains:&lt;br /&gt;
* The number of an extended function in the mapper&lt;br /&gt;
* A bit indicating whether the function should be enabled or disabled&lt;br /&gt;
&lt;br /&gt;
The address contains an 8-bit parameter to be passed to the function.&lt;br /&gt;
{|&lt;br /&gt;
|-&lt;br /&gt;
|&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ ADDRESS&lt;br /&gt;
|-&lt;br /&gt;
! 15 || 14 || 13 || 12 || 11 || 10 || 9 || 8 || 7 || 6 || 5 || 4 || 3 || 2 || 1 || 0&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#BBB;&amp;quot; colspan=&amp;quot;2&amp;quot;| Page&lt;br /&gt;
|style=&amp;quot;background-color:#BBB;&amp;quot; colspan=&amp;quot;3&amp;quot;| Bank&lt;br /&gt;
|style=&amp;quot;background-color:#BBB;&amp;quot;| 0&lt;br /&gt;
|style=&amp;quot;background-color:#BBB;&amp;quot;| 0&lt;br /&gt;
|style=&amp;quot;background-color:#AAF;&amp;quot; colspan=&amp;quot;8&amp;quot;| Parameter&lt;br /&gt;
|style=&amp;quot;background-color:#FAA;&amp;quot;| 1&lt;br /&gt;
|}&lt;br /&gt;
|&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ DATA&lt;br /&gt;
|-&lt;br /&gt;
! 7 || 6 || 5 || 4 || 3 || 2 || 1 || 0&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FAA;&amp;quot;| 1&lt;br /&gt;
|style=&amp;quot;background-color:#AAF;&amp;quot;| A&lt;br /&gt;
|style=&amp;quot;background-color:#BBB;&amp;quot;| 0&lt;br /&gt;
|style=&amp;quot;background-color:#AAF;&amp;quot; colspan=&amp;quot;5&amp;quot;| Function&lt;br /&gt;
|}&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Functions ===&lt;br /&gt;
==== 0x00: Cartridge information ====&lt;br /&gt;
When activated, any read access to the given bank will return the cartridge information (8 KB, mirrored on NEO-16).&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ PARAMETER&lt;br /&gt;
|-&lt;br /&gt;
! 8 || 7 || 6 || 5 || 4 || 3 || 2 || 1&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#BBB;&amp;quot;| 0&lt;br /&gt;
|style=&amp;quot;background-color:#BBB;&amp;quot;| 0&lt;br /&gt;
|style=&amp;quot;background-color:#BBB;&amp;quot;| 0&lt;br /&gt;
|style=&amp;quot;background-color:#BBB;&amp;quot;| 0&lt;br /&gt;
|style=&amp;quot;background-color:#BBB;&amp;quot;| 0&lt;br /&gt;
|style=&amp;quot;background-color:#AAF;&amp;quot; colspan=&amp;quot;5&amp;quot;| Bank&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Examples:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Case || Pseudo-code&lt;br /&gt;
|-&lt;br /&gt;
| Activate information in bank 2 of NEO-16 || &amp;lt;tt&amp;gt;[0x7005] = 0xC0&amp;lt;/tt&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Disactivate information in bank 2 of NEO-16 || &amp;lt;tt&amp;gt;[0x7005] = 0x80&amp;lt;/tt&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== 0x01: Cartridge configuration ====&lt;br /&gt;
&lt;br /&gt;
==== 0x04: Activate SRAM/FRAM ====&lt;br /&gt;
When activated, any read/write access to the specified bank (defined in the parameter) is redirected to the selected segment of the SRAM/FRAM.&lt;br /&gt;
&lt;br /&gt;
SRAM/FRAM is accessed through 8 KB segments (on the NEO-16, the segment is mirrored).&lt;br /&gt;
&lt;br /&gt;
Up to 16 segments can be accessed, for a total capacity of 128 KB.&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ PARAMETER&lt;br /&gt;
|-&lt;br /&gt;
! 8 || 7 || 6 || 5 || 4 || 3 || 2 || 1&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#AAF;&amp;quot; colspan=&amp;quot;4&amp;quot;| Segment&lt;br /&gt;
|style=&amp;quot;background-color:#BBB;&amp;quot;| 0&lt;br /&gt;
|style=&amp;quot;background-color:#AAF;&amp;quot; colspan=&amp;quot;5&amp;quot;| Bank&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== 0x05: Activate device ====&lt;br /&gt;
Activate or disactivate the given device.&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ PARAMETER&lt;br /&gt;
|-&lt;br /&gt;
! 8 || 7 || 6 || 5 || 4 || 3 || 2 || 1&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#BBB;&amp;quot;| 0&lt;br /&gt;
|style=&amp;quot;background-color:#BBB;&amp;quot;| 0&lt;br /&gt;
|style=&amp;quot;background-color:#BBB;&amp;quot;| 0&lt;br /&gt;
|style=&amp;quot;background-color:#AAF;&amp;quot; colspan=&amp;quot;5&amp;quot;| Device&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Devices:&lt;br /&gt;
* &amp;lt;tt&amp;gt;00&amp;lt;/tt&amp;gt;: MSX-Music (OPLL)&lt;br /&gt;
* &amp;lt;tt&amp;gt;01&amp;lt;/tt&amp;gt;: MSX-Audio&lt;br /&gt;
* &amp;lt;tt&amp;gt;02&amp;lt;/tt&amp;gt;: SCC&lt;br /&gt;
* &amp;lt;tt&amp;gt;03&amp;lt;/tt&amp;gt;: SCC+&lt;br /&gt;
* &amp;lt;tt&amp;gt;04&amp;lt;/tt&amp;gt;: 2nd PSG (port 10h)&lt;br /&gt;
* &amp;lt;tt&amp;gt;05&amp;lt;/tt&amp;gt;: Darky (2 x ePSG)&lt;br /&gt;
* &amp;lt;tt&amp;gt;06&amp;lt;/tt&amp;gt;: Darky Jr. (2 x PSG)&lt;br /&gt;
* &amp;lt;tt&amp;gt;08&amp;lt;/tt&amp;gt;: OPM (SFK-01, SFG-01 et SFG-05 ver.1)&lt;br /&gt;
* &amp;lt;tt&amp;gt;09&amp;lt;/tt&amp;gt;: OPP (SFG-05 ver.2)&lt;br /&gt;
* &amp;lt;tt&amp;gt;12&amp;lt;/tt&amp;gt;: OPL4&lt;br /&gt;
* &amp;lt;tt&amp;gt;15&amp;lt;/tt&amp;gt;: SAM2695&lt;br /&gt;
&lt;br /&gt;
== Appendix ==&lt;br /&gt;
=== Programmable processor and emulation ===&lt;br /&gt;
Here is a pseudo code in C to handle NEO mappers extension for programmable processor based cartridges or for emulators:&lt;br /&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;
// Extended function prototypes&lt;br /&gt;
typedef void (*funcEnable_t)(bool, uint8);&lt;br /&gt;
typedef void (*funcWrite_t)(uint16, uint8);&lt;br /&gt;
typedef uint8 (*funcRead_t)(uint16);&lt;br /&gt;
// Extended functions table&lt;br /&gt;
funcEnable_t funcEnableTable[32];&lt;br /&gt;
funcWrite_t funcWriteTable[3];&lt;br /&gt;
funcRead_t funcReadTable[3];&lt;br /&gt;
&lt;br /&gt;
// Handle device initialization&lt;br /&gt;
void NEO16_Init()&lt;br /&gt;
{&lt;br /&gt;
	for (uint8 i = 0; i &amp;lt; 3; i++)&lt;br /&gt;
	{&lt;br /&gt;
		bankValue[i] = 0x0000;&lt;br /&gt;
		funcWriteTable[i] = NULL;&lt;br /&gt;
		funcReadTable[i] = NULL;		&lt;br /&gt;
	}&lt;br /&gt;
	for (uint8 i = 0; i &amp;lt; 32; i++)&lt;br /&gt;
		funcTab[i] = NULL;&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; // Get the corresponding bank number&lt;br /&gt;
	if (bank &amp;gt; 2)&lt;br /&gt;
		return; // skip&lt;br /&gt;
&lt;br /&gt;
	if (funcWriteTable[bank] != NULL) // Check for bank write callback&lt;br /&gt;
	{&lt;br /&gt;
		funcWriteTable[bank](address, value);&lt;br /&gt;
	}&lt;br /&gt;
	else if ((address &amp;amp; 0x0001) &amp;amp;&amp;amp; (value &amp;amp; 0x80)) // Handle extended function&lt;br /&gt;
	{&lt;br /&gt;
		uint8 funcId = value &amp;amp; 0x3F; // Get function ID&lt;br /&gt;
		if (funcEnableTable[funcId] != NULL)&lt;br /&gt;
			funcEnableTable[funcId](value &amp;amp; 0x40, (address &amp;gt;&amp;gt; 1) &amp;amp; 0xFF); // Execute function specific code&lt;br /&gt;
	}&lt;br /&gt;
	else // Write to the given bank register&lt;br /&gt;
	{&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;
&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; // Get the corresponding bank number&lt;br /&gt;
	if (bank &amp;gt; 2)&lt;br /&gt;
		return 0xFF; // skip&lt;br /&gt;
&lt;br /&gt;
	if (funcReadTable[bank] != NULL) // Check for bank read callback&lt;br /&gt;
		return funcReadTable[bank](address);&lt;br /&gt;
	else&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;
=== Extension example ===&lt;br /&gt;
Here is a pseudo code in C to handle a SRAM extension for NEO mapper:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
uint8 sramSeg; // Current SRAM segment [0:15]&lt;br /&gt;
uint8 sramBank; // Current bank where SRAM is selected (0xFF if not selected)&lt;br /&gt;
uint8* sramData; // SRAM data (hardware specific)&lt;br /&gt;
&lt;br /&gt;
// Write to SRAM&lt;br /&gt;
void SRAM_Write(uint16 address, uint8 value)&lt;br /&gt;
{&lt;br /&gt;
	sramData[(sramSeg * 0x2000) + (address &amp;amp; 0x1FFF)] = value; // &lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// Read from SRAM&lt;br /&gt;
uint8 SRAM_read(uint16 address)&lt;br /&gt;
{&lt;br /&gt;
	return sramData[(sramSeg * 0x2000) + (address &amp;amp; 0x1FFF)];	&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// Enable/disable SRAM feature&lt;br /&gt;
void SRAM_Enable(bool enable, uint8 param)&lt;br /&gt;
{&lt;br /&gt;
	if (sramBank != 0xFF) // Disable previous SRAM registration&lt;br /&gt;
	{&lt;br /&gt;
		if (funcWriteTable[sramBank] == SRAM_Write)&lt;br /&gt;
			funcWriteTable[sramBank] = NULL;&lt;br /&gt;
		if (funcReadTable[sramBank] == SRAM_Read)&lt;br /&gt;
			funcReadTable[sramBank] = NULL;&lt;br /&gt;
		sramBank = 0xFF;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	if (enable) // Enable a SRAM segment in the given bank&lt;br /&gt;
	{&lt;br /&gt;
		uint8 bank = param &amp;amp; 0x07; // Get bank number&lt;br /&gt;
		if (bank &amp;gt; 2)&lt;br /&gt;
			return; // skip (for NEO-16)&lt;br /&gt;
&lt;br /&gt;
		sramSeg = (param &amp;gt;&amp;gt; 4) &amp;amp; 0x0F; // SRAM segment number&lt;br /&gt;
		sramBank = bank;&lt;br /&gt;
		funcWriteTable[sramBank] = SRAM_Write; // Register SRAM callbacks&lt;br /&gt;
		funcReadTable[sramBank] = SRAM_Read;&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// Initialize SRAM feature&lt;br /&gt;
void SRAM_Init()&lt;br /&gt;
{&lt;br /&gt;
	sramBank = 0xFF;&lt;br /&gt;
	funcTab[0x04] = SRAM_Init; // Register to function 0x04 (SRAM/FRAM feature)&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Then, you just need to call &amp;lt;tt&amp;gt;SRAM_Init()&amp;lt;/tt&amp;gt; from &amp;lt;tt&amp;gt;NEO16_Init()&amp;lt;/tt&amp;gt; to register the feature.&lt;/div&gt;</summary>
		<author><name>Aoineko</name></author>	</entry>

	<entry>
		<id>https://aoineko.org/msxgl/index.php?title=NEO_mapper/Extension&amp;diff=3824</id>
		<title>NEO mapper/Extension</title>
		<link rel="alternate" type="text/html" href="https://aoineko.org/msxgl/index.php?title=NEO_mapper/Extension&amp;diff=3824"/>
				<updated>2026-04-13T20:21:41Z</updated>
		
		<summary type="html">&lt;p&gt;Aoineko: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{WARNING|This page is still in the proposal stage and should not yet be considered an official specification.}}&lt;br /&gt;
&lt;br /&gt;
Proposal for an extension to the [[NEO mapper]] format.&lt;br /&gt;
&lt;br /&gt;
== Specifications ==&lt;br /&gt;
&lt;br /&gt;
=== Principles ===&lt;br /&gt;
&lt;br /&gt;
Any write operation to the NEO mapper with data bit 7 set to 1 and address bit 0 set to 1 is considered an access to extended features. In that case, the mapper bank register is not modified.&lt;br /&gt;
&lt;br /&gt;
All other write operations should be considered normal access to the mapper's bank register.&lt;br /&gt;
&lt;br /&gt;
The data contains:&lt;br /&gt;
* The number of an extended function in the mapper&lt;br /&gt;
* A bit indicating whether the function should be enabled or disabled&lt;br /&gt;
&lt;br /&gt;
The address contains an 8-bit parameter to be passed to the function.&lt;br /&gt;
{|&lt;br /&gt;
|-&lt;br /&gt;
|&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ ADDRESS&lt;br /&gt;
|-&lt;br /&gt;
! 15 || 14 || 13 || 12 || 11 || 10 || 9 || 8 || 7 || 6 || 5 || 4 || 3 || 2 || 1 || 0&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#BBB;&amp;quot; colspan=&amp;quot;2&amp;quot;| Page&lt;br /&gt;
|style=&amp;quot;background-color:#BBB;&amp;quot; colspan=&amp;quot;3&amp;quot;| Bank&lt;br /&gt;
|style=&amp;quot;background-color:#BBB;&amp;quot;| 0&lt;br /&gt;
|style=&amp;quot;background-color:#BBB;&amp;quot;| 0&lt;br /&gt;
|style=&amp;quot;background-color:#AAF;&amp;quot; colspan=&amp;quot;8&amp;quot;| Parameter&lt;br /&gt;
|style=&amp;quot;background-color:#FAA;&amp;quot;| 1&lt;br /&gt;
|}&lt;br /&gt;
|&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ DATA&lt;br /&gt;
|-&lt;br /&gt;
! 7 || 6 || 5 || 4 || 3 || 2 || 1 || 0&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FAA;&amp;quot;| 1&lt;br /&gt;
|style=&amp;quot;background-color:#AAF;&amp;quot;| A&lt;br /&gt;
|style=&amp;quot;background-color:#BBB;&amp;quot;| 0&lt;br /&gt;
|style=&amp;quot;background-color:#AAF;&amp;quot; colspan=&amp;quot;5&amp;quot;| Function&lt;br /&gt;
|}&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Functions ===&lt;br /&gt;
==== 0x00: Cartridge information ====&lt;br /&gt;
When activated, any read access to the given bank will return the cartridge information (8 KB, mirrored on NEO-16).&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ PARAMETER&lt;br /&gt;
|-&lt;br /&gt;
! 8 || 7 || 6 || 5 || 4 || 3 || 2 || 1&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#BBB;&amp;quot;| 0&lt;br /&gt;
|style=&amp;quot;background-color:#BBB;&amp;quot;| 0&lt;br /&gt;
|style=&amp;quot;background-color:#BBB;&amp;quot;| 0&lt;br /&gt;
|style=&amp;quot;background-color:#BBB;&amp;quot;| 0&lt;br /&gt;
|style=&amp;quot;background-color:#BBB;&amp;quot;| 0&lt;br /&gt;
|style=&amp;quot;background-color:#AAF;&amp;quot; colspan=&amp;quot;5&amp;quot;| Bank&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Examples:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Case ||&lt;br /&gt;
|-&lt;br /&gt;
| Activate information in bank 2 of NEO-16 || &amp;lt;tt&amp;gt;[0x7005] = 0xC0&amp;lt;/tt&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
==== 0x01: Cartridge configuration ====&lt;br /&gt;
&lt;br /&gt;
==== 0x04: Activate SRAM/FRAM ====&lt;br /&gt;
When activated, any read/write access to the specified bank (defined in the parameter) is redirected to the selected segment of the SRAM/FRAM.&lt;br /&gt;
&lt;br /&gt;
SRAM/FRAM is accessed through 8 KB segments (on the NEO-16, the segment is mirrored).&lt;br /&gt;
&lt;br /&gt;
Up to 16 segments can be accessed, for a total capacity of 128 KB.&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ PARAMETER&lt;br /&gt;
|-&lt;br /&gt;
! 8 || 7 || 6 || 5 || 4 || 3 || 2 || 1&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#AAF;&amp;quot; colspan=&amp;quot;4&amp;quot;| Segment&lt;br /&gt;
|style=&amp;quot;background-color:#BBB;&amp;quot;| 0&lt;br /&gt;
|style=&amp;quot;background-color:#AAF;&amp;quot; colspan=&amp;quot;5&amp;quot;| Bank&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== 0x05: Activate device ====&lt;br /&gt;
Activate or disactivate the given device.&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ PARAMETER&lt;br /&gt;
|-&lt;br /&gt;
! 8 || 7 || 6 || 5 || 4 || 3 || 2 || 1&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#BBB;&amp;quot;| 0&lt;br /&gt;
|style=&amp;quot;background-color:#BBB;&amp;quot;| 0&lt;br /&gt;
|style=&amp;quot;background-color:#BBB;&amp;quot;| 0&lt;br /&gt;
|style=&amp;quot;background-color:#AAF;&amp;quot; colspan=&amp;quot;5&amp;quot;| Device&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Devices:&lt;br /&gt;
* &amp;lt;tt&amp;gt;00&amp;lt;/tt&amp;gt;: MSX-Music (OPLL)&lt;br /&gt;
* &amp;lt;tt&amp;gt;01&amp;lt;/tt&amp;gt;: MSX-Audio&lt;br /&gt;
* &amp;lt;tt&amp;gt;02&amp;lt;/tt&amp;gt;: SCC&lt;br /&gt;
* &amp;lt;tt&amp;gt;03&amp;lt;/tt&amp;gt;: SCC+&lt;br /&gt;
* &amp;lt;tt&amp;gt;04&amp;lt;/tt&amp;gt;: 2nd PSG (port 10h)&lt;br /&gt;
* &amp;lt;tt&amp;gt;05&amp;lt;/tt&amp;gt;: Darky (2 x ePSG)&lt;br /&gt;
* &amp;lt;tt&amp;gt;06&amp;lt;/tt&amp;gt;: Darky Jr. (2 x PSG)&lt;br /&gt;
* &amp;lt;tt&amp;gt;08&amp;lt;/tt&amp;gt;: OPM (SFK-01, SFG-01 et SFG-05 ver.1)&lt;br /&gt;
* &amp;lt;tt&amp;gt;09&amp;lt;/tt&amp;gt;: OPP (SFG-05 ver.2)&lt;br /&gt;
* &amp;lt;tt&amp;gt;12&amp;lt;/tt&amp;gt;: OPL4&lt;br /&gt;
* &amp;lt;tt&amp;gt;15&amp;lt;/tt&amp;gt;: SAM2695&lt;br /&gt;
&lt;br /&gt;
== Appendix ==&lt;br /&gt;
=== Programmable processor and emulation ===&lt;br /&gt;
Here is a pseudo code in C to handle NEO mappers extension for programmable processor based cartridges or for emulators:&lt;br /&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;
// Extended function prototypes&lt;br /&gt;
typedef void (*funcEnable_t)(bool, uint8);&lt;br /&gt;
typedef void (*funcWrite_t)(uint16, uint8);&lt;br /&gt;
typedef uint8 (*funcRead_t)(uint16);&lt;br /&gt;
// Extended functions table&lt;br /&gt;
funcEnable_t funcEnableTable[32];&lt;br /&gt;
funcWrite_t funcWriteTable[3];&lt;br /&gt;
funcRead_t funcReadTable[3];&lt;br /&gt;
&lt;br /&gt;
// Handle device initialization&lt;br /&gt;
void NEO16_Init()&lt;br /&gt;
{&lt;br /&gt;
	for (uint8 i = 0; i &amp;lt; 3; i++)&lt;br /&gt;
	{&lt;br /&gt;
		bankValue[i] = 0x0000;&lt;br /&gt;
		funcWriteTable[i] = NULL;&lt;br /&gt;
		funcReadTable[i] = NULL;		&lt;br /&gt;
	}&lt;br /&gt;
	for (uint8 i = 0; i &amp;lt; 32; i++)&lt;br /&gt;
		funcTab[i] = NULL;&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; // Get the corresponding bank number&lt;br /&gt;
	if (bank &amp;gt; 2)&lt;br /&gt;
		return; // skip&lt;br /&gt;
&lt;br /&gt;
	if (funcWriteTable[bank] != NULL) // Check for bank write callback&lt;br /&gt;
	{&lt;br /&gt;
		funcWriteTable[bank](address, value);&lt;br /&gt;
	}&lt;br /&gt;
	else if ((address &amp;amp; 0x0001) &amp;amp;&amp;amp; (value &amp;amp; 0x80)) // Handle extended function&lt;br /&gt;
	{&lt;br /&gt;
		uint8 funcId = value &amp;amp; 0x3F; // Get function ID&lt;br /&gt;
		if (funcEnableTable[funcId] != NULL)&lt;br /&gt;
			funcEnableTable[funcId](value &amp;amp; 0x40, (address &amp;gt;&amp;gt; 1) &amp;amp; 0xFF); // Execute function specific code&lt;br /&gt;
	}&lt;br /&gt;
	else // Write to the given bank register&lt;br /&gt;
	{&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;
&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; // Get the corresponding bank number&lt;br /&gt;
	if (bank &amp;gt; 2)&lt;br /&gt;
		return 0xFF; // skip&lt;br /&gt;
&lt;br /&gt;
	if (funcReadTable[bank] != NULL) // Check for bank read callback&lt;br /&gt;
		return funcReadTable[bank](address);&lt;br /&gt;
	else&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;
=== Extension example ===&lt;br /&gt;
Here is a pseudo code in C to handle a SRAM extension for NEO mapper:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
uint8 sramSeg; // Current SRAM segment [0:15]&lt;br /&gt;
uint8 sramBank; // Current bank where SRAM is selected (0xFF if not selected)&lt;br /&gt;
uint8* sramData; // SRAM data (hardware specific)&lt;br /&gt;
&lt;br /&gt;
// Write to SRAM&lt;br /&gt;
void SRAM_Write(uint16 address, uint8 value)&lt;br /&gt;
{&lt;br /&gt;
	sramData[(sramSeg * 0x2000) + (address &amp;amp; 0x1FFF)] = value; // &lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// Read from SRAM&lt;br /&gt;
uint8 SRAM_read(uint16 address)&lt;br /&gt;
{&lt;br /&gt;
	return sramData[(sramSeg * 0x2000) + (address &amp;amp; 0x1FFF)];	&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// Enable/disable SRAM feature&lt;br /&gt;
void SRAM_Enable(bool enable, uint8 param)&lt;br /&gt;
{&lt;br /&gt;
	if (sramBank != 0xFF) // Disable previous SRAM registration&lt;br /&gt;
	{&lt;br /&gt;
		if (funcWriteTable[sramBank] == SRAM_Write)&lt;br /&gt;
			funcWriteTable[sramBank] = NULL;&lt;br /&gt;
		if (funcReadTable[sramBank] == SRAM_Read)&lt;br /&gt;
			funcReadTable[sramBank] = NULL;&lt;br /&gt;
		sramBank = 0xFF;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	if (enable) // Enable a SRAM segment in the given bank&lt;br /&gt;
	{&lt;br /&gt;
		uint8 bank = param &amp;amp; 0x07; // Get bank number&lt;br /&gt;
		if (bank &amp;gt; 2)&lt;br /&gt;
			return; // skip (for NEO-16)&lt;br /&gt;
&lt;br /&gt;
		sramSeg = (param &amp;gt;&amp;gt; 4) &amp;amp; 0x0F; // SRAM segment number&lt;br /&gt;
		sramBank = bank;&lt;br /&gt;
		funcWriteTable[sramBank] = SRAM_Write; // Register SRAM callbacks&lt;br /&gt;
		funcReadTable[sramBank] = SRAM_Read;&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// Initialize SRAM feature&lt;br /&gt;
void SRAM_Init()&lt;br /&gt;
{&lt;br /&gt;
	sramBank = 0xFF;&lt;br /&gt;
	funcTab[0x04] = SRAM_Init; // Register to function 0x04 (SRAM/FRAM feature)&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Then, you just need to call &amp;lt;tt&amp;gt;SRAM_Init()&amp;lt;/tt&amp;gt; from &amp;lt;tt&amp;gt;NEO16_Init()&amp;lt;/tt&amp;gt; to register the feature.&lt;/div&gt;</summary>
		<author><name>Aoineko</name></author>	</entry>

	<entry>
		<id>https://aoineko.org/msxgl/index.php?title=NEO_mapper/Extension&amp;diff=3823</id>
		<title>NEO mapper/Extension</title>
		<link rel="alternate" type="text/html" href="https://aoineko.org/msxgl/index.php?title=NEO_mapper/Extension&amp;diff=3823"/>
				<updated>2026-04-13T20:18:45Z</updated>
		
		<summary type="html">&lt;p&gt;Aoineko: /* 0x00: Cartridge information */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{WARNING|This page is still in the proposal stage and should not yet be considered an official specification.}}&lt;br /&gt;
&lt;br /&gt;
Proposal for an extension to the [[NEO mapper]] format.&lt;br /&gt;
&lt;br /&gt;
== Specifications ==&lt;br /&gt;
&lt;br /&gt;
=== Principles ===&lt;br /&gt;
&lt;br /&gt;
Any write operation to the NEO mapper with data bit 7 set to 1 and address bit 0 set to 1 is considered an access to extended features. In that case, the mapper bank register is not modified.&lt;br /&gt;
&lt;br /&gt;
All other write operations should be considered normal access to the mapper's bank register.&lt;br /&gt;
&lt;br /&gt;
The data contains:&lt;br /&gt;
* The number of an extended function in the mapper&lt;br /&gt;
* A bit indicating whether the function should be enabled or disabled&lt;br /&gt;
&lt;br /&gt;
The address contains an 8-bit parameter to be passed to the function.&lt;br /&gt;
{|&lt;br /&gt;
|-&lt;br /&gt;
|&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ ADDRESS&lt;br /&gt;
|-&lt;br /&gt;
! 15 || 14 || 13 || 12 || 11 || 10 || 9 || 8 || 7 || 6 || 5 || 4 || 3 || 2 || 1 || 0&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#BBB;&amp;quot; colspan=&amp;quot;2&amp;quot;| Page&lt;br /&gt;
|style=&amp;quot;background-color:#BBB;&amp;quot; colspan=&amp;quot;3&amp;quot;| Bank&lt;br /&gt;
|style=&amp;quot;background-color:#BBB;&amp;quot;| 0&lt;br /&gt;
|style=&amp;quot;background-color:#BBB;&amp;quot;| 0&lt;br /&gt;
|style=&amp;quot;background-color:#AAF;&amp;quot; colspan=&amp;quot;8&amp;quot;| Parameter&lt;br /&gt;
|style=&amp;quot;background-color:#FAA;&amp;quot;| 1&lt;br /&gt;
|}&lt;br /&gt;
|&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ DATA&lt;br /&gt;
|-&lt;br /&gt;
! 7 || 6 || 5 || 4 || 3 || 2 || 1 || 0&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FAA;&amp;quot;| 1&lt;br /&gt;
|style=&amp;quot;background-color:#AAF;&amp;quot;| A&lt;br /&gt;
|style=&amp;quot;background-color:#BBB;&amp;quot;| 0&lt;br /&gt;
|style=&amp;quot;background-color:#AAF;&amp;quot; colspan=&amp;quot;5&amp;quot;| Function&lt;br /&gt;
|}&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Functions ===&lt;br /&gt;
==== 0x00: Cartridge information ====&lt;br /&gt;
When activated, any read access to the given bank will return the cartridge information (8 KB, mirrored on NEO-16).&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ PARAMETER&lt;br /&gt;
|-&lt;br /&gt;
! 8 || 7 || 6 || 5 || 4 || 3 || 2 || 1&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#BBB;&amp;quot;| 0&lt;br /&gt;
|style=&amp;quot;background-color:#BBB;&amp;quot;| 0&lt;br /&gt;
|style=&amp;quot;background-color:#BBB;&amp;quot;| 0&lt;br /&gt;
|style=&amp;quot;background-color:#BBB;&amp;quot;| 0&lt;br /&gt;
|style=&amp;quot;background-color:#BBB;&amp;quot;| 0&lt;br /&gt;
|style=&amp;quot;background-color:#AAF;&amp;quot; colspan=&amp;quot;5&amp;quot;| Bank&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Examples:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Case ||&lt;br /&gt;
|-&lt;br /&gt;
| Activate information in bank 2 of NEO-16 || &amp;lt;tt&amp;gt;[0x] = 0x02&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== 0x01: Cartridge configuration ====&lt;br /&gt;
&lt;br /&gt;
==== 0x04: Activate SRAM/FRAM ====&lt;br /&gt;
When activated, any read/write access to the specified bank (defined in the parameter) is redirected to the selected segment of the SRAM/FRAM.&lt;br /&gt;
&lt;br /&gt;
SRAM/FRAM is accessed through 8 KB segments (on the NEO-16, the segment is mirrored).&lt;br /&gt;
&lt;br /&gt;
Up to 16 segments can be accessed, for a total capacity of 128 KB.&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ PARAMETER&lt;br /&gt;
|-&lt;br /&gt;
! 8 || 7 || 6 || 5 || 4 || 3 || 2 || 1&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#AAF;&amp;quot; colspan=&amp;quot;4&amp;quot;| Segment&lt;br /&gt;
|style=&amp;quot;background-color:#BBB;&amp;quot;| 0&lt;br /&gt;
|style=&amp;quot;background-color:#AAF;&amp;quot; colspan=&amp;quot;5&amp;quot;| Bank&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== 0x05: Activate device ====&lt;br /&gt;
Activate or disactivate the given device.&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ PARAMETER&lt;br /&gt;
|-&lt;br /&gt;
! 8 || 7 || 6 || 5 || 4 || 3 || 2 || 1&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#BBB;&amp;quot;| 0&lt;br /&gt;
|style=&amp;quot;background-color:#BBB;&amp;quot;| 0&lt;br /&gt;
|style=&amp;quot;background-color:#BBB;&amp;quot;| 0&lt;br /&gt;
|style=&amp;quot;background-color:#AAF;&amp;quot; colspan=&amp;quot;5&amp;quot;| Device&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Devices:&lt;br /&gt;
* &amp;lt;tt&amp;gt;00&amp;lt;/tt&amp;gt;: MSX-Music (OPLL)&lt;br /&gt;
* &amp;lt;tt&amp;gt;01&amp;lt;/tt&amp;gt;: MSX-Audio&lt;br /&gt;
* &amp;lt;tt&amp;gt;02&amp;lt;/tt&amp;gt;: SCC&lt;br /&gt;
* &amp;lt;tt&amp;gt;03&amp;lt;/tt&amp;gt;: SCC+&lt;br /&gt;
* &amp;lt;tt&amp;gt;04&amp;lt;/tt&amp;gt;: 2nd PSG (port 10h)&lt;br /&gt;
* &amp;lt;tt&amp;gt;05&amp;lt;/tt&amp;gt;: Darky (2 x ePSG)&lt;br /&gt;
* &amp;lt;tt&amp;gt;06&amp;lt;/tt&amp;gt;: Darky Jr. (2 x PSG)&lt;br /&gt;
* &amp;lt;tt&amp;gt;08&amp;lt;/tt&amp;gt;: OPM (SFK-01, SFG-01 et SFG-05 ver.1)&lt;br /&gt;
* &amp;lt;tt&amp;gt;09&amp;lt;/tt&amp;gt;: OPP (SFG-05 ver.2)&lt;br /&gt;
* &amp;lt;tt&amp;gt;12&amp;lt;/tt&amp;gt;: OPL4&lt;br /&gt;
* &amp;lt;tt&amp;gt;15&amp;lt;/tt&amp;gt;: SAM2695&lt;br /&gt;
&lt;br /&gt;
== Appendix ==&lt;br /&gt;
=== Programmable processor and emulation ===&lt;br /&gt;
Here is a pseudo code in C to handle NEO mappers extension for programmable processor based cartridges or for emulators:&lt;br /&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;
// Extended function prototypes&lt;br /&gt;
typedef void (*funcEnable_t)(bool, uint8);&lt;br /&gt;
typedef void (*funcWrite_t)(uint16, uint8);&lt;br /&gt;
typedef uint8 (*funcRead_t)(uint16);&lt;br /&gt;
// Extended functions table&lt;br /&gt;
funcEnable_t funcEnableTable[32];&lt;br /&gt;
funcWrite_t funcWriteTable[3];&lt;br /&gt;
funcRead_t funcReadTable[3];&lt;br /&gt;
&lt;br /&gt;
// Handle device initialization&lt;br /&gt;
void NEO16_Init()&lt;br /&gt;
{&lt;br /&gt;
	for (uint8 i = 0; i &amp;lt; 3; i++)&lt;br /&gt;
	{&lt;br /&gt;
		bankValue[i] = 0x0000;&lt;br /&gt;
		funcWriteTable[i] = NULL;&lt;br /&gt;
		funcReadTable[i] = NULL;		&lt;br /&gt;
	}&lt;br /&gt;
	for (uint8 i = 0; i &amp;lt; 32; i++)&lt;br /&gt;
		funcTab[i] = NULL;&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; // Get the corresponding bank number&lt;br /&gt;
	if (bank &amp;gt; 2)&lt;br /&gt;
		return; // skip&lt;br /&gt;
&lt;br /&gt;
	if (funcWriteTable[bank] != NULL) // Check for bank write callback&lt;br /&gt;
	{&lt;br /&gt;
		funcWriteTable[bank](address, value);&lt;br /&gt;
	}&lt;br /&gt;
	else if ((address &amp;amp; 0x0001) &amp;amp;&amp;amp; (value &amp;amp; 0x80)) // Handle extended function&lt;br /&gt;
	{&lt;br /&gt;
		uint8 funcId = value &amp;amp; 0x3F; // Get function ID&lt;br /&gt;
		if (funcEnableTable[funcId] != NULL)&lt;br /&gt;
			funcEnableTable[funcId](value &amp;amp; 0x40, (address &amp;gt;&amp;gt; 1) &amp;amp; 0xFF); // Execute function specific code&lt;br /&gt;
	}&lt;br /&gt;
	else // Write to the given bank register&lt;br /&gt;
	{&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;
&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; // Get the corresponding bank number&lt;br /&gt;
	if (bank &amp;gt; 2)&lt;br /&gt;
		return 0xFF; // skip&lt;br /&gt;
&lt;br /&gt;
	if (funcReadTable[bank] != NULL) // Check for bank read callback&lt;br /&gt;
		return funcReadTable[bank](address);&lt;br /&gt;
	else&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;
=== Extension example ===&lt;br /&gt;
Here is a pseudo code in C to handle a SRAM extension for NEO mapper:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
uint8 sramSeg; // Current SRAM segment [0:15]&lt;br /&gt;
uint8 sramBank; // Current bank where SRAM is selected (0xFF if not selected)&lt;br /&gt;
uint8* sramData; // SRAM data (hardware specific)&lt;br /&gt;
&lt;br /&gt;
// Write to SRAM&lt;br /&gt;
void SRAM_Write(uint16 address, uint8 value)&lt;br /&gt;
{&lt;br /&gt;
	sramData[(sramSeg * 0x2000) + (address &amp;amp; 0x1FFF)] = value; // &lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// Read from SRAM&lt;br /&gt;
uint8 SRAM_read(uint16 address)&lt;br /&gt;
{&lt;br /&gt;
	return sramData[(sramSeg * 0x2000) + (address &amp;amp; 0x1FFF)];	&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// Enable/disable SRAM feature&lt;br /&gt;
void SRAM_Enable(bool enable, uint8 param)&lt;br /&gt;
{&lt;br /&gt;
	if (sramBank != 0xFF) // Disable previous SRAM registration&lt;br /&gt;
	{&lt;br /&gt;
		if (funcWriteTable[sramBank] == SRAM_Write)&lt;br /&gt;
			funcWriteTable[sramBank] = NULL;&lt;br /&gt;
		if (funcReadTable[sramBank] == SRAM_Read)&lt;br /&gt;
			funcReadTable[sramBank] = NULL;&lt;br /&gt;
		sramBank = 0xFF;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	if (enable) // Enable a SRAM segment in the given bank&lt;br /&gt;
	{&lt;br /&gt;
		uint8 bank = param &amp;amp; 0x07; // Get bank number&lt;br /&gt;
		if (bank &amp;gt; 2)&lt;br /&gt;
			return; // skip (for NEO-16)&lt;br /&gt;
&lt;br /&gt;
		sramSeg = (param &amp;gt;&amp;gt; 4) &amp;amp; 0x0F; // SRAM segment number&lt;br /&gt;
		sramBank = bank;&lt;br /&gt;
		funcWriteTable[sramBank] = SRAM_Write; // Register SRAM callbacks&lt;br /&gt;
		funcReadTable[sramBank] = SRAM_Read;&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// Initialize SRAM feature&lt;br /&gt;
void SRAM_Init()&lt;br /&gt;
{&lt;br /&gt;
	sramBank = 0xFF;&lt;br /&gt;
	funcTab[0x04] = SRAM_Init; // Register to function 0x04 (SRAM/FRAM feature)&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Then, you just need to call &amp;lt;tt&amp;gt;SRAM_Init()&amp;lt;/tt&amp;gt; from &amp;lt;tt&amp;gt;NEO16_Init()&amp;lt;/tt&amp;gt; to register the feature.&lt;/div&gt;</summary>
		<author><name>Aoineko</name></author>	</entry>

	<entry>
		<id>https://aoineko.org/msxgl/index.php?title=NEO_mapper/Extension&amp;diff=3822</id>
		<title>NEO mapper/Extension</title>
		<link rel="alternate" type="text/html" href="https://aoineko.org/msxgl/index.php?title=NEO_mapper/Extension&amp;diff=3822"/>
				<updated>2026-04-06T21:13:09Z</updated>
		
		<summary type="html">&lt;p&gt;Aoineko: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{WARNING|This page is still in the proposal stage and should not yet be considered an official specification.}}&lt;br /&gt;
&lt;br /&gt;
Proposal for an extension to the [[NEO mapper]] format.&lt;br /&gt;
&lt;br /&gt;
== Specifications ==&lt;br /&gt;
&lt;br /&gt;
=== Principles ===&lt;br /&gt;
&lt;br /&gt;
Any write operation to the NEO mapper with data bit 7 set to 1 and address bit 0 set to 1 is considered an access to extended features. In that case, the mapper bank register is not modified.&lt;br /&gt;
&lt;br /&gt;
All other write operations should be considered normal access to the mapper's bank register.&lt;br /&gt;
&lt;br /&gt;
The data contains:&lt;br /&gt;
* The number of an extended function in the mapper&lt;br /&gt;
* A bit indicating whether the function should be enabled or disabled&lt;br /&gt;
&lt;br /&gt;
The address contains an 8-bit parameter to be passed to the function.&lt;br /&gt;
{|&lt;br /&gt;
|-&lt;br /&gt;
|&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ ADDRESS&lt;br /&gt;
|-&lt;br /&gt;
! 15 || 14 || 13 || 12 || 11 || 10 || 9 || 8 || 7 || 6 || 5 || 4 || 3 || 2 || 1 || 0&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#BBB;&amp;quot; colspan=&amp;quot;2&amp;quot;| Page&lt;br /&gt;
|style=&amp;quot;background-color:#BBB;&amp;quot; colspan=&amp;quot;3&amp;quot;| Bank&lt;br /&gt;
|style=&amp;quot;background-color:#BBB;&amp;quot;| 0&lt;br /&gt;
|style=&amp;quot;background-color:#BBB;&amp;quot;| 0&lt;br /&gt;
|style=&amp;quot;background-color:#AAF;&amp;quot; colspan=&amp;quot;8&amp;quot;| Parameter&lt;br /&gt;
|style=&amp;quot;background-color:#FAA;&amp;quot;| 1&lt;br /&gt;
|}&lt;br /&gt;
|&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ DATA&lt;br /&gt;
|-&lt;br /&gt;
! 7 || 6 || 5 || 4 || 3 || 2 || 1 || 0&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FAA;&amp;quot;| 1&lt;br /&gt;
|style=&amp;quot;background-color:#AAF;&amp;quot;| A&lt;br /&gt;
|style=&amp;quot;background-color:#BBB;&amp;quot;| 0&lt;br /&gt;
|style=&amp;quot;background-color:#AAF;&amp;quot; colspan=&amp;quot;5&amp;quot;| Function&lt;br /&gt;
|}&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Functions ===&lt;br /&gt;
==== 0x00: Cartridge information ====&lt;br /&gt;
When activated, any read access to the given bank will return the cartridge information (8 KB, mirrored on NEO-16).&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ PARAMETER&lt;br /&gt;
|-&lt;br /&gt;
! 8 || 7 || 6 || 5 || 4 || 3 || 2 || 1&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#BBB;&amp;quot;| 0&lt;br /&gt;
|style=&amp;quot;background-color:#BBB;&amp;quot;| 0&lt;br /&gt;
|style=&amp;quot;background-color:#BBB;&amp;quot;| 0&lt;br /&gt;
|style=&amp;quot;background-color:#BBB;&amp;quot;| 0&lt;br /&gt;
|style=&amp;quot;background-color:#BBB;&amp;quot;| 0&lt;br /&gt;
|style=&amp;quot;background-color:#AAF;&amp;quot; colspan=&amp;quot;5&amp;quot;| Bank&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== 0x01: Cartridge configuration ====&lt;br /&gt;
&lt;br /&gt;
==== 0x04: Activate SRAM/FRAM ====&lt;br /&gt;
When activated, any read/write access to the specified bank (defined in the parameter) is redirected to the selected segment of the SRAM/FRAM.&lt;br /&gt;
&lt;br /&gt;
SRAM/FRAM is accessed through 8 KB segments (on the NEO-16, the segment is mirrored).&lt;br /&gt;
&lt;br /&gt;
Up to 16 segments can be accessed, for a total capacity of 128 KB.&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ PARAMETER&lt;br /&gt;
|-&lt;br /&gt;
! 8 || 7 || 6 || 5 || 4 || 3 || 2 || 1&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#AAF;&amp;quot; colspan=&amp;quot;4&amp;quot;| Segment&lt;br /&gt;
|style=&amp;quot;background-color:#BBB;&amp;quot;| 0&lt;br /&gt;
|style=&amp;quot;background-color:#AAF;&amp;quot; colspan=&amp;quot;5&amp;quot;| Bank&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== 0x05: Activate device ====&lt;br /&gt;
Activate or disactivate the given device.&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ PARAMETER&lt;br /&gt;
|-&lt;br /&gt;
! 8 || 7 || 6 || 5 || 4 || 3 || 2 || 1&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#BBB;&amp;quot;| 0&lt;br /&gt;
|style=&amp;quot;background-color:#BBB;&amp;quot;| 0&lt;br /&gt;
|style=&amp;quot;background-color:#BBB;&amp;quot;| 0&lt;br /&gt;
|style=&amp;quot;background-color:#AAF;&amp;quot; colspan=&amp;quot;5&amp;quot;| Device&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Devices:&lt;br /&gt;
* &amp;lt;tt&amp;gt;00&amp;lt;/tt&amp;gt;: MSX-Music (OPLL)&lt;br /&gt;
* &amp;lt;tt&amp;gt;01&amp;lt;/tt&amp;gt;: MSX-Audio&lt;br /&gt;
* &amp;lt;tt&amp;gt;02&amp;lt;/tt&amp;gt;: SCC&lt;br /&gt;
* &amp;lt;tt&amp;gt;03&amp;lt;/tt&amp;gt;: SCC+&lt;br /&gt;
* &amp;lt;tt&amp;gt;04&amp;lt;/tt&amp;gt;: 2nd PSG (port 10h)&lt;br /&gt;
* &amp;lt;tt&amp;gt;05&amp;lt;/tt&amp;gt;: Darky (2 x ePSG)&lt;br /&gt;
* &amp;lt;tt&amp;gt;06&amp;lt;/tt&amp;gt;: Darky Jr. (2 x PSG)&lt;br /&gt;
* &amp;lt;tt&amp;gt;08&amp;lt;/tt&amp;gt;: OPM (SFK-01, SFG-01 et SFG-05 ver.1)&lt;br /&gt;
* &amp;lt;tt&amp;gt;09&amp;lt;/tt&amp;gt;: OPP (SFG-05 ver.2)&lt;br /&gt;
* &amp;lt;tt&amp;gt;12&amp;lt;/tt&amp;gt;: OPL4&lt;br /&gt;
* &amp;lt;tt&amp;gt;15&amp;lt;/tt&amp;gt;: SAM2695&lt;br /&gt;
&lt;br /&gt;
== Appendix ==&lt;br /&gt;
=== Programmable processor and emulation ===&lt;br /&gt;
Here is a pseudo code in C to handle NEO mappers extension for programmable processor based cartridges or for emulators:&lt;br /&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;
// Extended function prototypes&lt;br /&gt;
typedef void (*funcEnable_t)(bool, uint8);&lt;br /&gt;
typedef void (*funcWrite_t)(uint16, uint8);&lt;br /&gt;
typedef uint8 (*funcRead_t)(uint16);&lt;br /&gt;
// Extended functions table&lt;br /&gt;
funcEnable_t funcEnableTable[32];&lt;br /&gt;
funcWrite_t funcWriteTable[3];&lt;br /&gt;
funcRead_t funcReadTable[3];&lt;br /&gt;
&lt;br /&gt;
// Handle device initialization&lt;br /&gt;
void NEO16_Init()&lt;br /&gt;
{&lt;br /&gt;
	for (uint8 i = 0; i &amp;lt; 3; i++)&lt;br /&gt;
	{&lt;br /&gt;
		bankValue[i] = 0x0000;&lt;br /&gt;
		funcWriteTable[i] = NULL;&lt;br /&gt;
		funcReadTable[i] = NULL;		&lt;br /&gt;
	}&lt;br /&gt;
	for (uint8 i = 0; i &amp;lt; 32; i++)&lt;br /&gt;
		funcTab[i] = NULL;&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; // Get the corresponding bank number&lt;br /&gt;
	if (bank &amp;gt; 2)&lt;br /&gt;
		return; // skip&lt;br /&gt;
&lt;br /&gt;
	if (funcWriteTable[bank] != NULL) // Check for bank write callback&lt;br /&gt;
	{&lt;br /&gt;
		funcWriteTable[bank](address, value);&lt;br /&gt;
	}&lt;br /&gt;
	else if ((address &amp;amp; 0x0001) &amp;amp;&amp;amp; (value &amp;amp; 0x80)) // Handle extended function&lt;br /&gt;
	{&lt;br /&gt;
		uint8 funcId = value &amp;amp; 0x3F; // Get function ID&lt;br /&gt;
		if (funcEnableTable[funcId] != NULL)&lt;br /&gt;
			funcEnableTable[funcId](value &amp;amp; 0x40, (address &amp;gt;&amp;gt; 1) &amp;amp; 0xFF); // Execute function specific code&lt;br /&gt;
	}&lt;br /&gt;
	else // Write to the given bank register&lt;br /&gt;
	{&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;
&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; // Get the corresponding bank number&lt;br /&gt;
	if (bank &amp;gt; 2)&lt;br /&gt;
		return 0xFF; // skip&lt;br /&gt;
&lt;br /&gt;
	if (funcReadTable[bank] != NULL) // Check for bank read callback&lt;br /&gt;
		return funcReadTable[bank](address);&lt;br /&gt;
	else&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;
=== Extension example ===&lt;br /&gt;
Here is a pseudo code in C to handle a SRAM extension for NEO mapper:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
uint8 sramSeg; // Current SRAM segment [0:15]&lt;br /&gt;
uint8 sramBank; // Current bank where SRAM is selected (0xFF if not selected)&lt;br /&gt;
uint8* sramData; // SRAM data (hardware specific)&lt;br /&gt;
&lt;br /&gt;
// Write to SRAM&lt;br /&gt;
void SRAM_Write(uint16 address, uint8 value)&lt;br /&gt;
{&lt;br /&gt;
	sramData[(sramSeg * 0x2000) + (address &amp;amp; 0x1FFF)] = value; // &lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// Read from SRAM&lt;br /&gt;
uint8 SRAM_read(uint16 address)&lt;br /&gt;
{&lt;br /&gt;
	return sramData[(sramSeg * 0x2000) + (address &amp;amp; 0x1FFF)];	&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// Enable/disable SRAM feature&lt;br /&gt;
void SRAM_Enable(bool enable, uint8 param)&lt;br /&gt;
{&lt;br /&gt;
	if (sramBank != 0xFF) // Disable previous SRAM registration&lt;br /&gt;
	{&lt;br /&gt;
		if (funcWriteTable[sramBank] == SRAM_Write)&lt;br /&gt;
			funcWriteTable[sramBank] = NULL;&lt;br /&gt;
		if (funcReadTable[sramBank] == SRAM_Read)&lt;br /&gt;
			funcReadTable[sramBank] = NULL;&lt;br /&gt;
		sramBank = 0xFF;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	if (enable) // Enable a SRAM segment in the given bank&lt;br /&gt;
	{&lt;br /&gt;
		uint8 bank = param &amp;amp; 0x07; // Get bank number&lt;br /&gt;
		if (bank &amp;gt; 2)&lt;br /&gt;
			return; // skip (for NEO-16)&lt;br /&gt;
&lt;br /&gt;
		sramSeg = (param &amp;gt;&amp;gt; 4) &amp;amp; 0x0F; // SRAM segment number&lt;br /&gt;
		sramBank = bank;&lt;br /&gt;
		funcWriteTable[sramBank] = SRAM_Write; // Register SRAM callbacks&lt;br /&gt;
		funcReadTable[sramBank] = SRAM_Read;&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// Initialize SRAM feature&lt;br /&gt;
void SRAM_Init()&lt;br /&gt;
{&lt;br /&gt;
	sramBank = 0xFF;&lt;br /&gt;
	funcTab[0x04] = SRAM_Init; // Register to function 0x04 (SRAM/FRAM feature)&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Then, you just need to call &amp;lt;tt&amp;gt;SRAM_Init()&amp;lt;/tt&amp;gt; from &amp;lt;tt&amp;gt;NEO16_Init()&amp;lt;/tt&amp;gt; to register the feature.&lt;/div&gt;</summary>
		<author><name>Aoineko</name></author>	</entry>

	<entry>
		<id>https://aoineko.org/msxgl/index.php?title=NEO_mapper/Extension&amp;diff=3821</id>
		<title>NEO mapper/Extension</title>
		<link rel="alternate" type="text/html" href="https://aoineko.org/msxgl/index.php?title=NEO_mapper/Extension&amp;diff=3821"/>
				<updated>2026-04-06T21:06:26Z</updated>
		
		<summary type="html">&lt;p&gt;Aoineko: /* Appendix */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{WARNING|This page is still in the proposal stage and should not yet be considered an official specification.}}&lt;br /&gt;
&lt;br /&gt;
Proposal for an extension to the [[NEO mapper]] format.&lt;br /&gt;
&lt;br /&gt;
== Specifications ==&lt;br /&gt;
&lt;br /&gt;
=== Principles ===&lt;br /&gt;
&lt;br /&gt;
Any write operation to the NEO mapper with data bit 7 set to 1 and address bit 0 set to 1 is considered an access to extended features. In that case, the mapper bank register is not modified.&lt;br /&gt;
&lt;br /&gt;
All other write operations should be considered normal access to the mapper's bank register.&lt;br /&gt;
&lt;br /&gt;
The data contains:&lt;br /&gt;
* The number of an extended function in the mapper&lt;br /&gt;
* A bit indicating whether the function should be enabled or disabled&lt;br /&gt;
&lt;br /&gt;
The address contains an 8-bit parameter to be passed to the function.&lt;br /&gt;
{|&lt;br /&gt;
|-&lt;br /&gt;
|&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ ADDRESS&lt;br /&gt;
|-&lt;br /&gt;
! 15 || 14 || 13 || 12 || 11 || 10 || 9 || 8 || 7 || 6 || 5 || 4 || 3 || 2 || 1 || 0&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#BBB;&amp;quot; colspan=&amp;quot;2&amp;quot;| Page&lt;br /&gt;
|style=&amp;quot;background-color:#BBB;&amp;quot; colspan=&amp;quot;3&amp;quot;| Bank&lt;br /&gt;
|style=&amp;quot;background-color:#BBB;&amp;quot;| 0&lt;br /&gt;
|style=&amp;quot;background-color:#BBB;&amp;quot;| 0&lt;br /&gt;
|style=&amp;quot;background-color:#AAF;&amp;quot; colspan=&amp;quot;8&amp;quot;| Parameter&lt;br /&gt;
|style=&amp;quot;background-color:#FAA;&amp;quot;| 1&lt;br /&gt;
|}&lt;br /&gt;
|&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ DATA&lt;br /&gt;
|-&lt;br /&gt;
! 7 || 6 || 5 || 4 || 3 || 2 || 1 || 0&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FAA;&amp;quot;| 1&lt;br /&gt;
|style=&amp;quot;background-color:#AAF;&amp;quot;| A&lt;br /&gt;
|style=&amp;quot;background-color:#BBB;&amp;quot;| 0&lt;br /&gt;
|style=&amp;quot;background-color:#AAF;&amp;quot; colspan=&amp;quot;5&amp;quot;| Function&lt;br /&gt;
|}&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Functions ===&lt;br /&gt;
==== 0x00: Cartridge information ====&lt;br /&gt;
When activated, any read access to the given bank will return the cartridge information (8 KB, mirrored on NEO-16).&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ PARAMETER&lt;br /&gt;
|-&lt;br /&gt;
! 8 || 7 || 6 || 5 || 4 || 3 || 2 || 1&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#BBB;&amp;quot;| 0&lt;br /&gt;
|style=&amp;quot;background-color:#BBB;&amp;quot;| 0&lt;br /&gt;
|style=&amp;quot;background-color:#BBB;&amp;quot;| 0&lt;br /&gt;
|style=&amp;quot;background-color:#BBB;&amp;quot;| 0&lt;br /&gt;
|style=&amp;quot;background-color:#BBB;&amp;quot;| 0&lt;br /&gt;
|style=&amp;quot;background-color:#AAF;&amp;quot; colspan=&amp;quot;5&amp;quot;| Bank&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== 0x01: Cartridge configuration ====&lt;br /&gt;
&lt;br /&gt;
==== 0x04: Activate SRAM/FRAM ====&lt;br /&gt;
When activated, any read/write access to the specified bank (defined in the parameter) is redirected to the selected segment of the SRAM/FRAM.&lt;br /&gt;
&lt;br /&gt;
SRAM/FRAM is accessed through 8 KB segments (on the NEO-16, the segment is mirrored).&lt;br /&gt;
&lt;br /&gt;
Up to 16 segments can be accessed, for a total capacity of 128 KB.&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ PARAMETER&lt;br /&gt;
|-&lt;br /&gt;
! 8 || 7 || 6 || 5 || 4 || 3 || 2 || 1&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#AAF;&amp;quot; colspan=&amp;quot;4&amp;quot;| Segment&lt;br /&gt;
|style=&amp;quot;background-color:#BBB;&amp;quot;| 0&lt;br /&gt;
|style=&amp;quot;background-color:#AAF;&amp;quot; colspan=&amp;quot;5&amp;quot;| Bank&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== 0x05: Activate device ====&lt;br /&gt;
Activate or disactivate the given device.&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ PARAMETER&lt;br /&gt;
|-&lt;br /&gt;
! 8 || 7 || 6 || 5 || 4 || 3 || 2 || 1&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#BBB;&amp;quot;| 0&lt;br /&gt;
|style=&amp;quot;background-color:#BBB;&amp;quot;| 0&lt;br /&gt;
|style=&amp;quot;background-color:#BBB;&amp;quot;| 0&lt;br /&gt;
|style=&amp;quot;background-color:#AAF;&amp;quot; colspan=&amp;quot;5&amp;quot;| Device&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Devices:&lt;br /&gt;
* &amp;lt;tt&amp;gt;00&amp;lt;/tt&amp;gt;: MSX-Music (OPLL)&lt;br /&gt;
* &amp;lt;tt&amp;gt;01&amp;lt;/tt&amp;gt;: MSX-Audio&lt;br /&gt;
* &amp;lt;tt&amp;gt;02&amp;lt;/tt&amp;gt;: SCC&lt;br /&gt;
* &amp;lt;tt&amp;gt;03&amp;lt;/tt&amp;gt;: SCC+&lt;br /&gt;
* &amp;lt;tt&amp;gt;04&amp;lt;/tt&amp;gt;: 2nd PSG (port 10h)&lt;br /&gt;
* &amp;lt;tt&amp;gt;05&amp;lt;/tt&amp;gt;: Darky (2 x ePSG)&lt;br /&gt;
* &amp;lt;tt&amp;gt;06&amp;lt;/tt&amp;gt;: Darky Jr. (2 x PSG)&lt;br /&gt;
* &amp;lt;tt&amp;gt;08&amp;lt;/tt&amp;gt;: OPM (SFK-01, SFG-01 et SFG-05 ver.1)&lt;br /&gt;
* &amp;lt;tt&amp;gt;09&amp;lt;/tt&amp;gt;: OPP (SFG-05 ver.2)&lt;br /&gt;
* &amp;lt;tt&amp;gt;12&amp;lt;/tt&amp;gt;: OPL4&lt;br /&gt;
* &amp;lt;tt&amp;gt;15&amp;lt;/tt&amp;gt;: SAM2695&lt;br /&gt;
&lt;br /&gt;
== Appendix ==&lt;br /&gt;
=== Programmable processor and emulation ===&lt;br /&gt;
Here is a pseudo code in C to handle NEO mappers extension for programmable processor based cartridges or for emulators:&lt;br /&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;
// Extended function prototypes&lt;br /&gt;
typedef void (*funcEnable_t)(bool, uint8);&lt;br /&gt;
typedef void (*funcWrite_t)(uint16, uint8);&lt;br /&gt;
typedef uint8 (*funcRead_t)(uint16);&lt;br /&gt;
// Extended functions table&lt;br /&gt;
funcEnable_t funcEnableTable[32];&lt;br /&gt;
funcWrite_t funcWriteTable[3];&lt;br /&gt;
funcRead_t funcReadTable[3];&lt;br /&gt;
&lt;br /&gt;
// Handle device initialization&lt;br /&gt;
void NEO16_Init()&lt;br /&gt;
{&lt;br /&gt;
	for (uint8 i = 0; i &amp;lt; 3; i++)&lt;br /&gt;
	{&lt;br /&gt;
		bankValue[i] = 0x0000;&lt;br /&gt;
		funcWriteTable[i] = NULL;&lt;br /&gt;
		funcReadTable[i] = NULL;		&lt;br /&gt;
	}&lt;br /&gt;
	for (uint8 i = 0; i &amp;lt; 32; i++)&lt;br /&gt;
		funcTab[i] = NULL;&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; // Get the corresponding bank number&lt;br /&gt;
	if (bank &amp;gt; 2)&lt;br /&gt;
		return; // skip&lt;br /&gt;
&lt;br /&gt;
	if (funcWriteTable[bank] != NULL) // Check for bank write callback&lt;br /&gt;
	{&lt;br /&gt;
		funcWriteTable[bank](address, value);&lt;br /&gt;
	}&lt;br /&gt;
	else if ((address &amp;amp; 0x0001) &amp;amp;&amp;amp; (value &amp;amp; 0x80)) // Handle extended function&lt;br /&gt;
	{&lt;br /&gt;
		uint8 funcId = value &amp;amp; 0x3F; // Get function ID&lt;br /&gt;
		if (funcEnableTable[funcId] != NULL)&lt;br /&gt;
			funcEnableTable[funcId](value &amp;amp; 0x40, (address &amp;gt;&amp;gt; 1) &amp;amp; 0xFF); // Execute function specific code&lt;br /&gt;
	}&lt;br /&gt;
	else // Write to the given bank register&lt;br /&gt;
	{&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;
&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; // Get the corresponding bank number&lt;br /&gt;
	if (bank &amp;gt; 2)&lt;br /&gt;
		return 0xFF; // skip&lt;br /&gt;
&lt;br /&gt;
	if (funcReadTable[bank] != NULL) // Check for bank read callback&lt;br /&gt;
		return funcReadTable[bank](address);&lt;br /&gt;
	else&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;
=== Extension example ===&lt;br /&gt;
Here is a pseudo code in C to handle a SRAM extension for NEO mapper:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
uint8 sramSeg; // Current SRAM segment [0:15]&lt;br /&gt;
uint8 sramBank; // Current bank where SRAM is selected (0xFF if not selected)&lt;br /&gt;
uint8* sramData; // SRAM data (hardware specific)&lt;br /&gt;
&lt;br /&gt;
// Write to SRAM&lt;br /&gt;
void SRAM_Write(uint16 address, uint8 value)&lt;br /&gt;
{&lt;br /&gt;
	sramData[(sramSeg * 0x2000) + (address &amp;amp; 0x1FFF)] = value; // &lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// Read from SRAM&lt;br /&gt;
uint8 SRAM_read(uint16 address)&lt;br /&gt;
{&lt;br /&gt;
	return sramData[(sramSeg * 0x2000) + (address &amp;amp; 0x1FFF)];	&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// Enable/disable SRAM feature&lt;br /&gt;
void SRAM_Enable(bool enable, uint8 param)&lt;br /&gt;
{&lt;br /&gt;
	if (sramBank != 0xFF) // Disable previous SRAM registration&lt;br /&gt;
	{&lt;br /&gt;
		if (funcWriteTable[sramBank] == SRAM_Write)&lt;br /&gt;
			funcWriteTable[sramBank] = NULL;&lt;br /&gt;
		if (funcReadTable[sramBank] == SRAM_Read)&lt;br /&gt;
			funcReadTable[sramBank] = NULL;&lt;br /&gt;
		sramBank = 0xFF;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	if (enable) // Enable a SRAM segment in the given bank&lt;br /&gt;
	{&lt;br /&gt;
		uint8 bank = param &amp;amp; 0x07; // Get bank number&lt;br /&gt;
		if (bank &amp;gt; 2)&lt;br /&gt;
			return; // skip (for NEO-16)&lt;br /&gt;
&lt;br /&gt;
		sramSeg = (param &amp;gt;&amp;gt; 4) &amp;amp; 0x0F; // SRAM segment number&lt;br /&gt;
		sramBank = bank;&lt;br /&gt;
		funcWriteTable[sramBank] = SRAM_Write; // Register SRAM callbacks&lt;br /&gt;
		funcReadTable[sramBank] = SRAM_Read;&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// Initialize SRAM feature&lt;br /&gt;
void SRAM_Init()&lt;br /&gt;
{&lt;br /&gt;
	sramBank = 0xFF;&lt;br /&gt;
	funcTab[0x04] = SRAM_Init; // Register to function 0x04 (SRAM/FRAM feature)&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;/div&gt;</summary>
		<author><name>Aoineko</name></author>	</entry>

	<entry>
		<id>https://aoineko.org/msxgl/index.php?title=NEO_mapper/Extension&amp;diff=3820</id>
		<title>NEO mapper/Extension</title>
		<link rel="alternate" type="text/html" href="https://aoineko.org/msxgl/index.php?title=NEO_mapper/Extension&amp;diff=3820"/>
				<updated>2026-04-06T21:03:03Z</updated>
		
		<summary type="html">&lt;p&gt;Aoineko: /* Programmable processor and emulation */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{WARNING|This page is still in the proposal stage and should not yet be considered an official specification.}}&lt;br /&gt;
&lt;br /&gt;
Proposal for an extension to the [[NEO mapper]] format.&lt;br /&gt;
&lt;br /&gt;
== Specifications ==&lt;br /&gt;
&lt;br /&gt;
=== Principles ===&lt;br /&gt;
&lt;br /&gt;
Any write operation to the NEO mapper with data bit 7 set to 1 and address bit 0 set to 1 is considered an access to extended features. In that case, the mapper bank register is not modified.&lt;br /&gt;
&lt;br /&gt;
All other write operations should be considered normal access to the mapper's bank register.&lt;br /&gt;
&lt;br /&gt;
The data contains:&lt;br /&gt;
* The number of an extended function in the mapper&lt;br /&gt;
* A bit indicating whether the function should be enabled or disabled&lt;br /&gt;
&lt;br /&gt;
The address contains an 8-bit parameter to be passed to the function.&lt;br /&gt;
{|&lt;br /&gt;
|-&lt;br /&gt;
|&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ ADDRESS&lt;br /&gt;
|-&lt;br /&gt;
! 15 || 14 || 13 || 12 || 11 || 10 || 9 || 8 || 7 || 6 || 5 || 4 || 3 || 2 || 1 || 0&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#BBB;&amp;quot; colspan=&amp;quot;2&amp;quot;| Page&lt;br /&gt;
|style=&amp;quot;background-color:#BBB;&amp;quot; colspan=&amp;quot;3&amp;quot;| Bank&lt;br /&gt;
|style=&amp;quot;background-color:#BBB;&amp;quot;| 0&lt;br /&gt;
|style=&amp;quot;background-color:#BBB;&amp;quot;| 0&lt;br /&gt;
|style=&amp;quot;background-color:#AAF;&amp;quot; colspan=&amp;quot;8&amp;quot;| Parameter&lt;br /&gt;
|style=&amp;quot;background-color:#FAA;&amp;quot;| 1&lt;br /&gt;
|}&lt;br /&gt;
|&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ DATA&lt;br /&gt;
|-&lt;br /&gt;
! 7 || 6 || 5 || 4 || 3 || 2 || 1 || 0&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FAA;&amp;quot;| 1&lt;br /&gt;
|style=&amp;quot;background-color:#AAF;&amp;quot;| A&lt;br /&gt;
|style=&amp;quot;background-color:#BBB;&amp;quot;| 0&lt;br /&gt;
|style=&amp;quot;background-color:#AAF;&amp;quot; colspan=&amp;quot;5&amp;quot;| Function&lt;br /&gt;
|}&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Functions ===&lt;br /&gt;
==== 0x00: Cartridge information ====&lt;br /&gt;
When activated, any read access to the given bank will return the cartridge information (8 KB, mirrored on NEO-16).&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ PARAMETER&lt;br /&gt;
|-&lt;br /&gt;
! 8 || 7 || 6 || 5 || 4 || 3 || 2 || 1&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#BBB;&amp;quot;| 0&lt;br /&gt;
|style=&amp;quot;background-color:#BBB;&amp;quot;| 0&lt;br /&gt;
|style=&amp;quot;background-color:#BBB;&amp;quot;| 0&lt;br /&gt;
|style=&amp;quot;background-color:#BBB;&amp;quot;| 0&lt;br /&gt;
|style=&amp;quot;background-color:#BBB;&amp;quot;| 0&lt;br /&gt;
|style=&amp;quot;background-color:#AAF;&amp;quot; colspan=&amp;quot;5&amp;quot;| Bank&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== 0x01: Cartridge configuration ====&lt;br /&gt;
&lt;br /&gt;
==== 0x04: Activate SRAM/FRAM ====&lt;br /&gt;
When activated, any read/write access to the specified bank (defined in the parameter) is redirected to the selected segment of the SRAM/FRAM.&lt;br /&gt;
&lt;br /&gt;
SRAM/FRAM is accessed through 8 KB segments (on the NEO-16, the segment is mirrored).&lt;br /&gt;
&lt;br /&gt;
Up to 16 segments can be accessed, for a total capacity of 128 KB.&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ PARAMETER&lt;br /&gt;
|-&lt;br /&gt;
! 8 || 7 || 6 || 5 || 4 || 3 || 2 || 1&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#AAF;&amp;quot; colspan=&amp;quot;4&amp;quot;| Segment&lt;br /&gt;
|style=&amp;quot;background-color:#BBB;&amp;quot;| 0&lt;br /&gt;
|style=&amp;quot;background-color:#AAF;&amp;quot; colspan=&amp;quot;5&amp;quot;| Bank&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== 0x05: Activate device ====&lt;br /&gt;
Activate or disactivate the given device.&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ PARAMETER&lt;br /&gt;
|-&lt;br /&gt;
! 8 || 7 || 6 || 5 || 4 || 3 || 2 || 1&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#BBB;&amp;quot;| 0&lt;br /&gt;
|style=&amp;quot;background-color:#BBB;&amp;quot;| 0&lt;br /&gt;
|style=&amp;quot;background-color:#BBB;&amp;quot;| 0&lt;br /&gt;
|style=&amp;quot;background-color:#AAF;&amp;quot; colspan=&amp;quot;5&amp;quot;| Device&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Devices:&lt;br /&gt;
* &amp;lt;tt&amp;gt;00&amp;lt;/tt&amp;gt;: MSX-Music (OPLL)&lt;br /&gt;
* &amp;lt;tt&amp;gt;01&amp;lt;/tt&amp;gt;: MSX-Audio&lt;br /&gt;
* &amp;lt;tt&amp;gt;02&amp;lt;/tt&amp;gt;: SCC&lt;br /&gt;
* &amp;lt;tt&amp;gt;03&amp;lt;/tt&amp;gt;: SCC+&lt;br /&gt;
* &amp;lt;tt&amp;gt;04&amp;lt;/tt&amp;gt;: 2nd PSG (port 10h)&lt;br /&gt;
* &amp;lt;tt&amp;gt;05&amp;lt;/tt&amp;gt;: Darky (2 x ePSG)&lt;br /&gt;
* &amp;lt;tt&amp;gt;06&amp;lt;/tt&amp;gt;: Darky Jr. (2 x PSG)&lt;br /&gt;
* &amp;lt;tt&amp;gt;08&amp;lt;/tt&amp;gt;: OPM (SFK-01, SFG-01 et SFG-05 ver.1)&lt;br /&gt;
* &amp;lt;tt&amp;gt;09&amp;lt;/tt&amp;gt;: OPP (SFG-05 ver.2)&lt;br /&gt;
* &amp;lt;tt&amp;gt;12&amp;lt;/tt&amp;gt;: OPL4&lt;br /&gt;
* &amp;lt;tt&amp;gt;15&amp;lt;/tt&amp;gt;: SAM2695&lt;br /&gt;
&lt;br /&gt;
== Appendix ==&lt;br /&gt;
=== Programmable processor and emulation ===&lt;br /&gt;
Here is a pseudo code in C to handle NEO mappers extension for programmable processor based cartridges or for emulators:&lt;br /&gt;
&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;
// Extended function prototypes&lt;br /&gt;
typedef void (*funcEnable_t)(bool, uint8);&lt;br /&gt;
typedef void (*funcWrite_t)(uint16, uint8);&lt;br /&gt;
typedef uint8 (*funcRead_t)(uint16);&lt;br /&gt;
// Extended functions table&lt;br /&gt;
funcEnable_t funcEnableTable[32];&lt;br /&gt;
funcWrite_t funcWriteTable[3];&lt;br /&gt;
funcRead_t funcReadTable[3];&lt;br /&gt;
&lt;br /&gt;
// Handle device initialization&lt;br /&gt;
void NEO16_Init()&lt;br /&gt;
{&lt;br /&gt;
	for (uint8 i = 0; i &amp;lt; 3; i++)&lt;br /&gt;
	{&lt;br /&gt;
		bankValue[i] = 0x0000;&lt;br /&gt;
		funcWriteTable[i] = NULL;&lt;br /&gt;
		funcReadTable[i] = NULL;		&lt;br /&gt;
	}&lt;br /&gt;
	for (uint8 i = 0; i &amp;lt; 32; i++)&lt;br /&gt;
		funcTab[i] = NULL;&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; // Get the corresponding bank number&lt;br /&gt;
	if (bank &amp;gt; 2)&lt;br /&gt;
		return; // skip&lt;br /&gt;
&lt;br /&gt;
	if (funcWriteTable[bank] != NULL) // Check for bank write callback&lt;br /&gt;
	{&lt;br /&gt;
		funcWriteTable[bank](address, value);&lt;br /&gt;
	}&lt;br /&gt;
	else if ((address &amp;amp; 0x0001) &amp;amp;&amp;amp; (value &amp;amp; 0x80)) // Handle extended function&lt;br /&gt;
	{&lt;br /&gt;
		uint8 funcId = value &amp;amp; 0x3F; // Get function ID&lt;br /&gt;
		if (funcEnableTable[funcId] != NULL)&lt;br /&gt;
			funcEnableTable[funcId](value &amp;amp; 0x40, (address &amp;gt;&amp;gt; 1) &amp;amp; 0xFF); // Execute function specific code&lt;br /&gt;
	}&lt;br /&gt;
	else // Write to the given bank register&lt;br /&gt;
	{&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;
&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; // Get the corresponding bank number&lt;br /&gt;
	if (bank &amp;gt; 2)&lt;br /&gt;
		return 0xFF; // skip&lt;br /&gt;
&lt;br /&gt;
	if (funcReadTable[bank] != NULL) // Check for bank read callback&lt;br /&gt;
		return funcReadTable[bank](address);&lt;br /&gt;
	else&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;
=== Extension example ===&lt;br /&gt;
Here is a pseudo code in C to handle a SRAM extension for NEO mapper:&lt;br /&gt;
&lt;br /&gt;
NEO-16 mapper:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
uint8 sramSeg; // Current SRAM segment [0:15]&lt;br /&gt;
uint8 sramBank; // Current bank where SRAM is selected (0xFF if not selected)&lt;br /&gt;
uint8* sramData; // SRAM data (hardware specific)&lt;br /&gt;
&lt;br /&gt;
// Write to SRAM&lt;br /&gt;
void SRAM_Write(uint16 address, uint8 value)&lt;br /&gt;
{&lt;br /&gt;
	sramData[(sramSeg * 0x2000) + (address &amp;amp; 0x1FFF)] = value; // &lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// Read from SRAM&lt;br /&gt;
uint8 SRAM_read(uint16 address)&lt;br /&gt;
{&lt;br /&gt;
	return sramData[(sramSeg * 0x2000) + (address &amp;amp; 0x1FFF)];	&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// Enable/disable SRAM feature&lt;br /&gt;
void SRAM_Enable(bool enable, uint8 param)&lt;br /&gt;
{&lt;br /&gt;
	if (sramBank != 0xFF) // Disable previous SRAM registration&lt;br /&gt;
	{&lt;br /&gt;
		if (funcWriteTable[sramBank] == SRAM_Write)&lt;br /&gt;
			funcWriteTable[sramBank] = NULL;&lt;br /&gt;
		if (funcReadTable[sramBank] == SRAM_Read)&lt;br /&gt;
			funcReadTable[sramBank] = NULL;&lt;br /&gt;
		sramBank = 0xFF;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	if (enable) // Enable a SRAM segment in the given bank&lt;br /&gt;
	{&lt;br /&gt;
		sramSeg = (param &amp;gt;&amp;gt; 4) &amp;amp; 0x0F; // SRAM segment number&lt;br /&gt;
		sramBank = param &amp;amp; 0x07; // Mapper bank (todo: check if bank number is valid)&lt;br /&gt;
		funcWriteTable[sramBank] = SRAM_Write; // Register SRAM callbacks&lt;br /&gt;
		funcReadTable[sramBank] = SRAM_Read;&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// Initialize SRAM feature&lt;br /&gt;
void SRAM_Init()&lt;br /&gt;
{&lt;br /&gt;
	sramBank = 0xFF;&lt;br /&gt;
	funcTab[0x04] = SRAM_Init; // Register to function 0x04 (SRAM/FRAM feature)&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;/div&gt;</summary>
		<author><name>Aoineko</name></author>	</entry>

	<entry>
		<id>https://aoineko.org/msxgl/index.php?title=NEO_mapper/Extension&amp;diff=3819</id>
		<title>NEO mapper/Extension</title>
		<link rel="alternate" type="text/html" href="https://aoineko.org/msxgl/index.php?title=NEO_mapper/Extension&amp;diff=3819"/>
				<updated>2026-04-06T20:51:32Z</updated>
		
		<summary type="html">&lt;p&gt;Aoineko: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{WARNING|This page is still in the proposal stage and should not yet be considered an official specification.}}&lt;br /&gt;
&lt;br /&gt;
Proposal for an extension to the [[NEO mapper]] format.&lt;br /&gt;
&lt;br /&gt;
== Specifications ==&lt;br /&gt;
&lt;br /&gt;
=== Principles ===&lt;br /&gt;
&lt;br /&gt;
Any write operation to the NEO mapper with data bit 7 set to 1 and address bit 0 set to 1 is considered an access to extended features. In that case, the mapper bank register is not modified.&lt;br /&gt;
&lt;br /&gt;
All other write operations should be considered normal access to the mapper's bank register.&lt;br /&gt;
&lt;br /&gt;
The data contains:&lt;br /&gt;
* The number of an extended function in the mapper&lt;br /&gt;
* A bit indicating whether the function should be enabled or disabled&lt;br /&gt;
&lt;br /&gt;
The address contains an 8-bit parameter to be passed to the function.&lt;br /&gt;
{|&lt;br /&gt;
|-&lt;br /&gt;
|&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ ADDRESS&lt;br /&gt;
|-&lt;br /&gt;
! 15 || 14 || 13 || 12 || 11 || 10 || 9 || 8 || 7 || 6 || 5 || 4 || 3 || 2 || 1 || 0&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#BBB;&amp;quot; colspan=&amp;quot;2&amp;quot;| Page&lt;br /&gt;
|style=&amp;quot;background-color:#BBB;&amp;quot; colspan=&amp;quot;3&amp;quot;| Bank&lt;br /&gt;
|style=&amp;quot;background-color:#BBB;&amp;quot;| 0&lt;br /&gt;
|style=&amp;quot;background-color:#BBB;&amp;quot;| 0&lt;br /&gt;
|style=&amp;quot;background-color:#AAF;&amp;quot; colspan=&amp;quot;8&amp;quot;| Parameter&lt;br /&gt;
|style=&amp;quot;background-color:#FAA;&amp;quot;| 1&lt;br /&gt;
|}&lt;br /&gt;
|&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ DATA&lt;br /&gt;
|-&lt;br /&gt;
! 7 || 6 || 5 || 4 || 3 || 2 || 1 || 0&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FAA;&amp;quot;| 1&lt;br /&gt;
|style=&amp;quot;background-color:#AAF;&amp;quot;| A&lt;br /&gt;
|style=&amp;quot;background-color:#BBB;&amp;quot;| 0&lt;br /&gt;
|style=&amp;quot;background-color:#AAF;&amp;quot; colspan=&amp;quot;5&amp;quot;| Function&lt;br /&gt;
|}&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Functions ===&lt;br /&gt;
==== 0x00: Cartridge information ====&lt;br /&gt;
When activated, any read access to the given bank will return the cartridge information (8 KB, mirrored on NEO-16).&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ PARAMETER&lt;br /&gt;
|-&lt;br /&gt;
! 8 || 7 || 6 || 5 || 4 || 3 || 2 || 1&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#BBB;&amp;quot;| 0&lt;br /&gt;
|style=&amp;quot;background-color:#BBB;&amp;quot;| 0&lt;br /&gt;
|style=&amp;quot;background-color:#BBB;&amp;quot;| 0&lt;br /&gt;
|style=&amp;quot;background-color:#BBB;&amp;quot;| 0&lt;br /&gt;
|style=&amp;quot;background-color:#BBB;&amp;quot;| 0&lt;br /&gt;
|style=&amp;quot;background-color:#AAF;&amp;quot; colspan=&amp;quot;5&amp;quot;| Bank&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== 0x01: Cartridge configuration ====&lt;br /&gt;
&lt;br /&gt;
==== 0x04: Activate SRAM/FRAM ====&lt;br /&gt;
When activated, any read/write access to the specified bank (defined in the parameter) is redirected to the selected segment of the SRAM/FRAM.&lt;br /&gt;
&lt;br /&gt;
SRAM/FRAM is accessed through 8 KB segments (on the NEO-16, the segment is mirrored).&lt;br /&gt;
&lt;br /&gt;
Up to 16 segments can be accessed, for a total capacity of 128 KB.&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ PARAMETER&lt;br /&gt;
|-&lt;br /&gt;
! 8 || 7 || 6 || 5 || 4 || 3 || 2 || 1&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#AAF;&amp;quot; colspan=&amp;quot;4&amp;quot;| Segment&lt;br /&gt;
|style=&amp;quot;background-color:#BBB;&amp;quot;| 0&lt;br /&gt;
|style=&amp;quot;background-color:#AAF;&amp;quot; colspan=&amp;quot;5&amp;quot;| Bank&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== 0x05: Activate device ====&lt;br /&gt;
Activate or disactivate the given device.&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ PARAMETER&lt;br /&gt;
|-&lt;br /&gt;
! 8 || 7 || 6 || 5 || 4 || 3 || 2 || 1&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#BBB;&amp;quot;| 0&lt;br /&gt;
|style=&amp;quot;background-color:#BBB;&amp;quot;| 0&lt;br /&gt;
|style=&amp;quot;background-color:#BBB;&amp;quot;| 0&lt;br /&gt;
|style=&amp;quot;background-color:#AAF;&amp;quot; colspan=&amp;quot;5&amp;quot;| Device&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Devices:&lt;br /&gt;
* &amp;lt;tt&amp;gt;00&amp;lt;/tt&amp;gt;: MSX-Music (OPLL)&lt;br /&gt;
* &amp;lt;tt&amp;gt;01&amp;lt;/tt&amp;gt;: MSX-Audio&lt;br /&gt;
* &amp;lt;tt&amp;gt;02&amp;lt;/tt&amp;gt;: SCC&lt;br /&gt;
* &amp;lt;tt&amp;gt;03&amp;lt;/tt&amp;gt;: SCC+&lt;br /&gt;
* &amp;lt;tt&amp;gt;04&amp;lt;/tt&amp;gt;: 2nd PSG (port 10h)&lt;br /&gt;
* &amp;lt;tt&amp;gt;05&amp;lt;/tt&amp;gt;: Darky (2 x ePSG)&lt;br /&gt;
* &amp;lt;tt&amp;gt;06&amp;lt;/tt&amp;gt;: Darky Jr. (2 x PSG)&lt;br /&gt;
* &amp;lt;tt&amp;gt;08&amp;lt;/tt&amp;gt;: OPM (SFK-01, SFG-01 et SFG-05 ver.1)&lt;br /&gt;
* &amp;lt;tt&amp;gt;09&amp;lt;/tt&amp;gt;: OPP (SFG-05 ver.2)&lt;br /&gt;
* &amp;lt;tt&amp;gt;12&amp;lt;/tt&amp;gt;: OPL4&lt;br /&gt;
* &amp;lt;tt&amp;gt;15&amp;lt;/tt&amp;gt;: SAM2695&lt;br /&gt;
&lt;br /&gt;
== Appendix ==&lt;br /&gt;
=== Programmable processor and emulation ===&lt;br /&gt;
Here is a pseudo code in C to handle NEO mappers extension for programmable processor based cartridges or for emulators:&lt;br /&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;
// Extended function prototypes&lt;br /&gt;
typedef void (*funcEnable_t)(bool, uint8);&lt;br /&gt;
typedef void (*funcWrite_t)(uint16, uint8);&lt;br /&gt;
typedef uint8 (*funcRead_t)(uint16);&lt;br /&gt;
// Extended functions table&lt;br /&gt;
funcEnable_t funcEnableTable[32];&lt;br /&gt;
funcWrite_t funcWriteTable[3];&lt;br /&gt;
funcRead_t funcReadTable[3];&lt;br /&gt;
&lt;br /&gt;
// Handle device initialization&lt;br /&gt;
void NEO16_Init()&lt;br /&gt;
{&lt;br /&gt;
	for (uint8 i = 0; i &amp;lt; 3; i++)&lt;br /&gt;
	{&lt;br /&gt;
		bankValue[i] = 0x0000;&lt;br /&gt;
		funcWriteTable[i] = NULL;&lt;br /&gt;
		funcReadTable[i] = NULL;		&lt;br /&gt;
	}&lt;br /&gt;
	for (uint8 i = 0; i &amp;lt; 32; i++)&lt;br /&gt;
		funcTab[i] = NULL;&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; // Get the corresponding bank number&lt;br /&gt;
	if (bank &amp;gt; 2)&lt;br /&gt;
		return; // skip&lt;br /&gt;
&lt;br /&gt;
	if (funcWriteTable[bank] != NULL) // Check for bank write callback&lt;br /&gt;
	{&lt;br /&gt;
		funcWriteTable[bank](address, value);&lt;br /&gt;
	}&lt;br /&gt;
	else if ((address &amp;amp; 0x0001) &amp;amp;&amp;amp; (value &amp;amp; 0x80)) // Handle extended function&lt;br /&gt;
	{&lt;br /&gt;
		uint8 funcId = value &amp;amp; 0x3F; // Get function ID&lt;br /&gt;
		if (funcEnableTable[funcId] != NULL)&lt;br /&gt;
			funcEnableTable[funcId](value &amp;amp; 0x40, (address &amp;gt;&amp;gt; 1) &amp;amp; 0xFF); // Execute function specific code&lt;br /&gt;
	}&lt;br /&gt;
	else // Write to the given bank register&lt;br /&gt;
	{&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;
&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; // Get the corresponding bank number&lt;br /&gt;
	if (bank &amp;gt; 2)&lt;br /&gt;
		return 0xFF; // skip&lt;br /&gt;
&lt;br /&gt;
	if (funcReadTable[bank] != NULL) // Check for bank read callback&lt;br /&gt;
		return funcReadTable[bank](address);&lt;br /&gt;
	else&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;/div&gt;</summary>
		<author><name>Aoineko</name></author>	</entry>

	<entry>
		<id>https://aoineko.org/msxgl/index.php?title=NEO_mapper&amp;diff=3818</id>
		<title>NEO mapper</title>
		<link rel="alternate" type="text/html" href="https://aoineko.org/msxgl/index.php?title=NEO_mapper&amp;diff=3818"/>
				<updated>2026-04-06T20:04:30Z</updated>
		
		<summary type="html">&lt;p&gt;Aoineko: +2 bits for segment number&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;
* '''Mega-USB 512''': ''WIP hardware...''&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;
** Add 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/Extension&amp;diff=3817</id>
		<title>NEO mapper/Extension</title>
		<link rel="alternate" type="text/html" href="https://aoineko.org/msxgl/index.php?title=NEO_mapper/Extension&amp;diff=3817"/>
				<updated>2026-04-06T19:48:55Z</updated>
		
		<summary type="html">&lt;p&gt;Aoineko: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{WARNING|This page is still in the proposal stage and should not yet be considered an official specification.}}&lt;br /&gt;
&lt;br /&gt;
Proposal for an extension to the [[NEO mapper]] format.&lt;br /&gt;
&lt;br /&gt;
== Specifications ==&lt;br /&gt;
&lt;br /&gt;
=== Principles ===&lt;br /&gt;
&lt;br /&gt;
Any write operation to the NEO mapper with data bit 7 set to 1 and address bit 0 set to 1 is considered an access to extended features. In that case, the mapper bank register is not modified.&lt;br /&gt;
&lt;br /&gt;
All other write operations should be considered normal access to the mapper's bank register.&lt;br /&gt;
&lt;br /&gt;
The data contains:&lt;br /&gt;
* The number of an extended function in the mapper&lt;br /&gt;
* A bit indicating whether the function should be enabled or disabled&lt;br /&gt;
&lt;br /&gt;
The address contains an 8-bit parameter to be passed to the function.&lt;br /&gt;
{|&lt;br /&gt;
|-&lt;br /&gt;
|&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ ADDRESS&lt;br /&gt;
|-&lt;br /&gt;
! 15 || 14 || 13 || 12 || 11 || 10 || 9 || 8 || 7 || 6 || 5 || 4 || 3 || 2 || 1 || 0&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#BBB;&amp;quot; colspan=&amp;quot;2&amp;quot;| Page&lt;br /&gt;
|style=&amp;quot;background-color:#BBB;&amp;quot; colspan=&amp;quot;3&amp;quot;| Bank&lt;br /&gt;
|style=&amp;quot;background-color:#BBB;&amp;quot;| 0&lt;br /&gt;
|style=&amp;quot;background-color:#BBB;&amp;quot;| 0&lt;br /&gt;
|style=&amp;quot;background-color:#AAF;&amp;quot; colspan=&amp;quot;8&amp;quot;| Parameter&lt;br /&gt;
|style=&amp;quot;background-color:#FAA;&amp;quot;| 1&lt;br /&gt;
|}&lt;br /&gt;
|&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ DATA&lt;br /&gt;
|-&lt;br /&gt;
! 7 || 6 || 5 || 4 || 3 || 2 || 1 || 0&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FAA;&amp;quot;| 1&lt;br /&gt;
|style=&amp;quot;background-color:#AAF;&amp;quot;| A&lt;br /&gt;
|style=&amp;quot;background-color:#BBB;&amp;quot;| 0&lt;br /&gt;
|style=&amp;quot;background-color:#AAF;&amp;quot; colspan=&amp;quot;5&amp;quot;| Function&lt;br /&gt;
|}&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Functions ===&lt;br /&gt;
==== 0x00: Cartridge information ====&lt;br /&gt;
When activated, any read access to the given bank will return the cartridge information (8 KB, mirrored on NEO-16).&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ PARAMETER&lt;br /&gt;
|-&lt;br /&gt;
! 8 || 7 || 6 || 5 || 4 || 3 || 2 || 1&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#BBB;&amp;quot;| 0&lt;br /&gt;
|style=&amp;quot;background-color:#BBB;&amp;quot;| 0&lt;br /&gt;
|style=&amp;quot;background-color:#BBB;&amp;quot;| 0&lt;br /&gt;
|style=&amp;quot;background-color:#BBB;&amp;quot;| 0&lt;br /&gt;
|style=&amp;quot;background-color:#BBB;&amp;quot;| 0&lt;br /&gt;
|style=&amp;quot;background-color:#AAF;&amp;quot; colspan=&amp;quot;5&amp;quot;| Bank&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== 0x01: Cartridge configuration ====&lt;br /&gt;
&lt;br /&gt;
==== 0x04: Activate SRAM/FRAM ====&lt;br /&gt;
When activated, any read/write access to the specified bank (defined in the parameter) is redirected to the selected segment of the SRAM/FRAM.&lt;br /&gt;
&lt;br /&gt;
SRAM/FRAM is accessed through 8 KB segments (on the NEO-16, the segment is mirrored).&lt;br /&gt;
&lt;br /&gt;
Up to 16 segments can be accessed, for a total capacity of 128 KB.&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ PARAMETER&lt;br /&gt;
|-&lt;br /&gt;
! 8 || 7 || 6 || 5 || 4 || 3 || 2 || 1&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#AAF;&amp;quot; colspan=&amp;quot;4&amp;quot;| Segment&lt;br /&gt;
|style=&amp;quot;background-color:#BBB;&amp;quot;| 0&lt;br /&gt;
|style=&amp;quot;background-color:#AAF;&amp;quot; colspan=&amp;quot;5&amp;quot;| Bank&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== 0x05: Activate device ====&lt;br /&gt;
Activate or disactivate the given device.&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ PARAMETER&lt;br /&gt;
|-&lt;br /&gt;
! 8 || 7 || 6 || 5 || 4 || 3 || 2 || 1&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#BBB;&amp;quot;| 0&lt;br /&gt;
|style=&amp;quot;background-color:#BBB;&amp;quot;| 0&lt;br /&gt;
|style=&amp;quot;background-color:#BBB;&amp;quot;| 0&lt;br /&gt;
|style=&amp;quot;background-color:#AAF;&amp;quot; colspan=&amp;quot;5&amp;quot;| Device&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Devices:&lt;br /&gt;
* &amp;lt;tt&amp;gt;00&amp;lt;/tt&amp;gt;: MSX-Music (OPLL)&lt;br /&gt;
* &amp;lt;tt&amp;gt;01&amp;lt;/tt&amp;gt;: MSX-Audio&lt;br /&gt;
* &amp;lt;tt&amp;gt;02&amp;lt;/tt&amp;gt;: SCC&lt;br /&gt;
* &amp;lt;tt&amp;gt;03&amp;lt;/tt&amp;gt;: SCC+&lt;br /&gt;
* &amp;lt;tt&amp;gt;04&amp;lt;/tt&amp;gt;: 2nd PSG (port 10h)&lt;br /&gt;
* &amp;lt;tt&amp;gt;05&amp;lt;/tt&amp;gt;: Darky (2 x ePSG)&lt;br /&gt;
* &amp;lt;tt&amp;gt;06&amp;lt;/tt&amp;gt;: Darky Jr. (2 x PSG)&lt;br /&gt;
* &amp;lt;tt&amp;gt;08&amp;lt;/tt&amp;gt;: OPM (SFK-01, SFG-01 et SFG-05 ver.1)&lt;br /&gt;
* &amp;lt;tt&amp;gt;09&amp;lt;/tt&amp;gt;: OPP (SFG-05 ver.2)&lt;br /&gt;
* &amp;lt;tt&amp;gt;12&amp;lt;/tt&amp;gt;: OPL4&lt;br /&gt;
* &amp;lt;tt&amp;gt;15&amp;lt;/tt&amp;gt;: SAM2695&lt;/div&gt;</summary>
		<author><name>Aoineko</name></author>	</entry>

	<entry>
		<id>https://aoineko.org/msxgl/index.php?title=NEO_mapper/Extension&amp;diff=3816</id>
		<title>NEO mapper/Extension</title>
		<link rel="alternate" type="text/html" href="https://aoineko.org/msxgl/index.php?title=NEO_mapper/Extension&amp;diff=3816"/>
				<updated>2026-04-06T19:48:30Z</updated>
		
		<summary type="html">&lt;p&gt;Aoineko: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{WARNING|This page is still in the proposal stage and should not yet be considered an official specification.}}&lt;br /&gt;
&lt;br /&gt;
Proposal for an extension to the [[NEO mapper]] format.&lt;br /&gt;
&lt;br /&gt;
== Specifications ==&lt;br /&gt;
&lt;br /&gt;
=== Principles ===&lt;br /&gt;
&lt;br /&gt;
Any write operation to the NEO mapper with data bit 7 set to 1 and address bit 0 set to 1 is considered an access to extended features. In that case, the mapper bank register is not modified.&lt;br /&gt;
&lt;br /&gt;
All other write operations should be considered normal access to the mapper's bank register.&lt;br /&gt;
&lt;br /&gt;
The data contains:&lt;br /&gt;
* The number of an extended function in the mapper&lt;br /&gt;
* A bit indicating whether the function should be enabled or disabled&lt;br /&gt;
&lt;br /&gt;
The address contains an 8-bit parameter to be passed to the function.&lt;br /&gt;
{|&lt;br /&gt;
|-&lt;br /&gt;
|&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ ADDRESS&lt;br /&gt;
|-&lt;br /&gt;
! 15 || 14 || 13 || 12 || 11 || 10 || 9 || 8 || 7 || 6 || 5 || 4 || 3 || 2 || 1 || 0&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#BBB;&amp;quot; colspan=&amp;quot;2&amp;quot;| Page&lt;br /&gt;
|style=&amp;quot;background-color:#BBB;&amp;quot; colspan=&amp;quot;3&amp;quot;| Bank&lt;br /&gt;
|style=&amp;quot;background-color:#BBB;&amp;quot;| 0&lt;br /&gt;
|style=&amp;quot;background-color:#BBB;&amp;quot;| 0&lt;br /&gt;
|style=&amp;quot;background-color:#AAF;&amp;quot; colspan=&amp;quot;8&amp;quot;| Parameter&lt;br /&gt;
|style=&amp;quot;background-color:#FAA;&amp;quot;| 1&lt;br /&gt;
|}&lt;br /&gt;
|&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ DATA&lt;br /&gt;
|-&lt;br /&gt;
! 7 || 6 || 5 || 4 || 3 || 2 || 1 || 0&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FAA;&amp;quot;| 1&lt;br /&gt;
|style=&amp;quot;background-color:#AAF;&amp;quot;| A&lt;br /&gt;
|style=&amp;quot;background-color:#BBB;&amp;quot;| 0&lt;br /&gt;
|style=&amp;quot;background-color:#AAF;&amp;quot; colspan=&amp;quot;5&amp;quot;| Function&lt;br /&gt;
|}&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Functions ===&lt;br /&gt;
==== 0x00: Cartridge information ====&lt;br /&gt;
When activated, any read access to the given bank will return the cartridge information (8 KB, mirrored on NEO-16).&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ PARAMETER&lt;br /&gt;
|-&lt;br /&gt;
! 8 || 7 || 6 || 5 || 4 || 3 || 2 || 1&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#BBB;&amp;quot;| 0&lt;br /&gt;
|style=&amp;quot;background-color:#BBB;&amp;quot;| 0&lt;br /&gt;
|style=&amp;quot;background-color:#BBB;&amp;quot;| 0&lt;br /&gt;
|style=&amp;quot;background-color:#BBB;&amp;quot;| 0&lt;br /&gt;
|style=&amp;quot;background-color:#BBB;&amp;quot;| 0&lt;br /&gt;
|style=&amp;quot;background-color:#AAF;&amp;quot; colspan=&amp;quot;5&amp;quot;| Bank&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== 0x01: Cartridge configuration ====&lt;br /&gt;
&lt;br /&gt;
==== 0x04: Activate SRAM/FRAM ====&lt;br /&gt;
When activated, any read/write access to the specified bank (defined in the parameter) is redirected to the selected segment of the SRAM/FRAM.&lt;br /&gt;
&lt;br /&gt;
SRAM/FRAM is accessed through 8 KB segments (on the NEO-16, the segment is mirrored).&lt;br /&gt;
&lt;br /&gt;
Up to 16 segments can be accessed, for a total capacity of 128 KB.&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ PARAMETER&lt;br /&gt;
|-&lt;br /&gt;
! 8 || 7 || 6 || 5 || 4 || 3 || 2 || 1&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#AAF;&amp;quot; colspan=&amp;quot;4&amp;quot;| Segment&lt;br /&gt;
|style=&amp;quot;background-color:#BBB;&amp;quot;| 0&lt;br /&gt;
|style=&amp;quot;background-color:#AAF;&amp;quot; colspan=&amp;quot;5&amp;quot;| Bank&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== 0x05: Activate device ====&lt;br /&gt;
Activate or disactivate the given device.&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ PARAMETER&lt;br /&gt;
|-&lt;br /&gt;
! 8 || 7 || 6 || 5 || 4 || 3 || 2 || 1&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#BBB;&amp;quot;| 0&lt;br /&gt;
|style=&amp;quot;background-color:#BBB;&amp;quot;| 0&lt;br /&gt;
|style=&amp;quot;background-color:#BBB;&amp;quot;| 0&lt;br /&gt;
|style=&amp;quot;background-color:#AAF;&amp;quot; colspan=&amp;quot;5&amp;quot;| Device&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Devices:&lt;br /&gt;
* &amp;lt;tt&amp;gt;00&amp;lt;/tt&amp;gt;: MSX-Music (OPLL)&lt;br /&gt;
* &amp;lt;tt&amp;gt;01&amp;lt;/tt&amp;gt;: MSX-Audio&lt;br /&gt;
* &amp;lt;tt&amp;gt;02&amp;lt;/tt&amp;gt;: SCC&lt;br /&gt;
* &amp;lt;tt&amp;gt;03&amp;lt;/tt&amp;gt;: SCC+&lt;br /&gt;
* &amp;lt;tt&amp;gt;04&amp;lt;/tt&amp;gt;: 2nd PSG (port 10h)&lt;br /&gt;
* &amp;lt;tt&amp;gt;05&amp;lt;/tt&amp;gt;: Darky (2 x ePSG)&lt;br /&gt;
* &amp;lt;tt&amp;gt;06&amp;lt;/tt&amp;gt;: Darky Jr. (2 x PSG)&lt;br /&gt;
* &amp;lt;tt&amp;gt;07&amp;lt;/tt&amp;gt;: &lt;br /&gt;
* &amp;lt;tt&amp;gt;08&amp;lt;/tt&amp;gt;: OPM (SFK-01, SFG-01 et SFG-05 ver.1)&lt;br /&gt;
* &amp;lt;tt&amp;gt;09&amp;lt;/tt&amp;gt;: OPP (SFG-05 ver.2)&lt;br /&gt;
* &amp;lt;tt&amp;gt;10&amp;lt;/tt&amp;gt;: &lt;br /&gt;
* &amp;lt;tt&amp;gt;11&amp;lt;/tt&amp;gt;: OPL4&lt;br /&gt;
* &amp;lt;tt&amp;gt;12&amp;lt;/tt&amp;gt;: SAM2695&lt;/div&gt;</summary>
		<author><name>Aoineko</name></author>	</entry>

	<entry>
		<id>https://aoineko.org/msxgl/index.php?title=NEO_mapper/Extension&amp;diff=3815</id>
		<title>NEO mapper/Extension</title>
		<link rel="alternate" type="text/html" href="https://aoineko.org/msxgl/index.php?title=NEO_mapper/Extension&amp;diff=3815"/>
				<updated>2026-04-06T19:47:24Z</updated>
		
		<summary type="html">&lt;p&gt;Aoineko: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{WARNING|This page is still in the proposal stage and should not yet be considered an official specification.}}&lt;br /&gt;
&lt;br /&gt;
Proposal for an extension to the [[NEO mapper]] format.&lt;br /&gt;
&lt;br /&gt;
== Specifications ==&lt;br /&gt;
&lt;br /&gt;
=== Principles ===&lt;br /&gt;
&lt;br /&gt;
Any write operation to the NEO mapper with data bit 7 set to 1 and address bit 0 set to 1 is considered an access to extended features. In that case, the mapper bank register is not modified.&lt;br /&gt;
&lt;br /&gt;
All other write operations should be considered normal access to the mapper's bank register.&lt;br /&gt;
&lt;br /&gt;
The data contains:&lt;br /&gt;
* The number of an extended function in the mapper&lt;br /&gt;
* A bit indicating whether the function should be enabled or disabled&lt;br /&gt;
&lt;br /&gt;
The address contains an 8-bit parameter to be passed to the function.&lt;br /&gt;
{|&lt;br /&gt;
|-&lt;br /&gt;
|&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ ADDRESS&lt;br /&gt;
|-&lt;br /&gt;
! 15 || 14 || 13 || 12 || 11 || 10 || 9 || 8 || 7 || 6 || 5 || 4 || 3 || 2 || 1 || 0&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#BBB;&amp;quot; colspan=&amp;quot;2&amp;quot;| Page&lt;br /&gt;
|style=&amp;quot;background-color:#BBB;&amp;quot; colspan=&amp;quot;3&amp;quot;| Bank&lt;br /&gt;
|style=&amp;quot;background-color:#BBB;&amp;quot;| 0&lt;br /&gt;
|style=&amp;quot;background-color:#BBB;&amp;quot;| 0&lt;br /&gt;
|style=&amp;quot;background-color:#AAF;&amp;quot; colspan=&amp;quot;8&amp;quot;| Parameter&lt;br /&gt;
|style=&amp;quot;background-color:#FAA;&amp;quot;| 1&lt;br /&gt;
|}&lt;br /&gt;
|&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ DATA&lt;br /&gt;
|-&lt;br /&gt;
! 7 || 6 || 5 || 4 || 3 || 2 || 1 || 0&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FAA;&amp;quot;| 1&lt;br /&gt;
|style=&amp;quot;background-color:#AAF;&amp;quot;| A&lt;br /&gt;
|style=&amp;quot;background-color:#BBB;&amp;quot;| 0&lt;br /&gt;
|style=&amp;quot;background-color:#AAF;&amp;quot; colspan=&amp;quot;5&amp;quot;| Function&lt;br /&gt;
|}&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Functions ===&lt;br /&gt;
==== 0x00: Cartridge information ====&lt;br /&gt;
When activated, any read access to the given bank will return the cartridge information (8 KB, mirrored on NEO-16).&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ PARAMETER&lt;br /&gt;
|-&lt;br /&gt;
! 8 || 7 || 6 || 5 || 4 || 3 || 2 || 1&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#BBB;&amp;quot;| 0&lt;br /&gt;
|style=&amp;quot;background-color:#BBB;&amp;quot;| 0&lt;br /&gt;
|style=&amp;quot;background-color:#BBB;&amp;quot;| 0&lt;br /&gt;
|style=&amp;quot;background-color:#BBB;&amp;quot;| 0&lt;br /&gt;
|style=&amp;quot;background-color:#BBB;&amp;quot;| 0&lt;br /&gt;
|style=&amp;quot;background-color:#AAF;&amp;quot; colspan=&amp;quot;5&amp;quot;| Bank&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== 0x01: Cartridge configuration ====&lt;br /&gt;
&lt;br /&gt;
==== 0x04: Activate SRAM/FRAM ====&lt;br /&gt;
When activated, any read/write access to the specified bank (defined in the parameter) is redirected to the selected segment of the SRAM/FRAM.&lt;br /&gt;
&lt;br /&gt;
SRAM/FRAM is accessed through 8 KB segments (on the NEO-16, the segment is mirrored).&lt;br /&gt;
&lt;br /&gt;
Up to 16 segments can be accessed, for a total capacity of 128 KB.&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ PARAMETER&lt;br /&gt;
|-&lt;br /&gt;
! 8 || 7 || 6 || 5 || 4 || 3 || 2 || 1&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#AAF;&amp;quot; colspan=&amp;quot;4&amp;quot;| Segment&lt;br /&gt;
|style=&amp;quot;background-color:#BBB;&amp;quot;| 0&lt;br /&gt;
|style=&amp;quot;background-color:#AAF;&amp;quot; colspan=&amp;quot;5&amp;quot;| Bank&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== 0x05: Activate device ====&lt;br /&gt;
Activate or disactivate the given device.&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ PARAMETER&lt;br /&gt;
|-&lt;br /&gt;
! 8 || 7 || 6 || 5 || 4 || 3 || 2 || 1&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#BBB;&amp;quot;| 0&lt;br /&gt;
|style=&amp;quot;background-color:#BBB;&amp;quot;| 0&lt;br /&gt;
|style=&amp;quot;background-color:#BBB;&amp;quot;| 0&lt;br /&gt;
|style=&amp;quot;background-color:#AAF;&amp;quot; colspan=&amp;quot;5&amp;quot;| Device&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Devices:&lt;br /&gt;
* &amp;lt;tt&amp;gt;00&amp;lt;/tt&amp;gt;: MSX-Music (OPLL)&lt;br /&gt;
* &amp;lt;tt&amp;gt;01&amp;lt;/tt&amp;gt;: MSX-Audio&lt;br /&gt;
* &amp;lt;tt&amp;gt;02&amp;lt;/tt&amp;gt;: SCC&lt;br /&gt;
* &amp;lt;tt&amp;gt;03&amp;lt;/tt&amp;gt;: SCC+&lt;br /&gt;
* &amp;lt;tt&amp;gt;04&amp;lt;/tt&amp;gt;: 2nd PSG (port 10h)&lt;br /&gt;
* &amp;lt;tt&amp;gt;05&amp;lt;/tt&amp;gt;: Darky (2 x ePSG)&lt;br /&gt;
* &amp;lt;tt&amp;gt;06&amp;lt;/tt&amp;gt;: Darky Jr. (2 x PSG)&lt;br /&gt;
* &amp;lt;tt&amp;gt;07&amp;lt;/tt&amp;gt;: &lt;br /&gt;
* &amp;lt;tt&amp;gt;08&amp;lt;/tt&amp;gt;: OPM (SFK-01, SFG-01 et SFG-05 ver.1)&lt;br /&gt;
* &amp;lt;tt&amp;gt;09&amp;lt;/tt&amp;gt;: OPP (SFG-05 ver.2)&lt;br /&gt;
* &amp;lt;tt&amp;gt;10&amp;lt;/tt&amp;gt;: &lt;br /&gt;
* &amp;lt;tt&amp;gt;11&amp;lt;/tt&amp;gt;: OPL4&lt;br /&gt;
* &amp;lt;tt&amp;gt;12&amp;lt;/tt&amp;gt;: &lt;br /&gt;
* &amp;lt;tt&amp;gt;13&amp;lt;/tt&amp;gt;: &lt;br /&gt;
* &amp;lt;tt&amp;gt;14&amp;lt;/tt&amp;gt;: &lt;br /&gt;
* &amp;lt;tt&amp;gt;15&amp;lt;/tt&amp;gt;: &lt;br /&gt;
* &amp;lt;tt&amp;gt;16&amp;lt;/tt&amp;gt;: OPNA (NEC PC)&lt;br /&gt;
* &amp;lt;tt&amp;gt;17&amp;lt;/tt&amp;gt;: OPNB (Neogeo)&lt;br /&gt;
* &amp;lt;tt&amp;gt;18&amp;lt;/tt&amp;gt;: SAA1099 (SAM Coupé)&lt;br /&gt;
* &amp;lt;tt&amp;gt;18&amp;lt;/tt&amp;gt;: SAM2695&lt;/div&gt;</summary>
		<author><name>Aoineko</name></author>	</entry>

	</feed>