<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
	<id>https://sneslab.net/mw/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Vitor+Vilela</id>
	<title>SnesLab - User contributions [en]</title>
	<link rel="self" type="application/atom+xml" href="https://sneslab.net/mw/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Vitor+Vilela"/>
	<link rel="alternate" type="text/html" href="https://sneslab.net/wiki/Special:Contributions/Vitor_Vilela"/>
	<updated>2026-04-29T03:22:29Z</updated>
	<subtitle>User contributions</subtitle>
	<generator>MediaWiki 1.39.5</generator>
	<entry>
		<id>https://sneslab.net/mw/index.php?title=Widescreen&amp;diff=1941</id>
		<title>Widescreen</title>
		<link rel="alternate" type="text/html" href="https://sneslab.net/mw/index.php?title=Widescreen&amp;diff=1941"/>
		<updated>2021-07-07T16:45:54Z</updated>

		<summary type="html">&lt;p&gt;Vitor Vilela: /* Screen */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Screen ==&lt;br /&gt;
The currently studied aspect ratios for SNES widescreen are the following:&lt;br /&gt;
&lt;br /&gt;
# 16:9 widescreen. There&#039;s an additional 48 columns to the left and right side of the screen. Resolution is 352x224, stretched to simulate the 8:7 pixel aspect ratio.&lt;br /&gt;
# 21:9 widescreen (actually 64:27). There&#039;s an additional 96 columns to the left and right side of the screen. Resolution is 448x224, stretched to simulate the 8:7 pixel aspect ratio.&lt;br /&gt;
# 2:1 widescreen. There&#039;s an additional 64 columns to the left and right side of the screen. Resolution is 384x224, stretched to simulate the 8:7 pixel aspect ratio.&lt;br /&gt;
&lt;br /&gt;
16:9 (352x224) and 21:9 (448x224) are the most important ones currently.&lt;br /&gt;
&lt;br /&gt;
=== Reference table ===&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! DAR (display aspect ratio) !! Numerical DAR !! SNES internal resolution !! Extras columns per side !! Numerical PAR (pixel aspect ratio) !! Notes&lt;br /&gt;
|-&lt;br /&gt;
| 8:7 || 1.1428 || 256x224 || 0 || 1.0000 || Most of the emulators doesn&#039;t apply pixel aspect ratio (leaves as 1:1). Keep this value as reference.&lt;br /&gt;
|-&lt;br /&gt;
| 4:3 || 1.3333 || 256x224 || 0 || 1.1667 || Real hardware reference. Certain TVs pixel aspect ratio are 1.1428 instead of 1.1667, due of signal interpretation differences.&lt;br /&gt;
|-&lt;br /&gt;
| 16:10 || 1.6000 || 304x224 || 24 || 1.1789 || Used to be common on some PC monitors, mostly replaced to 16:9.&lt;br /&gt;
|-&lt;br /&gt;
| 16:9 || 1.7778 || 352x224 || 48 || 1.1313 || Most common widescreen nowadays, being the recommended choice.&lt;br /&gt;
|-&lt;br /&gt;
| 2:1 || 2.0000 || 384x224 || 64 || 1.1667 || Some smartphones (marketed as 18:9) often uses this aspect ratio and calls it as ultrawide. The 21:9 version can be used keeping in mind a 1:1 PAR.&lt;br /&gt;
|-&lt;br /&gt;
| 21:9 || 2.3703 || 448x224 || 96 || 1.1851 || Commonly used on cinema and ultrawide monitors. &amp;quot;21:9&amp;quot; is a marketing term. The real aspect ratio is 64:27 (used by the HDMI standard) and it&#039;s used as reference for this table.&lt;br /&gt;
|-&lt;br /&gt;
| 24:9 || 2.6667 || 512x224 || 128 || 1.1667 || Maximum widescreen possible. Also known as 8:3. Horizontal scrolling is not really possible, NES-like methods would be needed.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Comparison with 4:3 standard ===&lt;br /&gt;
&lt;br /&gt;
The 256x224 SNES screen is not 4:3, but rather 8:7. CRT screens usually stretches the image by multiplying the internal screen width by 8/7 or 7/6, depending on the TV model. 8/7 seems to be more common, while 7/6 gives an perfect 4:3 output, since 8:7 (screen aspect ratio) * 7/6 (pixel aspect ratio) = 4/3 (actual aspect ratio), while 8:7 (screen aspect ratio) * 8/7 (pixel aspect ratio) = 64:49 (more like 4.0000:3.0625). Use the above reference table for clarification.&lt;br /&gt;
&lt;br /&gt;
=== Important note ===&lt;br /&gt;
All values consider the NTSC signal as reference. PAL equivalence calculations are not yet available.&lt;br /&gt;
&lt;br /&gt;
== Objects ==&lt;br /&gt;
&lt;br /&gt;
Since OAM sprite width is 9-bit wide, allowing values between -256 to +255, the internal range is adjusted in a manner the negative range also wraps positively. You can assume the values to range between -128 and +384, which are mapped that way: if unsigned position is greater than or equal to 384, subtract 512 from it. Else, keep value as is.&lt;br /&gt;
&lt;br /&gt;
Sprites that already knows how to handle the left screen boundary (position -1 to -16) can be easily adapted to work with the widescreen range. Otherwise, it&#039;s recommended to port the relative screen position to use 16-bit values.&lt;br /&gt;
&lt;br /&gt;
In addition, it doesn&#039;t break other emulators, since the additional visible area is implicitly invisible on the SNES hardware specification.&lt;br /&gt;
&lt;br /&gt;
== Windowing ==&lt;br /&gt;
&lt;br /&gt;
Assume that the windowing internal size is 512 lines long instead of 256 lines long. If you take the windowing calculations based from this perspective, windowing HDMA will work regardless of the aspect ratio being currently used (16:9, 21:9, etc.)&lt;br /&gt;
&lt;br /&gt;
Given that a window is between 00:FF, this means that 00 would be -128 in equivalent absolute position, 80 would be +128 and FF would be +383.&lt;br /&gt;
&lt;br /&gt;
Formula when default PPU is used:&lt;br /&gt;
f(x) -&amp;gt; x&lt;br /&gt;
&lt;br /&gt;
Formula when widescreen is active:&lt;br /&gt;
f(x) -&amp;gt; 2*x - 128&lt;br /&gt;
&lt;br /&gt;
== Emulator ==&lt;br /&gt;
https://github.com/DerKoun/bsnes-hd&lt;br /&gt;
&lt;br /&gt;
https://www.reddit.com/r/emulation/comments/bmc9t9/bsneshd_beta_5_bsnes_1073_formally_hd_mode_7_mod/&lt;/div&gt;</summary>
		<author><name>Vitor Vilela</name></author>
	</entry>
	<entry>
		<id>https://sneslab.net/mw/index.php?title=Widescreen&amp;diff=1940</id>
		<title>Widescreen</title>
		<link rel="alternate" type="text/html" href="https://sneslab.net/mw/index.php?title=Widescreen&amp;diff=1940"/>
		<updated>2021-07-07T16:45:13Z</updated>

		<summary type="html">&lt;p&gt;Vitor Vilela: /* Reference table */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Screen ==&lt;br /&gt;
The currently studied aspect ratios for SNES widescreen are the following:&lt;br /&gt;
&lt;br /&gt;
# 16:9 widescreen. There&#039;s an additional 48 columns to the left and right side of the screen. Resolution is 352x224, stretched to simulate the 8:7 pixel aspect ratio.&lt;br /&gt;
# 21:9 widescreen (actually 64:27). There&#039;s an additional 96 columns to the left and right side of the screen. Resolution is 448x224, stretched to simulate the 8:7 pixel aspect ratio.&lt;br /&gt;
# 2:1 widescreen. There&#039;s an additional 64 columns to the left and right side of the screen. Resolution is 384x224, stretched to simulate the 8:7 pixel aspect ratio.&lt;br /&gt;
&lt;br /&gt;
=== Reference table ===&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! DAR (display aspect ratio) !! Numerical DAR !! SNES internal resolution !! Extras columns per side !! Numerical PAR (pixel aspect ratio) !! Notes&lt;br /&gt;
|-&lt;br /&gt;
| 8:7 || 1.1428 || 256x224 || 0 || 1.0000 || Most of the emulators doesn&#039;t apply pixel aspect ratio (leaves as 1:1). Keep this value as reference.&lt;br /&gt;
|-&lt;br /&gt;
| 4:3 || 1.3333 || 256x224 || 0 || 1.1667 || Real hardware reference. Certain TVs pixel aspect ratio are 1.1428 instead of 1.1667, due of signal interpretation differences.&lt;br /&gt;
|-&lt;br /&gt;
| 16:10 || 1.6000 || 304x224 || 24 || 1.1789 || Used to be common on some PC monitors, mostly replaced to 16:9.&lt;br /&gt;
|-&lt;br /&gt;
| 16:9 || 1.7778 || 352x224 || 48 || 1.1313 || Most common widescreen nowadays, being the recommended choice.&lt;br /&gt;
|-&lt;br /&gt;
| 2:1 || 2.0000 || 384x224 || 64 || 1.1667 || Some smartphones (marketed as 18:9) often uses this aspect ratio and calls it as ultrawide. The 21:9 version can be used keeping in mind a 1:1 PAR.&lt;br /&gt;
|-&lt;br /&gt;
| 21:9 || 2.3703 || 448x224 || 96 || 1.1851 || Commonly used on cinema and ultrawide monitors. &amp;quot;21:9&amp;quot; is a marketing term. The real aspect ratio is 64:27 (used by the HDMI standard) and it&#039;s used as reference for this table.&lt;br /&gt;
|-&lt;br /&gt;
| 24:9 || 2.6667 || 512x224 || 128 || 1.1667 || Maximum widescreen possible. Also known as 8:3. Horizontal scrolling is not really possible, NES-like methods would be needed.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Comparison with 4:3 standard ===&lt;br /&gt;
&lt;br /&gt;
The 256x224 SNES screen is not 4:3, but rather 8:7. CRT screens usually stretches the image by multiplying the internal screen width by 8/7 or 7/6, depending on the TV model. 8/7 seems to be more common, while 7/6 gives an perfect 4:3 output, since 8:7 (screen aspect ratio) * 7/6 (pixel aspect ratio) = 4/3 (actual aspect ratio), while 8:7 (screen aspect ratio) * 8/7 (pixel aspect ratio) = 64:49 (more like 4.0000:3.0625). Use the above reference table for clarification.&lt;br /&gt;
&lt;br /&gt;
=== Important note ===&lt;br /&gt;
All values consider the NTSC signal as reference. PAL equivalence calculations are not yet available.&lt;br /&gt;
&lt;br /&gt;
== Objects ==&lt;br /&gt;
&lt;br /&gt;
Since OAM sprite width is 9-bit wide, allowing values between -256 to +255, the internal range is adjusted in a manner the negative range also wraps positively. You can assume the values to range between -128 and +384, which are mapped that way: if unsigned position is greater than or equal to 384, subtract 512 from it. Else, keep value as is.&lt;br /&gt;
&lt;br /&gt;
Sprites that already knows how to handle the left screen boundary (position -1 to -16) can be easily adapted to work with the widescreen range. Otherwise, it&#039;s recommended to port the relative screen position to use 16-bit values.&lt;br /&gt;
&lt;br /&gt;
In addition, it doesn&#039;t break other emulators, since the additional visible area is implicitly invisible on the SNES hardware specification.&lt;br /&gt;
&lt;br /&gt;
== Windowing ==&lt;br /&gt;
&lt;br /&gt;
Assume that the windowing internal size is 512 lines long instead of 256 lines long. If you take the windowing calculations based from this perspective, windowing HDMA will work regardless of the aspect ratio being currently used (16:9, 21:9, etc.)&lt;br /&gt;
&lt;br /&gt;
Given that a window is between 00:FF, this means that 00 would be -128 in equivalent absolute position, 80 would be +128 and FF would be +383.&lt;br /&gt;
&lt;br /&gt;
Formula when default PPU is used:&lt;br /&gt;
f(x) -&amp;gt; x&lt;br /&gt;
&lt;br /&gt;
Formula when widescreen is active:&lt;br /&gt;
f(x) -&amp;gt; 2*x - 128&lt;br /&gt;
&lt;br /&gt;
== Emulator ==&lt;br /&gt;
https://github.com/DerKoun/bsnes-hd&lt;br /&gt;
&lt;br /&gt;
https://www.reddit.com/r/emulation/comments/bmc9t9/bsneshd_beta_5_bsnes_1073_formally_hd_mode_7_mod/&lt;/div&gt;</summary>
		<author><name>Vitor Vilela</name></author>
	</entry>
	<entry>
		<id>https://sneslab.net/mw/index.php?title=Widescreen&amp;diff=1918</id>
		<title>Widescreen</title>
		<link rel="alternate" type="text/html" href="https://sneslab.net/mw/index.php?title=Widescreen&amp;diff=1918"/>
		<updated>2021-06-09T05:21:47Z</updated>

		<summary type="html">&lt;p&gt;Vitor Vilela: /* Windowing */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Screen ==&lt;br /&gt;
The currently studied aspect ratios for SNES widescreen are the following:&lt;br /&gt;
&lt;br /&gt;
# 16:9 widescreen. There&#039;s an additional 48 columns to the left and right side of the screen. Resolution is 352x224, stretched to simulate the 8:7 pixel aspect ratio.&lt;br /&gt;
# 21:9 widescreen (actually 64:27). There&#039;s an additional 96 columns to the left and right side of the screen. Resolution is 448x224, stretched to simulate the 8:7 pixel aspect ratio.&lt;br /&gt;
# 2:1 widescreen. There&#039;s an additional 64 columns to the left and right side of the screen. Resolution is 384x224, stretched to simulate the 8:7 pixel aspect ratio.&lt;br /&gt;
&lt;br /&gt;
=== Reference table ===&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! DAR (display aspect ratio) !! Numerical DAR !! SNES internal resolution !! Extras columns per side !! Numerical PAR (pixel aspect ratio) !! Notes&lt;br /&gt;
|-&lt;br /&gt;
| 8:7 || 1.1428 || 256x224 || 0 || 1.0000 || Most of the emulators doesn&#039;t apply pixel aspect ratio (leaves as 1:1). Keep this value as reference.&lt;br /&gt;
|-&lt;br /&gt;
| 4:3 || 1.3333 || 256x224 || 0 || 1.1667 || Real hardware reference. Certain TVs pixel aspect ratio are 1.1428 instead of 1.1667, due of signal interpretation differences.&lt;br /&gt;
|-&lt;br /&gt;
| 16:10 || 1.6000 || 304x224 || 24 || 1.1789 || Used to be common on some PC monitors, mostly replaced to 16:9.&lt;br /&gt;
|-&lt;br /&gt;
| 16:9 || 1.7778 || 352x224 || 48 || 1.1313 || Most common widescreen nowadays, being the recommended choice.&lt;br /&gt;
|-&lt;br /&gt;
| 2:1 || 2.0000 || 384x224 || 64 || 1.1667 || Uncommon, recommended only if your SNES game targets VR.&lt;br /&gt;
|-&lt;br /&gt;
| 21:9 || 2.3703 || 448x224 || 96 || 1.1851 || Commonly used on cinema and ultrawide monitors. &amp;quot;21:9&amp;quot; is a marketing term. The real aspect ratio is 64:27 (used by the HDMI standard) and it&#039;s used as reference for this table.&lt;br /&gt;
|-&lt;br /&gt;
| 24:9 || 2.6667 || 512x224 || 128 || 1.1667 || Maximum widescreen possible. Also known as 8:3. Horizontal scrolling is not really possible, NES-like methods would be needed.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Comparison with 4:3 standard ===&lt;br /&gt;
&lt;br /&gt;
The 256x224 SNES screen is not 4:3, but rather 8:7. CRT screens usually stretches the image by multiplying the internal screen width by 8/7 or 7/6, depending on the TV model. 8/7 seems to be more common, while 7/6 gives an perfect 4:3 output, since 8:7 (screen aspect ratio) * 7/6 (pixel aspect ratio) = 4/3 (actual aspect ratio), while 8:7 (screen aspect ratio) * 8/7 (pixel aspect ratio) = 64:49 (more like 4.0000:3.0625). Use the above reference table for clarification.&lt;br /&gt;
&lt;br /&gt;
=== Important note ===&lt;br /&gt;
All values consider the NTSC signal as reference. PAL equivalence calculations are not yet available.&lt;br /&gt;
&lt;br /&gt;
== Objects ==&lt;br /&gt;
&lt;br /&gt;
Since OAM sprite width is 9-bit wide, allowing values between -256 to +255, the internal range is adjusted in a manner the negative range also wraps positively. You can assume the values to range between -128 and +384, which are mapped that way: if unsigned position is greater than or equal to 384, subtract 512 from it. Else, keep value as is.&lt;br /&gt;
&lt;br /&gt;
Sprites that already knows how to handle the left screen boundary (position -1 to -16) can be easily adapted to work with the widescreen range. Otherwise, it&#039;s recommended to port the relative screen position to use 16-bit values.&lt;br /&gt;
&lt;br /&gt;
In addition, it doesn&#039;t break other emulators, since the additional visible area is implicitly invisible on the SNES hardware specification.&lt;br /&gt;
&lt;br /&gt;
== Windowing ==&lt;br /&gt;
&lt;br /&gt;
Assume that the windowing internal size is 512 lines long instead of 256 lines long. If you take the windowing calculations based from this perspective, windowing HDMA will work regardless of the aspect ratio being currently used (16:9, 21:9, etc.)&lt;br /&gt;
&lt;br /&gt;
Given that a window is between 00:FF, this means that 00 would be -128 in equivalent absolute position, 80 would be +128 and FF would be +383.&lt;br /&gt;
&lt;br /&gt;
Formula when default PPU is used:&lt;br /&gt;
f(x) -&amp;gt; x&lt;br /&gt;
&lt;br /&gt;
Formula when widescreen is active:&lt;br /&gt;
f(x) -&amp;gt; 2*x - 128&lt;br /&gt;
&lt;br /&gt;
== Emulator ==&lt;br /&gt;
https://github.com/DerKoun/bsnes-hd&lt;br /&gt;
&lt;br /&gt;
https://www.reddit.com/r/emulation/comments/bmc9t9/bsneshd_beta_5_bsnes_1073_formally_hd_mode_7_mod/&lt;/div&gt;</summary>
		<author><name>Vitor Vilela</name></author>
	</entry>
	<entry>
		<id>https://sneslab.net/mw/index.php?title=Widescreen&amp;diff=1912</id>
		<title>Widescreen</title>
		<link rel="alternate" type="text/html" href="https://sneslab.net/mw/index.php?title=Widescreen&amp;diff=1912"/>
		<updated>2021-05-22T06:10:38Z</updated>

		<summary type="html">&lt;p&gt;Vitor Vilela: Add 16:10 and 24:9&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Screen ==&lt;br /&gt;
The currently studied aspect ratios for SNES widescreen are the following:&lt;br /&gt;
&lt;br /&gt;
# 16:9 widescreen. There&#039;s an additional 48 columns to the left and right side of the screen. Resolution is 352x224, stretched to simulate the 8:7 pixel aspect ratio.&lt;br /&gt;
# 21:9 widescreen (actually 64:27). There&#039;s an additional 96 columns to the left and right side of the screen. Resolution is 448x224, stretched to simulate the 8:7 pixel aspect ratio.&lt;br /&gt;
# 2:1 widescreen. There&#039;s an additional 64 columns to the left and right side of the screen. Resolution is 384x224, stretched to simulate the 8:7 pixel aspect ratio.&lt;br /&gt;
&lt;br /&gt;
=== Reference table ===&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! DAR (display aspect ratio) !! Numerical DAR !! SNES internal resolution !! Extras columns per side !! Numerical PAR (pixel aspect ratio) !! Notes&lt;br /&gt;
|-&lt;br /&gt;
| 8:7 || 1.1428 || 256x224 || 0 || 1.0000 || Most of the emulators doesn&#039;t apply pixel aspect ratio (leaves as 1:1). Keep this value as reference.&lt;br /&gt;
|-&lt;br /&gt;
| 4:3 || 1.3333 || 256x224 || 0 || 1.1667 || Real hardware reference. Certain TVs pixel aspect ratio are 1.1428 instead of 1.1667, due of signal interpretation differences.&lt;br /&gt;
|-&lt;br /&gt;
| 16:10 || 1.6000 || 304x224 || 24 || 1.1789 || Used to be common on some PC monitors, mostly replaced to 16:9.&lt;br /&gt;
|-&lt;br /&gt;
| 16:9 || 1.7778 || 352x224 || 48 || 1.1313 || Most common widescreen nowadays, being the recommended choice.&lt;br /&gt;
|-&lt;br /&gt;
| 2:1 || 2.0000 || 384x224 || 64 || 1.1667 || Uncommon, recommended only if your SNES game targets VR.&lt;br /&gt;
|-&lt;br /&gt;
| 21:9 || 2.3703 || 448x224 || 96 || 1.1851 || Commonly used on cinema and ultrawide monitors. &amp;quot;21:9&amp;quot; is a marketing term. The real aspect ratio is 64:27 (used by the HDMI standard) and it&#039;s used as reference for this table.&lt;br /&gt;
|-&lt;br /&gt;
| 24:9 || 2.6667 || 512x224 || 128 || 1.1667 || Maximum widescreen possible. Also known as 8:3. Horizontal scrolling is not really possible, NES-like methods would be needed.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Comparison with 4:3 standard ===&lt;br /&gt;
&lt;br /&gt;
The 256x224 SNES screen is not 4:3, but rather 8:7. CRT screens usually stretches the image by multiplying the internal screen width by 8/7 or 7/6, depending on the TV model. 8/7 seems to be more common, while 7/6 gives an perfect 4:3 output, since 8:7 (screen aspect ratio) * 7/6 (pixel aspect ratio) = 4/3 (actual aspect ratio), while 8:7 (screen aspect ratio) * 8/7 (pixel aspect ratio) = 64:49 (more like 4.0000:3.0625). Use the above reference table for clarification.&lt;br /&gt;
&lt;br /&gt;
=== Important note ===&lt;br /&gt;
All values consider the NTSC signal as reference. PAL equivalence calculations are not yet available.&lt;br /&gt;
&lt;br /&gt;
== Objects ==&lt;br /&gt;
&lt;br /&gt;
Since OAM sprite width is 9-bit wide, allowing values between -256 to +255, the internal range is adjusted in a manner the negative range also wraps positively. You can assume the values to range between -128 and +384, which are mapped that way: if unsigned position is greater than or equal to 384, subtract 512 from it. Else, keep value as is.&lt;br /&gt;
&lt;br /&gt;
Sprites that already knows how to handle the left screen boundary (position -1 to -16) can be easily adapted to work with the widescreen range. Otherwise, it&#039;s recommended to port the relative screen position to use 16-bit values.&lt;br /&gt;
&lt;br /&gt;
In addition, it doesn&#039;t break other emulators, since the additional visible area is implicitly invisible on the SNES hardware specification.&lt;br /&gt;
&lt;br /&gt;
== Windowing ==&lt;br /&gt;
&lt;br /&gt;
Assume that the windowing internal size is 512 lines long instead of 256 lines long. If you take the windowing calculations based from this perspective, windowing HDMA will work regardless of the aspect ratio being currently used (16:9, 21:9, etc.)&lt;br /&gt;
&lt;br /&gt;
== Emulator ==&lt;br /&gt;
https://github.com/DerKoun/bsnes-hd&lt;br /&gt;
&lt;br /&gt;
https://www.reddit.com/r/emulation/comments/bmc9t9/bsneshd_beta_5_bsnes_1073_formally_hd_mode_7_mod/&lt;/div&gt;</summary>
		<author><name>Vitor Vilela</name></author>
	</entry>
	<entry>
		<id>https://sneslab.net/mw/index.php?title=How_to_apply_ROM_patches&amp;diff=1863</id>
		<title>How to apply ROM patches</title>
		<link rel="alternate" type="text/html" href="https://sneslab.net/mw/index.php?title=How_to_apply_ROM_patches&amp;diff=1863"/>
		<updated>2021-04-16T04:52:10Z</updated>

		<summary type="html">&lt;p&gt;Vitor Vilela: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;It&#039;s common when distributing new game enhancements, ROM hacks and specific features people end up releasing in &#039;&#039;&#039;patch&#039;&#039;&#039; format instead of uploading the modified ROM image to the public. The reason for that is because patches only contain &#039;&#039;&#039;the changes made&#039;&#039;&#039; to the ROM, making them &#039;&#039;&#039;smaller to distribute&#039;&#039;&#039; specially on big ROMs present on newer consoles like Playstation 1, Nintendo 64 and newer. But the main reason for using and distributing patches is because since they only include the changes made to the ROM, it will not contain any copyrighted code and thus the patches are immune to any copyright claim, unless if patch itself contains copyrighted data.&lt;br /&gt;
&lt;br /&gt;
When downloading a patch, you will have to use a tool that knows how to read the patch data and apply it over the original game ROM. That&#039;s the main issue you have when using patches, because you will need to download a tool for applying the patch and the original game ROM for applying it.&lt;br /&gt;
&lt;br /&gt;
The most common patch types are IPS and BPS. For applying IPS patches, you can use Lunar IPS. For applying BPS patches, you can use FLIPS or beat.&lt;br /&gt;
&lt;br /&gt;
== Patching Procedure ==&lt;br /&gt;
# Download the game patch. For example, Gradius III SA-1 version can be downloaded here: https://github.com/VitorVilela7/SA1-Root/releases. Notice that the patch we will use is &amp;quot;Gradius-III-USA.bps&amp;quot; for this example.&lt;br /&gt;
# The original ROM file. For the example, you will need the original American (USA) Gradius III ROM.&lt;br /&gt;
# Download either FLIPS or beat. You can download FLIPS for Windows here: https://sneslab.net/tools/floating.zip&lt;br /&gt;
# Open flips.exe&lt;br /&gt;
# Click &amp;quot;Apply patch&amp;quot;. An file dialog will appear. Pick the patch file you downloaded.&lt;br /&gt;
# Another file dialog will appear. Select the original ROM file.&lt;br /&gt;
# And the last file dialog will appear. Type the name of the new ROM file that will contain the patch together.&lt;br /&gt;
&lt;br /&gt;
If you receive a message saying &amp;quot;The patch was successfully applied&amp;quot;, then it means the ROM file you just saved has the patch applied. Now you can test it on your favorite emulator!&lt;br /&gt;
&lt;br /&gt;
== Alternative ==&lt;br /&gt;
Other known ROM patchers available:&lt;br /&gt;
# beat&lt;br /&gt;
# https://www.marcrobledo.com/RomPatcher.js/&lt;/div&gt;</summary>
		<author><name>Vitor Vilela</name></author>
	</entry>
	<entry>
		<id>https://sneslab.net/mw/index.php?title=Widescreen&amp;diff=1830</id>
		<title>Widescreen</title>
		<link rel="alternate" type="text/html" href="https://sneslab.net/mw/index.php?title=Widescreen&amp;diff=1830"/>
		<updated>2021-04-11T10:08:28Z</updated>

		<summary type="html">&lt;p&gt;Vitor Vilela: /* Reference table */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Screen ==&lt;br /&gt;
The currently studied aspect ratios for SNES widescreen are the following:&lt;br /&gt;
&lt;br /&gt;
# 16:9 widescreen. There&#039;s an additional 48 columns to the left and right side of the screen. Resolution is 352x224, stretched to simulate the 8:7 pixel aspect ratio.&lt;br /&gt;
# 21:9 widescreen (actually 64:27). There&#039;s an additional 96 columns to the left and right side of the screen. Resolution is 448x224, stretched to simulate the 8:7 pixel aspect ratio.&lt;br /&gt;
# 2:1 widescreen. There&#039;s an additional 64 columns to the left and right side of the screen. Resolution is 384x224, stretched to simulate the 8:7 pixel aspect ratio.&lt;br /&gt;
&lt;br /&gt;
=== Reference table ===&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! DAR (display aspect ratio) !! Numerical DAR !! SNES internal resolution !! Extras columns per side !! Numerical PAR (pixel aspect ratio) !! Notes&lt;br /&gt;
|-&lt;br /&gt;
| 8:7 || 1.1428 || 256x224 || 0 || 1.0000 || Most of the emulators doesn&#039;t apply pixel aspect ratio (leaves as 1:1). Keep this value as reference.&lt;br /&gt;
|-&lt;br /&gt;
| 4:3 || 1.3333 || 256x224 || 0 || 1.1667 || Real hardware reference. Certain TVs pixel aspect ratio are 1.1428 instead of 1.1667, due of signal interpretation differences.&lt;br /&gt;
|-&lt;br /&gt;
| 16:9 || 1.7778 || 352x224 || 48 || 1.1313 || Most common widescreen nowadays, being the recommended choice.&lt;br /&gt;
|-&lt;br /&gt;
| 2:1 || 2.0000 || 384x224 || 64 || 1.1667 || Uncommon, recommended only if your SNES game targets VR.&lt;br /&gt;
|-&lt;br /&gt;
| 21:9 || 2.3703 || 448x224 || 96 || 1.1851 || Commonly used on cinema and ultrawide monitors. &amp;quot;21:9&amp;quot; is a marketing term. The real aspect ratio is 64:27 (used by the HDMI standard) and it&#039;s used as reference for this table.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Comparison with 4:3 standard ===&lt;br /&gt;
&lt;br /&gt;
The 256x224 SNES screen is not 4:3, but rather 8:7. CRT screens usually stretches the image by multiplying the internal screen width by 8/7 or 7/6, depending on the TV model. 8/7 seems to be more common, while 7/6 gives an perfect 4:3 output, since 8:7 (screen aspect ratio) * 7/6 (pixel aspect ratio) = 4/3 (actual aspect ratio), while 8:7 (screen aspect ratio) * 8/7 (pixel aspect ratio) = 64:49 (more like 4.0000:3.0625). Use the above reference table for clarification.&lt;br /&gt;
&lt;br /&gt;
=== Important note ===&lt;br /&gt;
All values consider the NTSC signal as reference. PAL equivalence calculations are not yet available.&lt;br /&gt;
&lt;br /&gt;
== Objects ==&lt;br /&gt;
&lt;br /&gt;
Since OAM sprite width is 9-bit wide, allowing values between -256 to +255, the internal range is adjusted in a manner the negative range also wraps positively. You can assume the values to range between -128 and +384, which are mapped that way: if unsigned position is greater than or equal to 384, subtract 512 from it. Else, keep value as is.&lt;br /&gt;
&lt;br /&gt;
Sprites that already knows how to handle the left screen boundary (position -1 to -16) can be easily adapted to work with the widescreen range. Otherwise, it&#039;s recommended to port the relative screen position to use 16-bit values.&lt;br /&gt;
&lt;br /&gt;
In addition, it doesn&#039;t break other emulators, since the additional visible area is implicitly invisible on the SNES hardware specification.&lt;br /&gt;
&lt;br /&gt;
== Windowing ==&lt;br /&gt;
&lt;br /&gt;
Assume that the windowing internal size is 512 lines long instead of 256 lines long. If you take the windowing calculations based from this perspective, windowing HDMA will work regardless of the aspect ratio being currently used (16:9, 21:9, etc.)&lt;br /&gt;
&lt;br /&gt;
== Emulator ==&lt;br /&gt;
https://github.com/DerKoun/bsnes-hd&lt;br /&gt;
&lt;br /&gt;
https://www.reddit.com/r/emulation/comments/bmc9t9/bsneshd_beta_5_bsnes_1073_formally_hd_mode_7_mod/&lt;/div&gt;</summary>
		<author><name>Vitor Vilela</name></author>
	</entry>
	<entry>
		<id>https://sneslab.net/mw/index.php?title=Widescreen&amp;diff=1829</id>
		<title>Widescreen</title>
		<link rel="alternate" type="text/html" href="https://sneslab.net/mw/index.php?title=Widescreen&amp;diff=1829"/>
		<updated>2021-04-11T10:07:13Z</updated>

		<summary type="html">&lt;p&gt;Vitor Vilela: /* Reference table */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Screen ==&lt;br /&gt;
The currently studied aspect ratios for SNES widescreen are the following:&lt;br /&gt;
&lt;br /&gt;
# 16:9 widescreen. There&#039;s an additional 48 columns to the left and right side of the screen. Resolution is 352x224, stretched to simulate the 8:7 pixel aspect ratio.&lt;br /&gt;
# 21:9 widescreen (actually 64:27). There&#039;s an additional 96 columns to the left and right side of the screen. Resolution is 448x224, stretched to simulate the 8:7 pixel aspect ratio.&lt;br /&gt;
# 2:1 widescreen. There&#039;s an additional 64 columns to the left and right side of the screen. Resolution is 384x224, stretched to simulate the 8:7 pixel aspect ratio.&lt;br /&gt;
&lt;br /&gt;
=== Reference table ===&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! DAR (display aspect ratio) !! Numerical DAR !! SNES internal resolution !! Extras columns per side !! Numerical PAR (pixel aspect ratio) !! Notes&lt;br /&gt;
|-&lt;br /&gt;
| 8:7 || 1.1428 || 256x224 || 0 || 1.0000 || Most of the emulators doesn&#039;t apply pixel aspect ratio (leaves as 1:1). Keep this value as reference.&lt;br /&gt;
|-&lt;br /&gt;
| 4:3 || 1.3333 || 256x224 || 0 || 1.1667 || Real hardware reference. Certain TVs pixel aspect ratio are 1.1428 instead of 1.1667, due of signal interpretation differences.&lt;br /&gt;
|-&lt;br /&gt;
| 16:9 || 1.7778 || 352x224 || 48 || 1.1313 || Most common widescreen nowadays, being the recommended choice.&lt;br /&gt;
|-&lt;br /&gt;
| 2:1 || 2.0000 || 384x224 || 64 || 1.1667 || N/A&lt;br /&gt;
|-&lt;br /&gt;
| 21:9 || 2.3703 || 448x224 || 96 || 1.1851 || Commonly used on cinema and ultrawide monitors. &amp;quot;21:9&amp;quot; is a marketing term. The real aspect ratio is 64:27 (used by the HDMI standard) and it&#039;s used as reference for this table.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Comparison with 4:3 standard ===&lt;br /&gt;
&lt;br /&gt;
The 256x224 SNES screen is not 4:3, but rather 8:7. CRT screens usually stretches the image by multiplying the internal screen width by 8/7 or 7/6, depending on the TV model. 8/7 seems to be more common, while 7/6 gives an perfect 4:3 output, since 8:7 (screen aspect ratio) * 7/6 (pixel aspect ratio) = 4/3 (actual aspect ratio), while 8:7 (screen aspect ratio) * 8/7 (pixel aspect ratio) = 64:49 (more like 4.0000:3.0625). Use the above reference table for clarification.&lt;br /&gt;
&lt;br /&gt;
=== Important note ===&lt;br /&gt;
All values consider the NTSC signal as reference. PAL equivalence calculations are not yet available.&lt;br /&gt;
&lt;br /&gt;
== Objects ==&lt;br /&gt;
&lt;br /&gt;
Since OAM sprite width is 9-bit wide, allowing values between -256 to +255, the internal range is adjusted in a manner the negative range also wraps positively. You can assume the values to range between -128 and +384, which are mapped that way: if unsigned position is greater than or equal to 384, subtract 512 from it. Else, keep value as is.&lt;br /&gt;
&lt;br /&gt;
Sprites that already knows how to handle the left screen boundary (position -1 to -16) can be easily adapted to work with the widescreen range. Otherwise, it&#039;s recommended to port the relative screen position to use 16-bit values.&lt;br /&gt;
&lt;br /&gt;
In addition, it doesn&#039;t break other emulators, since the additional visible area is implicitly invisible on the SNES hardware specification.&lt;br /&gt;
&lt;br /&gt;
== Windowing ==&lt;br /&gt;
&lt;br /&gt;
Assume that the windowing internal size is 512 lines long instead of 256 lines long. If you take the windowing calculations based from this perspective, windowing HDMA will work regardless of the aspect ratio being currently used (16:9, 21:9, etc.)&lt;br /&gt;
&lt;br /&gt;
== Emulator ==&lt;br /&gt;
https://github.com/DerKoun/bsnes-hd&lt;br /&gt;
&lt;br /&gt;
https://www.reddit.com/r/emulation/comments/bmc9t9/bsneshd_beta_5_bsnes_1073_formally_hd_mode_7_mod/&lt;/div&gt;</summary>
		<author><name>Vitor Vilela</name></author>
	</entry>
	<entry>
		<id>https://sneslab.net/mw/index.php?title=Widescreen&amp;diff=1828</id>
		<title>Widescreen</title>
		<link rel="alternate" type="text/html" href="https://sneslab.net/mw/index.php?title=Widescreen&amp;diff=1828"/>
		<updated>2021-04-11T09:57:34Z</updated>

		<summary type="html">&lt;p&gt;Vitor Vilela: /* Reference table */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Screen ==&lt;br /&gt;
The currently studied aspect ratios for SNES widescreen are the following:&lt;br /&gt;
&lt;br /&gt;
# 16:9 widescreen. There&#039;s an additional 48 columns to the left and right side of the screen. Resolution is 352x224, stretched to simulate the 8:7 pixel aspect ratio.&lt;br /&gt;
# 21:9 widescreen (actually 64:27). There&#039;s an additional 96 columns to the left and right side of the screen. Resolution is 448x224, stretched to simulate the 8:7 pixel aspect ratio.&lt;br /&gt;
# 2:1 widescreen. There&#039;s an additional 64 columns to the left and right side of the screen. Resolution is 384x224, stretched to simulate the 8:7 pixel aspect ratio.&lt;br /&gt;
&lt;br /&gt;
=== Reference table ===&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! DAR (display aspect ratio) !! Numerical DAR !! SNES internal resolution !! Numerical PAR (pixel aspect ratio) !! Notes&lt;br /&gt;
|-&lt;br /&gt;
| 8:7 || 1.1428 || 256x224 || 1.0000 || Most of the emulators doesn&#039;t apply pixel aspect ratio (leaves as 1:1). Keep this value as reference.&lt;br /&gt;
|-&lt;br /&gt;
| 4:3 || 1.3333 || 256x224 || 1.1667 || Real hardware reference. Certain TVs pixel aspect ratio are 1.1428 instead of 1.1667, due of signal interpretation differences.&lt;br /&gt;
|-&lt;br /&gt;
| 16:9 || 1.7778 || 352x224 || 1.1313 || N/A&lt;br /&gt;
|-&lt;br /&gt;
| 21:9 || 2.3703 || 448x224 || 1.1851 || &amp;quot;21:9&amp;quot; is a marketing term. The real aspect ratio is 64:27 (used by the HDMI standard) and it&#039;s used as reference for this table.&lt;br /&gt;
|-&lt;br /&gt;
| 2:1 || 2.0000 || 384x224 || 1.1667 || N/A&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Comparison with 4:3 standard ===&lt;br /&gt;
&lt;br /&gt;
The 256x224 SNES screen is not 4:3, but rather 8:7. CRT screens usually stretches the image by multiplying the internal screen width by 8/7 or 7/6, depending on the TV model. 8/7 seems to be more common, while 7/6 gives an perfect 4:3 output, since 8:7 (screen aspect ratio) * 7/6 (pixel aspect ratio) = 4/3 (actual aspect ratio), while 8:7 (screen aspect ratio) * 8/7 (pixel aspect ratio) = 64:49 (more like 4.0000:3.0625). Use the above reference table for clarification.&lt;br /&gt;
&lt;br /&gt;
=== Important note ===&lt;br /&gt;
All values consider the NTSC signal as reference. PAL equivalence calculations are not yet available.&lt;br /&gt;
&lt;br /&gt;
== Objects ==&lt;br /&gt;
&lt;br /&gt;
Since OAM sprite width is 9-bit wide, allowing values between -256 to +255, the internal range is adjusted in a manner the negative range also wraps positively. You can assume the values to range between -128 and +384, which are mapped that way: if unsigned position is greater than or equal to 384, subtract 512 from it. Else, keep value as is.&lt;br /&gt;
&lt;br /&gt;
Sprites that already knows how to handle the left screen boundary (position -1 to -16) can be easily adapted to work with the widescreen range. Otherwise, it&#039;s recommended to port the relative screen position to use 16-bit values.&lt;br /&gt;
&lt;br /&gt;
In addition, it doesn&#039;t break other emulators, since the additional visible area is implicitly invisible on the SNES hardware specification.&lt;br /&gt;
&lt;br /&gt;
== Windowing ==&lt;br /&gt;
&lt;br /&gt;
Assume that the windowing internal size is 512 lines long instead of 256 lines long. If you take the windowing calculations based from this perspective, windowing HDMA will work regardless of the aspect ratio being currently used (16:9, 21:9, etc.)&lt;br /&gt;
&lt;br /&gt;
== Emulator ==&lt;br /&gt;
https://github.com/DerKoun/bsnes-hd&lt;br /&gt;
&lt;br /&gt;
https://www.reddit.com/r/emulation/comments/bmc9t9/bsneshd_beta_5_bsnes_1073_formally_hd_mode_7_mod/&lt;/div&gt;</summary>
		<author><name>Vitor Vilela</name></author>
	</entry>
	<entry>
		<id>https://sneslab.net/mw/index.php?title=Widescreen&amp;diff=1827</id>
		<title>Widescreen</title>
		<link rel="alternate" type="text/html" href="https://sneslab.net/mw/index.php?title=Widescreen&amp;diff=1827"/>
		<updated>2021-04-11T09:54:57Z</updated>

		<summary type="html">&lt;p&gt;Vitor Vilela: /* Screen */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Screen ==&lt;br /&gt;
The currently studied aspect ratios for SNES widescreen are the following:&lt;br /&gt;
&lt;br /&gt;
# 16:9 widescreen. There&#039;s an additional 48 columns to the left and right side of the screen. Resolution is 352x224, stretched to simulate the 8:7 pixel aspect ratio.&lt;br /&gt;
# 21:9 widescreen (actually 64:27). There&#039;s an additional 96 columns to the left and right side of the screen. Resolution is 448x224, stretched to simulate the 8:7 pixel aspect ratio.&lt;br /&gt;
# 2:1 widescreen. There&#039;s an additional 64 columns to the left and right side of the screen. Resolution is 384x224, stretched to simulate the 8:7 pixel aspect ratio.&lt;br /&gt;
&lt;br /&gt;
=== Reference table ===&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Target aspect ratio !! Numerical aspect ratio !! SNES internal resolution !! Numerical pixel aspect ratio !! Notes&lt;br /&gt;
|-&lt;br /&gt;
| 8:7 || 1.1428 || 256x224 || 1.0000 || Most of the emulators doesn&#039;t apply pixel aspect ratio (leaves as 1:1). Keep this value as reference.&lt;br /&gt;
|-&lt;br /&gt;
| 4:3 || 1.3333 || 256x224 || 1.1667 || Real hardware reference. Certain TVs pixel aspect ratio are 1.1428 instead of 1.1667, due of signal interpretation differences.&lt;br /&gt;
|-&lt;br /&gt;
| 16:9 || 1.7778 || 352x224 || 1.1313 || N/A&lt;br /&gt;
|-&lt;br /&gt;
| 21:9 || 2.3703 || 448x224 || 1.1851 || &amp;quot;21:9&amp;quot; is a marketing term. The real aspect ratio is 64:27 (used by the HDMI standard) and it&#039;s used as reference for this table.&lt;br /&gt;
|-&lt;br /&gt;
| 2:1 || 2.0000 || 384x224 || 1.1667 || N/A&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Comparison with 4:3 standard ===&lt;br /&gt;
&lt;br /&gt;
The 256x224 SNES screen is not 4:3, but rather 8:7. CRT screens usually stretches the image by multiplying the internal screen width by 8/7 or 7/6, depending on the TV model. 8/7 seems to be more common, while 7/6 gives an perfect 4:3 output, since 8:7 (screen aspect ratio) * 7/6 (pixel aspect ratio) = 4/3 (actual aspect ratio), while 8:7 (screen aspect ratio) * 8/7 (pixel aspect ratio) = 64:49 (more like 4.0000:3.0625). Use the above reference table for clarification.&lt;br /&gt;
&lt;br /&gt;
=== Important note ===&lt;br /&gt;
All values consider the NTSC signal as reference. PAL equivalence calculations are not yet available.&lt;br /&gt;
&lt;br /&gt;
== Objects ==&lt;br /&gt;
&lt;br /&gt;
Since OAM sprite width is 9-bit wide, allowing values between -256 to +255, the internal range is adjusted in a manner the negative range also wraps positively. You can assume the values to range between -128 and +384, which are mapped that way: if unsigned position is greater than or equal to 384, subtract 512 from it. Else, keep value as is.&lt;br /&gt;
&lt;br /&gt;
Sprites that already knows how to handle the left screen boundary (position -1 to -16) can be easily adapted to work with the widescreen range. Otherwise, it&#039;s recommended to port the relative screen position to use 16-bit values.&lt;br /&gt;
&lt;br /&gt;
In addition, it doesn&#039;t break other emulators, since the additional visible area is implicitly invisible on the SNES hardware specification.&lt;br /&gt;
&lt;br /&gt;
== Windowing ==&lt;br /&gt;
&lt;br /&gt;
Assume that the windowing internal size is 512 lines long instead of 256 lines long. If you take the windowing calculations based from this perspective, windowing HDMA will work regardless of the aspect ratio being currently used (16:9, 21:9, etc.)&lt;br /&gt;
&lt;br /&gt;
== Emulator ==&lt;br /&gt;
https://github.com/DerKoun/bsnes-hd&lt;br /&gt;
&lt;br /&gt;
https://www.reddit.com/r/emulation/comments/bmc9t9/bsneshd_beta_5_bsnes_1073_formally_hd_mode_7_mod/&lt;/div&gt;</summary>
		<author><name>Vitor Vilela</name></author>
	</entry>
	<entry>
		<id>https://sneslab.net/mw/index.php?title=Widescreen&amp;diff=1826</id>
		<title>Widescreen</title>
		<link rel="alternate" type="text/html" href="https://sneslab.net/mw/index.php?title=Widescreen&amp;diff=1826"/>
		<updated>2021-04-11T09:52:24Z</updated>

		<summary type="html">&lt;p&gt;Vitor Vilela: /* Screen */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Screen ==&lt;br /&gt;
We have two standard widescreen settings available:&lt;br /&gt;
&lt;br /&gt;
1) 16:9 widescreen. There&#039;s an additional 48 columns to the left and right side of the screen. Resolution is 352x224, stretched to simulate the 8:7 pixel aspect ratio.&lt;br /&gt;
&lt;br /&gt;
2) 21:9 widescreen (actually 64:27). There&#039;s an additional 96 columns to the left and right side of the screen. Resolution is 448x224, stretched to simulate the 8:7 pixel aspect ratio.&lt;br /&gt;
&lt;br /&gt;
3) 2:1 widescreen. There&#039;s an additional 64 columns to the left and right side of the screen. Resolution is 384x224, stretched to simulate the 8:7 pixel aspect ratio.&lt;br /&gt;
&lt;br /&gt;
=== Reference table ===&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Target aspect ratio !! Numerical aspect ratio !! SNES internal resolution !! Numerical pixel aspect ratio !! Notes&lt;br /&gt;
|-&lt;br /&gt;
| 8:7 || 1.1428 || 256x224 || 1.0000 || Most of the emulators doesn&#039;t apply pixel aspect ratio (leaves as 1:1). Keep this value as reference.&lt;br /&gt;
|-&lt;br /&gt;
| 4:3 || 1.3333 || 256x224 || 1.1667 || Real hardware reference. Certain TVs pixel aspect ratio are 1.1428 instead of 1.1667, due of signal interpretation differences.&lt;br /&gt;
|-&lt;br /&gt;
| 16:9 || 1.7778 || 352x224 || 1.1313 || N/A&lt;br /&gt;
|-&lt;br /&gt;
| 21:9 || 2.3703 || 448x224 || 1.1851 || &amp;quot;21:9&amp;quot; is a marketing term. The real aspect ratio is 64:27 (used by the HDMI standard) and it&#039;s used as reference for this table.&lt;br /&gt;
|-&lt;br /&gt;
| 2:1 || 2.0000 || 384x224 || 1.1667 || N/A&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Comparison with 4:3 standard ===&lt;br /&gt;
&lt;br /&gt;
The 256x224 SNES screen is not 4:3, but rather 8:7. CRT screens usually stretches the image by multiplying the internal screen width by 8/7 or 7/6, depending on the TV model. 8/7 seems to be more common, while 7/6 gives an perfect 4:3 output, since 8:7 (screen aspect ratio) * 7/6 (pixel aspect ratio) = 4/3 (actual aspect ratio), while 8:7 (screen aspect ratio) * 8/7 (pixel aspect ratio) = 64:49 (more like 4.0000:3.0625). Use the above reference table for clarification.&lt;br /&gt;
&lt;br /&gt;
=== Important note ===&lt;br /&gt;
All values consider the NTSC signal as reference. PAL equivalence calculations are not yet available.&lt;br /&gt;
&lt;br /&gt;
== Objects ==&lt;br /&gt;
&lt;br /&gt;
Since OAM sprite width is 9-bit wide, allowing values between -256 to +255, the internal range is adjusted in a manner the negative range also wraps positively. You can assume the values to range between -128 and +384, which are mapped that way: if unsigned position is greater than or equal to 384, subtract 512 from it. Else, keep value as is.&lt;br /&gt;
&lt;br /&gt;
Sprites that already knows how to handle the left screen boundary (position -1 to -16) can be easily adapted to work with the widescreen range. Otherwise, it&#039;s recommended to port the relative screen position to use 16-bit values.&lt;br /&gt;
&lt;br /&gt;
In addition, it doesn&#039;t break other emulators, since the additional visible area is implicitly invisible on the SNES hardware specification.&lt;br /&gt;
&lt;br /&gt;
== Windowing ==&lt;br /&gt;
&lt;br /&gt;
Assume that the windowing internal size is 512 lines long instead of 256 lines long. If you take the windowing calculations based from this perspective, windowing HDMA will work regardless of the aspect ratio being currently used (16:9, 21:9, etc.)&lt;br /&gt;
&lt;br /&gt;
== Emulator ==&lt;br /&gt;
https://github.com/DerKoun/bsnes-hd&lt;br /&gt;
&lt;br /&gt;
https://www.reddit.com/r/emulation/comments/bmc9t9/bsneshd_beta_5_bsnes_1073_formally_hd_mode_7_mod/&lt;/div&gt;</summary>
		<author><name>Vitor Vilela</name></author>
	</entry>
	<entry>
		<id>https://sneslab.net/mw/index.php?title=Widescreen&amp;diff=1825</id>
		<title>Widescreen</title>
		<link rel="alternate" type="text/html" href="https://sneslab.net/mw/index.php?title=Widescreen&amp;diff=1825"/>
		<updated>2021-04-11T09:28:32Z</updated>

		<summary type="html">&lt;p&gt;Vitor Vilela: /* Screen */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Screen ==&lt;br /&gt;
We have two standard widescreen settings available:&lt;br /&gt;
&lt;br /&gt;
1) 16:9 widescreen. There&#039;s an additional 48 columns to the left and right side of the screen. Resolution is 352x224, stretched to simulate the 8:7 pixel aspect ratio.&lt;br /&gt;
&lt;br /&gt;
2) 21:9 widescreen (actually 64:27). There&#039;s an additional 96 columns to the left and right side of the screen. Resolution is 448x224, stretched to simulate the 8:7 pixel aspect ratio.&lt;br /&gt;
&lt;br /&gt;
3) 2:1 widescreen. There&#039;s an additional 64 columns to the left and right side of the screen. Resolution is 384x224, stretched to simulate the 8:7 pixel aspect ratio.&lt;br /&gt;
&lt;br /&gt;
=== Reference table ===&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Target aspect ratio !! Numerical aspect ratio !! SNES internal resolution !! Numerical pixel aspect ratio !! Notes&lt;br /&gt;
|-&lt;br /&gt;
| 8:7 || 1.1428 || 256x224 || 1.0000 || Most of the emulators doesn&#039;t apply pixel aspect ratio (leaves as 1:1). Keep this value as reference.&lt;br /&gt;
|-&lt;br /&gt;
| 4:3 || 1.3333 || 256x224 || 1.1667 || Real hardware reference. Certain TVs pixel aspect ratio are 1.1428 instead of 1.1667, due of signal interpretation differences.&lt;br /&gt;
|-&lt;br /&gt;
| 16:9 || 1.7778 || 352x224 || 1.1313 || N/A&lt;br /&gt;
|-&lt;br /&gt;
| 21:9 || 2.3703 || 448x224 || 1.1851 || N/A&lt;br /&gt;
|-&lt;br /&gt;
| 2:1 || 2.0000 || 384x224 || 1.1667 || N/A&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Comparison with 4:3 standard ===&lt;br /&gt;
&lt;br /&gt;
The 256x224 SNES screen is not 4:3, but rather 8:7. CRT screens usually stretches the image by multiplying the internal screen width by 8/7 or 7/6, depending on the TV model. 8/7 seems to be more common, while 7/6 gives an perfect 4:3 output, since 8:7 (screen aspect ratio) * 7/6 (pixel aspect ratio) = 4/3 (actual aspect ratio), while 8:7 (screen aspect ratio) * 8/7 (pixel aspect ratio) = 64:49 (more like 4.0000:3.0625). Use the above reference table for clarification.&lt;br /&gt;
&lt;br /&gt;
=== Important note ===&lt;br /&gt;
All values consider the NTSC signal as reference. PAL equivalence calculations are not yet available.&lt;br /&gt;
&lt;br /&gt;
== Objects ==&lt;br /&gt;
&lt;br /&gt;
Since OAM sprite width is 9-bit wide, allowing values between -256 to +255, the internal range is adjusted in a manner the negative range also wraps positively. You can assume the values to range between -128 and +384, which are mapped that way: if unsigned position is greater than or equal to 384, subtract 512 from it. Else, keep value as is.&lt;br /&gt;
&lt;br /&gt;
Sprites that already knows how to handle the left screen boundary (position -1 to -16) can be easily adapted to work with the widescreen range. Otherwise, it&#039;s recommended to port the relative screen position to use 16-bit values.&lt;br /&gt;
&lt;br /&gt;
In addition, it doesn&#039;t break other emulators, since the additional visible area is implicitly invisible on the SNES hardware specification.&lt;br /&gt;
&lt;br /&gt;
== Windowing ==&lt;br /&gt;
&lt;br /&gt;
Assume that the windowing internal size is 512 lines long instead of 256 lines long. If you take the windowing calculations based from this perspective, windowing HDMA will work regardless of the aspect ratio being currently used (16:9, 21:9, etc.)&lt;br /&gt;
&lt;br /&gt;
== Emulator ==&lt;br /&gt;
https://github.com/DerKoun/bsnes-hd&lt;br /&gt;
&lt;br /&gt;
https://www.reddit.com/r/emulation/comments/bmc9t9/bsneshd_beta_5_bsnes_1073_formally_hd_mode_7_mod/&lt;/div&gt;</summary>
		<author><name>Vitor Vilela</name></author>
	</entry>
	<entry>
		<id>https://sneslab.net/mw/index.php?title=Widescreen&amp;diff=1824</id>
		<title>Widescreen</title>
		<link rel="alternate" type="text/html" href="https://sneslab.net/mw/index.php?title=Widescreen&amp;diff=1824"/>
		<updated>2021-04-11T09:22:45Z</updated>

		<summary type="html">&lt;p&gt;Vitor Vilela: Add 2:1 and details table&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Screen ==&lt;br /&gt;
We have two standard widescreen settings available:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
1) 16:9 widescreen. There&#039;s an additional 48 columns to the left and right side of the screen. Resolution is 352x224, stretched to simulate the 8:7 pixel aspect ratio.&lt;br /&gt;
&lt;br /&gt;
2) 21:9 widescreen (actually 64:27). There&#039;s an additional 96 columns to the left and right side of the screen. Resolution is 448x224, stretched to simulate the 8:7 pixel aspect ratio.&lt;br /&gt;
&lt;br /&gt;
3) 2:1 widescreen. There&#039;s an additional 64 columns to the left and right side of the screen. Resolution is 384x224, stretched to simulate the 8:7 pixel aspect ratio.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Target aspect ratio !! Numerical aspect ratio !! SNES internal resolution !! Numerical pixel aspect ratio !! Notes&lt;br /&gt;
|-&lt;br /&gt;
| 4:3 || 1.3333 || 256x224 || 1.1667 || Real hardware reference. Sometimes, TV screens pixel aspect ratio are 1.1428 instead of 1.1667.&lt;br /&gt;
|-&lt;br /&gt;
| 16:9 || 1.7778 || 352x224 || 1.1313 || N/A&lt;br /&gt;
|-&lt;br /&gt;
| 21:9 || 2.3703 || 448x224 || 1.1851 || N/A&lt;br /&gt;
|-&lt;br /&gt;
| 2:1 || 2.0000 || 384x224 || 1.1667 || N/A&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Comparison with 4:3 standard ===&lt;br /&gt;
&lt;br /&gt;
The 256x224 SNES screen is not 4:3, but rather 8:7. CRT screens usually stretches the image by multiplying the internal screen width by 8/7 or 7/6, depending on the TV model. 8/7 seems to be more common, while 7/6 gives an perfect 4:3 output, since 8:7 (screen aspect ratio) * 7/6 (pixel aspect ratio) = 4/3 (actual aspect ratio), while 8:7 (screen aspect ratio) * 8/7 (pixel aspect ratio) = 64:49 (more like 4.0000:3.0625).&lt;br /&gt;
&lt;br /&gt;
== Objects ==&lt;br /&gt;
&lt;br /&gt;
Since OAM sprite width is 9-bit wide, allowing values between -256 to +255, the internal range is adjusted in a manner the negative range also wraps positively. You can assume the values to range between -128 and +384, which are mapped that way: if unsigned position is greater than or equal to 384, subtract 512 from it. Else, keep value as is.&lt;br /&gt;
&lt;br /&gt;
Sprites that already knows how to handle the left screen boundary (position -1 to -16) can be easily adapted to work with the widescreen range. Otherwise, it&#039;s recommended to port the relative screen position to use 16-bit values.&lt;br /&gt;
&lt;br /&gt;
In addition, it doesn&#039;t break other emulators, since the additional visible area is implicitly invisible on the SNES hardware specification.&lt;br /&gt;
&lt;br /&gt;
== Windowing ==&lt;br /&gt;
&lt;br /&gt;
Assume that the windowing internal size is 512 lines long instead of 256 lines long. If you take the windowing calculations based from this perspective, windowing HDMA will work regardless of the aspect ratio being currently used (16:9, 21:9, etc.)&lt;br /&gt;
&lt;br /&gt;
== Emulator ==&lt;br /&gt;
https://github.com/DerKoun/bsnes-hd&lt;br /&gt;
&lt;br /&gt;
https://www.reddit.com/r/emulation/comments/bmc9t9/bsneshd_beta_5_bsnes_1073_formally_hd_mode_7_mod/&lt;/div&gt;</summary>
		<author><name>Vitor Vilela</name></author>
	</entry>
	<entry>
		<id>https://sneslab.net/mw/index.php?title=Widescreen&amp;diff=1823</id>
		<title>Widescreen</title>
		<link rel="alternate" type="text/html" href="https://sneslab.net/mw/index.php?title=Widescreen&amp;diff=1823"/>
		<updated>2021-04-10T05:25:53Z</updated>

		<summary type="html">&lt;p&gt;Vitor Vilela: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Screen ==&lt;br /&gt;
We have two standard widescreen settings available:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
1) 16:9 widescreen. There&#039;s an additional 48 columns to the left and right side of the screen. Resolution is 352x224, stretched to simulate the 8:7 pixel aspect ratio.&lt;br /&gt;
&lt;br /&gt;
2) 21:9 widescreen (actually 64:27). There&#039;s an additional 96 columns to the left and right side of the screen. Resolution is 448x224, stretched to simulate the 8:7 pixel aspect ratio.&lt;br /&gt;
&lt;br /&gt;
=== Comparison with 4:3 standard ===&lt;br /&gt;
&lt;br /&gt;
The 256x224 SNES screen is not 4:3, but rather 8:7. CRT screens usually stretches the image by multiplying the internal screen width by 8/7 or 7/6, depending on the TV model. 8/7 seems to be more common, while 7/6 gives an perfect 4:3 output, since 8:7 (screen aspect ratio) * 7/6 (pixel aspect ratio) = 4/3 (actual aspect ratio), while 8:7 (screen aspect ratio) * 8/7 (pixel aspect ratio) = 64:49 (more like 4.0000:3.0625).&lt;br /&gt;
&lt;br /&gt;
== Objects ==&lt;br /&gt;
&lt;br /&gt;
Since OAM sprite width is 9-bit wide, allowing values between -256 to +255, the internal range is adjusted in a manner the negative range also wraps positively. You can assume the values to range between -128 and +384, which are mapped that way: if unsigned position is greater than or equal to 384, subtract 512 from it. Else, keep value as is.&lt;br /&gt;
&lt;br /&gt;
Sprites that already knows how to handle the left screen boundary (position -1 to -16) can be easily adapted to work with the widescreen range. Otherwise, it&#039;s recommended to port the relative screen position to use 16-bit values.&lt;br /&gt;
&lt;br /&gt;
In addition, it doesn&#039;t break other emulators, since the additional visible area is implicitly invisible on the SNES hardware specification.&lt;br /&gt;
&lt;br /&gt;
== Windowing ==&lt;br /&gt;
&lt;br /&gt;
Assume that the windowing internal size is 512 lines long instead of 256 lines long. If you take the windowing calculations based from this perspective, windowing HDMA will work regardless of the aspect ratio being currently used (16:9, 21:9, etc.)&lt;br /&gt;
&lt;br /&gt;
== Emulator ==&lt;br /&gt;
https://github.com/DerKoun/bsnes-hd&lt;br /&gt;
&lt;br /&gt;
https://www.reddit.com/r/emulation/comments/bmc9t9/bsneshd_beta_5_bsnes_1073_formally_hd_mode_7_mod/&lt;/div&gt;</summary>
		<author><name>Vitor Vilela</name></author>
	</entry>
	<entry>
		<id>https://sneslab.net/mw/index.php?title=Widescreen&amp;diff=1822</id>
		<title>Widescreen</title>
		<link rel="alternate" type="text/html" href="https://sneslab.net/mw/index.php?title=Widescreen&amp;diff=1822"/>
		<updated>2021-04-10T05:21:47Z</updated>

		<summary type="html">&lt;p&gt;Vitor Vilela: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Screen ==&lt;br /&gt;
We have two screen settings available:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
1) 16:9 widescreen. There&#039;s an additional 48 columns to the left and right side of the screen. Resolution is 352x224, stretched to simulate the 8:7 pixel aspect ratio.&lt;br /&gt;
&lt;br /&gt;
2) 21:9 widescreen (actually 64:27). There&#039;s an additional 96 columns to the left and right side of the screen. Resolution is 448x224, stretched to simulate the 8:7 pixel aspect ratio.&lt;br /&gt;
&lt;br /&gt;
== Objects ==&lt;br /&gt;
&lt;br /&gt;
Since OAM sprite width is 9-bit wide, allowing values between -256 to +255, the internal range is adjusted in a manner the negative range also wraps positively. You can assume the values to range between -128 and +384, which are mapped that way: if unsigned position is greater than or equal to 384, subtract 512 from it. Else, keep value as is.&lt;br /&gt;
&lt;br /&gt;
Sprites that already knows how to handle the left screen boundary (position -1 to -16) can be easily adapted to work with the widescreen range. Otherwise, it&#039;s recommended to port the relative screen position to use 16-bit values.&lt;br /&gt;
&lt;br /&gt;
In addition, it doesn&#039;t break other emulators, since the additional visible area is implicitly invisible on the SNES hardware specification.&lt;br /&gt;
&lt;br /&gt;
== Windowing ==&lt;br /&gt;
&lt;br /&gt;
Assume that the windowing internal size is 512 lines long instead of 256 lines long. If you take the windowing calculations based from this perspective, windowing HDMA will work regardless of the aspect ratio being currently used (16:9, 21:9, etc.)&lt;br /&gt;
&lt;br /&gt;
== Emulator ==&lt;br /&gt;
https://github.com/DerKoun/bsnes-hd&lt;br /&gt;
&lt;br /&gt;
https://www.reddit.com/r/emulation/comments/bmc9t9/bsneshd_beta_5_bsnes_1073_formally_hd_mode_7_mod/&lt;/div&gt;</summary>
		<author><name>Vitor Vilela</name></author>
	</entry>
	<entry>
		<id>https://sneslab.net/mw/index.php?title=Widescreen&amp;diff=1821</id>
		<title>Widescreen</title>
		<link rel="alternate" type="text/html" href="https://sneslab.net/mw/index.php?title=Widescreen&amp;diff=1821"/>
		<updated>2021-04-10T05:20:37Z</updated>

		<summary type="html">&lt;p&gt;Vitor Vilela: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Screen ==&lt;br /&gt;
We have two screen settings available:&lt;br /&gt;
&lt;br /&gt;
1) 16:9 widescreen. There&#039;s an additional 48 columns to the left and right side of the screen. Resolution is 352x224, stretched to simulate the 8:7 pixel aspect ratio.&lt;br /&gt;
2) 21:9 widescreen (actually 64:27). There&#039;s an additional 96 columns to the left and right side of the screen. Resolution is 448x224, stretched to simulate the 8:7 pixel aspect ratio.&lt;br /&gt;
&lt;br /&gt;
== Objects ==&lt;br /&gt;
&lt;br /&gt;
Since OAM sprite width is 9-bit wide, allowing values between -256 to +255, the internal range is adjusted in a manner the negative range also wraps positively. You can assume the values to range between -128 and +384, which are mapped that way: if unsigned position is greater than or equal to 384, subtract 512 from it. Else, keep value as is.&lt;br /&gt;
&lt;br /&gt;
Sprites that already knows how to handle the left screen boundary (position -1 to -16) can be easily adapted to work with the widescreen range. Otherwise, it&#039;s recommended to port the relative screen position to use 16-bit values.&lt;br /&gt;
&lt;br /&gt;
In addition, it doesn&#039;t break other emulators, since the additional visible area is implicitly invisible on the SNES hardware specification.&lt;br /&gt;
&lt;br /&gt;
== Windowing ==&lt;br /&gt;
&lt;br /&gt;
Assume that the windowing internal size is 512 lines long instead of 256 lines long. If you take the windowing calculations based from this perspective, windowing HDMA will work regardless of the aspect ratio being currently used (16:9, 21:9, etc.)&lt;br /&gt;
&lt;br /&gt;
== Emulator ==&lt;br /&gt;
https://github.com/DerKoun/bsnes-hd&lt;br /&gt;
https://www.reddit.com/r/emulation/comments/bmc9t9/bsneshd_beta_5_bsnes_1073_formally_hd_mode_7_mod/&lt;/div&gt;</summary>
		<author><name>Vitor Vilela</name></author>
	</entry>
	<entry>
		<id>https://sneslab.net/mw/index.php?title=WidescreenRomHacking&amp;diff=1820</id>
		<title>WidescreenRomHacking</title>
		<link rel="alternate" type="text/html" href="https://sneslab.net/mw/index.php?title=WidescreenRomHacking&amp;diff=1820"/>
		<updated>2021-04-10T04:57:02Z</updated>

		<summary type="html">&lt;p&gt;Vitor Vilela: Vitor Vilela moved page WidescreenRomHacking to Widescreen&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;#REDIRECT [[Widescreen]]&lt;/div&gt;</summary>
		<author><name>Vitor Vilela</name></author>
	</entry>
	<entry>
		<id>https://sneslab.net/mw/index.php?title=Widescreen&amp;diff=1819</id>
		<title>Widescreen</title>
		<link rel="alternate" type="text/html" href="https://sneslab.net/mw/index.php?title=Widescreen&amp;diff=1819"/>
		<updated>2021-04-10T04:57:02Z</updated>

		<summary type="html">&lt;p&gt;Vitor Vilela: Vitor Vilela moved page WidescreenRomHacking to Widescreen&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;(&#039;&#039;first draft, please point out any mistakes and ask any questions&#039;&#039;)&lt;br /&gt;
== widescreen-specific code ==&lt;br /&gt;
=== objects ===&lt;br /&gt;
Objects are up to 64 pixels wide.&amp;lt;br&amp;gt;&lt;br /&gt;
For their x coordinates we have a 9 bit unsigned integer,&amp;lt;br&amp;gt;&lt;br /&gt;
i.e. values from 0 to 511.&amp;lt;br&amp;gt;&lt;br /&gt;
0 to 255 are the visible columns of the screen.&amp;lt;br&amp;gt;&lt;br /&gt;
To be able to have objects start off the left side and extend into the screen, the values wrap,&amp;lt;br&amp;gt;&lt;br /&gt;
i.e. 449 to 511 is treated as -63 to -1.&amp;lt;br&amp;gt;&lt;br /&gt;
256 to 448 place objects outside of the visible area.&lt;br /&gt;
&lt;br /&gt;
For widescreen 16:9 we add 64 pixels to each side.&amp;lt;br&amp;gt;&lt;br /&gt;
So the visible columns of the (wide) screen are now -64 to 319,&amp;lt;br&amp;gt;&lt;br /&gt;
or technically 448 to 511 and 0 to 319.&amp;lt;br&amp;gt;&lt;br /&gt;
So with objects partially off screen to the left the minimal coordinate with visible content is -127 aka 385.&lt;br /&gt;
&lt;br /&gt;
Using that coordinate space you can place objects in the widescreen area quite similar to placing them in the normal screen area.&amp;lt;br&amp;gt;&lt;br /&gt;
It should also not break support on other emulators or hardware AFAIK.&lt;br /&gt;
== emulator ==&lt;br /&gt;
https://www.reddit.com/r/emulation/comments/bmc9t9/bsneshd_beta_5_bsnes_1073_formally_hd_mode_7_mod/ &amp;lt;br&amp;gt;&lt;br /&gt;
(repo comming soon)&lt;/div&gt;</summary>
		<author><name>Vitor Vilela</name></author>
	</entry>
	<entry>
		<id>https://sneslab.net/mw/index.php?title=SA-1&amp;diff=1796</id>
		<title>SA-1</title>
		<link rel="alternate" type="text/html" href="https://sneslab.net/mw/index.php?title=SA-1&amp;diff=1796"/>
		<updated>2021-04-06T01:44:14Z</updated>

		<summary type="html">&lt;p&gt;Vitor Vilela: Add register $223F&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&#039;&#039;&#039;Nintendo SA-1&#039;&#039;&#039; is an [[enhancement chip]] made by [http://en.wikipedia.org/wiki/Nintendo Nintendo], used in 33 SNES games. The RF5A123 chip is based on the [[65c816]] processor, the same one used by the main SNES CPU, the [[RF5A22]]. With identical architecture to the SNES one, the chip is ideal for games and ROM hacks that can reuse code from the main CPU, thus not having to learn an additional assembling language or architecture.&lt;br /&gt;
&lt;br /&gt;
When you are on the SA-1 context, the SA-1 CPU is often referred as &amp;quot;C-CPU&amp;quot; (&amp;quot;C&amp;quot; stands for co-processor) while the SNES CPU is often referred as &amp;quot;S-CPU&amp;quot; (&amp;quot;S&amp;quot; stands for SNES). There is no master or slave, because both processors can interrupt each other though IRQs, keeping in mind that initially SA-1 boots up in the sleeping state and must be initialized by the SNES CPU.&lt;br /&gt;
&lt;br /&gt;
{{TOClimit|4}}&lt;br /&gt;
&lt;br /&gt;
== Features ==&lt;br /&gt;
&lt;br /&gt;
The embedded co-processor has a &#039;&#039;&#039;10.74 MHz&#039;&#039;&#039; base clock speed, which is four times faster compared to the 2.68 MHz base clock speed from the S-CPU. In addition to that, it includes additional hardware circuits for data I/O, bitmap manipulation modes, arithmetic registers and high-speed internal memory.&lt;br /&gt;
&lt;br /&gt;
* 16-bit 65c816 processor clocked at 10.74 MHz.&lt;br /&gt;
* 2 kB internal work memory (I-RAM), clocked at 10.74 MHz.&lt;br /&gt;
* Multi-processor processing, with parallel operating mode and automatic memory sharing control.&lt;br /&gt;
* Large capacity memory, with a total capability of 8 MB ROM and 256 kB BW-RAM, both clocked at 5.37 MHz, with ROM having an effective 10.74 MHz speed because of the 16-bit data bus.&lt;br /&gt;
* High speed arithmetic multiplication, division and cumulative sum (multiply with add) hardware.&lt;br /&gt;
* Bitmap and Character Conversion functions for fast graphics manipulation.&lt;br /&gt;
* Custom DMA circuit for fast transfers between ROM, I-RAM and BW-RAM.&lt;br /&gt;
* Variable-Length Bit data processing for enhanced algorithms such as graphics and data compression.&lt;br /&gt;
* Super MMC memory mapping capabilities for BW-RAM and bank switching for multiple ROM image access and mirroring.&lt;br /&gt;
&lt;br /&gt;
== ROM Hacking ==&lt;br /&gt;
&lt;br /&gt;
[[SA-1 Root]] and [[SA-1 Pack]] are known patches used for enabling SA-1 on SNES games that didn&#039;t include the chip previously and had problems with slowdown, such as [[Super Mario World]], [[Gradius III]] and [[Contra III]].&lt;br /&gt;
&lt;br /&gt;
= Technical Information =&lt;br /&gt;
There is not much technical information available on how the SA-1 chip works. Most of the findings are recent and are based on both official documents from Nintendo and experiments on real SA-1 carts. This section is getting continuously updated with new information and findings though the time. The information available here is expected to be accurate. Information about undefined behavior or design details is considered scarce right now.&lt;br /&gt;
&lt;br /&gt;
== Hardware Registers ==&lt;br /&gt;
The SA-1 internal registers are assigned on range $2200-$23FF, on banks $00-$3F and $80-$BF. $2200 though $22FF are write-only registers while $2300 though $23FF are read-only registers.&lt;br /&gt;
&lt;br /&gt;
* Attempting to read a write-only register yields [[open bus]].&lt;br /&gt;
* Attempting to write a SA-1 write register on SNES side or vice-versa yields nothing, with the exception of hybrid write registers.&lt;br /&gt;
* Attempting to read a SA-1 read register on SNES side or vice-versa yields open bus.&lt;br /&gt;
&lt;br /&gt;
=== Register Summary ===&lt;br /&gt;
&lt;br /&gt;
==== Write Registers ====&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Address !! Length !! Code !! Access !! Description&lt;br /&gt;
|-&lt;br /&gt;
| $2200 || 1 byte || CCNT || SNES || SA-1 CPU CONTROL&lt;br /&gt;
|-&lt;br /&gt;
| $2201 || 1 byte || SIE || SNES || SUPER NES CPU INT ENABLE&lt;br /&gt;
|-&lt;br /&gt;
| $2202 || 1 byte || SIC || SNES || SUPER NES CPU INT CLEAR&lt;br /&gt;
|-&lt;br /&gt;
| $2203 || 2 bytes || CRV || SNES || SA-1 CPU RESET VECTOR&lt;br /&gt;
|-&lt;br /&gt;
| $2205 || 2 bytes || CNV || SNES || SA-1 CPU NMI VECTOR&lt;br /&gt;
|-&lt;br /&gt;
| $2207 || 2 bytes || CIV || SNES || SA-1 CPU IRQ VECTOR&lt;br /&gt;
|-&lt;br /&gt;
| $2209 || 1 byte || SCNT || SA-1 || SUPER NES CPU CONTROL&lt;br /&gt;
|-&lt;br /&gt;
| $220A || 1 byte || CIE || SA-1 || SA-1 CPU INT ENABLE&lt;br /&gt;
|-&lt;br /&gt;
| $220B || 1 byte || CIC || SA-1 || SA-1 CPU INT CLEAR&lt;br /&gt;
|-&lt;br /&gt;
| $220C || 2 bytes || SNV || SA-1 || SUPER NES CPU NMI VECTOR&lt;br /&gt;
|-&lt;br /&gt;
| $220E || 2 bytes || SIV || SA-1 || SUPER NES CPU IRQ VECTOR&lt;br /&gt;
|-&lt;br /&gt;
| $2210 || 1 byte || TMC || SA-1 || H/V TIMER CONTROL&lt;br /&gt;
|-&lt;br /&gt;
| $2211 || 1 byte || CTR || SA-1 || SA-1 CPU TIMER RESTART&lt;br /&gt;
|-&lt;br /&gt;
| $2212 || 2 bytes || HCNT || SA-1 || SET H-COUNT&lt;br /&gt;
|-&lt;br /&gt;
| $2214 || 2 bytes || VCNT || SA-1 || SET V-COUNT&lt;br /&gt;
|-&lt;br /&gt;
| $2220 || 1 byte || CXB || SNES || SET SUPER MMC BANK C&lt;br /&gt;
|-&lt;br /&gt;
| $2221 || 1 byte || DXB || SNES || SET SUPER MMC BANK D&lt;br /&gt;
|-&lt;br /&gt;
| $2222 || 1 byte || EXB || SNES || SET SUPER MMC BANK E&lt;br /&gt;
|-&lt;br /&gt;
| $2223 || 1 byte || FXB || SNES || SET SUPER MMC BANK F&lt;br /&gt;
|-&lt;br /&gt;
| $2224 || 1 byte || BMAPS || SNES || SUPER NES CPU BW-RAM ADDRESS MAPPING&lt;br /&gt;
|-&lt;br /&gt;
| $2225 || 1 byte || BMAP || SA-1 || SA-1 CPU BW-RAM ADDRESS MAPPING&lt;br /&gt;
|-&lt;br /&gt;
| $2226 || 1 byte || SBWE || SNES || SUPER NES CPU BW-RAM WRITE ENABLE&lt;br /&gt;
|-&lt;br /&gt;
| $2227 || 1 byte || CBWE || SA-1 || SA-1 CPU BW-RAM WRITE ENABLE&lt;br /&gt;
|-&lt;br /&gt;
| $2228 || 1 byte || BPWA || SNES || BW-RAM WRITE-PROTECTED AREA&lt;br /&gt;
|-&lt;br /&gt;
| $2229 || 1 byte || SIWP || SNES || SA-1 I-RAM WRITE PROTECTION&lt;br /&gt;
|-&lt;br /&gt;
| $222A || 1 byte || CIWP || SA-1 || SA-1 I-RAM WRITE PROTECTION&lt;br /&gt;
|-&lt;br /&gt;
| $2230 || 1 byte || DCNT || SA-1 || DMA CONTROL&lt;br /&gt;
|-&lt;br /&gt;
| $2231 || 1 byte || CDMA || Both || CHARACTER CONVERSION OMA PARAMETERS&lt;br /&gt;
|-&lt;br /&gt;
| $2232 || 3 bytes || SDA || Both || DMA SOURCE DEVICE START ADDRESS&lt;br /&gt;
|-&lt;br /&gt;
| $2235 || 3 bytes || DDA || Both || DMA DESTINATION START ADDRESS&lt;br /&gt;
|-&lt;br /&gt;
| $2238 || 2 bytes || DTC || SA-1 || DMA TERMINAL COUNTER&lt;br /&gt;
|-&lt;br /&gt;
| $223F || 1 byte || BBF || SA-1 || BW-RAM BIT MAP FORMAT&lt;br /&gt;
|-&lt;br /&gt;
| $2240 || 16 bytes || BRF || SA-1 || BIT MAP REGISTER FILE&lt;br /&gt;
|-&lt;br /&gt;
| $2250 || 1 byte || MCNT || SA-1 || ARITHMETIC CONTROL&lt;br /&gt;
|-&lt;br /&gt;
| $2251 || 2 bytes || MA || SA-1 || ARITHMETIC PARAMETERS: MULTIPLICAND/DIVIDEND&lt;br /&gt;
|-&lt;br /&gt;
| $2253 || 2 bytes || MB || SA-1 || ARITHMETIC PARAMETERS: MULTIPLIER/DIVISOR&lt;br /&gt;
|-&lt;br /&gt;
| $2258 || 1 byte || VBD || SA-1 || VARIABLE-LENGTH BIT PROCESSING&lt;br /&gt;
|-&lt;br /&gt;
| $2259 || 3 bytes || VDA || SA-1 || VARIABLE-LENGTH BIT GAME PAK ROM START ADDRESS&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Read Registers ====&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Address !! Length !! Code !! Access !! Description&lt;br /&gt;
|-&lt;br /&gt;
| $2300 || 1 bytes || SFR || SNES || SUPER NES CPU FLAG READ&lt;br /&gt;
|-&lt;br /&gt;
| $2301 || 1 bytes || CFR || SA-1 || SA-1 CPU FLAG READ&lt;br /&gt;
|-&lt;br /&gt;
| $2302 || 2 bytes || HCR || SA-1 || H-COUNT READ&lt;br /&gt;
|-&lt;br /&gt;
| $2304 || 2 bytes || VCR || SA-1 || V-COUNT READ&lt;br /&gt;
|-&lt;br /&gt;
| $2306 || 5 bytes || MR || SA-1 || ARITHMETIC RESULT [PRODUCT/QUOTIENT/ACCUMULATIVE SUM]&lt;br /&gt;
|-&lt;br /&gt;
| $230B || 1 bytes || OF || SA-1 || ARITHMETIC OVERFLOW FLAG&lt;br /&gt;
|-&lt;br /&gt;
| $230C || 2 bytes || VDP || SA-1 || VARIABLE-LENGTH DATA READ PORT&lt;br /&gt;
|-&lt;br /&gt;
| $230E || 1 byte || VC || SNES || VERSION CODE REGISTER (OPEN BUS)&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Register Details ===&lt;br /&gt;
&lt;br /&gt;
==== $2200 - SA-1 CPU CONTROL ====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== $2201 - SUPER NES CPU INT ENABLE ====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== $2202 - SUPER NES CPU INT CLEAR ====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== $2203 - SA-1 CPU RESET VECTOR ====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== $2205 - SA-1 CPU NMI VECTOR ====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== $2207 - SA-1 CPU IRQ VECTOR ====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== $2209 - SUPER NES CPU CONTROL ====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== $220A - SA-1 CPU INT ENABLE ====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== $220B - SA-1 CPU INT CLEAR ====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== $220C - SUPER NES CPU NMI VECTOR ====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== $220E - SUPER NES CPU IRQ VECTOR ====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== $2210 - H/V TIMER CONTROL ====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== $2211 - SA-1 CPU TIMER RESTART ====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== $2212 - SET H-COUNT ====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== $2214 - SET V-COUNT ====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== $2220-$2223 - SET SUPER MMC BANK C/D/E/F ====&lt;br /&gt;
{{32bit-reg|2220|2221|2222|2223&lt;br /&gt;
|CBM|0|0|0|0|CB2|CB1|CB0&lt;br /&gt;
|DBM|0|0|0|0|CB2|CB1|CB0&lt;br /&gt;
|EBM|0|0|0|0|CB2|CB1|CB0&lt;br /&gt;
|FBM|0|0|0|0|CB2|CB1|CB0}}&lt;br /&gt;
&lt;br /&gt;
CB2~CB0: Which megabyte of the ROM to map to $C0-$CF / $D0-$DF / $E0-$EF / $F0-$FF.&lt;br /&gt;
&lt;br /&gt;
CBM/DBM/EBM/FBM: If set, apply image projection to LoROM banks as well.&lt;br /&gt;
{|style=&amp;quot;width:auto&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Flag !! Bank Range&lt;br /&gt;
|-&lt;br /&gt;
| CBM || Apply to banks $00-$1F&lt;br /&gt;
|-&lt;br /&gt;
| DBM || Apply to banks $20-$3F&lt;br /&gt;
|-&lt;br /&gt;
| EBM || Apply to banks $80-$9F&lt;br /&gt;
|-&lt;br /&gt;
| FBM || Apply to banks $A0-$BF&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Registers are responsible for setting up the ROM bank mapping.&lt;br /&gt;
By default, the values { $00, $01, $02, $03 } are loaded on power up.&lt;br /&gt;
&lt;br /&gt;
Bits CBM/DBM/EBM/FBM determine if the mapping should apply to the LoROM banks as well, otherwise they will have the constant value of { $00, $01, $02, $03 } regardless of the ROM size. Given that, it&#039;s possible the entire 8 MB layout at once by storing values { $04, $05, $06, $07 } to the registers. Snes9x 1.53 and older always treated these flags as set, making the mapping always apply to the LoROM banks.&lt;br /&gt;
&lt;br /&gt;
{|style=&amp;quot;width:auto&amp;quot;&lt;br /&gt;
|+Common values&lt;br /&gt;
|-&lt;br /&gt;
! Register !! $2220 !! $2221 !! $2222 !! $2223 !! Comment&lt;br /&gt;
|-&lt;br /&gt;
| Value || $00 || $01 || $02 || $03 || Default values&lt;br /&gt;
|-&lt;br /&gt;
| Value || $04 || $05 || $06 || $07 || Maps the first 4 MB to banks $00-$3F and $80-$BF, with LoROM-like layout. The last 4 MB is mapped to $C0-$FF, with HiROM-like layout.&lt;br /&gt;
|-&lt;br /&gt;
| Value || $80 || $81 || $80 || $81 || Simulates the standard LoROM map with FastROM compatibility by mapping the first 2 MB to $00-$3F and $80-$BF.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The Super MMC register affects all memory maps, including SNES, SA-1, SA-1 DMA and SA-1 Variable Length Bit maps.&lt;br /&gt;
bsnes 0.7x does not apply the custom memory mapping to Variable Length Bit circuit.&lt;br /&gt;
&lt;br /&gt;
Hardware verification has shown that the unused bits has no effects to the chip pinout and therefore the maximum ROM size for the SA-1 without using a custom ROM controller outside the chip is 8 MB (megabytes).&lt;br /&gt;
&lt;br /&gt;
==== $2224 - SUPER NES CPU BW-RAM ADDRESS MAPPING ====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== $2225 - SA-1 CPU BW-RAM ADDRESS MAPPING ====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== $2226 - SUPER NES CPU BW-RAM WRITE ENABLE ====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== $2227 - SA-1 CPU BW-RAM WRITE ENABLE ====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== $2228 - BW-RAM WRITE-PROTECTED AREA ====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== $2229 - SA-1 I-RAM WRITE PROTECTION ====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== $222A - SA-1 I-RAM WRITE PROTECTION ====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== $2230 - DMA CONTROL ====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== $2231 - CHARACTER CONVERSION OMA PARAMETERS ====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== $2232 - DMA SOURCE DEVICE START ADDRESS ====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== $2235 - DMA DESTINATION START ADDRESS ====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== $2238 - DMA TERMINAL COUNTER ====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== $223F - BW-RAM BIT MAP FORMAT ====&lt;br /&gt;
{{8bit-reg|223F|SEL42|-|-|-|-|-|-|-}}&lt;br /&gt;
{| style=&amp;quot;width:auto&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Bits !! Meaning&lt;br /&gt;
|-&lt;br /&gt;
| SEL42 || 0 to make banks $60-$6F split in 4 bits chunks (4BPP) or 1 to split in 2 bits chunks (2BPP)&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== $2240 - BIT MAP REGISTER FILE ====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== $2250 - ARITHMETIC CONTROL ====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== $2251 - ARITHMETIC PARAMETERS: MULTIPLICAND/DIVIDEND ====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== $2253 - ARITHMETIC PARAMETERS: MULTIPLIER/DIVISOR ====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== $2258 - VARIABLE-LENGTH BIT PROCESSING ====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== $2259 - VARIABLE-LENGTH BIT GAME PAK ROM START ADDRESS ====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== $2300 - SUPER NES CPU FLAG READ ====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== $2301 - SA-1 CPU FLAG READ ====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== $2302 - H-COUNT READ ====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== $2304 - V-COUNT READ ====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== $2306 - ARITHMETIC RESULT [PRODUCT/QUOTIENT/ACCUMULATIVE SUM] ====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== $230B - ARITHMETIC OVERFLOW FLAG ====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== $230C - VARIABLE-LENGTH DATA READ PORT ====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== $230E - VERSION CODE REGISTER (OPEN BUS) ====&lt;br /&gt;
{{8bit-reg|230E|VC7|VC6|VC5|VC4|VC3|VC2|VC1|VC0}}&lt;br /&gt;
{| style=&amp;quot;width:auto&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Bits !! Meaning&lt;br /&gt;
|-&lt;br /&gt;
| VC0 ~ VC7 || SA-1 Device Version&lt;br /&gt;
|}&lt;br /&gt;
According the SNES Development Book II, this register was supposed to hold the SA-1 chip version code, however tests made on some real carts has shown that this register in particular is actually [[open bus]].&lt;br /&gt;
-----&lt;br /&gt;
&lt;br /&gt;
== Memory and Bus ==&lt;br /&gt;
&lt;br /&gt;
=== Memory Map ===&lt;br /&gt;
&lt;br /&gt;
==== SNES Side ====&lt;br /&gt;
&lt;br /&gt;
==== SA-1 Side ====&lt;br /&gt;
&lt;br /&gt;
==== Open Bus Behavior ====&lt;br /&gt;
&lt;br /&gt;
=== ROM ===&lt;br /&gt;
&lt;br /&gt;
=== I-RAM ===&lt;br /&gt;
&lt;br /&gt;
==== Write Protection ====&lt;br /&gt;
&lt;br /&gt;
=== BW-RAM ===&lt;br /&gt;
&lt;br /&gt;
==== Write Protection ====&lt;br /&gt;
&lt;br /&gt;
=== Virtual Bitmap Memory ===&lt;br /&gt;
&lt;br /&gt;
=== Super MMC ===&lt;br /&gt;
&lt;br /&gt;
=== Bus Conflicts ===&lt;br /&gt;
&lt;br /&gt;
== Direct Memory Access ==&lt;br /&gt;
&lt;br /&gt;
=== Character Conversion DMA ===&lt;br /&gt;
&lt;br /&gt;
=== Parallel DMA ===&lt;br /&gt;
&lt;br /&gt;
=== Interactions with SNES DMA ===&lt;br /&gt;
&lt;br /&gt;
=== Undefined Behavior ===&lt;br /&gt;
&lt;br /&gt;
== Variable Length Bit ==&lt;br /&gt;
&lt;br /&gt;
=== Fixed Mode ===&lt;br /&gt;
&lt;br /&gt;
=== Automatic Mode ===&lt;br /&gt;
&lt;br /&gt;
=== Mixed Mode ===&lt;br /&gt;
&lt;br /&gt;
== Arithmetic Operations ==&lt;br /&gt;
&lt;br /&gt;
=== Multiplication ===&lt;br /&gt;
&lt;br /&gt;
=== Division ===&lt;br /&gt;
&lt;br /&gt;
=== Cumulative Sum ===&lt;br /&gt;
&lt;br /&gt;
== Parallelism and I/O ==&lt;br /&gt;
&lt;br /&gt;
=== IRQ ===&lt;br /&gt;
&lt;br /&gt;
=== NMI ===&lt;br /&gt;
&lt;br /&gt;
=== FastROM Interactions ===&lt;br /&gt;
&lt;br /&gt;
[[Category:SNES Hardware]] [[Category:ASM]]&lt;/div&gt;</summary>
		<author><name>Vitor Vilela</name></author>
	</entry>
	<entry>
		<id>https://sneslab.net/mw/index.php?title=Super_R-Type_RAM_Map&amp;diff=1640</id>
		<title>Super R-Type RAM Map</title>
		<link rel="alternate" type="text/html" href="https://sneslab.net/mw/index.php?title=Super_R-Type_RAM_Map&amp;diff=1640"/>
		<updated>2020-12-31T09:25:30Z</updated>

		<summary type="html">&lt;p&gt;Vitor Vilela: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Address !! Size !! Type !! Description&lt;br /&gt;
|-&lt;br /&gt;
| $7E:004C || 2 bytes || Flow || If #$0080 is set, run the game, otherwise wait for NMI.&lt;br /&gt;
|-&lt;br /&gt;
| $7E:004E || 2 bytes || Flow || 16-bit frame counter, incremented every time the NMI runs.&lt;br /&gt;
|-&lt;br /&gt;
| $7E:0050 || 2 bytes || Flow || 16-bit frame counter, incremented every time the game logic runs.&lt;br /&gt;
|-&lt;br /&gt;
| $7E:0080 || 1 byte || PPU || $2100 register mirror&lt;br /&gt;
|-&lt;br /&gt;
| $7E:0082 || 1 byte || CPU || $4200 register mirror, only written once because $4200 is always #$81&lt;br /&gt;
|-&lt;br /&gt;
| $7E:00F4 || 1 byte || PPU || Copy of PPU status flag, $213E&lt;br /&gt;
|-&lt;br /&gt;
| $7E:0700 || Unknown ||  || &lt;br /&gt;
|-&lt;br /&gt;
| $7E:1580 || Unknown ||  || &lt;br /&gt;
|-&lt;br /&gt;
| $7E:1832 || Unknown ||  || Seems to be a group related to BG 0&lt;br /&gt;
|-&lt;br /&gt;
| $7E:1836 || 2 bytes || PPU || BG 0 X position&lt;br /&gt;
|-&lt;br /&gt;
| $7E:1838 || 2 bytes || PPU || BG 0 Y position&lt;br /&gt;
|-&lt;br /&gt;
| $7E:1862 || Unknown ||  || Seems to be a group related to BG 1&lt;br /&gt;
|-&lt;br /&gt;
| $7E:1866 || 2 bytes || PPU || BG 1 X position&lt;br /&gt;
|-&lt;br /&gt;
| $7E:1868 || 2 bytes || PPU || BG 1 Y position&lt;br /&gt;
|-&lt;br /&gt;
| $7E:1892 || Unknown ||  || Seems to be a group related to BG 2&lt;br /&gt;
|-&lt;br /&gt;
| $7E:1896 || 2 bytes || PPU || BG 2 X position&lt;br /&gt;
|-&lt;br /&gt;
| $7E:1898 || 2 bytes || PPU || BG 2 Y position&lt;br /&gt;
|-&lt;br /&gt;
| $7E:1902 || 128 bytes ||  || Each entry has 8 bytes.&lt;br /&gt;
|-&lt;br /&gt;
| $7E:2200 || 512 bytes || OAM || OAM table&lt;br /&gt;
|-&lt;br /&gt;
| $7E:2400 || 32 bytes || OAM || OAM attribute table&lt;br /&gt;
|-&lt;br /&gt;
| $7E:24A0 || 1024 bytes || VRAM || Unknown data that is transferred to VRAM&lt;br /&gt;
|-&lt;br /&gt;
| $7E:2F60 || 512 bytes || Palette || CGRAM&lt;br /&gt;
|-&lt;br /&gt;
| $7E:8000 || 32768 bytes || Empty || Unused data, initialized at reset.&lt;br /&gt;
|-&lt;br /&gt;
| $7F:0000 || 65536 bytes || Empty || Unused data, not even initialized.&lt;br /&gt;
|}&lt;/div&gt;</summary>
		<author><name>Vitor Vilela</name></author>
	</entry>
	<entry>
		<id>https://sneslab.net/mw/index.php?title=Super_R-Type_RAM_Map&amp;diff=1639</id>
		<title>Super R-Type RAM Map</title>
		<link rel="alternate" type="text/html" href="https://sneslab.net/mw/index.php?title=Super_R-Type_RAM_Map&amp;diff=1639"/>
		<updated>2020-12-31T09:24:59Z</updated>

		<summary type="html">&lt;p&gt;Vitor Vilela: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Address !! Size !! Type !! Description&lt;br /&gt;
|-&lt;br /&gt;
| $7E:004C || 2 bytes || Flow || If #$0080 is set, run the game, otherwise wait for NMI.&lt;br /&gt;
|-&lt;br /&gt;
| $7E:004E || 2 bytes || Flow || 16-bit frame counter, incremented every time the NMI runs.&lt;br /&gt;
|-&lt;br /&gt;
| $7E:0050 || 2 bytes || Flow || 16-bit frame counter, incremented every time the game logic runs.&lt;br /&gt;
|-&lt;br /&gt;
| $7E:0080 || 1 byte || PPU || $2100 register mirror&lt;br /&gt;
|-&lt;br /&gt;
| $7E:0082 || 1 byte || CPU || $4200 register mirror, only written once because $4200 is always #$81&lt;br /&gt;
|-&lt;br /&gt;
| $7E:00F4 || 1 byte || PPU || Copy of PPU status flag, $213E&lt;br /&gt;
|-&lt;br /&gt;
| $7E:0700 || Unknown ||  || &lt;br /&gt;
|-&lt;br /&gt;
| $7E:1580 || Unknown ||  || &lt;br /&gt;
|-&lt;br /&gt;
| $7E:1832 || Unknown ||  || Seems to be a group related to BG 0&lt;br /&gt;
|-&lt;br /&gt;
| $7E:1836 || 2 bytes || PPU || BG 0 X position&lt;br /&gt;
|-&lt;br /&gt;
| $7E:1838 || 2 bytes || PPU || BG 0 Y position&lt;br /&gt;
|-&lt;br /&gt;
| $7E:1862 || Unknown ||  || Seems to be a group related to BG 1&lt;br /&gt;
|-&lt;br /&gt;
| $7E:1866 || 2 bytes || PPU || BG 1 X position&lt;br /&gt;
|-&lt;br /&gt;
| $7E:1868 || 2 bytes || PPU || BG 1 Y position&lt;br /&gt;
|-&lt;br /&gt;
| $7E:1892 || Unknown ||  || Seems to be a group related to BG 2&lt;br /&gt;
|-&lt;br /&gt;
| $7E:1896 || 2 bytes || PPU || BG 2 X position&lt;br /&gt;
|-&lt;br /&gt;
| $7E:1898 || 2 bytes || PPU || BG 3 Y position&lt;br /&gt;
|-&lt;br /&gt;
| $7E:1902 || 128 bytes ||  || Each entry has 8 bytes.&lt;br /&gt;
|-&lt;br /&gt;
| $7E:2200 || 512 bytes || OAM || OAM table&lt;br /&gt;
|-&lt;br /&gt;
| $7E:2400 || 32 bytes || OAM || OAM attribute table&lt;br /&gt;
|-&lt;br /&gt;
| $7E:24A0 || 1024 bytes || VRAM || Unknown data that is transferred to VRAM&lt;br /&gt;
|-&lt;br /&gt;
| $7E:2F60 || 512 bytes || Palette || CGRAM&lt;br /&gt;
|-&lt;br /&gt;
| $7E:8000 || 32768 bytes || Empty || Unused data, initialized at reset.&lt;br /&gt;
|-&lt;br /&gt;
| $7F:0000 || 65536 bytes || Empty || Unused data, not even initialized.&lt;br /&gt;
|}&lt;/div&gt;</summary>
		<author><name>Vitor Vilela</name></author>
	</entry>
	<entry>
		<id>https://sneslab.net/mw/index.php?title=Super_R-Type_RAM_Map&amp;diff=1638</id>
		<title>Super R-Type RAM Map</title>
		<link rel="alternate" type="text/html" href="https://sneslab.net/mw/index.php?title=Super_R-Type_RAM_Map&amp;diff=1638"/>
		<updated>2020-12-31T09:24:22Z</updated>

		<summary type="html">&lt;p&gt;Vitor Vilela: Discovered Super R-Type RAM addresses during SA-1 Root conversion&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Address !! Size !! Type !! Description&lt;br /&gt;
|-&lt;br /&gt;
! $7E:004C&lt;br /&gt;
| 2 bytes || Flow || If #$0080 is set, run the game, otherwise wait for NMI.&lt;br /&gt;
|-&lt;br /&gt;
! $7E:004E&lt;br /&gt;
| 2 bytes || Flow || 16-bit frame counter, incremented every time the NMI runs.&lt;br /&gt;
|-&lt;br /&gt;
! $7E:0050&lt;br /&gt;
| 2 bytes || Flow || 16-bit frame counter, incremented every time the game logic runs.&lt;br /&gt;
|-&lt;br /&gt;
! $7E:0080&lt;br /&gt;
| 1 byte || PPU || $2100 register mirror&lt;br /&gt;
|-&lt;br /&gt;
! $7E:0082&lt;br /&gt;
| 1 byte || CPU || $4200 register mirror, only written once because $4200 is always #$81&lt;br /&gt;
|-&lt;br /&gt;
! $7E:00F4&lt;br /&gt;
| 1 byte || PPU || Copy of PPU status flag, $213E&lt;br /&gt;
|-&lt;br /&gt;
! $7E:0700&lt;br /&gt;
| Unknown ||  || &lt;br /&gt;
|-&lt;br /&gt;
! $7E:1580&lt;br /&gt;
| Unknown ||  || &lt;br /&gt;
|-&lt;br /&gt;
! $7E:1832&lt;br /&gt;
| Unknown ||  || Seems to be a group related to BG 0&lt;br /&gt;
|-&lt;br /&gt;
! $7E:1836&lt;br /&gt;
| 2 bytes || PPU || BG 0 X position&lt;br /&gt;
|-&lt;br /&gt;
! $7E:1838&lt;br /&gt;
| 2 bytes || PPU || BG 0 Y position&lt;br /&gt;
|-&lt;br /&gt;
! $7E:1862&lt;br /&gt;
| Unknown ||  || Seems to be a group related to BG 1&lt;br /&gt;
|-&lt;br /&gt;
! $7E:1866&lt;br /&gt;
| 2 bytes || PPU || BG 1 X position&lt;br /&gt;
|-&lt;br /&gt;
! $7E:1868&lt;br /&gt;
| 2 bytes || PPU || BG 1 Y position&lt;br /&gt;
|-&lt;br /&gt;
! $7E:1892&lt;br /&gt;
| Unknown ||  || Seems to be a group related to BG 2&lt;br /&gt;
|-&lt;br /&gt;
! $7E:1896&lt;br /&gt;
| 2 bytes || PPU || BG 2 X position&lt;br /&gt;
|-&lt;br /&gt;
! $7E:1898&lt;br /&gt;
| 2 bytes || PPU || BG 3 Y position&lt;br /&gt;
|-&lt;br /&gt;
! $7E:1902&lt;br /&gt;
| 128 bytes ||  || Each entry has 8 bytes.&lt;br /&gt;
|-&lt;br /&gt;
! $7E:2200&lt;br /&gt;
| 512 bytes || OAM || OAM table&lt;br /&gt;
|-&lt;br /&gt;
! $7E:2400&lt;br /&gt;
| 32 bytes || OAM || OAM attribute table&lt;br /&gt;
|-&lt;br /&gt;
! $7E:24A0&lt;br /&gt;
| 1024 bytes || VRAM || Unknown data that is transferred to VRAM&lt;br /&gt;
|-&lt;br /&gt;
! $7E:2F60&lt;br /&gt;
| 512 bytes || Palette || CGRAM&lt;br /&gt;
|-&lt;br /&gt;
! $7E:8000&lt;br /&gt;
| 32768 bytes || Empty || Unused data, initialized at reset.&lt;br /&gt;
|-&lt;br /&gt;
! $7F:0000&lt;br /&gt;
| 65536 bytes || Empty || Unused data, not even initialized.&lt;br /&gt;
|}&lt;/div&gt;</summary>
		<author><name>Vitor Vilela</name></author>
	</entry>
	<entry>
		<id>https://sneslab.net/mw/index.php?title=Good_coding_practices&amp;diff=1624</id>
		<title>Good coding practices</title>
		<link rel="alternate" type="text/html" href="https://sneslab.net/mw/index.php?title=Good_coding_practices&amp;diff=1624"/>
		<updated>2020-12-12T04:25:39Z</updated>

		<summary type="html">&lt;p&gt;Vitor Vilela: /* Conventions */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This document is an effort to create a coding standard and by consequence a global library that can be used on SNES homebrew and ROM hacking. The objective is creating a standard that lets coders maintain existing code with less difficulty, promote a clean and easy-to-understand code, standardize conventions and promote coding agility for faster results and less time thinking on how to code.&lt;br /&gt;
&lt;br /&gt;
Since there are some SNES assemblers available, our guideline will be focused on [[Asar]]. However some of the thoughts can be applied to other assemblers without problem.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Feel free to edit with your own thoughts&#039;&#039;&#039;, the idea is mixing everyone opinions until we get into a consensus. Further discussion can be made on the #homebrew channel of the SnesLab Discord: https://discord.gg/dXzrk5bX&lt;br /&gt;
&lt;br /&gt;
== Code writing thoughts ==&lt;br /&gt;
&lt;br /&gt;
=== Code labels ===&lt;br /&gt;
* code label refers to any beginning of a routine.&lt;br /&gt;
* they should be all lowercase and each word should be separated using a underscore. Example: example_routine&lt;br /&gt;
* consider not using more than two underscores to not make it difficulty to read. Not a good example: this_label_is_too_long&lt;br /&gt;
&lt;br /&gt;
=== Opcodes and commands ===&lt;br /&gt;
* mnemonics (the opcode name) should be either all in lowercase (lda #$00) or uppercase (LDA #$00). LDa #$00, Lda #$00 or LdA #$00, etc., is not recommended. The consistency should stay though the entire project.&lt;br /&gt;
* commands should all be lowercased: lorom, org, print, etc.&lt;br /&gt;
* hexadecimal numbers should be all uppercased for readability, even if the mnemonics or commands are in lowercase. Example: lda #$A0 or org $B0C04F.&lt;br /&gt;
&lt;br /&gt;
=== Spacing ===&lt;br /&gt;
* given most editors default preferences, the recommendation is to use 4-space tabulation. The tabulation must be replaced with spaces, for keeping compatibility with editors that has tab size of 8 (Notepad).&lt;br /&gt;
* leave a blank line between the last opcode or command and a label.&lt;br /&gt;
&lt;br /&gt;
=== Comments ===&lt;br /&gt;
* keep it simple and objective.&lt;br /&gt;
&lt;br /&gt;
== Conventions ==&lt;br /&gt;
* Don&#039;t put the whole code on a single ASM file.&lt;br /&gt;
* Group .asm files into its own folder when they are related to a specific group of algorithms. For example, a math folder containing sqrt.asm, trig.asm and power.asm and a hdma code containing layer_wavy.asm, gradient_wavy.asm and brightness.asm&lt;br /&gt;
* There is no specific guidelines how routines should be arranged, but the ordering of them should look like a book story where the reader expects to the code explain itself sequentially. A good example is a SMW sprite, where the init label comes before main label, because it&#039;s executed earlier.&lt;br /&gt;
* Using the brk handler strongly recommended for catching errors in development. Using different operands can also be used to distinguish different errors.&lt;br /&gt;
* Take advantage of assembler conditional statements to add debug code. Having multiple levels of debug flags can also be greatly useful.&lt;br /&gt;
* Include a method for adding configuration options to your code.&lt;br /&gt;
* When possible it is better to use labels to point at RAM addresses rather than using the address as raw values or defines.  This allows addresses to not only be allocated automatically but also allows reorganization to be much easier.&lt;br /&gt;
* Using structs to represent data (both ram and rom) should be preferred when it the data is related and has structure to it.&lt;br /&gt;
&lt;br /&gt;
== Memory map and ROM structure ==&lt;br /&gt;
* Make good use of bank 0&lt;br /&gt;
The first SNES bank ($00) is special because it can be accessed at Direct Page level, when using a DP value between $8000 and $FFFF. Consider placing useful, intensive use tables. They can be the differential when dealing with time-critical routines such as graphics manipulation or intensively used routines such as trigonometric functions.&lt;br /&gt;
* Use the hirom mapper whenever practical&lt;br /&gt;
In the context of a homebrew it is almost always better to use the hirom mapper than the lorom mapper.  The hirom mapper can be used similar to lorom in many situations, however has strong advantages with large data blocks allowing for contiguous allocations and not requiring special cased bank switching logic to handle wrapping.&lt;br /&gt;
&lt;br /&gt;
== Cycle optimization ==&lt;br /&gt;
* Do not code thinking already on optimization. Get the routine working first.&lt;br /&gt;
Comments: Often an algorithm or routine takes several hours to get it working, it requires extensive thoughts and coding thinking already on possible optimizations will make the coding process way slower. It also increases the chances of getting premature bugs, because it makes harder to verify if the algorithm is correct.&lt;br /&gt;
&lt;br /&gt;
* Micro-optimizations are bad, consider only doing them if it&#039;s a critical routine of your program.&lt;br /&gt;
Comments: An optimization is considered &#039;micro-optimization&#039; when you start sacrificing the readability in exchange of 1-2 cycle optimization. An example is taking off the CLC because there 50 lines ago there was a BCS opcode that jumps to the of the routine or the previous ADC implies that the operation will never generate carry (for example, a sum that will never exceed #$FF).  If you are in an extremely performance critical path (such as NMI) any micro optimizations that you are required to make should be firmly documented after algorithm and code flow options have been exhausted.&lt;br /&gt;
&lt;br /&gt;
* Give a focus on generating efficient algorithms before thinking on any assembly-level optimization.&lt;br /&gt;
Comments: Observe if your overall algorithm is effect and fast. Sometimes you can do the same thing much more effectively if done in another way. Observe the trade off between memory and time usage. Sometimes an algorithm that uses more memory will be much faster than an algorithm that uses almost no memory but requires much more iterations. If the algorithm involves iterating a list (for example, a list of active enemies on screen), try making the algorithm only iterate once or twice on the enemy list. It will be much faster than optimizing an algorithm that iterates the enemy list quadratic times.&lt;br /&gt;
&lt;br /&gt;
* Code inlining should only be considered on critical situations.&lt;br /&gt;
Comments: Often coders prefer getting rid of the JSR/RTS and inlining all of the code at the once, which sounds logical if the routine is only called once. However the practice is not recommended, given that routines can end-up reused across other resources. Splitting an inline code into routines will also likely make it easier to edit because it will allow to isolate each routine to its own role. A good way to check if inlining will be really benefit is evaluating the cycle cost of using JSR + RTS times the amount of inlining routines times the amount of time the code section is called.&lt;br /&gt;
&lt;br /&gt;
== Bus I/O ==&lt;br /&gt;
Sometimes HDMA or DMA transfers end up not working as expected. This guide proposes a fix for it.&lt;br /&gt;
&lt;br /&gt;
=== DMA and HDMA ===&lt;br /&gt;
&lt;br /&gt;
Known problems (specially over ROM hacking) related to DMA/HDMA:&lt;br /&gt;
# A DMA transfer outside the loading screen fails to happen or corrupts the entire memory. For example, a memory copy while the game is running.&lt;br /&gt;
# HDMA flickers when a V-Blank overflow occurs.&lt;br /&gt;
# HDMA flickers when the screen is vertically scrolled.&lt;br /&gt;
# Several HDMA transfers in sequence or use of extensive indirect HDMA transfers causes some of the transfers not happen or not give any effect at all.&lt;br /&gt;
&lt;br /&gt;
Channel usage recommendation:&lt;br /&gt;
&lt;br /&gt;
* Channel 0: DMA - exclusive for transfers inside interrupts&lt;br /&gt;
* Channel 1: DMA - exclusive for transfers outside interrupts&lt;br /&gt;
* Channel 2 though 7: HDMA - earlier channels should be dedicated to H-Blanking sensitive PPU transfers and latter channels should be dedicated for registers that doesn&#039;t depend on H-blanking at channel such as $2100 and $2140+.&lt;br /&gt;
&lt;br /&gt;
This fixes the first problem mentioned and reduces the probability of the fourth issue from happening by prioritizing H-Blanking sensitive HDMAs.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note&#039;&#039;&#039; about Super Mario World hacking: Lunar Magic enforces channel 2 on all its DMA transfers and most of the ASM hacks focuses on using channel 0. Therefore for compatibility, the recommended DMA remap is: 0 -&amp;gt; outside IRQ/NMI DMA; 1 -&amp;gt; window HDMA (was channel 7); 2 -&amp;gt; inside IRQ/NMI DMA; 3 though 7 -&amp;gt; user HDMA.&lt;br /&gt;
&lt;br /&gt;
HDMA setup recommendation:&lt;br /&gt;
* Don&#039;t zero $420C at the start of your V-Blanking routine.&lt;br /&gt;
* In addition to above, update $420C as soon as your V-Blanking routine starts. Don&#039;t do at the end of the V-Blanking routine or you have the risk of your HDMA not being initialized correctly, specially if $420C is cleared at the beginning of the V-Blanking routine.&lt;br /&gt;
* Unless if the values remain static, update the HDMA registers ($43xx) during the V-Blanking routine.&lt;/div&gt;</summary>
		<author><name>Vitor Vilela</name></author>
	</entry>
	<entry>
		<id>https://sneslab.net/mw/index.php?title=Good_coding_practices&amp;diff=1623</id>
		<title>Good coding practices</title>
		<link rel="alternate" type="text/html" href="https://sneslab.net/mw/index.php?title=Good_coding_practices&amp;diff=1623"/>
		<updated>2020-12-12T04:22:47Z</updated>

		<summary type="html">&lt;p&gt;Vitor Vilela: /* DMA and HDMA */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This document is an effort to create a coding standard and by consequence a global library that can be used on SNES homebrew and ROM hacking. The objective is creating a standard that lets coders maintain existing code with less difficulty, promote a clean and easy-to-understand code, standardize conventions and promote coding agility for faster results and less time thinking on how to code.&lt;br /&gt;
&lt;br /&gt;
Since there are some SNES assemblers available, our guideline will be focused on [[Asar]]. However some of the thoughts can be applied to other assemblers without problem.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Feel free to edit with your own thoughts&#039;&#039;&#039;, the idea is mixing everyone opinions until we get into a consensus. Further discussion can be made on the #homebrew channel of the SnesLab Discord: https://discord.gg/dXzrk5bX&lt;br /&gt;
&lt;br /&gt;
== Code writing thoughts ==&lt;br /&gt;
&lt;br /&gt;
=== Code labels ===&lt;br /&gt;
* code label refers to any beginning of a routine.&lt;br /&gt;
* they should be all lowercase and each word should be separated using a underscore. Example: example_routine&lt;br /&gt;
* consider not using more than two underscores to not make it difficulty to read. Not a good example: this_label_is_too_long&lt;br /&gt;
&lt;br /&gt;
=== Opcodes and commands ===&lt;br /&gt;
* mnemonics (the opcode name) should be either all in lowercase (lda #$00) or uppercase (LDA #$00). LDa #$00, Lda #$00 or LdA #$00, etc., is not recommended. The consistency should stay though the entire project.&lt;br /&gt;
* commands should all be lowercased: lorom, org, print, etc.&lt;br /&gt;
* hexadecimal numbers should be all uppercased for readability, even if the mnemonics or commands are in lowercase. Example: lda #$A0 or org $B0C04F.&lt;br /&gt;
&lt;br /&gt;
=== Spacing ===&lt;br /&gt;
* given most editors default preferences, the recommendation is to use 4-space tabulation. The tabulation must be replaced with spaces, for keeping compatibility with editors that has tab size of 8 (Notepad).&lt;br /&gt;
* leave a blank line between the last opcode or command and a label.&lt;br /&gt;
&lt;br /&gt;
=== Comments ===&lt;br /&gt;
* keep it simple and objective.&lt;br /&gt;
&lt;br /&gt;
== Conventions ==&lt;br /&gt;
* Don&#039;t put the whole code on a single ASM file.&lt;br /&gt;
* Group .asm files into its own folder when they are related to a specific group of algorithms. For example, a math folder containing sqrt.asm, trig.asm and power.asm and a hdma code containing layer_wavy.asm, gradient_wavy.asm and brightness.asm&lt;br /&gt;
* There is no specific guidelines how routines should be arranged, but the ordination should look like a book story where the reader excepts to the code explain itself sequentially. A good example is a SMW sprite, where the init label comes before main label, because it&#039;s executed earlier.&lt;br /&gt;
* Using the brk handler strongly recommended for catching errors in development. Using different operands can also be used to distinguish different errors.&lt;br /&gt;
* Take advantage of assembler conditional statements to add debug code.  Having multiple levels of debug flags can also be greatly useful.&lt;br /&gt;
* Include a method for adding configuration options to your code.&lt;br /&gt;
* When possible it is better to use labels to point at RAM addresses rather than using the address as raw values or defines.  This allows addresses to not only be allocated automatically but also allows reorganization to be much easier.&lt;br /&gt;
* Using structs to represent data (both ram and rom) should be preferred when it the data is related and has structure to it.&lt;br /&gt;
&lt;br /&gt;
== Memory map and ROM structure ==&lt;br /&gt;
* Make good use of bank 0&lt;br /&gt;
The first SNES bank ($00) is special because it can be accessed at Direct Page level, when using a DP value between $8000 and $FFFF. Consider placing useful, intensive use tables. They can be the differential when dealing with time-critical routines such as graphics manipulation or intensively used routines such as trigonometric functions.&lt;br /&gt;
* Use the hirom mapper whenever practical&lt;br /&gt;
In the context of a homebrew it is almost always better to use the hirom mapper than the lorom mapper.  The hirom mapper can be used similar to lorom in many situations, however has strong advantages with large data blocks allowing for contiguous allocations and not requiring special cased bank switching logic to handle wrapping.&lt;br /&gt;
&lt;br /&gt;
== Cycle optimization ==&lt;br /&gt;
* Do not code thinking already on optimization. Get the routine working first.&lt;br /&gt;
Comments: Often an algorithm or routine takes several hours to get it working, it requires extensive thoughts and coding thinking already on possible optimizations will make the coding process way slower. It also increases the chances of getting premature bugs, because it makes harder to verify if the algorithm is correct.&lt;br /&gt;
&lt;br /&gt;
* Micro-optimizations are bad, consider only doing them if it&#039;s a critical routine of your program.&lt;br /&gt;
Comments: An optimization is considered &#039;micro-optimization&#039; when you start sacrificing the readability in exchange of 1-2 cycle optimization. An example is taking off the CLC because there 50 lines ago there was a BCS opcode that jumps to the of the routine or the previous ADC implies that the operation will never generate carry (for example, a sum that will never exceed #$FF).  If you are in an extremely performance critical path (such as NMI) any micro optimizations that you are required to make should be firmly documented after algorithm and code flow options have been exhausted.&lt;br /&gt;
&lt;br /&gt;
* Give a focus on generating efficient algorithms before thinking on any assembly-level optimization.&lt;br /&gt;
Comments: Observe if your overall algorithm is effect and fast. Sometimes you can do the same thing much more effectively if done in another way. Observe the trade off between memory and time usage. Sometimes an algorithm that uses more memory will be much faster than an algorithm that uses almost no memory but requires much more iterations. If the algorithm involves iterating a list (for example, a list of active enemies on screen), try making the algorithm only iterate once or twice on the enemy list. It will be much faster than optimizing an algorithm that iterates the enemy list quadratic times.&lt;br /&gt;
&lt;br /&gt;
* Code inlining should only be considered on critical situations.&lt;br /&gt;
Comments: Often coders prefer getting rid of the JSR/RTS and inlining all of the code at the once, which sounds logical if the routine is only called once. However the practice is not recommended, given that routines can end-up reused across other resources. Splitting an inline code into routines will also likely make it easier to edit because it will allow to isolate each routine to its own role. A good way to check if inlining will be really benefit is evaluating the cycle cost of using JSR + RTS times the amount of inlining routines times the amount of time the code section is called.&lt;br /&gt;
&lt;br /&gt;
== Bus I/O ==&lt;br /&gt;
Sometimes HDMA or DMA transfers end up not working as expected. This guide proposes a fix for it.&lt;br /&gt;
&lt;br /&gt;
=== DMA and HDMA ===&lt;br /&gt;
&lt;br /&gt;
Known problems (specially over ROM hacking) related to DMA/HDMA:&lt;br /&gt;
# A DMA transfer outside the loading screen fails to happen or corrupts the entire memory. For example, a memory copy while the game is running.&lt;br /&gt;
# HDMA flickers when a V-Blank overflow occurs.&lt;br /&gt;
# HDMA flickers when the screen is vertically scrolled.&lt;br /&gt;
# Several HDMA transfers in sequence or use of extensive indirect HDMA transfers causes some of the transfers not happen or not give any effect at all.&lt;br /&gt;
&lt;br /&gt;
Channel usage recommendation:&lt;br /&gt;
&lt;br /&gt;
* Channel 0: DMA - exclusive for transfers inside interrupts&lt;br /&gt;
* Channel 1: DMA - exclusive for transfers outside interrupts&lt;br /&gt;
* Channel 2 though 7: HDMA - earlier channels should be dedicated to H-Blanking sensitive PPU transfers and latter channels should be dedicated for registers that doesn&#039;t depend on H-blanking at channel such as $2100 and $2140+.&lt;br /&gt;
&lt;br /&gt;
This fixes the first problem mentioned and reduces the probability of the fourth issue from happening by prioritizing H-Blanking sensitive HDMAs.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note&#039;&#039;&#039; about Super Mario World hacking: Lunar Magic enforces channel 2 on all its DMA transfers and most of the ASM hacks focuses on using channel 0. Therefore for compatibility, the recommended DMA remap is: 0 -&amp;gt; outside IRQ/NMI DMA; 1 -&amp;gt; window HDMA (was channel 7); 2 -&amp;gt; inside IRQ/NMI DMA; 3 though 7 -&amp;gt; user HDMA.&lt;br /&gt;
&lt;br /&gt;
HDMA setup recommendation:&lt;br /&gt;
* Don&#039;t zero $420C at the start of your V-Blanking routine.&lt;br /&gt;
* In addition to above, update $420C as soon as your V-Blanking routine starts. Don&#039;t do at the end of the V-Blanking routine or you have the risk of your HDMA not being initialized correctly, specially if $420C is cleared at the beginning of the V-Blanking routine.&lt;br /&gt;
* Unless if the values remain static, update the HDMA registers ($43xx) during the V-Blanking routine.&lt;/div&gt;</summary>
		<author><name>Vitor Vilela</name></author>
	</entry>
	<entry>
		<id>https://sneslab.net/mw/index.php?title=Good_coding_practices&amp;diff=1622</id>
		<title>Good coding practices</title>
		<link rel="alternate" type="text/html" href="https://sneslab.net/mw/index.php?title=Good_coding_practices&amp;diff=1622"/>
		<updated>2020-12-12T04:21:41Z</updated>

		<summary type="html">&lt;p&gt;Vitor Vilela: /* DMA and HDMA */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This document is an effort to create a coding standard and by consequence a global library that can be used on SNES homebrew and ROM hacking. The objective is creating a standard that lets coders maintain existing code with less difficulty, promote a clean and easy-to-understand code, standardize conventions and promote coding agility for faster results and less time thinking on how to code.&lt;br /&gt;
&lt;br /&gt;
Since there are some SNES assemblers available, our guideline will be focused on [[Asar]]. However some of the thoughts can be applied to other assemblers without problem.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Feel free to edit with your own thoughts&#039;&#039;&#039;, the idea is mixing everyone opinions until we get into a consensus. Further discussion can be made on the #homebrew channel of the SnesLab Discord: https://discord.gg/dXzrk5bX&lt;br /&gt;
&lt;br /&gt;
== Code writing thoughts ==&lt;br /&gt;
&lt;br /&gt;
=== Code labels ===&lt;br /&gt;
* code label refers to any beginning of a routine.&lt;br /&gt;
* they should be all lowercase and each word should be separated using a underscore. Example: example_routine&lt;br /&gt;
* consider not using more than two underscores to not make it difficulty to read. Not a good example: this_label_is_too_long&lt;br /&gt;
&lt;br /&gt;
=== Opcodes and commands ===&lt;br /&gt;
* mnemonics (the opcode name) should be either all in lowercase (lda #$00) or uppercase (LDA #$00). LDa #$00, Lda #$00 or LdA #$00, etc., is not recommended. The consistency should stay though the entire project.&lt;br /&gt;
* commands should all be lowercased: lorom, org, print, etc.&lt;br /&gt;
* hexadecimal numbers should be all uppercased for readability, even if the mnemonics or commands are in lowercase. Example: lda #$A0 or org $B0C04F.&lt;br /&gt;
&lt;br /&gt;
=== Spacing ===&lt;br /&gt;
* given most editors default preferences, the recommendation is to use 4-space tabulation. The tabulation must be replaced with spaces, for keeping compatibility with editors that has tab size of 8 (Notepad).&lt;br /&gt;
* leave a blank line between the last opcode or command and a label.&lt;br /&gt;
&lt;br /&gt;
=== Comments ===&lt;br /&gt;
* keep it simple and objective.&lt;br /&gt;
&lt;br /&gt;
== Conventions ==&lt;br /&gt;
* Don&#039;t put the whole code on a single ASM file.&lt;br /&gt;
* Group .asm files into its own folder when they are related to a specific group of algorithms. For example, a math folder containing sqrt.asm, trig.asm and power.asm and a hdma code containing layer_wavy.asm, gradient_wavy.asm and brightness.asm&lt;br /&gt;
* There is no specific guidelines how routines should be arranged, but the ordination should look like a book story where the reader excepts to the code explain itself sequentially. A good example is a SMW sprite, where the init label comes before main label, because it&#039;s executed earlier.&lt;br /&gt;
* Using the brk handler strongly recommended for catching errors in development. Using different operands can also be used to distinguish different errors.&lt;br /&gt;
* Take advantage of assembler conditional statements to add debug code.  Having multiple levels of debug flags can also be greatly useful.&lt;br /&gt;
* Include a method for adding configuration options to your code.&lt;br /&gt;
* When possible it is better to use labels to point at RAM addresses rather than using the address as raw values or defines.  This allows addresses to not only be allocated automatically but also allows reorganization to be much easier.&lt;br /&gt;
* Using structs to represent data (both ram and rom) should be preferred when it the data is related and has structure to it.&lt;br /&gt;
&lt;br /&gt;
== Memory map and ROM structure ==&lt;br /&gt;
* Make good use of bank 0&lt;br /&gt;
The first SNES bank ($00) is special because it can be accessed at Direct Page level, when using a DP value between $8000 and $FFFF. Consider placing useful, intensive use tables. They can be the differential when dealing with time-critical routines such as graphics manipulation or intensively used routines such as trigonometric functions.&lt;br /&gt;
* Use the hirom mapper whenever practical&lt;br /&gt;
In the context of a homebrew it is almost always better to use the hirom mapper than the lorom mapper.  The hirom mapper can be used similar to lorom in many situations, however has strong advantages with large data blocks allowing for contiguous allocations and not requiring special cased bank switching logic to handle wrapping.&lt;br /&gt;
&lt;br /&gt;
== Cycle optimization ==&lt;br /&gt;
* Do not code thinking already on optimization. Get the routine working first.&lt;br /&gt;
Comments: Often an algorithm or routine takes several hours to get it working, it requires extensive thoughts and coding thinking already on possible optimizations will make the coding process way slower. It also increases the chances of getting premature bugs, because it makes harder to verify if the algorithm is correct.&lt;br /&gt;
&lt;br /&gt;
* Micro-optimizations are bad, consider only doing them if it&#039;s a critical routine of your program.&lt;br /&gt;
Comments: An optimization is considered &#039;micro-optimization&#039; when you start sacrificing the readability in exchange of 1-2 cycle optimization. An example is taking off the CLC because there 50 lines ago there was a BCS opcode that jumps to the of the routine or the previous ADC implies that the operation will never generate carry (for example, a sum that will never exceed #$FF).  If you are in an extremely performance critical path (such as NMI) any micro optimizations that you are required to make should be firmly documented after algorithm and code flow options have been exhausted.&lt;br /&gt;
&lt;br /&gt;
* Give a focus on generating efficient algorithms before thinking on any assembly-level optimization.&lt;br /&gt;
Comments: Observe if your overall algorithm is effect and fast. Sometimes you can do the same thing much more effectively if done in another way. Observe the trade off between memory and time usage. Sometimes an algorithm that uses more memory will be much faster than an algorithm that uses almost no memory but requires much more iterations. If the algorithm involves iterating a list (for example, a list of active enemies on screen), try making the algorithm only iterate once or twice on the enemy list. It will be much faster than optimizing an algorithm that iterates the enemy list quadratic times.&lt;br /&gt;
&lt;br /&gt;
* Code inlining should only be considered on critical situations.&lt;br /&gt;
Comments: Often coders prefer getting rid of the JSR/RTS and inlining all of the code at the once, which sounds logical if the routine is only called once. However the practice is not recommended, given that routines can end-up reused across other resources. Splitting an inline code into routines will also likely make it easier to edit because it will allow to isolate each routine to its own role. A good way to check if inlining will be really benefit is evaluating the cycle cost of using JSR + RTS times the amount of inlining routines times the amount of time the code section is called.&lt;br /&gt;
&lt;br /&gt;
== Bus I/O ==&lt;br /&gt;
Sometimes HDMA or DMA transfers end up not working as expected. This guide proposes a fix for it.&lt;br /&gt;
&lt;br /&gt;
=== DMA and HDMA ===&lt;br /&gt;
&lt;br /&gt;
Known problems (specially over ROM hacking) related to DMA/HDMA:&lt;br /&gt;
# A DMA transfer outside the loading screen fails to happen or corrupts the entire memory. For example, a memory copy while the game is running.&lt;br /&gt;
# HDMA flickers when a V-Blank overflow occurs.&lt;br /&gt;
# HDMA flickers when the screen is vertically scrolled.&lt;br /&gt;
# Several HDMA transfers in sequence or use of extensive indirect HDMA transfers causes some of the transfers not happen or not give any effect at all.&lt;br /&gt;
&lt;br /&gt;
Channel usage recommendation:&lt;br /&gt;
&lt;br /&gt;
* Channel 0: DMA - exclusive for transfers inside interrupts&lt;br /&gt;
* Channel 1: DMA - exclusive for transfers outside interrupts&lt;br /&gt;
* Channel 2 though 7: HDMA - earlier channels should be dedicated to H-Blanking sensitive PPU transfers and latter channels should be dedicated for registers that doesn&#039;t depend on H-blanking at channel such as $2100 and $2140+.&lt;br /&gt;
&lt;br /&gt;
This fixes the first problem mentioned and reduces the probability of the fourth issue from happening by prioritizing H-Blanking sensitive HDMAs.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note&#039;&#039;&#039; about Super Mario World hacking: Lunar Magic enforces channel 2 on all its DMA transfers and most of the ASM hacks focuses on using channel 0. Therefore for compatibility, the recommended DMA remap is: 0 -&amp;gt; outside IRQ/NMI DMA; 1 -&amp;gt; window HDMA (was channel 7); 2 -&amp;gt; inside IRQ/NMI DMA; 3 though 7 -&amp;gt; user HDMA.&lt;br /&gt;
&lt;br /&gt;
HDMA setup recommendation:&lt;br /&gt;
* Don&#039;t zero $420C at the start of your V-Blanking routine.&lt;br /&gt;
* In addition to above, update $420C as soon as your V-Blanking routine starts.&lt;br /&gt;
* Unless if the values remain static, update the HDMA registers ($43xx) during the V-Blanking routine.&lt;/div&gt;</summary>
		<author><name>Vitor Vilela</name></author>
	</entry>
	<entry>
		<id>https://sneslab.net/mw/index.php?title=Good_coding_practices&amp;diff=1621</id>
		<title>Good coding practices</title>
		<link rel="alternate" type="text/html" href="https://sneslab.net/mw/index.php?title=Good_coding_practices&amp;diff=1621"/>
		<updated>2020-12-12T04:18:57Z</updated>

		<summary type="html">&lt;p&gt;Vitor Vilela: /* Bus I/O */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This document is an effort to create a coding standard and by consequence a global library that can be used on SNES homebrew and ROM hacking. The objective is creating a standard that lets coders maintain existing code with less difficulty, promote a clean and easy-to-understand code, standardize conventions and promote coding agility for faster results and less time thinking on how to code.&lt;br /&gt;
&lt;br /&gt;
Since there are some SNES assemblers available, our guideline will be focused on [[Asar]]. However some of the thoughts can be applied to other assemblers without problem.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Feel free to edit with your own thoughts&#039;&#039;&#039;, the idea is mixing everyone opinions until we get into a consensus. Further discussion can be made on the #homebrew channel of the SnesLab Discord: https://discord.gg/dXzrk5bX&lt;br /&gt;
&lt;br /&gt;
== Code writing thoughts ==&lt;br /&gt;
&lt;br /&gt;
=== Code labels ===&lt;br /&gt;
* code label refers to any beginning of a routine.&lt;br /&gt;
* they should be all lowercase and each word should be separated using a underscore. Example: example_routine&lt;br /&gt;
* consider not using more than two underscores to not make it difficulty to read. Not a good example: this_label_is_too_long&lt;br /&gt;
&lt;br /&gt;
=== Opcodes and commands ===&lt;br /&gt;
* mnemonics (the opcode name) should be either all in lowercase (lda #$00) or uppercase (LDA #$00). LDa #$00, Lda #$00 or LdA #$00, etc., is not recommended. The consistency should stay though the entire project.&lt;br /&gt;
* commands should all be lowercased: lorom, org, print, etc.&lt;br /&gt;
* hexadecimal numbers should be all uppercased for readability, even if the mnemonics or commands are in lowercase. Example: lda #$A0 or org $B0C04F.&lt;br /&gt;
&lt;br /&gt;
=== Spacing ===&lt;br /&gt;
* given most editors default preferences, the recommendation is to use 4-space tabulation. The tabulation must be replaced with spaces, for keeping compatibility with editors that has tab size of 8 (Notepad).&lt;br /&gt;
* leave a blank line between the last opcode or command and a label.&lt;br /&gt;
&lt;br /&gt;
=== Comments ===&lt;br /&gt;
* keep it simple and objective.&lt;br /&gt;
&lt;br /&gt;
== Conventions ==&lt;br /&gt;
* Don&#039;t put the whole code on a single ASM file.&lt;br /&gt;
* Group .asm files into its own folder when they are related to a specific group of algorithms. For example, a math folder containing sqrt.asm, trig.asm and power.asm and a hdma code containing layer_wavy.asm, gradient_wavy.asm and brightness.asm&lt;br /&gt;
* There is no specific guidelines how routines should be arranged, but the ordination should look like a book story where the reader excepts to the code explain itself sequentially. A good example is a SMW sprite, where the init label comes before main label, because it&#039;s executed earlier.&lt;br /&gt;
* Using the brk handler strongly recommended for catching errors in development. Using different operands can also be used to distinguish different errors.&lt;br /&gt;
* Take advantage of assembler conditional statements to add debug code.  Having multiple levels of debug flags can also be greatly useful.&lt;br /&gt;
* Include a method for adding configuration options to your code.&lt;br /&gt;
* When possible it is better to use labels to point at RAM addresses rather than using the address as raw values or defines.  This allows addresses to not only be allocated automatically but also allows reorganization to be much easier.&lt;br /&gt;
* Using structs to represent data (both ram and rom) should be preferred when it the data is related and has structure to it.&lt;br /&gt;
&lt;br /&gt;
== Memory map and ROM structure ==&lt;br /&gt;
* Make good use of bank 0&lt;br /&gt;
The first SNES bank ($00) is special because it can be accessed at Direct Page level, when using a DP value between $8000 and $FFFF. Consider placing useful, intensive use tables. They can be the differential when dealing with time-critical routines such as graphics manipulation or intensively used routines such as trigonometric functions.&lt;br /&gt;
* Use the hirom mapper whenever practical&lt;br /&gt;
In the context of a homebrew it is almost always better to use the hirom mapper than the lorom mapper.  The hirom mapper can be used similar to lorom in many situations, however has strong advantages with large data blocks allowing for contiguous allocations and not requiring special cased bank switching logic to handle wrapping.&lt;br /&gt;
&lt;br /&gt;
== Cycle optimization ==&lt;br /&gt;
* Do not code thinking already on optimization. Get the routine working first.&lt;br /&gt;
Comments: Often an algorithm or routine takes several hours to get it working, it requires extensive thoughts and coding thinking already on possible optimizations will make the coding process way slower. It also increases the chances of getting premature bugs, because it makes harder to verify if the algorithm is correct.&lt;br /&gt;
&lt;br /&gt;
* Micro-optimizations are bad, consider only doing them if it&#039;s a critical routine of your program.&lt;br /&gt;
Comments: An optimization is considered &#039;micro-optimization&#039; when you start sacrificing the readability in exchange of 1-2 cycle optimization. An example is taking off the CLC because there 50 lines ago there was a BCS opcode that jumps to the of the routine or the previous ADC implies that the operation will never generate carry (for example, a sum that will never exceed #$FF).  If you are in an extremely performance critical path (such as NMI) any micro optimizations that you are required to make should be firmly documented after algorithm and code flow options have been exhausted.&lt;br /&gt;
&lt;br /&gt;
* Give a focus on generating efficient algorithms before thinking on any assembly-level optimization.&lt;br /&gt;
Comments: Observe if your overall algorithm is effect and fast. Sometimes you can do the same thing much more effectively if done in another way. Observe the trade off between memory and time usage. Sometimes an algorithm that uses more memory will be much faster than an algorithm that uses almost no memory but requires much more iterations. If the algorithm involves iterating a list (for example, a list of active enemies on screen), try making the algorithm only iterate once or twice on the enemy list. It will be much faster than optimizing an algorithm that iterates the enemy list quadratic times.&lt;br /&gt;
&lt;br /&gt;
* Code inlining should only be considered on critical situations.&lt;br /&gt;
Comments: Often coders prefer getting rid of the JSR/RTS and inlining all of the code at the once, which sounds logical if the routine is only called once. However the practice is not recommended, given that routines can end-up reused across other resources. Splitting an inline code into routines will also likely make it easier to edit because it will allow to isolate each routine to its own role. A good way to check if inlining will be really benefit is evaluating the cycle cost of using JSR + RTS times the amount of inlining routines times the amount of time the code section is called.&lt;br /&gt;
&lt;br /&gt;
== Bus I/O ==&lt;br /&gt;
Sometimes HDMA or DMA transfers end up not working as expected. This guide proposes a fix for it.&lt;br /&gt;
&lt;br /&gt;
=== DMA and HDMA ===&lt;br /&gt;
&lt;br /&gt;
Known problems (specially over ROM hacking) related to DMA/HDMA:&lt;br /&gt;
* A DMA transfer outside the loading screen fails to happen or corrupts the entire memory. For example, a memory copy while the game is running.&lt;br /&gt;
* HDMA flickers when a V-Blank overflow occurs.&lt;br /&gt;
* HDMA flickers when the screen is vertically scrolled.&lt;br /&gt;
* Several HDMA transfers in sequence or use of extensive indirect HDMA transfers causes some of the transfers not happen or not give any effect at all.&lt;br /&gt;
&lt;br /&gt;
Channel usage recommendation:&lt;br /&gt;
&lt;br /&gt;
* Channel 0: DMA - exclusive for transfers inside interrupts&lt;br /&gt;
* Channel 1: DMA - exclusive for transfers outside interrupts&lt;br /&gt;
* Channel 2 though 7: HDMA - earlier channels should be dedicated to H-Blanking sensitive PPU transfers and latter channels should be dedicated for registers that doesn&#039;t depend on H-blanking at channel such as $2100 and $2140+.&lt;br /&gt;
&lt;br /&gt;
This fixes the first problem mentioned and reduces the probability of the fourth issue from happening by prioritizing H-Blanking sensitive HDMAs.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note&#039;&#039;&#039; about Super Mario World hacking: Lunar Magic enforces channel 2 on all its DMA transfers and most of the ASM hacks focuses on using channel 0. Therefore for compatibility, the recommended DMA remap is: 0 -&amp;gt; outside IRQ/NMI DMA; 1 -&amp;gt; window HDMA (was channel 7); 2 -&amp;gt; inside IRQ/NMI DMA; 3 though 7 -&amp;gt; user HDMA.&lt;/div&gt;</summary>
		<author><name>Vitor Vilela</name></author>
	</entry>
	<entry>
		<id>https://sneslab.net/mw/index.php?title=Good_coding_practices&amp;diff=1620</id>
		<title>Good coding practices</title>
		<link rel="alternate" type="text/html" href="https://sneslab.net/mw/index.php?title=Good_coding_practices&amp;diff=1620"/>
		<updated>2020-12-12T03:19:01Z</updated>

		<summary type="html">&lt;p&gt;Vitor Vilela: /* DMA and HDMA */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This document is an effort to create a coding standard and by consequence a global library that can be used on SNES homebrew and ROM hacking. The objective is creating a standard that lets coders maintain existing code with less difficulty, promote a clean and easy-to-understand code, standardize conventions and promote coding agility for faster results and less time thinking on how to code.&lt;br /&gt;
&lt;br /&gt;
Since there are some SNES assemblers available, our guideline will be focused on [[Asar]]. However some of the thoughts can be applied to other assemblers without problem.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Feel free to edit with your own thoughts&#039;&#039;&#039;, the idea is mixing everyone opinions until we get into a consensus. Further discussion can be made on the #homebrew channel of the SnesLab Discord: https://discord.gg/dXzrk5bX&lt;br /&gt;
&lt;br /&gt;
== Code writing thoughts ==&lt;br /&gt;
&lt;br /&gt;
=== Code labels ===&lt;br /&gt;
* code label refers to any beginning of a routine.&lt;br /&gt;
* they should be all lowercase and each word should be separated using a underscore. Example: example_routine&lt;br /&gt;
* consider not using more than two underscores to not make it difficulty to read. Not a good example: this_label_is_too_long&lt;br /&gt;
&lt;br /&gt;
=== Opcodes and commands ===&lt;br /&gt;
* mnemonics (the opcode name) should be either all in lowercase (lda #$00) or uppercase (LDA #$00). LDa #$00, Lda #$00 or LdA #$00, etc., is not recommended. The consistency should stay though the entire project.&lt;br /&gt;
* commands should all be lowercased: lorom, org, print, etc.&lt;br /&gt;
* hexadecimal numbers should be all uppercased for readability, even if the mnemonics or commands are in lowercase. Example: lda #$A0 or org $B0C04F.&lt;br /&gt;
&lt;br /&gt;
=== Spacing ===&lt;br /&gt;
* given most editors default preferences, the recommendation is to use 4-space tabulation. The tabulation must be replaced with spaces, for keeping compatibility with editors that has tab size of 8 (Notepad).&lt;br /&gt;
* leave a blank line between the last opcode or command and a label.&lt;br /&gt;
&lt;br /&gt;
=== Comments ===&lt;br /&gt;
* keep it simple and objective.&lt;br /&gt;
&lt;br /&gt;
== Conventions ==&lt;br /&gt;
* Don&#039;t put the whole code on a single ASM file.&lt;br /&gt;
* Group .asm files into its own folder when they are related to a specific group of algorithms. For example, a math folder containing sqrt.asm, trig.asm and power.asm and a hdma code containing layer_wavy.asm, gradient_wavy.asm and brightness.asm&lt;br /&gt;
* There is no specific guidelines how routines should be arranged, but the ordination should look like a book story where the reader excepts to the code explain itself sequentially. A good example is a SMW sprite, where the init label comes before main label, because it&#039;s executed earlier.&lt;br /&gt;
* Using the brk handler strongly recommended for catching errors in development. Using different operands can also be used to distinguish different errors.&lt;br /&gt;
* Take advantage of assembler conditional statements to add debug code.  Having multiple levels of debug flags can also be greatly useful.&lt;br /&gt;
* Include a method for adding configuration options to your code.&lt;br /&gt;
* When possible it is better to use labels to point at RAM addresses rather than using the address as raw values or defines.  This allows addresses to not only be allocated automatically but also allows reorganization to be much easier.&lt;br /&gt;
* Using structs to represent data (both ram and rom) should be preferred when it the data is related and has structure to it.&lt;br /&gt;
&lt;br /&gt;
== Memory map and ROM structure ==&lt;br /&gt;
* Make good use of bank 0&lt;br /&gt;
The first SNES bank ($00) is special because it can be accessed at Direct Page level, when using a DP value between $8000 and $FFFF. Consider placing useful, intensive use tables. They can be the differential when dealing with time-critical routines such as graphics manipulation or intensively used routines such as trigonometric functions.&lt;br /&gt;
* Use the hirom mapper whenever practical&lt;br /&gt;
In the context of a homebrew it is almost always better to use the hirom mapper than the lorom mapper.  The hirom mapper can be used similar to lorom in many situations, however has strong advantages with large data blocks allowing for contiguous allocations and not requiring special cased bank switching logic to handle wrapping.&lt;br /&gt;
&lt;br /&gt;
== Cycle optimization ==&lt;br /&gt;
* Do not code thinking already on optimization. Get the routine working first.&lt;br /&gt;
Comments: Often an algorithm or routine takes several hours to get it working, it requires extensive thoughts and coding thinking already on possible optimizations will make the coding process way slower. It also increases the chances of getting premature bugs, because it makes harder to verify if the algorithm is correct.&lt;br /&gt;
&lt;br /&gt;
* Micro-optimizations are bad, consider only doing them if it&#039;s a critical routine of your program.&lt;br /&gt;
Comments: An optimization is considered &#039;micro-optimization&#039; when you start sacrificing the readability in exchange of 1-2 cycle optimization. An example is taking off the CLC because there 50 lines ago there was a BCS opcode that jumps to the of the routine or the previous ADC implies that the operation will never generate carry (for example, a sum that will never exceed #$FF).  If you are in an extremely performance critical path (such as NMI) any micro optimizations that you are required to make should be firmly documented after algorithm and code flow options have been exhausted.&lt;br /&gt;
&lt;br /&gt;
* Give a focus on generating efficient algorithms before thinking on any assembly-level optimization.&lt;br /&gt;
Comments: Observe if your overall algorithm is effect and fast. Sometimes you can do the same thing much more effectively if done in another way. Observe the trade off between memory and time usage. Sometimes an algorithm that uses more memory will be much faster than an algorithm that uses almost no memory but requires much more iterations. If the algorithm involves iterating a list (for example, a list of active enemies on screen), try making the algorithm only iterate once or twice on the enemy list. It will be much faster than optimizing an algorithm that iterates the enemy list quadratic times.&lt;br /&gt;
&lt;br /&gt;
* Code inlining should only be considered on critical situations.&lt;br /&gt;
Comments: Often coders prefer getting rid of the JSR/RTS and inlining all of the code at the once, which sounds logical if the routine is only called once. However the practice is not recommended, given that routines can end-up reused across other resources. Splitting an inline code into routines will also likely make it easier to edit because it will allow to isolate each routine to its own role. A good way to check if inlining will be really benefit is evaluating the cycle cost of using JSR + RTS times the amount of inlining routines times the amount of time the code section is called.&lt;br /&gt;
&lt;br /&gt;
== Bus I/O ==&lt;br /&gt;
Sometimes HDMA or DMA transfers end up not working as expected. This guide proposes a fix for it.&lt;br /&gt;
&lt;br /&gt;
=== DMA and HDMA ===&lt;br /&gt;
&lt;br /&gt;
Channel usage recommendation:&lt;br /&gt;
&lt;br /&gt;
* Channel 0: DMA - exclusive for transfers inside interrupts&lt;br /&gt;
* Channel 1: DMA - exclusive for transfers outside interrupts&lt;br /&gt;
* Channel 2 though 7: HDMA - earlier channels should be dedicated to H-Blanking sensitive PPU transfers and latter channels should be dedicated for registers that doesn&#039;t depend on H-blanking at channel such as $2100 and $2140+.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note&#039;&#039;&#039; about Super Mario World hacking: Lunar Magic enforces channel 2 on all its DMA transfers and most of the ASM hacks focuses on using channel 0. Therefore for compatibility, the recommended DMA remap is: 0 -&amp;gt; outside IRQ/NMI DMA; 1 -&amp;gt; window HDMA (was channel 7); 2 -&amp;gt; inside IRQ/NMI DMA; 3 though 7 -&amp;gt; user HDMA.&lt;/div&gt;</summary>
		<author><name>Vitor Vilela</name></author>
	</entry>
	<entry>
		<id>https://sneslab.net/mw/index.php?title=Good_coding_practices&amp;diff=1619</id>
		<title>Good coding practices</title>
		<link rel="alternate" type="text/html" href="https://sneslab.net/mw/index.php?title=Good_coding_practices&amp;diff=1619"/>
		<updated>2020-12-12T03:03:05Z</updated>

		<summary type="html">&lt;p&gt;Vitor Vilela: /* Bus I/O */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This document is an effort to create a coding standard and by consequence a global library that can be used on SNES homebrew and ROM hacking. The objective is creating a standard that lets coders maintain existing code with less difficulty, promote a clean and easy-to-understand code, standardize conventions and promote coding agility for faster results and less time thinking on how to code.&lt;br /&gt;
&lt;br /&gt;
Since there are some SNES assemblers available, our guideline will be focused on [[Asar]]. However some of the thoughts can be applied to other assemblers without problem.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Feel free to edit with your own thoughts&#039;&#039;&#039;, the idea is mixing everyone opinions until we get into a consensus. Further discussion can be made on the #homebrew channel of the SnesLab Discord: https://discord.gg/dXzrk5bX&lt;br /&gt;
&lt;br /&gt;
== Code writing thoughts ==&lt;br /&gt;
&lt;br /&gt;
=== Code labels ===&lt;br /&gt;
* code label refers to any beginning of a routine.&lt;br /&gt;
* they should be all lowercase and each word should be separated using a underscore. Example: example_routine&lt;br /&gt;
* consider not using more than two underscores to not make it difficulty to read. Not a good example: this_label_is_too_long&lt;br /&gt;
&lt;br /&gt;
=== Opcodes and commands ===&lt;br /&gt;
* mnemonics (the opcode name) should be either all in lowercase (lda #$00) or uppercase (LDA #$00). LDa #$00, Lda #$00 or LdA #$00, etc., is not recommended. The consistency should stay though the entire project.&lt;br /&gt;
* commands should all be lowercased: lorom, org, print, etc.&lt;br /&gt;
* hexadecimal numbers should be all uppercased for readability, even if the mnemonics or commands are in lowercase. Example: lda #$A0 or org $B0C04F.&lt;br /&gt;
&lt;br /&gt;
=== Spacing ===&lt;br /&gt;
* given most editors default preferences, the recommendation is to use 4-space tabulation. The tabulation must be replaced with spaces, for keeping compatibility with editors that has tab size of 8 (Notepad).&lt;br /&gt;
* leave a blank line between the last opcode or command and a label.&lt;br /&gt;
&lt;br /&gt;
=== Comments ===&lt;br /&gt;
* keep it simple and objective.&lt;br /&gt;
&lt;br /&gt;
== Conventions ==&lt;br /&gt;
* Don&#039;t put the whole code on a single ASM file.&lt;br /&gt;
* Group .asm files into its own folder when they are related to a specific group of algorithms. For example, a math folder containing sqrt.asm, trig.asm and power.asm and a hdma code containing layer_wavy.asm, gradient_wavy.asm and brightness.asm&lt;br /&gt;
* There is no specific guidelines how routines should be arranged, but the ordination should look like a book story where the reader excepts to the code explain itself sequentially. A good example is a SMW sprite, where the init label comes before main label, because it&#039;s executed earlier.&lt;br /&gt;
* Using the brk handler strongly recommended for catching errors in development. Using different operands can also be used to distinguish different errors.&lt;br /&gt;
* Take advantage of assembler conditional statements to add debug code.  Having multiple levels of debug flags can also be greatly useful.&lt;br /&gt;
* Include a method for adding configuration options to your code.&lt;br /&gt;
* When possible it is better to use labels to point at RAM addresses rather than using the address as raw values or defines.  This allows addresses to not only be allocated automatically but also allows reorganization to be much easier.&lt;br /&gt;
* Using structs to represent data (both ram and rom) should be preferred when it the data is related and has structure to it.&lt;br /&gt;
&lt;br /&gt;
== Memory map and ROM structure ==&lt;br /&gt;
* Make good use of bank 0&lt;br /&gt;
The first SNES bank ($00) is special because it can be accessed at Direct Page level, when using a DP value between $8000 and $FFFF. Consider placing useful, intensive use tables. They can be the differential when dealing with time-critical routines such as graphics manipulation or intensively used routines such as trigonometric functions.&lt;br /&gt;
* Use the hirom mapper whenever practical&lt;br /&gt;
In the context of a homebrew it is almost always better to use the hirom mapper than the lorom mapper.  The hirom mapper can be used similar to lorom in many situations, however has strong advantages with large data blocks allowing for contiguous allocations and not requiring special cased bank switching logic to handle wrapping.&lt;br /&gt;
&lt;br /&gt;
== Cycle optimization ==&lt;br /&gt;
* Do not code thinking already on optimization. Get the routine working first.&lt;br /&gt;
Comments: Often an algorithm or routine takes several hours to get it working, it requires extensive thoughts and coding thinking already on possible optimizations will make the coding process way slower. It also increases the chances of getting premature bugs, because it makes harder to verify if the algorithm is correct.&lt;br /&gt;
&lt;br /&gt;
* Micro-optimizations are bad, consider only doing them if it&#039;s a critical routine of your program.&lt;br /&gt;
Comments: An optimization is considered &#039;micro-optimization&#039; when you start sacrificing the readability in exchange of 1-2 cycle optimization. An example is taking off the CLC because there 50 lines ago there was a BCS opcode that jumps to the of the routine or the previous ADC implies that the operation will never generate carry (for example, a sum that will never exceed #$FF).  If you are in an extremely performance critical path (such as NMI) any micro optimizations that you are required to make should be firmly documented after algorithm and code flow options have been exhausted.&lt;br /&gt;
&lt;br /&gt;
* Give a focus on generating efficient algorithms before thinking on any assembly-level optimization.&lt;br /&gt;
Comments: Observe if your overall algorithm is effect and fast. Sometimes you can do the same thing much more effectively if done in another way. Observe the trade off between memory and time usage. Sometimes an algorithm that uses more memory will be much faster than an algorithm that uses almost no memory but requires much more iterations. If the algorithm involves iterating a list (for example, a list of active enemies on screen), try making the algorithm only iterate once or twice on the enemy list. It will be much faster than optimizing an algorithm that iterates the enemy list quadratic times.&lt;br /&gt;
&lt;br /&gt;
* Code inlining should only be considered on critical situations.&lt;br /&gt;
Comments: Often coders prefer getting rid of the JSR/RTS and inlining all of the code at the once, which sounds logical if the routine is only called once. However the practice is not recommended, given that routines can end-up reused across other resources. Splitting an inline code into routines will also likely make it easier to edit because it will allow to isolate each routine to its own role. A good way to check if inlining will be really benefit is evaluating the cycle cost of using JSR + RTS times the amount of inlining routines times the amount of time the code section is called.&lt;br /&gt;
&lt;br /&gt;
== Bus I/O ==&lt;br /&gt;
Sometimes HDMA or DMA transfers end up not working as expected. This guide proposes a fix for it.&lt;br /&gt;
&lt;br /&gt;
=== DMA and HDMA ===&lt;br /&gt;
&lt;br /&gt;
Channel usage recommendation:&lt;br /&gt;
&lt;br /&gt;
* Channel 0: DMA - exclusive for transfers inside interrupts&lt;br /&gt;
* Channel 1: DMA - exclusive for transfers outside interrupts&lt;br /&gt;
* Channel 2 though 7: HDMA - earlier channels should be dedicated to H-Blanking sensitive PPU transfers and latter channels should be dedicated for registers that doesn&#039;t depend on H-blanking at channel such as $2100 and $2140+.&lt;/div&gt;</summary>
		<author><name>Vitor Vilela</name></author>
	</entry>
	<entry>
		<id>https://sneslab.net/mw/index.php?title=Good_coding_practices&amp;diff=1618</id>
		<title>Good coding practices</title>
		<link rel="alternate" type="text/html" href="https://sneslab.net/mw/index.php?title=Good_coding_practices&amp;diff=1618"/>
		<updated>2020-12-12T02:58:37Z</updated>

		<summary type="html">&lt;p&gt;Vitor Vilela: Add I/O guidelines: HDMA, DMA, V-Blank, etc.&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This document is an effort to create a coding standard and by consequence a global library that can be used on SNES homebrew and ROM hacking. The objective is creating a standard that lets coders maintain existing code with less difficulty, promote a clean and easy-to-understand code, standardize conventions and promote coding agility for faster results and less time thinking on how to code.&lt;br /&gt;
&lt;br /&gt;
Since there are some SNES assemblers available, our guideline will be focused on [[Asar]]. However some of the thoughts can be applied to other assemblers without problem.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Feel free to edit with your own thoughts&#039;&#039;&#039;, the idea is mixing everyone opinions until we get into a consensus. Further discussion can be made on the #homebrew channel of the SnesLab Discord: https://discord.gg/dXzrk5bX&lt;br /&gt;
&lt;br /&gt;
== Code writing thoughts ==&lt;br /&gt;
&lt;br /&gt;
=== Code labels ===&lt;br /&gt;
* code label refers to any beginning of a routine.&lt;br /&gt;
* they should be all lowercase and each word should be separated using a underscore. Example: example_routine&lt;br /&gt;
* consider not using more than two underscores to not make it difficulty to read. Not a good example: this_label_is_too_long&lt;br /&gt;
&lt;br /&gt;
=== Opcodes and commands ===&lt;br /&gt;
* mnemonics (the opcode name) should be either all in lowercase (lda #$00) or uppercase (LDA #$00). LDa #$00, Lda #$00 or LdA #$00, etc., is not recommended. The consistency should stay though the entire project.&lt;br /&gt;
* commands should all be lowercased: lorom, org, print, etc.&lt;br /&gt;
* hexadecimal numbers should be all uppercased for readability, even if the mnemonics or commands are in lowercase. Example: lda #$A0 or org $B0C04F.&lt;br /&gt;
&lt;br /&gt;
=== Spacing ===&lt;br /&gt;
* given most editors default preferences, the recommendation is to use 4-space tabulation. The tabulation must be replaced with spaces, for keeping compatibility with editors that has tab size of 8 (Notepad).&lt;br /&gt;
* leave a blank line between the last opcode or command and a label.&lt;br /&gt;
&lt;br /&gt;
=== Comments ===&lt;br /&gt;
* keep it simple and objective.&lt;br /&gt;
&lt;br /&gt;
== Conventions ==&lt;br /&gt;
* Don&#039;t put the whole code on a single ASM file.&lt;br /&gt;
* Group .asm files into its own folder when they are related to a specific group of algorithms. For example, a math folder containing sqrt.asm, trig.asm and power.asm and a hdma code containing layer_wavy.asm, gradient_wavy.asm and brightness.asm&lt;br /&gt;
* There is no specific guidelines how routines should be arranged, but the ordination should look like a book story where the reader excepts to the code explain itself sequentially. A good example is a SMW sprite, where the init label comes before main label, because it&#039;s executed earlier.&lt;br /&gt;
* Using the brk handler strongly recommended for catching errors in development. Using different operands can also be used to distinguish different errors.&lt;br /&gt;
* Take advantage of assembler conditional statements to add debug code.  Having multiple levels of debug flags can also be greatly useful.&lt;br /&gt;
* Include a method for adding configuration options to your code.&lt;br /&gt;
* When possible it is better to use labels to point at RAM addresses rather than using the address as raw values or defines.  This allows addresses to not only be allocated automatically but also allows reorganization to be much easier.&lt;br /&gt;
* Using structs to represent data (both ram and rom) should be preferred when it the data is related and has structure to it.&lt;br /&gt;
&lt;br /&gt;
== Memory map and ROM structure ==&lt;br /&gt;
* Make good use of bank 0&lt;br /&gt;
The first SNES bank ($00) is special because it can be accessed at Direct Page level, when using a DP value between $8000 and $FFFF. Consider placing useful, intensive use tables. They can be the differential when dealing with time-critical routines such as graphics manipulation or intensively used routines such as trigonometric functions.&lt;br /&gt;
* Use the hirom mapper whenever practical&lt;br /&gt;
In the context of a homebrew it is almost always better to use the hirom mapper than the lorom mapper.  The hirom mapper can be used similar to lorom in many situations, however has strong advantages with large data blocks allowing for contiguous allocations and not requiring special cased bank switching logic to handle wrapping.&lt;br /&gt;
&lt;br /&gt;
== Cycle optimization ==&lt;br /&gt;
* Do not code thinking already on optimization. Get the routine working first.&lt;br /&gt;
Comments: Often an algorithm or routine takes several hours to get it working, it requires extensive thoughts and coding thinking already on possible optimizations will make the coding process way slower. It also increases the chances of getting premature bugs, because it makes harder to verify if the algorithm is correct.&lt;br /&gt;
&lt;br /&gt;
* Micro-optimizations are bad, consider only doing them if it&#039;s a critical routine of your program.&lt;br /&gt;
Comments: An optimization is considered &#039;micro-optimization&#039; when you start sacrificing the readability in exchange of 1-2 cycle optimization. An example is taking off the CLC because there 50 lines ago there was a BCS opcode that jumps to the of the routine or the previous ADC implies that the operation will never generate carry (for example, a sum that will never exceed #$FF).  If you are in an extremely performance critical path (such as NMI) any micro optimizations that you are required to make should be firmly documented after algorithm and code flow options have been exhausted.&lt;br /&gt;
&lt;br /&gt;
* Give a focus on generating efficient algorithms before thinking on any assembly-level optimization.&lt;br /&gt;
Comments: Observe if your overall algorithm is effect and fast. Sometimes you can do the same thing much more effectively if done in another way. Observe the trade off between memory and time usage. Sometimes an algorithm that uses more memory will be much faster than an algorithm that uses almost no memory but requires much more iterations. If the algorithm involves iterating a list (for example, a list of active enemies on screen), try making the algorithm only iterate once or twice on the enemy list. It will be much faster than optimizing an algorithm that iterates the enemy list quadratic times.&lt;br /&gt;
&lt;br /&gt;
* Code inlining should only be considered on critical situations.&lt;br /&gt;
Comments: Often coders prefer getting rid of the JSR/RTS and inlining all of the code at the once, which sounds logical if the routine is only called once. However the practice is not recommended, given that routines can end-up reused across other resources. Splitting an inline code into routines will also likely make it easier to edit because it will allow to isolate each routine to its own role. A good way to check if inlining will be really benefit is evaluating the cycle cost of using JSR + RTS times the amount of inlining routines times the amount of time the code section is called.&lt;br /&gt;
&lt;br /&gt;
== Bus I/O ==&lt;br /&gt;
Sometimes HDMA or DMA transfers end up not working as expected. This guide proposes a fix for it.&lt;/div&gt;</summary>
		<author><name>Vitor Vilela</name></author>
	</entry>
	<entry>
		<id>https://sneslab.net/mw/index.php?title=Good_coding_practices&amp;diff=1609</id>
		<title>Good coding practices</title>
		<link rel="alternate" type="text/html" href="https://sneslab.net/mw/index.php?title=Good_coding_practices&amp;diff=1609"/>
		<updated>2020-12-11T06:15:44Z</updated>

		<summary type="html">&lt;p&gt;Vitor Vilela: /* Code writing thoughts */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This document is an effort to create a coding standard and by consequence a global library that can be used on SNES homebrew and ROM hacking. The objective is creating a standard that lets coders maintain existing code with less difficulty, promote a clean and easy-to-understand code, standardize conventions and promote coding agility for faster results and less time thinking on how to code.&lt;br /&gt;
&lt;br /&gt;
Since there are some SNES assemblers available, our guideline will be focused on [[Asar]]. However some of the thoughts can be applied to other assemblers without problem.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Feel free to edit with your own thoughts&#039;&#039;&#039;, the idea is mixing everyone opinions until we get into a consensus. Further discussion can be made on the #homebrew channel of the SnesLab Discord: https://discord.gg/dXzrk5bX&lt;br /&gt;
&lt;br /&gt;
== Code writing thoughts ==&lt;br /&gt;
&lt;br /&gt;
=== Code labels ===&lt;br /&gt;
* code label refers to any beginning of a routine.&lt;br /&gt;
* they should be all lowercase and each word should be separated using a underscore. Example: example_routine&lt;br /&gt;
* consider not using more than two underscores to not make it difficulty to read. Not a good example: this_label_is_too_long&lt;br /&gt;
&lt;br /&gt;
=== Opcodes and commands ===&lt;br /&gt;
* mnemonics (the opcode name) should be either all in lowercase (lda #$00) or uppercase (LDA #$00). LDa #$00, Lda #$00 or LdA #$00, etc., is not recommended. The consistency should stay though the entire project.&lt;br /&gt;
* commands should all be lowercased: lorom, org, print, etc.&lt;br /&gt;
* hexadecimal numbers should be all uppercased for readability, even if the mnemonics or commands are in lowercase. Example: lda #$A0 or org $B0C04F.&lt;br /&gt;
&lt;br /&gt;
=== Spacing ===&lt;br /&gt;
* given most editors default preferences, the recommendation is to use 4-space tabulation. The tabulation must be replaced with spaces, for keeping compatibility with editors that has tab size of 8 (Notepad).&lt;br /&gt;
* leave a blank line between the last opcode or command and a label.&lt;br /&gt;
&lt;br /&gt;
=== Comments ===&lt;br /&gt;
* keep it simple and objective.&lt;br /&gt;
&lt;br /&gt;
== Conventions ==&lt;br /&gt;
* Don&#039;t put the whole code on a single ASM file.&lt;br /&gt;
* Group .asm files into its own folder when they are related to a specific group of algorithms. For example, a math folder containing sqrt.asm, trig.asm and power.asm and a hdma code containing layer_wavy.asm, gradient_wavy.asm and brightness.asm&lt;br /&gt;
* There is no specific guidelines how routines should be arranged, but the ordination should look like a book story where the reader excepts to the code explain itself sequentially. A good example is a SMW sprite, where the init label comes before main label, because it&#039;s executed earlier.&lt;br /&gt;
&lt;br /&gt;
== Memory map and ROM structure ==&lt;br /&gt;
* Make good use of bank 0&lt;br /&gt;
The first SNES bank ($00) is special because it can be accessed at Direct Page level, when using a DP value between $8000 and $FFFF. Consider placing useful, intensive use tables. They can be the differential when dealing with time-critical routines such as graphics manipulation or intensively used routines such as trigonometric functions.&lt;br /&gt;
&lt;br /&gt;
== Cycle optimization ==&lt;br /&gt;
* Do not code thinking already on optimization. Get the routine working first.&lt;br /&gt;
Comments: Often an algorithm or routine takes several hours to get it working, it requires extensive thoughts and coding thinking already on possible optimizations will make the coding process way slower. It also increases the chances of getting premature bugs, because it makes harder to verify if the algorithm is correct.&lt;br /&gt;
&lt;br /&gt;
* Micro-optimizations are bad, consider only doing them if it&#039;s a critical routine of your program.&lt;br /&gt;
Comments: An optimization is considered &#039;micro-optimization&#039; when you start sacrificing the readability in exchange of 1-2 cycle optimization. An example is taking off the CLC because there 50 lines ago there was a BCS opcode that jumps to the of the routine or the previous ADC implies that the operation will never generate carry (fcr example, a sum that will never exceed #$FF).&lt;br /&gt;
&lt;br /&gt;
* Give a focus on generating efficient algorithms before thinking on any assembly-level optimization.&lt;br /&gt;
Comments: Observe if your overall algorithm is effect and fast. Sometimes you can do the same thing much more effectively if done in another way. Observe the trade off between memory and time usage. Sometimes an algorithm that uses more memory will be much faster than an algorithm that uses almost no memory but requires much more iterations. If the algorithm involves iterating a list (for example, a list of active enemies on screen), try making the algorithm only iterate once or twice on the enemy list. It will be much faster than optimizing an algorithm that iterates the enemy list quadratic times.&lt;br /&gt;
&lt;br /&gt;
* Code inling should only be considered on critical situations.&lt;br /&gt;
Comments: Often coders prefer getting rid of the JSR/RTS and inling all of the code at the once, which sounds logigal if the routine is only called once. However the practice is not recommended, given that routines can end-up reused across other resources. Splitting an inline code into routines will also likely make it easier to edit because it will allow to isolate each routine to its own role. A good way to check if inling will be really benefit is evaluating the cycle cost of using JSR + RTS times the amount of inlined routines times the amount of time the code section is called.&lt;/div&gt;</summary>
		<author><name>Vitor Vilela</name></author>
	</entry>
	<entry>
		<id>https://sneslab.net/mw/index.php?title=Good_coding_practices&amp;diff=1608</id>
		<title>Good coding practices</title>
		<link rel="alternate" type="text/html" href="https://sneslab.net/mw/index.php?title=Good_coding_practices&amp;diff=1608"/>
		<updated>2020-12-11T04:15:02Z</updated>

		<summary type="html">&lt;p&gt;Vitor Vilela: /* Conventions */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This document is an effort to create a coding standard and by consequence a global library that can be used on SNES homebrew and ROM hacking. The objective is creating a standard that lets coders maintain existing code with less difficulty, promote a clean and easy-to-understand code, standardize conventions and promote coding agility for faster results and less time thinking on how to code.&lt;br /&gt;
&lt;br /&gt;
Since there are some SNES assemblers available, our guideline will be focused on [[Asar]]. However some of the thoughts can be applied to other assemblers without problem.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Feel free to edit with your own thoughts&#039;&#039;&#039;, the idea is mixing everyone opinions until we get into a consensus. Further discussion can be made on the #homebrew channel of the SnesLab Discord: https://discord.gg/dXzrk5bX&lt;br /&gt;
&lt;br /&gt;
== Code writing thoughts ==&lt;br /&gt;
&lt;br /&gt;
=== Code Labels ===&lt;br /&gt;
* code label refers to any beginning of a routine.&lt;br /&gt;
* they should be all lowercase and each word should be separated using a underscore. Example: example_routine&lt;br /&gt;
* consider not using more than two underscores to not make it difficulty to read. Not a good example: this_label_is_too_long&lt;br /&gt;
&lt;br /&gt;
== Conventions ==&lt;br /&gt;
* Don&#039;t put the whole code on a single ASM file.&lt;br /&gt;
* Group .asm files into its own folder when they are related to a specific group of algorithms. For example, a math folder containing sqrt.asm, trig.asm and power.asm and a hdma code containing layer_wavy.asm, gradient_wavy.asm and brightness.asm&lt;br /&gt;
* There is no specific guidelines how routines should be arranged, but the ordination should look like a book story where the reader excepts to the code explain itself sequentially. A good example is a SMW sprite, where the init label comes before main label, because it&#039;s executed earlier.&lt;br /&gt;
&lt;br /&gt;
== Memory map and ROM structure ==&lt;br /&gt;
* Make good use of bank 0&lt;br /&gt;
The first SNES bank ($00) is special because it can be accessed at Direct Page level, when using a DP value between $8000 and $FFFF. Consider placing useful, intensive use tables. They can be the differential when dealing with time-critical routines such as graphics manipulation or intensively used routines such as trigonometric functions.&lt;br /&gt;
&lt;br /&gt;
== Cycle optimization ==&lt;br /&gt;
* Do not code thinking already on optimization. Get the routine working first.&lt;br /&gt;
Comments: Often an algorithm or routine takes several hours to get it working, it requires extensive thoughts and coding thinking already on possible optimizations will make the coding process way slower. It also increases the chances of getting premature bugs, because it makes harder to verify if the algorithm is correct.&lt;br /&gt;
&lt;br /&gt;
* Micro-optimizations are bad, consider only doing them if it&#039;s a critical routine of your program.&lt;br /&gt;
Comments: An optimization is considered &#039;micro-optimization&#039; when you start sacrificing the readability in exchange of 1-2 cycle optimization. An example is taking off the CLC because there 50 lines ago there was a BCS opcode that jumps to the of the routine or the previous ADC implies that the operation will never generate carry (fcr example, a sum that will never exceed #$FF).&lt;br /&gt;
&lt;br /&gt;
* Give a focus on generating efficient algorithms before thinking on any assembly-level optimization.&lt;br /&gt;
Comments: Observe if your overall algorithm is effect and fast. Sometimes you can do the same thing much more effectively if done in another way. Observe the trade off between memory and time usage. Sometimes an algorithm that uses more memory will be much faster than an algorithm that uses almost no memory but requires much more iterations. If the algorithm involves iterating a list (for example, a list of active enemies on screen), try making the algorithm only iterate once or twice on the enemy list. It will be much faster than optimizing an algorithm that iterates the enemy list quadratic times.&lt;br /&gt;
&lt;br /&gt;
* Code inling should only be considered on critical situations.&lt;br /&gt;
Comments: Often coders prefer getting rid of the JSR/RTS and inling all of the code at the once, which sounds logigal if the routine is only called once. However the practice is not recommended, given that routines can end-up reused across other resources. Splitting an inline code into routines will also likely make it easier to edit because it will allow to isolate each routine to its own role. A good way to check if inling will be really benefit is evaluating the cycle cost of using JSR + RTS times the amount of inlined routines times the amount of time the code section is called.&lt;/div&gt;</summary>
		<author><name>Vitor Vilela</name></author>
	</entry>
	<entry>
		<id>https://sneslab.net/mw/index.php?title=Good_coding_practices&amp;diff=1607</id>
		<title>Good coding practices</title>
		<link rel="alternate" type="text/html" href="https://sneslab.net/mw/index.php?title=Good_coding_practices&amp;diff=1607"/>
		<updated>2020-12-11T04:06:01Z</updated>

		<summary type="html">&lt;p&gt;Vitor Vilela: /* Memory map and ROM structure */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This document is an effort to create a coding standard and by consequence a global library that can be used on SNES homebrew and ROM hacking. The objective is creating a standard that lets coders maintain existing code with less difficulty, promote a clean and easy-to-understand code, standardize conventions and promote coding agility for faster results and less time thinking on how to code.&lt;br /&gt;
&lt;br /&gt;
Since there are some SNES assemblers available, our guideline will be focused on [[Asar]]. However some of the thoughts can be applied to other assemblers without problem.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Feel free to edit with your own thoughts&#039;&#039;&#039;, the idea is mixing everyone opinions until we get into a consensus. Further discussion can be made on the #homebrew channel of the SnesLab Discord: https://discord.gg/dXzrk5bX&lt;br /&gt;
&lt;br /&gt;
== Code writing thoughts ==&lt;br /&gt;
&lt;br /&gt;
=== Code Labels ===&lt;br /&gt;
* code label refers to any beginning of a routine.&lt;br /&gt;
* they should be all lowercase and each word should be separated using a underscore. Example: example_routine&lt;br /&gt;
* consider not using more than two underscores to not make it difficulty to read. Not a good example: this_label_is_too_long&lt;br /&gt;
&lt;br /&gt;
== Conventions ==&lt;br /&gt;
&lt;br /&gt;
== Memory map and ROM structure ==&lt;br /&gt;
* Make good use of bank 0&lt;br /&gt;
The first SNES bank ($00) is special because it can be accessed at Direct Page level, when using a DP value between $8000 and $FFFF. Consider placing useful, intensive use tables. They can be the differential when dealing with time-critical routines such as graphics manipulation or intensively used routines such as trigonometric functions.&lt;br /&gt;
&lt;br /&gt;
== Cycle optimization ==&lt;br /&gt;
* Do not code thinking already on optimization. Get the routine working first.&lt;br /&gt;
Comments: Often an algorithm or routine takes several hours to get it working, it requires extensive thoughts and coding thinking already on possible optimizations will make the coding process way slower. It also increases the chances of getting premature bugs, because it makes harder to verify if the algorithm is correct.&lt;br /&gt;
&lt;br /&gt;
* Micro-optimizations are bad, consider only doing them if it&#039;s a critical routine of your program.&lt;br /&gt;
Comments: An optimization is considered &#039;micro-optimization&#039; when you start sacrificing the readability in exchange of 1-2 cycle optimization. An example is taking off the CLC because there 50 lines ago there was a BCS opcode that jumps to the of the routine or the previous ADC implies that the operation will never generate carry (fcr example, a sum that will never exceed #$FF).&lt;br /&gt;
&lt;br /&gt;
* Give a focus on generating efficient algorithms before thinking on any assembly-level optimization.&lt;br /&gt;
Comments: Observe if your overall algorithm is effect and fast. Sometimes you can do the same thing much more effectively if done in another way. Observe the trade off between memory and time usage. Sometimes an algorithm that uses more memory will be much faster than an algorithm that uses almost no memory but requires much more iterations. If the algorithm involves iterating a list (for example, a list of active enemies on screen), try making the algorithm only iterate once or twice on the enemy list. It will be much faster than optimizing an algorithm that iterates the enemy list quadratic times.&lt;br /&gt;
&lt;br /&gt;
* Code inling should only be considered on critical situations.&lt;br /&gt;
Comments: Often coders prefer getting rid of the JSR/RTS and inling all of the code at the once, which sounds logigal if the routine is only called once. However the practice is not recommended, given that routines can end-up reused across other resources. Splitting an inline code into routines will also likely make it easier to edit because it will allow to isolate each routine to its own role. A good way to check if inling will be really benefit is evaluating the cycle cost of using JSR + RTS times the amount of inlined routines times the amount of time the code section is called.&lt;/div&gt;</summary>
		<author><name>Vitor Vilela</name></author>
	</entry>
	<entry>
		<id>https://sneslab.net/mw/index.php?title=Good_coding_practices&amp;diff=1606</id>
		<title>Good coding practices</title>
		<link rel="alternate" type="text/html" href="https://sneslab.net/mw/index.php?title=Good_coding_practices&amp;diff=1606"/>
		<updated>2020-12-11T04:02:59Z</updated>

		<summary type="html">&lt;p&gt;Vitor Vilela: /* Cycle optimization */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This document is an effort to create a coding standard and by consequence a global library that can be used on SNES homebrew and ROM hacking. The objective is creating a standard that lets coders maintain existing code with less difficulty, promote a clean and easy-to-understand code, standardize conventions and promote coding agility for faster results and less time thinking on how to code.&lt;br /&gt;
&lt;br /&gt;
Since there are some SNES assemblers available, our guideline will be focused on [[Asar]]. However some of the thoughts can be applied to other assemblers without problem.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Feel free to edit with your own thoughts&#039;&#039;&#039;, the idea is mixing everyone opinions until we get into a consensus. Further discussion can be made on the #homebrew channel of the SnesLab Discord: https://discord.gg/dXzrk5bX&lt;br /&gt;
&lt;br /&gt;
== Code writing thoughts ==&lt;br /&gt;
&lt;br /&gt;
=== Code Labels ===&lt;br /&gt;
* code label refers to any beginning of a routine.&lt;br /&gt;
* they should be all lowercase and each word should be separated using a underscore. Example: example_routine&lt;br /&gt;
* consider not using more than two underscores to not make it difficulty to read. Not a good example: this_label_is_too_long&lt;br /&gt;
&lt;br /&gt;
== Conventions ==&lt;br /&gt;
&lt;br /&gt;
== Memory map and ROM structure ==&lt;br /&gt;
&lt;br /&gt;
== Cycle optimization ==&lt;br /&gt;
* Do not code thinking already on optimization. Get the routine working first.&lt;br /&gt;
Comments: Often an algorithm or routine takes several hours to get it working, it requires extensive thoughts and coding thinking already on possible optimizations will make the coding process way slower. It also increases the chances of getting premature bugs, because it makes harder to verify if the algorithm is correct.&lt;br /&gt;
&lt;br /&gt;
* Micro-optimizations are bad, consider only doing them if it&#039;s a critical routine of your program.&lt;br /&gt;
Comments: An optimization is considered &#039;micro-optimization&#039; when you start sacrificing the readability in exchange of 1-2 cycle optimization. An example is taking off the CLC because there 50 lines ago there was a BCS opcode that jumps to the of the routine or the previous ADC implies that the operation will never generate carry (fcr example, a sum that will never exceed #$FF).&lt;br /&gt;
&lt;br /&gt;
* Give a focus on generating efficient algorithms before thinking on any assembly-level optimization.&lt;br /&gt;
Comments: Observe if your overall algorithm is effect and fast. Sometimes you can do the same thing much more effectively if done in another way. Observe the trade off between memory and time usage. Sometimes an algorithm that uses more memory will be much faster than an algorithm that uses almost no memory but requires much more iterations. If the algorithm involves iterating a list (for example, a list of active enemies on screen), try making the algorithm only iterate once or twice on the enemy list. It will be much faster than optimizing an algorithm that iterates the enemy list quadratic times.&lt;br /&gt;
&lt;br /&gt;
* Code inling should only be considered on critical situations.&lt;br /&gt;
Comments: Often coders prefer getting rid of the JSR/RTS and inling all of the code at the once, which sounds logigal if the routine is only called once. However the practice is not recommended, given that routines can end-up reused across other resources. Splitting an inline code into routines will also likely make it easier to edit because it will allow to isolate each routine to its own role. A good way to check if inling will be really benefit is evaluating the cycle cost of using JSR + RTS times the amount of inlined routines times the amount of time the code section is called.&lt;/div&gt;</summary>
		<author><name>Vitor Vilela</name></author>
	</entry>
	<entry>
		<id>https://sneslab.net/mw/index.php?title=Good_coding_practices&amp;diff=1605</id>
		<title>Good coding practices</title>
		<link rel="alternate" type="text/html" href="https://sneslab.net/mw/index.php?title=Good_coding_practices&amp;diff=1605"/>
		<updated>2020-12-11T03:56:52Z</updated>

		<summary type="html">&lt;p&gt;Vitor Vilela: /* Code writing thoughts */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This document is an effort to create a coding standard and by consequence a global library that can be used on SNES homebrew and ROM hacking. The objective is creating a standard that lets coders maintain existing code with less difficulty, promote a clean and easy-to-understand code, standardize conventions and promote coding agility for faster results and less time thinking on how to code.&lt;br /&gt;
&lt;br /&gt;
Since there are some SNES assemblers available, our guideline will be focused on [[Asar]]. However some of the thoughts can be applied to other assemblers without problem.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Feel free to edit with your own thoughts&#039;&#039;&#039;, the idea is mixing everyone opinions until we get into a consensus. Further discussion can be made on the #homebrew channel of the SnesLab Discord: https://discord.gg/dXzrk5bX&lt;br /&gt;
&lt;br /&gt;
== Code writing thoughts ==&lt;br /&gt;
&lt;br /&gt;
=== Code Labels ===&lt;br /&gt;
* code label refers to any beginning of a routine.&lt;br /&gt;
* they should be all lowercase and each word should be separated using a underscore. Example: example_routine&lt;br /&gt;
* consider not using more than two underscores to not make it difficulty to read. Not a good example: this_label_is_too_long&lt;br /&gt;
&lt;br /&gt;
== Conventions ==&lt;br /&gt;
&lt;br /&gt;
== Memory map and ROM structure ==&lt;br /&gt;
&lt;br /&gt;
== Cycle optimization ==&lt;br /&gt;
* Do not code thinking already on optimization. Get the routine working first.&lt;br /&gt;
Comments: Often an algorithm or routine takes several hours to get it working, it requires extensive thoughts and coding thinking already on possible optimizations will make the coding process way slower. It also increases the chances of getting premature bugs, because it makes harder to verify if the algorithm is correct.&lt;br /&gt;
&lt;br /&gt;
* Micro-optimizations are bad, consider only doing them if it&#039;s a critical routine of your program.&lt;br /&gt;
Comments: An optimization is considered &#039;micro-optimization&#039; when you start sacrificing the readability in exchange of 1-2 cycle optimization. An example is taking off the CLC because there 50 lines ago there was a BCS opcode that jumps to the of the routine or the previous ADC implies that the operation will never generate carry (fcr example, a sum that will never exceed #$FF).&lt;br /&gt;
&lt;br /&gt;
* Code inling should only be considered on critical situations.&lt;br /&gt;
Comments: Often coders prefer getting rid of the JSR/RTS and inling all of the code at the once, which sounds logigal if the routine is only called once. However the practice is not recommended, given that routines can end-up reused across other resources. Splitting an inline code into routines will also likely make it easier to edit because it will allow to isolate each routine to its own role. A good way to check if inling will be really benefit is evaluating the cycle cost of using JSR + RTS times the amount of inlined routines times the amount of time the code section is called.&lt;/div&gt;</summary>
		<author><name>Vitor Vilela</name></author>
	</entry>
	<entry>
		<id>https://sneslab.net/mw/index.php?title=Good_coding_practices&amp;diff=1604</id>
		<title>Good coding practices</title>
		<link rel="alternate" type="text/html" href="https://sneslab.net/mw/index.php?title=Good_coding_practices&amp;diff=1604"/>
		<updated>2020-12-11T03:50:03Z</updated>

		<summary type="html">&lt;p&gt;Vitor Vilela: Keeping a note that it aims Asar right now&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This document is an effort to create a coding standard and by consequence a global library that can be used on SNES homebrew and ROM hacking. The objective is creating a standard that lets coders maintain existing code with less difficulty, promote a clean and easy-to-understand code, standardize conventions and promote coding agility for faster results and less time thinking on how to code.&lt;br /&gt;
&lt;br /&gt;
Since there are some SNES assemblers available, our guideline will be focused on [[Asar]]. However some of the thoughts can be applied to other assemblers without problem.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Feel free to edit with your own thoughts&#039;&#039;&#039;, the idea is mixing everyone opinions until we get into a consensus. Further discussion can be made on the #homebrew channel of the SnesLab Discord: https://discord.gg/dXzrk5bX&lt;br /&gt;
&lt;br /&gt;
== Code writing thoughts ==&lt;br /&gt;
&lt;br /&gt;
== Conventions ==&lt;br /&gt;
&lt;br /&gt;
== Memory map and ROM structure ==&lt;br /&gt;
&lt;br /&gt;
== Cycle optimization ==&lt;br /&gt;
* Do not code thinking already on optimization. Get the routine working first.&lt;br /&gt;
Comments: Often an algorithm or routine takes several hours to get it working, it requires extensive thoughts and coding thinking already on possible optimizations will make the coding process way slower. It also increases the chances of getting premature bugs, because it makes harder to verify if the algorithm is correct.&lt;br /&gt;
&lt;br /&gt;
* Micro-optimizations are bad, consider only doing them if it&#039;s a critical routine of your program.&lt;br /&gt;
Comments: An optimization is considered &#039;micro-optimization&#039; when you start sacrificing the readability in exchange of 1-2 cycle optimization. An example is taking off the CLC because there 50 lines ago there was a BCS opcode that jumps to the of the routine or the previous ADC implies that the operation will never generate carry (fcr example, a sum that will never exceed #$FF).&lt;br /&gt;
&lt;br /&gt;
* Code inling should only be considered on critical situations.&lt;br /&gt;
Comments: Often coders prefer getting rid of the JSR/RTS and inling all of the code at the once, which sounds logigal if the routine is only called once. However the practice is not recommended, given that routines can end-up reused across other resources. Splitting an inline code into routines will also likely make it easier to edit because it will allow to isolate each routine to its own role. A good way to check if inling will be really benefit is evaluating the cycle cost of using JSR + RTS times the amount of inlined routines times the amount of time the code section is called.&lt;/div&gt;</summary>
		<author><name>Vitor Vilela</name></author>
	</entry>
	<entry>
		<id>https://sneslab.net/mw/index.php?title=Good_coding_practices&amp;diff=1603</id>
		<title>Good coding practices</title>
		<link rel="alternate" type="text/html" href="https://sneslab.net/mw/index.php?title=Good_coding_practices&amp;diff=1603"/>
		<updated>2020-12-11T03:48:51Z</updated>

		<summary type="html">&lt;p&gt;Vitor Vilela: /* Cycle optimization */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This document is an effort to create a coding standard and by consequence a global library that can be used on SNES homebrew and ROM hacking. The objective is creating a standard that lets coders maintain existing code with less difficulty, promote a clean and easy-to-understand code, standardize conventions and promote coding agility for faster results and less time thinking on how to code. &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Feel free to edit with your own thoughts&#039;&#039;&#039;, the idea is mixing everyone opinions until we get into a consensus. Further discussion can be made on the #homebrew channel of the SnesLab Discord: https://discord.gg/dXzrk5bX&lt;br /&gt;
&lt;br /&gt;
== Code writing thoughts ==&lt;br /&gt;
&lt;br /&gt;
== Conventions ==&lt;br /&gt;
&lt;br /&gt;
== Memory map and ROM structure ==&lt;br /&gt;
&lt;br /&gt;
== Cycle optimization ==&lt;br /&gt;
* Do not code thinking already on optimization. Get the routine working first.&lt;br /&gt;
Comments: Often an algorithm or routine takes several hours to get it working, it requires extensive thoughts and coding thinking already on possible optimizations will make the coding process way slower. It also increases the chances of getting premature bugs, because it makes harder to verify if the algorithm is correct.&lt;br /&gt;
&lt;br /&gt;
* Micro-optimizations are bad, consider only doing them if it&#039;s a critical routine of your program.&lt;br /&gt;
Comments: An optimization is considered &#039;micro-optimization&#039; when you start sacrificing the readability in exchange of 1-2 cycle optimization. An example is taking off the CLC because there 50 lines ago there was a BCS opcode that jumps to the of the routine or the previous ADC implies that the operation will never generate carry (fcr example, a sum that will never exceed #$FF).&lt;br /&gt;
&lt;br /&gt;
* Code inling should only be considered on critical situations.&lt;br /&gt;
Comments: Often coders prefer getting rid of the JSR/RTS and inling all of the code at the once, which sounds logigal if the routine is only called once. However the practice is not recommended, given that routines can end-up reused across other resources. Splitting an inline code into routines will also likely make it easier to edit because it will allow to isolate each routine to its own role. A good way to check if inling will be really benefit is evaluating the cycle cost of using JSR + RTS times the amount of inlined routines times the amount of time the code section is called.&lt;/div&gt;</summary>
		<author><name>Vitor Vilela</name></author>
	</entry>
	<entry>
		<id>https://sneslab.net/mw/index.php?title=Good_coding_practices&amp;diff=1602</id>
		<title>Good coding practices</title>
		<link rel="alternate" type="text/html" href="https://sneslab.net/mw/index.php?title=Good_coding_practices&amp;diff=1602"/>
		<updated>2020-12-11T03:48:11Z</updated>

		<summary type="html">&lt;p&gt;Vitor Vilela: /* Cycle optimization */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This document is an effort to create a coding standard and by consequence a global library that can be used on SNES homebrew and ROM hacking. The objective is creating a standard that lets coders maintain existing code with less difficulty, promote a clean and easy-to-understand code, standardize conventions and promote coding agility for faster results and less time thinking on how to code. &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Feel free to edit with your own thoughts&#039;&#039;&#039;, the idea is mixing everyone opinions until we get into a consensus. Further discussion can be made on the #homebrew channel of the SnesLab Discord: https://discord.gg/dXzrk5bX&lt;br /&gt;
&lt;br /&gt;
== Code writing thoughts ==&lt;br /&gt;
&lt;br /&gt;
== Conventions ==&lt;br /&gt;
&lt;br /&gt;
== Memory map and ROM structure ==&lt;br /&gt;
&lt;br /&gt;
== Cycle optimization ==&lt;br /&gt;
* Do not code thinking already on optimization. Get the routine working first.&lt;br /&gt;
Comments: Often an algorithm or routine takes several hours to get it working, it requires extensive thoughts and coding thinking already on possible optimizations will make the coding process way slower.&lt;br /&gt;
&lt;br /&gt;
* Micro-optimizations are bad, consider only doing them if it&#039;s a critical routine of your program.&lt;br /&gt;
Comments: An optimization is considered &#039;micro-optimization&#039; when you start sacrificing the readability in exchange of 1-2 cycle optimization. An example is taking off the CLC because there 50 lines ago there was a BCS opcode that jumps to the of the routine or the previous ADC implies that the operation will never generate carry (fcr example, a sum that will never exceed #$FF).&lt;br /&gt;
&lt;br /&gt;
* Code inling should only be considered on critical situations.&lt;br /&gt;
Comments: Often coders prefer getting rid of the JSR/RTS and inling all of the code at the once, which sounds logigal if the routine is only called once. However the practice is not recommended, given that routines can end-up reused across other resources. Splitting an inline code into routines will also likely make it easier to edit because it will allow to isolate each routine to its own role. A good way to check if inling will be really benefit is evaluating the cycle cost of using JSR + RTS times the amount of inlined routines times the amount of time the code section is called.&lt;/div&gt;</summary>
		<author><name>Vitor Vilela</name></author>
	</entry>
	<entry>
		<id>https://sneslab.net/mw/index.php?title=Good_coding_practices&amp;diff=1601</id>
		<title>Good coding practices</title>
		<link rel="alternate" type="text/html" href="https://sneslab.net/mw/index.php?title=Good_coding_practices&amp;diff=1601"/>
		<updated>2020-12-11T03:29:26Z</updated>

		<summary type="html">&lt;p&gt;Vitor Vilela: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This document is an effort to create a coding standard and by consequence a global library that can be used on SNES homebrew and ROM hacking. The objective is creating a standard that lets coders maintain existing code with less difficulty, promote a clean and easy-to-understand code, standardize conventions and promote coding agility for faster results and less time thinking on how to code. &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Feel free to edit with your own thoughts&#039;&#039;&#039;, the idea is mixing everyone opinions until we get into a consensus. Further discussion can be made on the #homebrew channel of the SnesLab Discord: https://discord.gg/dXzrk5bX&lt;br /&gt;
&lt;br /&gt;
== Code writing thoughts ==&lt;br /&gt;
&lt;br /&gt;
== Conventions ==&lt;br /&gt;
&lt;br /&gt;
== Memory map and ROM structure ==&lt;br /&gt;
&lt;br /&gt;
== Cycle optimization ==&lt;/div&gt;</summary>
		<author><name>Vitor Vilela</name></author>
	</entry>
	<entry>
		<id>https://sneslab.net/mw/index.php?title=Good_coding_practices&amp;diff=1600</id>
		<title>Good coding practices</title>
		<link rel="alternate" type="text/html" href="https://sneslab.net/mw/index.php?title=Good_coding_practices&amp;diff=1600"/>
		<updated>2020-12-11T03:26:30Z</updated>

		<summary type="html">&lt;p&gt;Vitor Vilela: Created page with &amp;quot;This document is an effort to create a coding standard and by consequence a global library that can be used on SNES homebrew and ROM hacking. The objective is creating a stand...&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This document is an effort to create a coding standard and by consequence a global library that can be used on SNES homebrew and ROM hacking. The objective is creating a standard that lets coders maintain existing code with less difficulty, promote a clean and easy-to-understand code, standardize conventions and promote coding agility for faster results and less time thinking on how to code. &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Feel free to edit with your own thoughts&#039;&#039;&#039;, the idea is mixing everyone opinions until we get into a consensus. Further discussion can be made on the #homebrew channel of the SnesLab Discord: https://discord.gg/dXzrk5bX&lt;/div&gt;</summary>
		<author><name>Vitor Vilela</name></author>
	</entry>
	<entry>
		<id>https://sneslab.net/mw/index.php?title=SA-1&amp;diff=1599</id>
		<title>SA-1</title>
		<link rel="alternate" type="text/html" href="https://sneslab.net/mw/index.php?title=SA-1&amp;diff=1599"/>
		<updated>2020-12-11T02:55:36Z</updated>

		<summary type="html">&lt;p&gt;Vitor Vilela: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&#039;&#039;&#039;Nintendo SA-1&#039;&#039;&#039; is an [[enhancement chip]] made by [http://en.wikipedia.org/wiki/Nintendo Nintendo], used in 33 SNES games. The RF5A123 chip is based on the [[65c816]] processor, the same one used by the main SNES CPU, the [[RF5A22]]. With identical architecture to the SNES one, the chip is ideal for games and ROM hacks that can reuse code from the main CPU, thus not having to learn an additional assembling language or architecture.&lt;br /&gt;
&lt;br /&gt;
When you are on the SA-1 context, the SA-1 CPU is often referred as &amp;quot;C-CPU&amp;quot; (&amp;quot;C&amp;quot; stands for co-processor) while the SNES CPU is often referred as &amp;quot;S-CPU&amp;quot; (&amp;quot;S&amp;quot; stands for SNES). There is no master or slave, because both processors can interrupt each other though IRQs, keeping in mind that initially SA-1 boots up in the sleeping state and must be initialized by the SNES CPU.&lt;br /&gt;
&lt;br /&gt;
{{TOClimit|4}}&lt;br /&gt;
&lt;br /&gt;
== Features ==&lt;br /&gt;
&lt;br /&gt;
The embedded co-processor has a &#039;&#039;&#039;10.74 MHz&#039;&#039;&#039; base clock speed, which is four times faster compared to the 2.68 MHz base clock speed from the S-CPU. In addition to that, it includes additional hardware circuits for data I/O, bitmap manipulation modes, arithmetic registers and high-speed internal memory.&lt;br /&gt;
&lt;br /&gt;
* 16-bit 65c816 processor clocked at 10.74 MHz.&lt;br /&gt;
* 2 kB internal work memory (I-RAM), clocked at 10.74 MHz.&lt;br /&gt;
* Multi-processor processing, with parallel operating mode and automatic memory sharing control.&lt;br /&gt;
* Large capacity memory, with a total capability of 8 MB ROM and 256 kB BW-RAM, both clocked at 5.37 MHz, with ROM having an effective 10.74 MHz speed because of the 16-bit data bus.&lt;br /&gt;
* High speed arithmetic multiplication, division and cumulative sum (multiply with add) hardware.&lt;br /&gt;
* Bitmap and Character Conversion functions for fast graphics manipulation.&lt;br /&gt;
* Custom DMA circuit for fast transfers between ROM, I-RAM and BW-RAM.&lt;br /&gt;
* Variable-Length Bit data processing for enhanced algorithms such as graphics and data compression.&lt;br /&gt;
* Super MMC memory mapping capabilities for BW-RAM and bank switching for multiple ROM image access and mirroring.&lt;br /&gt;
&lt;br /&gt;
== ROM Hacking ==&lt;br /&gt;
&lt;br /&gt;
[[SA-1 Root]] and [[SA-1 Pack]] are known patches used for enabling SA-1 on SNES games that didn&#039;t include the chip previously and had problems with slowdown, such as [[Super Mario World]], [[Gradius III]] and [[Contra III]].&lt;br /&gt;
&lt;br /&gt;
= Technical Information =&lt;br /&gt;
There is not much technical information available on how the SA-1 chip works. Most of the findings are recent and are based on both official documents from Nintendo and experiments on real SA-1 carts. This section is getting continuously updated with new information and findings though the time. The information available here is expected to be accurate. Information about undefined behavior or design details is considered scarce right now.&lt;br /&gt;
&lt;br /&gt;
== Hardware Registers ==&lt;br /&gt;
The SA-1 internal registers are assigned on range $2200-$23FF, on banks $00-$3F and $80-$BF. $2200 though $22FF are write-only registers while $2300 though $23FF are read-only registers.&lt;br /&gt;
&lt;br /&gt;
* Attempting to read a write-only register yields [[open bus]].&lt;br /&gt;
* Attempting to write a SA-1 write register on SNES side or vice-versa yields nothing, with the exception of hybrid write registers.&lt;br /&gt;
* Attempting to read a SA-1 read register on SNES side or vice-versa yields open bus.&lt;br /&gt;
&lt;br /&gt;
=== Register Summary ===&lt;br /&gt;
&lt;br /&gt;
==== Write Registers ====&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Address !! Length !! Code !! Access !! Description&lt;br /&gt;
|-&lt;br /&gt;
| $2200 || 1 byte || CCNT || SNES || SA-1 CPU CONTROL&lt;br /&gt;
|-&lt;br /&gt;
| $2201 || 1 byte || SIE || SNES || SUPER NES CPU INT ENABLE&lt;br /&gt;
|-&lt;br /&gt;
| $2202 || 1 byte || SIC || SNES || SUPER NES CPU INT CLEAR&lt;br /&gt;
|-&lt;br /&gt;
| $2203 || 2 bytes || CRV || SNES || SA-1 CPU RESET VECTOR&lt;br /&gt;
|-&lt;br /&gt;
| $2205 || 2 bytes || CNV || SNES || SA-1 CPU NMI VECTOR&lt;br /&gt;
|-&lt;br /&gt;
| $2207 || 2 bytes || CIV || SNES || SA-1 CPU IRQ VECTOR&lt;br /&gt;
|-&lt;br /&gt;
| $2209 || 1 byte || SCNT || SA-1 || SUPER NES CPU CONTROL&lt;br /&gt;
|-&lt;br /&gt;
| $220A || 1 byte || CIE || SA-1 || SA-1 CPU INT ENABLE&lt;br /&gt;
|-&lt;br /&gt;
| $220B || 1 byte || CIC || SA-1 || SA-1 CPU INT CLEAR&lt;br /&gt;
|-&lt;br /&gt;
| $220C || 2 bytes || SNV || SA-1 || SUPER NES CPU NMI VECTOR&lt;br /&gt;
|-&lt;br /&gt;
| $220E || 2 bytes || SIV || SA-1 || SUPER NES CPU IRQ VECTOR&lt;br /&gt;
|-&lt;br /&gt;
| $2210 || 1 byte || TMC || SA-1 || H/V TIMER CONTROL&lt;br /&gt;
|-&lt;br /&gt;
| $2211 || 1 byte || CTR || SA-1 || SA-1 CPU TIMER RESTART&lt;br /&gt;
|-&lt;br /&gt;
| $2212 || 2 bytes || HCNT || SA-1 || SET H-COUNT&lt;br /&gt;
|-&lt;br /&gt;
| $2214 || 2 bytes || VCNT || SA-1 || SET V-COUNT&lt;br /&gt;
|-&lt;br /&gt;
| $2220 || 1 byte || CXB || SNES || SET SUPER MMC BANK C&lt;br /&gt;
|-&lt;br /&gt;
| $2221 || 1 byte || DXB || SNES || SET SUPER MMC BANK D&lt;br /&gt;
|-&lt;br /&gt;
| $2222 || 1 byte || EXB || SNES || SET SUPER MMC BANK E&lt;br /&gt;
|-&lt;br /&gt;
| $2223 || 1 byte || FXB || SNES || SET SUPER MMC BANK F&lt;br /&gt;
|-&lt;br /&gt;
| $2224 || 1 byte || BMAPS || SNES || SUPER NES CPU BW-RAM ADDRESS MAPPING&lt;br /&gt;
|-&lt;br /&gt;
| $2225 || 1 byte || BMAP || SA-1 || SA-1 CPU BW-RAM ADDRESS MAPPING&lt;br /&gt;
|-&lt;br /&gt;
| $2226 || 1 byte || SBWE || SNES || SUPER NES CPU BW-RAM WRITE ENABLE&lt;br /&gt;
|-&lt;br /&gt;
| $2227 || 1 byte || CBWE || SA-1 || SA-1 CPU BW-RAM WRITE ENABLE&lt;br /&gt;
|-&lt;br /&gt;
| $2228 || 1 byte || BPWA || SNES || BW-RAM WRITE-PROTECTED AREA&lt;br /&gt;
|-&lt;br /&gt;
| $2229 || 1 byte || SIWP || SNES || SA-1 I-RAM WRITE PROTECTION&lt;br /&gt;
|-&lt;br /&gt;
| $222A || 1 byte || CIWP || SA-1 || SA-1 I-RAM WRITE PROTECTION&lt;br /&gt;
|-&lt;br /&gt;
| $2230 || 1 byte || DCNT || SA-1 || DMA CONTROL&lt;br /&gt;
|-&lt;br /&gt;
| $2231 || 1 byte || CDMA || Both || CHARACTER CONVERSION OMA PARAMETERS&lt;br /&gt;
|-&lt;br /&gt;
| $2232 || 3 bytes || SDA || Both || DMA SOURCE DEVICE START ADDRESS&lt;br /&gt;
|-&lt;br /&gt;
| $2235 || 3 bytes || DDA || Both || DMA DESTINATION START ADDRESS&lt;br /&gt;
|-&lt;br /&gt;
| $2238 || 2 bytes || DTC || SA-1 || DMA TERMINAL COUNTER&lt;br /&gt;
|-&lt;br /&gt;
| $223F || 1 byte || BBF || SA-1 || BW-RAM BIT MAP FORMAT&lt;br /&gt;
|-&lt;br /&gt;
| $2240 || 16 bytes || BRF || SA-1 || BIT MAP REGISTER FILE&lt;br /&gt;
|-&lt;br /&gt;
| $2250 || 1 byte || MCNT || SA-1 || ARITHMETIC CONTROL&lt;br /&gt;
|-&lt;br /&gt;
| $2251 || 2 bytes || MA || SA-1 || ARITHMETIC PARAMETERS: MULTIPLICAND/DIVIDEND&lt;br /&gt;
|-&lt;br /&gt;
| $2253 || 2 bytes || MB || SA-1 || ARITHMETIC PARAMETERS: MULTIPLIER/DIVISOR&lt;br /&gt;
|-&lt;br /&gt;
| $2258 || 1 byte || VBD || SA-1 || VARIABLE-LENGTH BIT PROCESSING&lt;br /&gt;
|-&lt;br /&gt;
| $2259 || 3 bytes || VDA || SA-1 || VARIABLE-LENGTH BIT GAME PAK ROM START ADDRESS&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Read Registers ====&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Address !! Length !! Code !! Access !! Description&lt;br /&gt;
|-&lt;br /&gt;
| $2300 || 1 bytes || SFR || SNES || SUPER NES CPU FLAG READ&lt;br /&gt;
|-&lt;br /&gt;
| $2301 || 1 bytes || CFR || SA-1 || SA-1 CPU FLAG READ&lt;br /&gt;
|-&lt;br /&gt;
| $2302 || 2 bytes || HCR || SA-1 || H-COUNT READ&lt;br /&gt;
|-&lt;br /&gt;
| $2304 || 2 bytes || VCR || SA-1 || V-COUNT READ&lt;br /&gt;
|-&lt;br /&gt;
| $2306 || 5 bytes || MR || SA-1 || ARITHMETIC RESULT [PRODUCT/QUOTIENT/ACCUMULATIVE SUM]&lt;br /&gt;
|-&lt;br /&gt;
| $230B || 1 bytes || OF || SA-1 || ARITHMETIC OVERFLOW FLAG&lt;br /&gt;
|-&lt;br /&gt;
| $230C || 2 bytes || VDP || SA-1 || VARIABLE-LENGTH DATA READ PORT&lt;br /&gt;
|-&lt;br /&gt;
| $230E || 1 byte || VC || SNES || VERSION CODE REGISTER (OPEN BUS)&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Register Details ===&lt;br /&gt;
&lt;br /&gt;
==== $2200 - SA-1 CPU CONTROL ====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== $2201 - SUPER NES CPU INT ENABLE ====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== $2202 - SUPER NES CPU INT CLEAR ====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== $2203 - SA-1 CPU RESET VECTOR ====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== $2205 - SA-1 CPU NMI VECTOR ====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== $2207 - SA-1 CPU IRQ VECTOR ====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== $2209 - SUPER NES CPU CONTROL ====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== $220A - SA-1 CPU INT ENABLE ====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== $220B - SA-1 CPU INT CLEAR ====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== $220C - SUPER NES CPU NMI VECTOR ====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== $220E - SUPER NES CPU IRQ VECTOR ====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== $2210 - H/V TIMER CONTROL ====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== $2211 - SA-1 CPU TIMER RESTART ====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== $2212 - SET H-COUNT ====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== $2214 - SET V-COUNT ====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== $2220-$2223 - SET SUPER MMC BANK C/D/E/F ====&lt;br /&gt;
{{32bit-reg|2220|2221|2222|2223&lt;br /&gt;
|CBM|0|0|0|0|CB2|CB1|CB0&lt;br /&gt;
|DBM|0|0|0|0|CB2|CB1|CB0&lt;br /&gt;
|EBM|0|0|0|0|CB2|CB1|CB0&lt;br /&gt;
|FBM|0|0|0|0|CB2|CB1|CB0}}&lt;br /&gt;
&lt;br /&gt;
CB2~CB0: Which megabyte of the ROM to map to $C0-$CF / $D0-$DF / $E0-$EF / $F0-$FF.&lt;br /&gt;
&lt;br /&gt;
CBM/DBM/EBM/FBM: If set, apply image projection to LoROM banks as well.&lt;br /&gt;
{|style=&amp;quot;width:auto&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Flag !! Bank Range&lt;br /&gt;
|-&lt;br /&gt;
| CBM || Apply to banks $00-$1F&lt;br /&gt;
|-&lt;br /&gt;
| DBM || Apply to banks $20-$3F&lt;br /&gt;
|-&lt;br /&gt;
| EBM || Apply to banks $80-$9F&lt;br /&gt;
|-&lt;br /&gt;
| FBM || Apply to banks $A0-$BF&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Registers are responsible for setting up the ROM bank mapping.&lt;br /&gt;
By default, the values { $00, $01, $02, $03 } are loaded on power up.&lt;br /&gt;
&lt;br /&gt;
Bits CBM/DBM/EBM/FBM determine if the mapping should apply to the LoROM banks as well, otherwise they will have the constant value of { $00, $01, $02, $03 } regardless of the ROM size. Given that, it&#039;s possible the entire 8 MB layout at once by storing values { $04, $05, $06, $07 } to the registers. Snes9x 1.53 and older always treated these flags as set, making the mapping always apply to the LoROM banks.&lt;br /&gt;
&lt;br /&gt;
{|style=&amp;quot;width:auto&amp;quot;&lt;br /&gt;
|+Common values&lt;br /&gt;
|-&lt;br /&gt;
! Register !! $2220 !! $2221 !! $2222 !! $2223 !! Comment&lt;br /&gt;
|-&lt;br /&gt;
| Value || $00 || $01 || $02 || $03 || Default values&lt;br /&gt;
|-&lt;br /&gt;
| Value || $04 || $05 || $06 || $07 || Maps the first 4 MB to banks $00-$3F and $80-$BF, with LoROM-like layout. The last 4 MB is mapped to $C0-$FF, with HiROM-like layout.&lt;br /&gt;
|-&lt;br /&gt;
| Value || $80 || $81 || $80 || $81 || Simulates the standard LoROM map with FastROM compatibility by mapping the first 2 MB to $00-$3F and $80-$BF.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The Super MMC register affects all memory maps, including SNES, SA-1, SA-1 DMA and SA-1 Variable Length Bit maps.&lt;br /&gt;
bsnes 0.7x does not apply the custom memory mapping to Variable Length Bit circuit.&lt;br /&gt;
&lt;br /&gt;
Hardware verification has shown that the unused bits has no effects to the chip pinout and therefore the maximum ROM size for the SA-1 without using a custom ROM controller outside the chip is 8 MB (megabytes).&lt;br /&gt;
&lt;br /&gt;
==== $2224 - SUPER NES CPU BW-RAM ADDRESS MAPPING ====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== $2225 - SA-1 CPU BW-RAM ADDRESS MAPPING ====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== $2226 - SUPER NES CPU BW-RAM WRITE ENABLE ====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== $2227 - SA-1 CPU BW-RAM WRITE ENABLE ====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== $2228 - BW-RAM WRITE-PROTECTED AREA ====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== $2229 - SA-1 I-RAM WRITE PROTECTION ====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== $222A - SA-1 I-RAM WRITE PROTECTION ====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== $2230 - DMA CONTROL ====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== $2231 - CHARACTER CONVERSION OMA PARAMETERS ====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== $2232 - DMA SOURCE DEVICE START ADDRESS ====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== $2235 - DMA DESTINATION START ADDRESS ====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== $2238 - DMA TERMINAL COUNTER ====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== $223F - BW-RAM BIT MAP FORMAT ====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== $2240 - BIT MAP REGISTER FILE ====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== $2250 - ARITHMETIC CONTROL ====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== $2251 - ARITHMETIC PARAMETERS: MULTIPLICAND/DIVIDEND ====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== $2253 - ARITHMETIC PARAMETERS: MULTIPLIER/DIVISOR ====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== $2258 - VARIABLE-LENGTH BIT PROCESSING ====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== $2259 - VARIABLE-LENGTH BIT GAME PAK ROM START ADDRESS ====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== $2300 - SUPER NES CPU FLAG READ ====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== $2301 - SA-1 CPU FLAG READ ====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== $2302 - H-COUNT READ ====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== $2304 - V-COUNT READ ====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== $2306 - ARITHMETIC RESULT [PRODUCT/QUOTIENT/ACCUMULATIVE SUM] ====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== $230B - ARITHMETIC OVERFLOW FLAG ====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== $230C - VARIABLE-LENGTH DATA READ PORT ====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== $230E - VERSION CODE REGISTER (OPEN BUS) ====&lt;br /&gt;
{{8bit-reg|230E|VC7|VC6|VC5|VC4|VC3|VC2|VC1|VC0}}&lt;br /&gt;
{| style=&amp;quot;width:auto&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Bits !! Meaning&lt;br /&gt;
|-&lt;br /&gt;
| VC0 ~ VC7 || SA-1 Device Version&lt;br /&gt;
|}&lt;br /&gt;
According the SNES Development Book II, this register was supposed to hold the SA-1 chip version code, however tests made on some real carts has shown that this register in particular is actually [[open bus]].&lt;br /&gt;
-----&lt;br /&gt;
&lt;br /&gt;
== Memory and Bus ==&lt;br /&gt;
&lt;br /&gt;
=== Memory Map ===&lt;br /&gt;
&lt;br /&gt;
==== SNES Side ====&lt;br /&gt;
&lt;br /&gt;
==== SA-1 Side ====&lt;br /&gt;
&lt;br /&gt;
==== Open Bus Behavior ====&lt;br /&gt;
&lt;br /&gt;
=== ROM ===&lt;br /&gt;
&lt;br /&gt;
=== I-RAM ===&lt;br /&gt;
&lt;br /&gt;
==== Write Protection ====&lt;br /&gt;
&lt;br /&gt;
=== BW-RAM ===&lt;br /&gt;
&lt;br /&gt;
==== Write Protection ====&lt;br /&gt;
&lt;br /&gt;
=== Virtual Bitmap Memory ===&lt;br /&gt;
&lt;br /&gt;
=== Super MMC ===&lt;br /&gt;
&lt;br /&gt;
=== Bus Conflicts ===&lt;br /&gt;
&lt;br /&gt;
== Direct Memory Access ==&lt;br /&gt;
&lt;br /&gt;
=== Character Conversion DMA ===&lt;br /&gt;
&lt;br /&gt;
=== Parallel DMA ===&lt;br /&gt;
&lt;br /&gt;
=== Interactions with SNES DMA ===&lt;br /&gt;
&lt;br /&gt;
=== Undefined Behavior ===&lt;br /&gt;
&lt;br /&gt;
== Variable Length Bit ==&lt;br /&gt;
&lt;br /&gt;
=== Fixed Mode ===&lt;br /&gt;
&lt;br /&gt;
=== Automatic Mode ===&lt;br /&gt;
&lt;br /&gt;
=== Mixed Mode ===&lt;br /&gt;
&lt;br /&gt;
== Arithmetic Operations ==&lt;br /&gt;
&lt;br /&gt;
=== Multiplication ===&lt;br /&gt;
&lt;br /&gt;
=== Division ===&lt;br /&gt;
&lt;br /&gt;
=== Cumulative Sum ===&lt;br /&gt;
&lt;br /&gt;
== Parallelism and I/O ==&lt;br /&gt;
&lt;br /&gt;
=== IRQ ===&lt;br /&gt;
&lt;br /&gt;
=== NMI ===&lt;br /&gt;
&lt;br /&gt;
=== FastROM Interactions ===&lt;br /&gt;
&lt;br /&gt;
[[Category:SNES Hardware]] [[Category:ASM]]&lt;/div&gt;</summary>
		<author><name>Vitor Vilela</name></author>
	</entry>
	<entry>
		<id>https://sneslab.net/mw/index.php?title=SA-1&amp;diff=1598</id>
		<title>SA-1</title>
		<link rel="alternate" type="text/html" href="https://sneslab.net/mw/index.php?title=SA-1&amp;diff=1598"/>
		<updated>2020-12-11T02:46:47Z</updated>

		<summary type="html">&lt;p&gt;Vitor Vilela: /* Hardware Registers */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&#039;&#039;&#039;Nintendo SA-1&#039;&#039;&#039; is an [[enhancement chip]] made by [http://en.wikipedia.org/wiki/Nintendo Nintendo], used in 33 SNES games. The RF5A123 chip is based on the [[65c816]] processor, the same one used by the main SNES CPU, the [[RF5A22]]. With identical architectures to the SNES one, the chip is ideal for games and ROM hacks that would like to use the code from the main CPU, thus not having to learn an additional assembling language.&lt;br /&gt;
&lt;br /&gt;
{{TOClimit|4}}&lt;br /&gt;
&lt;br /&gt;
== Features ==&lt;br /&gt;
&lt;br /&gt;
With the &#039;&#039;&#039;10.74 MHz&#039;&#039;&#039; base clock speed, which is four times faster compared to the 2.68 MHz base speed from the S-CPU. In addition to that, it includes with additional hardware circuits for data I/O, bitmap manipulation modes and additional arithmetic registers.&lt;br /&gt;
&lt;br /&gt;
* 16-bit 65c816 processor clocked at 10.74 MHz.&lt;br /&gt;
* 2 kB fast internal work memory (I-RAM), clocked at 10.74 MHz.&lt;br /&gt;
* Multi-processor processing, with parallel operating mode and memory sharing control.&lt;br /&gt;
* Large capacity memory, with a total capability of 8 MB of ROM and 256 kB of BW-RAM, both clocked at 5.37 MHz, with ROM having an effective 10.74 MHz speed due of its 16-bit data bus.&lt;br /&gt;
* High speed arithmetic hardware of multiplication, division and cumulative sum (multiply with add).&lt;br /&gt;
* Bitmap and Character Conversion functions for fast graphics manipulation.&lt;br /&gt;
* Custom DMA circuit for fast transfers between ROM, I-RAM and BW-RAM.&lt;br /&gt;
* Variable-Length Bit data processing for enhanced algorithms such as graphics and data compression.&lt;br /&gt;
* Super MMC memory mapping capabilities for BW-RAM and bank switching for multiple ROM image access and mirroring.&lt;br /&gt;
&lt;br /&gt;
== ROM Hacking ==&lt;br /&gt;
&lt;br /&gt;
[[SA-1 Root]] and [[SA-1 Pack]] are known patches used for enabling SA-1 on SNES games that didn&#039;t include the chip previously and had problems with slowdown, such as [[Super Mario World]] and [[Gradius III]].&lt;br /&gt;
&lt;br /&gt;
= Technical Information =&lt;br /&gt;
There is not much technical information available on how the SA-1 chip works. Most of the findings are recent and are based on both official documents from Nintendo and experiments on real SA-1 carts. This section is getting continuously updated with new information and findings though the time. The information available here is expected to be accurate. Information about undefined behavior or design details is considered scarce right now.&lt;br /&gt;
&lt;br /&gt;
== Hardware Registers ==&lt;br /&gt;
The SA-1 internal registers are assigned on range $2200-$23FF, on banks $00-$3F and $80-$BF. $2200 though $22FF are write-only registers while $2300 though $23FF are read-only registers.&lt;br /&gt;
&lt;br /&gt;
* Attempting to read a write-only register yields [[open bus]].&lt;br /&gt;
* Attempting to write a SA-1 write register on SNES side or vice-versa yields nothing, with the exception of hybrid write registers.&lt;br /&gt;
* Attempting to read a SA-1 read register on SNES side or vice-versa yields open bus.&lt;br /&gt;
&lt;br /&gt;
=== Register Summary ===&lt;br /&gt;
&lt;br /&gt;
==== Write Registers ====&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Address !! Length !! Code !! Access !! Description&lt;br /&gt;
|-&lt;br /&gt;
| $2200 || 1 byte || CCNT || SNES || SA-1 CPU CONTROL&lt;br /&gt;
|-&lt;br /&gt;
| $2201 || 1 byte || SIE || SNES || SUPER NES CPU INT ENABLE&lt;br /&gt;
|-&lt;br /&gt;
| $2202 || 1 byte || SIC || SNES || SUPER NES CPU INT CLEAR&lt;br /&gt;
|-&lt;br /&gt;
| $2203 || 2 bytes || CRV || SNES || SA-1 CPU RESET VECTOR&lt;br /&gt;
|-&lt;br /&gt;
| $2205 || 2 bytes || CNV || SNES || SA-1 CPU NMI VECTOR&lt;br /&gt;
|-&lt;br /&gt;
| $2207 || 2 bytes || CIV || SNES || SA-1 CPU IRQ VECTOR&lt;br /&gt;
|-&lt;br /&gt;
| $2209 || 1 byte || SCNT || SA-1 || SUPER NES CPU CONTROL&lt;br /&gt;
|-&lt;br /&gt;
| $220A || 1 byte || CIE || SA-1 || SA-1 CPU INT ENABLE&lt;br /&gt;
|-&lt;br /&gt;
| $220B || 1 byte || CIC || SA-1 || SA-1 CPU INT CLEAR&lt;br /&gt;
|-&lt;br /&gt;
| $220C || 2 bytes || SNV || SA-1 || SUPER NES CPU NMI VECTOR&lt;br /&gt;
|-&lt;br /&gt;
| $220E || 2 bytes || SIV || SA-1 || SUPER NES CPU IRQ VECTOR&lt;br /&gt;
|-&lt;br /&gt;
| $2210 || 1 byte || TMC || SA-1 || H/V TIMER CONTROL&lt;br /&gt;
|-&lt;br /&gt;
| $2211 || 1 byte || CTR || SA-1 || SA-1 CPU TIMER RESTART&lt;br /&gt;
|-&lt;br /&gt;
| $2212 || 2 bytes || HCNT || SA-1 || SET H-COUNT&lt;br /&gt;
|-&lt;br /&gt;
| $2214 || 2 bytes || VCNT || SA-1 || SET V-COUNT&lt;br /&gt;
|-&lt;br /&gt;
| $2220 || 1 byte || CXB || SNES || SET SUPER MMC BANK C&lt;br /&gt;
|-&lt;br /&gt;
| $2221 || 1 byte || DXB || SNES || SET SUPER MMC BANK D&lt;br /&gt;
|-&lt;br /&gt;
| $2222 || 1 byte || EXB || SNES || SET SUPER MMC BANK E&lt;br /&gt;
|-&lt;br /&gt;
| $2223 || 1 byte || FXB || SNES || SET SUPER MMC BANK F&lt;br /&gt;
|-&lt;br /&gt;
| $2224 || 1 byte || BMAPS || SNES || SUPER NES CPU BW-RAM ADDRESS MAPPING&lt;br /&gt;
|-&lt;br /&gt;
| $2225 || 1 byte || BMAP || SA-1 || SA-1 CPU BW-RAM ADDRESS MAPPING&lt;br /&gt;
|-&lt;br /&gt;
| $2226 || 1 byte || SBWE || SNES || SUPER NES CPU BW-RAM WRITE ENABLE&lt;br /&gt;
|-&lt;br /&gt;
| $2227 || 1 byte || CBWE || SA-1 || SA-1 CPU BW-RAM WRITE ENABLE&lt;br /&gt;
|-&lt;br /&gt;
| $2228 || 1 byte || BPWA || SNES || BW-RAM WRITE-PROTECTED AREA&lt;br /&gt;
|-&lt;br /&gt;
| $2229 || 1 byte || SIWP || SNES || SA-1 I-RAM WRITE PROTECTION&lt;br /&gt;
|-&lt;br /&gt;
| $222A || 1 byte || CIWP || SA-1 || SA-1 I-RAM WRITE PROTECTION&lt;br /&gt;
|-&lt;br /&gt;
| $2230 || 1 byte || DCNT || SA-1 || DMA CONTROL&lt;br /&gt;
|-&lt;br /&gt;
| $2231 || 1 byte || CDMA || Both || CHARACTER CONVERSION OMA PARAMETERS&lt;br /&gt;
|-&lt;br /&gt;
| $2232 || 3 bytes || SDA || Both || DMA SOURCE DEVICE START ADDRESS&lt;br /&gt;
|-&lt;br /&gt;
| $2235 || 3 bytes || DDA || Both || DMA DESTINATION START ADDRESS&lt;br /&gt;
|-&lt;br /&gt;
| $2238 || 2 bytes || DTC || SA-1 || DMA TERMINAL COUNTER&lt;br /&gt;
|-&lt;br /&gt;
| $223F || 1 byte || BBF || SA-1 || BW-RAM BIT MAP FORMAT&lt;br /&gt;
|-&lt;br /&gt;
| $2240 || 16 bytes || BRF || SA-1 || BIT MAP REGISTER FILE&lt;br /&gt;
|-&lt;br /&gt;
| $2250 || 1 byte || MCNT || SA-1 || ARITHMETIC CONTROL&lt;br /&gt;
|-&lt;br /&gt;
| $2251 || 2 bytes || MA || SA-1 || ARITHMETIC PARAMETERS: MULTIPLICAND/DIVIDEND&lt;br /&gt;
|-&lt;br /&gt;
| $2253 || 2 bytes || MB || SA-1 || ARITHMETIC PARAMETERS: MULTIPLIER/DIVISOR&lt;br /&gt;
|-&lt;br /&gt;
| $2258 || 1 byte || VBD || SA-1 || VARIABLE-LENGTH BIT PROCESSING&lt;br /&gt;
|-&lt;br /&gt;
| $2259 || 3 bytes || VDA || SA-1 || VARIABLE-LENGTH BIT GAME PAK ROM START ADDRESS&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Read Registers ====&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Address !! Length !! Code !! Access !! Description&lt;br /&gt;
|-&lt;br /&gt;
| $2300 || 1 bytes || SFR || SNES || SUPER NES CPU FLAG READ&lt;br /&gt;
|-&lt;br /&gt;
| $2301 || 1 bytes || CFR || SA-1 || SA-1 CPU FLAG READ&lt;br /&gt;
|-&lt;br /&gt;
| $2302 || 2 bytes || HCR || SA-1 || H-COUNT READ&lt;br /&gt;
|-&lt;br /&gt;
| $2304 || 2 bytes || VCR || SA-1 || V-COUNT READ&lt;br /&gt;
|-&lt;br /&gt;
| $2306 || 5 bytes || MR || SA-1 || ARITHMETIC RESULT [PRODUCT/QUOTIENT/ACCUMULATIVE SUM]&lt;br /&gt;
|-&lt;br /&gt;
| $230B || 1 bytes || OF || SA-1 || ARITHMETIC OVERFLOW FLAG&lt;br /&gt;
|-&lt;br /&gt;
| $230C || 2 bytes || VDP || SA-1 || VARIABLE-LENGTH DATA READ PORT&lt;br /&gt;
|-&lt;br /&gt;
| $230E || 1 byte || VC || SNES || VERSION CODE REGISTER (OPEN BUS)&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Register Details ===&lt;br /&gt;
&lt;br /&gt;
==== $2200 - SA-1 CPU CONTROL ====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== $2201 - SUPER NES CPU INT ENABLE ====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== $2202 - SUPER NES CPU INT CLEAR ====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== $2203 - SA-1 CPU RESET VECTOR ====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== $2205 - SA-1 CPU NMI VECTOR ====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== $2207 - SA-1 CPU IRQ VECTOR ====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== $2209 - SUPER NES CPU CONTROL ====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== $220A - SA-1 CPU INT ENABLE ====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== $220B - SA-1 CPU INT CLEAR ====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== $220C - SUPER NES CPU NMI VECTOR ====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== $220E - SUPER NES CPU IRQ VECTOR ====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== $2210 - H/V TIMER CONTROL ====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== $2211 - SA-1 CPU TIMER RESTART ====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== $2212 - SET H-COUNT ====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== $2214 - SET V-COUNT ====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== $2220-$2223 - SET SUPER MMC BANK C/D/E/F ====&lt;br /&gt;
{{32bit-reg|2220|2221|2222|2223&lt;br /&gt;
|CBM|0|0|0|0|CB2|CB1|CB0&lt;br /&gt;
|DBM|0|0|0|0|CB2|CB1|CB0&lt;br /&gt;
|EBM|0|0|0|0|CB2|CB1|CB0&lt;br /&gt;
|FBM|0|0|0|0|CB2|CB1|CB0}}&lt;br /&gt;
&lt;br /&gt;
CB2~CB0: Which megabyte of the ROM to map to $C0-$CF / $D0-$DF / $E0-$EF / $F0-$FF.&lt;br /&gt;
&lt;br /&gt;
CBM/DBM/EBM/FBM: If set, apply image projection to LoROM banks as well.&lt;br /&gt;
{|style=&amp;quot;width:auto&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Flag !! Bank Range&lt;br /&gt;
|-&lt;br /&gt;
| CBM || Apply to banks $00-$1F&lt;br /&gt;
|-&lt;br /&gt;
| DBM || Apply to banks $20-$3F&lt;br /&gt;
|-&lt;br /&gt;
| EBM || Apply to banks $80-$9F&lt;br /&gt;
|-&lt;br /&gt;
| FBM || Apply to banks $A0-$BF&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Registers are responsible for setting up the ROM bank mapping.&lt;br /&gt;
By default, the values { $00, $01, $02, $03 } are loaded on power up.&lt;br /&gt;
&lt;br /&gt;
Bits CBM/DBM/EBM/FBM determine if the mapping should apply to the LoROM banks as well, otherwise they will have the constant value of { $00, $01, $02, $03 } regardless of the ROM size. Given that, it&#039;s possible the entire 8 MB layout at once by storing values { $04, $05, $06, $07 } to the registers. Snes9x 1.53 and older always treated these flags as set, making the mapping always apply to the LoROM banks.&lt;br /&gt;
&lt;br /&gt;
{|style=&amp;quot;width:auto&amp;quot;&lt;br /&gt;
|+Common values&lt;br /&gt;
|-&lt;br /&gt;
! Register !! $2220 !! $2221 !! $2222 !! $2223 !! Comment&lt;br /&gt;
|-&lt;br /&gt;
| Value || $00 || $01 || $02 || $03 || Default values&lt;br /&gt;
|-&lt;br /&gt;
| Value || $04 || $05 || $06 || $07 || Maps the first 4 MB to banks $00-$3F and $80-$BF, with LoROM-like layout. The last 4 MB is mapped to $C0-$FF, with HiROM-like layout.&lt;br /&gt;
|-&lt;br /&gt;
| Value || $80 || $81 || $80 || $81 || Simulates the standard LoROM map with FastROM compatibility by mapping the first 2 MB to $00-$3F and $80-$BF.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The Super MMC register affects all memory maps, including SNES, SA-1, SA-1 DMA and SA-1 Variable Length Bit maps.&lt;br /&gt;
bsnes 0.7x does not apply the custom memory mapping to Variable Length Bit circuit.&lt;br /&gt;
&lt;br /&gt;
Hardware verification has shown that the unused bits has no effects to the chip pinout and therefore the maximum ROM size for the SA-1 without using a custom ROM controller outside the chip is 8 MB (megabytes).&lt;br /&gt;
&lt;br /&gt;
==== $2224 - SUPER NES CPU BW-RAM ADDRESS MAPPING ====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== $2225 - SA-1 CPU BW-RAM ADDRESS MAPPING ====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== $2226 - SUPER NES CPU BW-RAM WRITE ENABLE ====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== $2227 - SA-1 CPU BW-RAM WRITE ENABLE ====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== $2228 - BW-RAM WRITE-PROTECTED AREA ====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== $2229 - SA-1 I-RAM WRITE PROTECTION ====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== $222A - SA-1 I-RAM WRITE PROTECTION ====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== $2230 - DMA CONTROL ====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== $2231 - CHARACTER CONVERSION OMA PARAMETERS ====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== $2232 - DMA SOURCE DEVICE START ADDRESS ====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== $2235 - DMA DESTINATION START ADDRESS ====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== $2238 - DMA TERMINAL COUNTER ====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== $223F - BW-RAM BIT MAP FORMAT ====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== $2240 - BIT MAP REGISTER FILE ====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== $2250 - ARITHMETIC CONTROL ====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== $2251 - ARITHMETIC PARAMETERS: MULTIPLICAND/DIVIDEND ====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== $2253 - ARITHMETIC PARAMETERS: MULTIPLIER/DIVISOR ====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== $2258 - VARIABLE-LENGTH BIT PROCESSING ====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== $2259 - VARIABLE-LENGTH BIT GAME PAK ROM START ADDRESS ====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== $2300 - SUPER NES CPU FLAG READ ====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== $2301 - SA-1 CPU FLAG READ ====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== $2302 - H-COUNT READ ====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== $2304 - V-COUNT READ ====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== $2306 - ARITHMETIC RESULT [PRODUCT/QUOTIENT/ACCUMULATIVE SUM] ====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== $230B - ARITHMETIC OVERFLOW FLAG ====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== $230C - VARIABLE-LENGTH DATA READ PORT ====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== $230E - VERSION CODE REGISTER (OPEN BUS) ====&lt;br /&gt;
{{8bit-reg|230E|VC7|VC6|VC5|VC4|VC3|VC2|VC1|VC0}}&lt;br /&gt;
{| style=&amp;quot;width:auto&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Bits !! Meaning&lt;br /&gt;
|-&lt;br /&gt;
| VC0 ~ VC7 || SA-1 Device Version&lt;br /&gt;
|}&lt;br /&gt;
According the SNES Development Book II, this register was supposed to hold the SA-1 chip version code, however tests made on some real carts has shown that this register in particular is actually [[open bus]].&lt;br /&gt;
-----&lt;br /&gt;
&lt;br /&gt;
== Memory and Bus ==&lt;br /&gt;
&lt;br /&gt;
=== Memory Map ===&lt;br /&gt;
&lt;br /&gt;
==== SNES Side ====&lt;br /&gt;
&lt;br /&gt;
==== SA-1 Side ====&lt;br /&gt;
&lt;br /&gt;
==== Open Bus Behavior ====&lt;br /&gt;
&lt;br /&gt;
=== ROM ===&lt;br /&gt;
&lt;br /&gt;
=== I-RAM ===&lt;br /&gt;
&lt;br /&gt;
==== Write Protection ====&lt;br /&gt;
&lt;br /&gt;
=== BW-RAM ===&lt;br /&gt;
&lt;br /&gt;
==== Write Protection ====&lt;br /&gt;
&lt;br /&gt;
=== Virtual Bitmap Memory ===&lt;br /&gt;
&lt;br /&gt;
=== Super MMC ===&lt;br /&gt;
&lt;br /&gt;
=== Bus Conflicts ===&lt;br /&gt;
&lt;br /&gt;
== Direct Memory Access ==&lt;br /&gt;
&lt;br /&gt;
=== Character Conversion DMA ===&lt;br /&gt;
&lt;br /&gt;
=== Parallel DMA ===&lt;br /&gt;
&lt;br /&gt;
=== Interactions with SNES DMA ===&lt;br /&gt;
&lt;br /&gt;
=== Undefined Behavior ===&lt;br /&gt;
&lt;br /&gt;
== Variable Length Bit ==&lt;br /&gt;
&lt;br /&gt;
=== Fixed Mode ===&lt;br /&gt;
&lt;br /&gt;
=== Automatic Mode ===&lt;br /&gt;
&lt;br /&gt;
=== Mixed Mode ===&lt;br /&gt;
&lt;br /&gt;
== Arithmetic Operations ==&lt;br /&gt;
&lt;br /&gt;
=== Multiplication ===&lt;br /&gt;
&lt;br /&gt;
=== Division ===&lt;br /&gt;
&lt;br /&gt;
=== Cumulative Sum ===&lt;br /&gt;
&lt;br /&gt;
== Parallelism and I/O ==&lt;br /&gt;
&lt;br /&gt;
=== IRQ ===&lt;br /&gt;
&lt;br /&gt;
=== NMI ===&lt;br /&gt;
&lt;br /&gt;
=== FastROM Interactions ===&lt;br /&gt;
&lt;br /&gt;
[[Category:SNES Hardware]] [[Category:ASM]]&lt;/div&gt;</summary>
		<author><name>Vitor Vilela</name></author>
	</entry>
	<entry>
		<id>https://sneslab.net/mw/index.php?title=SA-1&amp;diff=1597</id>
		<title>SA-1</title>
		<link rel="alternate" type="text/html" href="https://sneslab.net/mw/index.php?title=SA-1&amp;diff=1597"/>
		<updated>2020-12-11T02:46:24Z</updated>

		<summary type="html">&lt;p&gt;Vitor Vilela: /* Hardware Registers */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&#039;&#039;&#039;Nintendo SA-1&#039;&#039;&#039; is an [[enhancement chip]] made by [http://en.wikipedia.org/wiki/Nintendo Nintendo], used in 33 SNES games. The RF5A123 chip is based on the [[65c816]] processor, the same one used by the main SNES CPU, the [[RF5A22]]. With identical architectures to the SNES one, the chip is ideal for games and ROM hacks that would like to use the code from the main CPU, thus not having to learn an additional assembling language.&lt;br /&gt;
&lt;br /&gt;
{{TOClimit|4}}&lt;br /&gt;
&lt;br /&gt;
== Features ==&lt;br /&gt;
&lt;br /&gt;
With the &#039;&#039;&#039;10.74 MHz&#039;&#039;&#039; base clock speed, which is four times faster compared to the 2.68 MHz base speed from the S-CPU. In addition to that, it includes with additional hardware circuits for data I/O, bitmap manipulation modes and additional arithmetic registers.&lt;br /&gt;
&lt;br /&gt;
* 16-bit 65c816 processor clocked at 10.74 MHz.&lt;br /&gt;
* 2 kB fast internal work memory (I-RAM), clocked at 10.74 MHz.&lt;br /&gt;
* Multi-processor processing, with parallel operating mode and memory sharing control.&lt;br /&gt;
* Large capacity memory, with a total capability of 8 MB of ROM and 256 kB of BW-RAM, both clocked at 5.37 MHz, with ROM having an effective 10.74 MHz speed due of its 16-bit data bus.&lt;br /&gt;
* High speed arithmetic hardware of multiplication, division and cumulative sum (multiply with add).&lt;br /&gt;
* Bitmap and Character Conversion functions for fast graphics manipulation.&lt;br /&gt;
* Custom DMA circuit for fast transfers between ROM, I-RAM and BW-RAM.&lt;br /&gt;
* Variable-Length Bit data processing for enhanced algorithms such as graphics and data compression.&lt;br /&gt;
* Super MMC memory mapping capabilities for BW-RAM and bank switching for multiple ROM image access and mirroring.&lt;br /&gt;
&lt;br /&gt;
== ROM Hacking ==&lt;br /&gt;
&lt;br /&gt;
[[SA-1 Root]] and [[SA-1 Pack]] are known patches used for enabling SA-1 on SNES games that didn&#039;t include the chip previously and had problems with slowdown, such as [[Super Mario World]] and [[Gradius III]].&lt;br /&gt;
&lt;br /&gt;
= Technical Information =&lt;br /&gt;
There is not much technical information available on how the SA-1 chip works. Most of the findings are recent and are based on both official documents from Nintendo and experiments on real SA-1 carts. This section is getting continuously updated with new information and findings though the time. The information available here is expected to be accurate. Information about undefined behavior or design details is considered scarce right now.&lt;br /&gt;
&lt;br /&gt;
== Hardware Registers ==&lt;br /&gt;
The SA-1 internal registers are assigned on range $2200-$23FF, on banks $00-$3F and $80-$BF. $2200 though $22FF are write-only registers while $2300 though $23FF are read-only registers.&lt;br /&gt;
&lt;br /&gt;
- Attempting to read a write-only register yields [[open bus]].&lt;br /&gt;
- Attempting to write a SA-1 write register on SNES side or vice-versa yields nothing, with the exception of hybrid write registers.&lt;br /&gt;
- Attempting to read a SA-1 read register on SNES side or vice-versa yields open bus.&lt;br /&gt;
&lt;br /&gt;
=== Register Summary ===&lt;br /&gt;
&lt;br /&gt;
==== Write Registers ====&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Address !! Length !! Code !! Access !! Description&lt;br /&gt;
|-&lt;br /&gt;
| $2200 || 1 byte || CCNT || SNES || SA-1 CPU CONTROL&lt;br /&gt;
|-&lt;br /&gt;
| $2201 || 1 byte || SIE || SNES || SUPER NES CPU INT ENABLE&lt;br /&gt;
|-&lt;br /&gt;
| $2202 || 1 byte || SIC || SNES || SUPER NES CPU INT CLEAR&lt;br /&gt;
|-&lt;br /&gt;
| $2203 || 2 bytes || CRV || SNES || SA-1 CPU RESET VECTOR&lt;br /&gt;
|-&lt;br /&gt;
| $2205 || 2 bytes || CNV || SNES || SA-1 CPU NMI VECTOR&lt;br /&gt;
|-&lt;br /&gt;
| $2207 || 2 bytes || CIV || SNES || SA-1 CPU IRQ VECTOR&lt;br /&gt;
|-&lt;br /&gt;
| $2209 || 1 byte || SCNT || SA-1 || SUPER NES CPU CONTROL&lt;br /&gt;
|-&lt;br /&gt;
| $220A || 1 byte || CIE || SA-1 || SA-1 CPU INT ENABLE&lt;br /&gt;
|-&lt;br /&gt;
| $220B || 1 byte || CIC || SA-1 || SA-1 CPU INT CLEAR&lt;br /&gt;
|-&lt;br /&gt;
| $220C || 2 bytes || SNV || SA-1 || SUPER NES CPU NMI VECTOR&lt;br /&gt;
|-&lt;br /&gt;
| $220E || 2 bytes || SIV || SA-1 || SUPER NES CPU IRQ VECTOR&lt;br /&gt;
|-&lt;br /&gt;
| $2210 || 1 byte || TMC || SA-1 || H/V TIMER CONTROL&lt;br /&gt;
|-&lt;br /&gt;
| $2211 || 1 byte || CTR || SA-1 || SA-1 CPU TIMER RESTART&lt;br /&gt;
|-&lt;br /&gt;
| $2212 || 2 bytes || HCNT || SA-1 || SET H-COUNT&lt;br /&gt;
|-&lt;br /&gt;
| $2214 || 2 bytes || VCNT || SA-1 || SET V-COUNT&lt;br /&gt;
|-&lt;br /&gt;
| $2220 || 1 byte || CXB || SNES || SET SUPER MMC BANK C&lt;br /&gt;
|-&lt;br /&gt;
| $2221 || 1 byte || DXB || SNES || SET SUPER MMC BANK D&lt;br /&gt;
|-&lt;br /&gt;
| $2222 || 1 byte || EXB || SNES || SET SUPER MMC BANK E&lt;br /&gt;
|-&lt;br /&gt;
| $2223 || 1 byte || FXB || SNES || SET SUPER MMC BANK F&lt;br /&gt;
|-&lt;br /&gt;
| $2224 || 1 byte || BMAPS || SNES || SUPER NES CPU BW-RAM ADDRESS MAPPING&lt;br /&gt;
|-&lt;br /&gt;
| $2225 || 1 byte || BMAP || SA-1 || SA-1 CPU BW-RAM ADDRESS MAPPING&lt;br /&gt;
|-&lt;br /&gt;
| $2226 || 1 byte || SBWE || SNES || SUPER NES CPU BW-RAM WRITE ENABLE&lt;br /&gt;
|-&lt;br /&gt;
| $2227 || 1 byte || CBWE || SA-1 || SA-1 CPU BW-RAM WRITE ENABLE&lt;br /&gt;
|-&lt;br /&gt;
| $2228 || 1 byte || BPWA || SNES || BW-RAM WRITE-PROTECTED AREA&lt;br /&gt;
|-&lt;br /&gt;
| $2229 || 1 byte || SIWP || SNES || SA-1 I-RAM WRITE PROTECTION&lt;br /&gt;
|-&lt;br /&gt;
| $222A || 1 byte || CIWP || SA-1 || SA-1 I-RAM WRITE PROTECTION&lt;br /&gt;
|-&lt;br /&gt;
| $2230 || 1 byte || DCNT || SA-1 || DMA CONTROL&lt;br /&gt;
|-&lt;br /&gt;
| $2231 || 1 byte || CDMA || Both || CHARACTER CONVERSION OMA PARAMETERS&lt;br /&gt;
|-&lt;br /&gt;
| $2232 || 3 bytes || SDA || Both || DMA SOURCE DEVICE START ADDRESS&lt;br /&gt;
|-&lt;br /&gt;
| $2235 || 3 bytes || DDA || Both || DMA DESTINATION START ADDRESS&lt;br /&gt;
|-&lt;br /&gt;
| $2238 || 2 bytes || DTC || SA-1 || DMA TERMINAL COUNTER&lt;br /&gt;
|-&lt;br /&gt;
| $223F || 1 byte || BBF || SA-1 || BW-RAM BIT MAP FORMAT&lt;br /&gt;
|-&lt;br /&gt;
| $2240 || 16 bytes || BRF || SA-1 || BIT MAP REGISTER FILE&lt;br /&gt;
|-&lt;br /&gt;
| $2250 || 1 byte || MCNT || SA-1 || ARITHMETIC CONTROL&lt;br /&gt;
|-&lt;br /&gt;
| $2251 || 2 bytes || MA || SA-1 || ARITHMETIC PARAMETERS: MULTIPLICAND/DIVIDEND&lt;br /&gt;
|-&lt;br /&gt;
| $2253 || 2 bytes || MB || SA-1 || ARITHMETIC PARAMETERS: MULTIPLIER/DIVISOR&lt;br /&gt;
|-&lt;br /&gt;
| $2258 || 1 byte || VBD || SA-1 || VARIABLE-LENGTH BIT PROCESSING&lt;br /&gt;
|-&lt;br /&gt;
| $2259 || 3 bytes || VDA || SA-1 || VARIABLE-LENGTH BIT GAME PAK ROM START ADDRESS&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Read Registers ====&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Address !! Length !! Code !! Access !! Description&lt;br /&gt;
|-&lt;br /&gt;
| $2300 || 1 bytes || SFR || SNES || SUPER NES CPU FLAG READ&lt;br /&gt;
|-&lt;br /&gt;
| $2301 || 1 bytes || CFR || SA-1 || SA-1 CPU FLAG READ&lt;br /&gt;
|-&lt;br /&gt;
| $2302 || 2 bytes || HCR || SA-1 || H-COUNT READ&lt;br /&gt;
|-&lt;br /&gt;
| $2304 || 2 bytes || VCR || SA-1 || V-COUNT READ&lt;br /&gt;
|-&lt;br /&gt;
| $2306 || 5 bytes || MR || SA-1 || ARITHMETIC RESULT [PRODUCT/QUOTIENT/ACCUMULATIVE SUM]&lt;br /&gt;
|-&lt;br /&gt;
| $230B || 1 bytes || OF || SA-1 || ARITHMETIC OVERFLOW FLAG&lt;br /&gt;
|-&lt;br /&gt;
| $230C || 2 bytes || VDP || SA-1 || VARIABLE-LENGTH DATA READ PORT&lt;br /&gt;
|-&lt;br /&gt;
| $230E || 1 byte || VC || SNES || VERSION CODE REGISTER (OPEN BUS)&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Register Details ===&lt;br /&gt;
&lt;br /&gt;
==== $2200 - SA-1 CPU CONTROL ====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== $2201 - SUPER NES CPU INT ENABLE ====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== $2202 - SUPER NES CPU INT CLEAR ====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== $2203 - SA-1 CPU RESET VECTOR ====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== $2205 - SA-1 CPU NMI VECTOR ====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== $2207 - SA-1 CPU IRQ VECTOR ====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== $2209 - SUPER NES CPU CONTROL ====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== $220A - SA-1 CPU INT ENABLE ====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== $220B - SA-1 CPU INT CLEAR ====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== $220C - SUPER NES CPU NMI VECTOR ====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== $220E - SUPER NES CPU IRQ VECTOR ====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== $2210 - H/V TIMER CONTROL ====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== $2211 - SA-1 CPU TIMER RESTART ====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== $2212 - SET H-COUNT ====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== $2214 - SET V-COUNT ====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== $2220-$2223 - SET SUPER MMC BANK C/D/E/F ====&lt;br /&gt;
{{32bit-reg|2220|2221|2222|2223&lt;br /&gt;
|CBM|0|0|0|0|CB2|CB1|CB0&lt;br /&gt;
|DBM|0|0|0|0|CB2|CB1|CB0&lt;br /&gt;
|EBM|0|0|0|0|CB2|CB1|CB0&lt;br /&gt;
|FBM|0|0|0|0|CB2|CB1|CB0}}&lt;br /&gt;
&lt;br /&gt;
CB2~CB0: Which megabyte of the ROM to map to $C0-$CF / $D0-$DF / $E0-$EF / $F0-$FF.&lt;br /&gt;
&lt;br /&gt;
CBM/DBM/EBM/FBM: If set, apply image projection to LoROM banks as well.&lt;br /&gt;
{|style=&amp;quot;width:auto&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Flag !! Bank Range&lt;br /&gt;
|-&lt;br /&gt;
| CBM || Apply to banks $00-$1F&lt;br /&gt;
|-&lt;br /&gt;
| DBM || Apply to banks $20-$3F&lt;br /&gt;
|-&lt;br /&gt;
| EBM || Apply to banks $80-$9F&lt;br /&gt;
|-&lt;br /&gt;
| FBM || Apply to banks $A0-$BF&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Registers are responsible for setting up the ROM bank mapping.&lt;br /&gt;
By default, the values { $00, $01, $02, $03 } are loaded on power up.&lt;br /&gt;
&lt;br /&gt;
Bits CBM/DBM/EBM/FBM determine if the mapping should apply to the LoROM banks as well, otherwise they will have the constant value of { $00, $01, $02, $03 } regardless of the ROM size. Given that, it&#039;s possible the entire 8 MB layout at once by storing values { $04, $05, $06, $07 } to the registers. Snes9x 1.53 and older always treated these flags as set, making the mapping always apply to the LoROM banks.&lt;br /&gt;
&lt;br /&gt;
{|style=&amp;quot;width:auto&amp;quot;&lt;br /&gt;
|+Common values&lt;br /&gt;
|-&lt;br /&gt;
! Register !! $2220 !! $2221 !! $2222 !! $2223 !! Comment&lt;br /&gt;
|-&lt;br /&gt;
| Value || $00 || $01 || $02 || $03 || Default values&lt;br /&gt;
|-&lt;br /&gt;
| Value || $04 || $05 || $06 || $07 || Maps the first 4 MB to banks $00-$3F and $80-$BF, with LoROM-like layout. The last 4 MB is mapped to $C0-$FF, with HiROM-like layout.&lt;br /&gt;
|-&lt;br /&gt;
| Value || $80 || $81 || $80 || $81 || Simulates the standard LoROM map with FastROM compatibility by mapping the first 2 MB to $00-$3F and $80-$BF.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The Super MMC register affects all memory maps, including SNES, SA-1, SA-1 DMA and SA-1 Variable Length Bit maps.&lt;br /&gt;
bsnes 0.7x does not apply the custom memory mapping to Variable Length Bit circuit.&lt;br /&gt;
&lt;br /&gt;
Hardware verification has shown that the unused bits has no effects to the chip pinout and therefore the maximum ROM size for the SA-1 without using a custom ROM controller outside the chip is 8 MB (megabytes).&lt;br /&gt;
&lt;br /&gt;
==== $2224 - SUPER NES CPU BW-RAM ADDRESS MAPPING ====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== $2225 - SA-1 CPU BW-RAM ADDRESS MAPPING ====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== $2226 - SUPER NES CPU BW-RAM WRITE ENABLE ====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== $2227 - SA-1 CPU BW-RAM WRITE ENABLE ====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== $2228 - BW-RAM WRITE-PROTECTED AREA ====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== $2229 - SA-1 I-RAM WRITE PROTECTION ====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== $222A - SA-1 I-RAM WRITE PROTECTION ====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== $2230 - DMA CONTROL ====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== $2231 - CHARACTER CONVERSION OMA PARAMETERS ====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== $2232 - DMA SOURCE DEVICE START ADDRESS ====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== $2235 - DMA DESTINATION START ADDRESS ====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== $2238 - DMA TERMINAL COUNTER ====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== $223F - BW-RAM BIT MAP FORMAT ====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== $2240 - BIT MAP REGISTER FILE ====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== $2250 - ARITHMETIC CONTROL ====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== $2251 - ARITHMETIC PARAMETERS: MULTIPLICAND/DIVIDEND ====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== $2253 - ARITHMETIC PARAMETERS: MULTIPLIER/DIVISOR ====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== $2258 - VARIABLE-LENGTH BIT PROCESSING ====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== $2259 - VARIABLE-LENGTH BIT GAME PAK ROM START ADDRESS ====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== $2300 - SUPER NES CPU FLAG READ ====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== $2301 - SA-1 CPU FLAG READ ====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== $2302 - H-COUNT READ ====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== $2304 - V-COUNT READ ====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== $2306 - ARITHMETIC RESULT [PRODUCT/QUOTIENT/ACCUMULATIVE SUM] ====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== $230B - ARITHMETIC OVERFLOW FLAG ====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== $230C - VARIABLE-LENGTH DATA READ PORT ====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== $230E - VERSION CODE REGISTER (OPEN BUS) ====&lt;br /&gt;
{{8bit-reg|230E|VC7|VC6|VC5|VC4|VC3|VC2|VC1|VC0}}&lt;br /&gt;
{| style=&amp;quot;width:auto&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Bits !! Meaning&lt;br /&gt;
|-&lt;br /&gt;
| VC0 ~ VC7 || SA-1 Device Version&lt;br /&gt;
|}&lt;br /&gt;
According the SNES Development Book II, this register was supposed to hold the SA-1 chip version code, however tests made on some real carts has shown that this register in particular is actually [[open bus]].&lt;br /&gt;
-----&lt;br /&gt;
&lt;br /&gt;
== Memory and Bus ==&lt;br /&gt;
&lt;br /&gt;
=== Memory Map ===&lt;br /&gt;
&lt;br /&gt;
==== SNES Side ====&lt;br /&gt;
&lt;br /&gt;
==== SA-1 Side ====&lt;br /&gt;
&lt;br /&gt;
==== Open Bus Behavior ====&lt;br /&gt;
&lt;br /&gt;
=== ROM ===&lt;br /&gt;
&lt;br /&gt;
=== I-RAM ===&lt;br /&gt;
&lt;br /&gt;
==== Write Protection ====&lt;br /&gt;
&lt;br /&gt;
=== BW-RAM ===&lt;br /&gt;
&lt;br /&gt;
==== Write Protection ====&lt;br /&gt;
&lt;br /&gt;
=== Virtual Bitmap Memory ===&lt;br /&gt;
&lt;br /&gt;
=== Super MMC ===&lt;br /&gt;
&lt;br /&gt;
=== Bus Conflicts ===&lt;br /&gt;
&lt;br /&gt;
== Direct Memory Access ==&lt;br /&gt;
&lt;br /&gt;
=== Character Conversion DMA ===&lt;br /&gt;
&lt;br /&gt;
=== Parallel DMA ===&lt;br /&gt;
&lt;br /&gt;
=== Interactions with SNES DMA ===&lt;br /&gt;
&lt;br /&gt;
=== Undefined Behavior ===&lt;br /&gt;
&lt;br /&gt;
== Variable Length Bit ==&lt;br /&gt;
&lt;br /&gt;
=== Fixed Mode ===&lt;br /&gt;
&lt;br /&gt;
=== Automatic Mode ===&lt;br /&gt;
&lt;br /&gt;
=== Mixed Mode ===&lt;br /&gt;
&lt;br /&gt;
== Arithmetic Operations ==&lt;br /&gt;
&lt;br /&gt;
=== Multiplication ===&lt;br /&gt;
&lt;br /&gt;
=== Division ===&lt;br /&gt;
&lt;br /&gt;
=== Cumulative Sum ===&lt;br /&gt;
&lt;br /&gt;
== Parallelism and I/O ==&lt;br /&gt;
&lt;br /&gt;
=== IRQ ===&lt;br /&gt;
&lt;br /&gt;
=== NMI ===&lt;br /&gt;
&lt;br /&gt;
=== FastROM Interactions ===&lt;br /&gt;
&lt;br /&gt;
[[Category:SNES Hardware]] [[Category:ASM]]&lt;/div&gt;</summary>
		<author><name>Vitor Vilela</name></author>
	</entry>
	<entry>
		<id>https://sneslab.net/mw/index.php?title=SA-1&amp;diff=1596</id>
		<title>SA-1</title>
		<link rel="alternate" type="text/html" href="https://sneslab.net/mw/index.php?title=SA-1&amp;diff=1596"/>
		<updated>2020-12-11T02:43:09Z</updated>

		<summary type="html">&lt;p&gt;Vitor Vilela: /* $2220-$2223 - SET SUPER MMC BANK C/D/E/F */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&#039;&#039;&#039;Nintendo SA-1&#039;&#039;&#039; is an [[enhancement chip]] made by [http://en.wikipedia.org/wiki/Nintendo Nintendo], used in 33 SNES games. The RF5A123 chip is based on the [[65c816]] processor, the same one used by the main SNES CPU, the [[RF5A22]]. With identical architectures to the SNES one, the chip is ideal for games and ROM hacks that would like to use the code from the main CPU, thus not having to learn an additional assembling language.&lt;br /&gt;
&lt;br /&gt;
{{TOClimit|4}}&lt;br /&gt;
&lt;br /&gt;
== Features ==&lt;br /&gt;
&lt;br /&gt;
With the &#039;&#039;&#039;10.74 MHz&#039;&#039;&#039; base clock speed, which is four times faster compared to the 2.68 MHz base speed from the S-CPU. In addition to that, it includes with additional hardware circuits for data I/O, bitmap manipulation modes and additional arithmetic registers.&lt;br /&gt;
&lt;br /&gt;
* 16-bit 65c816 processor clocked at 10.74 MHz.&lt;br /&gt;
* 2 kB fast internal work memory (I-RAM), clocked at 10.74 MHz.&lt;br /&gt;
* Multi-processor processing, with parallel operating mode and memory sharing control.&lt;br /&gt;
* Large capacity memory, with a total capability of 8 MB of ROM and 256 kB of BW-RAM, both clocked at 5.37 MHz, with ROM having an effective 10.74 MHz speed due of its 16-bit data bus.&lt;br /&gt;
* High speed arithmetic hardware of multiplication, division and cumulative sum (multiply with add).&lt;br /&gt;
* Bitmap and Character Conversion functions for fast graphics manipulation.&lt;br /&gt;
* Custom DMA circuit for fast transfers between ROM, I-RAM and BW-RAM.&lt;br /&gt;
* Variable-Length Bit data processing for enhanced algorithms such as graphics and data compression.&lt;br /&gt;
* Super MMC memory mapping capabilities for BW-RAM and bank switching for multiple ROM image access and mirroring.&lt;br /&gt;
&lt;br /&gt;
== ROM Hacking ==&lt;br /&gt;
&lt;br /&gt;
[[SA-1 Root]] and [[SA-1 Pack]] are known patches used for enabling SA-1 on SNES games that didn&#039;t include the chip previously and had problems with slowdown, such as [[Super Mario World]] and [[Gradius III]].&lt;br /&gt;
&lt;br /&gt;
= Technical Information =&lt;br /&gt;
There is not much technical information available on how the SA-1 chip works. Most of the findings are recent and are based on both official documents from Nintendo and experiments on real SA-1 carts. This section is getting continuously updated with new information and findings though the time. The information available here is expected to be accurate. Information about undefined behavior or design details is considered scarce right now.&lt;br /&gt;
&lt;br /&gt;
== Hardware Registers ==&lt;br /&gt;
The SA-1 internal registers are assigned on range $2200-$23FF, on banks $00-$3F and $80-$BF. $2200 though $22FF are write-only registers while $2300 though $23FF are read-only registers.&lt;br /&gt;
&lt;br /&gt;
=== Register Summary ===&lt;br /&gt;
&lt;br /&gt;
==== Write Registers ====&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Address !! Length !! Code !! Access !! Description&lt;br /&gt;
|-&lt;br /&gt;
| $2200 || 1 byte || CCNT || SNES || SA-1 CPU CONTROL&lt;br /&gt;
|-&lt;br /&gt;
| $2201 || 1 byte || SIE || SNES || SUPER NES CPU INT ENABLE&lt;br /&gt;
|-&lt;br /&gt;
| $2202 || 1 byte || SIC || SNES || SUPER NES CPU INT CLEAR&lt;br /&gt;
|-&lt;br /&gt;
| $2203 || 2 bytes || CRV || SNES || SA-1 CPU RESET VECTOR&lt;br /&gt;
|-&lt;br /&gt;
| $2205 || 2 bytes || CNV || SNES || SA-1 CPU NMI VECTOR&lt;br /&gt;
|-&lt;br /&gt;
| $2207 || 2 bytes || CIV || SNES || SA-1 CPU IRQ VECTOR&lt;br /&gt;
|-&lt;br /&gt;
| $2209 || 1 byte || SCNT || SA-1 || SUPER NES CPU CONTROL&lt;br /&gt;
|-&lt;br /&gt;
| $220A || 1 byte || CIE || SA-1 || SA-1 CPU INT ENABLE&lt;br /&gt;
|-&lt;br /&gt;
| $220B || 1 byte || CIC || SA-1 || SA-1 CPU INT CLEAR&lt;br /&gt;
|-&lt;br /&gt;
| $220C || 2 bytes || SNV || SA-1 || SUPER NES CPU NMI VECTOR&lt;br /&gt;
|-&lt;br /&gt;
| $220E || 2 bytes || SIV || SA-1 || SUPER NES CPU IRQ VECTOR&lt;br /&gt;
|-&lt;br /&gt;
| $2210 || 1 byte || TMC || SA-1 || H/V TIMER CONTROL&lt;br /&gt;
|-&lt;br /&gt;
| $2211 || 1 byte || CTR || SA-1 || SA-1 CPU TIMER RESTART&lt;br /&gt;
|-&lt;br /&gt;
| $2212 || 2 bytes || HCNT || SA-1 || SET H-COUNT&lt;br /&gt;
|-&lt;br /&gt;
| $2214 || 2 bytes || VCNT || SA-1 || SET V-COUNT&lt;br /&gt;
|-&lt;br /&gt;
| $2220 || 1 byte || CXB || SNES || SET SUPER MMC BANK C&lt;br /&gt;
|-&lt;br /&gt;
| $2221 || 1 byte || DXB || SNES || SET SUPER MMC BANK D&lt;br /&gt;
|-&lt;br /&gt;
| $2222 || 1 byte || EXB || SNES || SET SUPER MMC BANK E&lt;br /&gt;
|-&lt;br /&gt;
| $2223 || 1 byte || FXB || SNES || SET SUPER MMC BANK F&lt;br /&gt;
|-&lt;br /&gt;
| $2224 || 1 byte || BMAPS || SNES || SUPER NES CPU BW-RAM ADDRESS MAPPING&lt;br /&gt;
|-&lt;br /&gt;
| $2225 || 1 byte || BMAP || SA-1 || SA-1 CPU BW-RAM ADDRESS MAPPING&lt;br /&gt;
|-&lt;br /&gt;
| $2226 || 1 byte || SBWE || SNES || SUPER NES CPU BW-RAM WRITE ENABLE&lt;br /&gt;
|-&lt;br /&gt;
| $2227 || 1 byte || CBWE || SA-1 || SA-1 CPU BW-RAM WRITE ENABLE&lt;br /&gt;
|-&lt;br /&gt;
| $2228 || 1 byte || BPWA || SNES || BW-RAM WRITE-PROTECTED AREA&lt;br /&gt;
|-&lt;br /&gt;
| $2229 || 1 byte || SIWP || SNES || SA-1 I-RAM WRITE PROTECTION&lt;br /&gt;
|-&lt;br /&gt;
| $222A || 1 byte || CIWP || SA-1 || SA-1 I-RAM WRITE PROTECTION&lt;br /&gt;
|-&lt;br /&gt;
| $2230 || 1 byte || DCNT || SA-1 || DMA CONTROL&lt;br /&gt;
|-&lt;br /&gt;
| $2231 || 1 byte || CDMA || Both || CHARACTER CONVERSION OMA PARAMETERS&lt;br /&gt;
|-&lt;br /&gt;
| $2232 || 3 bytes || SDA || Both || DMA SOURCE DEVICE START ADDRESS&lt;br /&gt;
|-&lt;br /&gt;
| $2235 || 3 bytes || DDA || Both || DMA DESTINATION START ADDRESS&lt;br /&gt;
|-&lt;br /&gt;
| $2238 || 2 bytes || DTC || SA-1 || DMA TERMINAL COUNTER&lt;br /&gt;
|-&lt;br /&gt;
| $223F || 1 byte || BBF || SA-1 || BW-RAM BIT MAP FORMAT&lt;br /&gt;
|-&lt;br /&gt;
| $2240 || 16 bytes || BRF || SA-1 || BIT MAP REGISTER FILE&lt;br /&gt;
|-&lt;br /&gt;
| $2250 || 1 byte || MCNT || SA-1 || ARITHMETIC CONTROL&lt;br /&gt;
|-&lt;br /&gt;
| $2251 || 2 bytes || MA || SA-1 || ARITHMETIC PARAMETERS: MULTIPLICAND/DIVIDEND&lt;br /&gt;
|-&lt;br /&gt;
| $2253 || 2 bytes || MB || SA-1 || ARITHMETIC PARAMETERS: MULTIPLIER/DIVISOR&lt;br /&gt;
|-&lt;br /&gt;
| $2258 || 1 byte || VBD || SA-1 || VARIABLE-LENGTH BIT PROCESSING&lt;br /&gt;
|-&lt;br /&gt;
| $2259 || 3 bytes || VDA || SA-1 || VARIABLE-LENGTH BIT GAME PAK ROM START ADDRESS&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Read Registers ====&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Address !! Length !! Code !! Access !! Description&lt;br /&gt;
|-&lt;br /&gt;
| $2300 || 1 bytes || SFR || SNES || SUPER NES CPU FLAG READ&lt;br /&gt;
|-&lt;br /&gt;
| $2301 || 1 bytes || CFR || SA-1 || SA-1 CPU FLAG READ&lt;br /&gt;
|-&lt;br /&gt;
| $2302 || 2 bytes || HCR || SA-1 || H-COUNT READ&lt;br /&gt;
|-&lt;br /&gt;
| $2304 || 2 bytes || VCR || SA-1 || V-COUNT READ&lt;br /&gt;
|-&lt;br /&gt;
| $2306 || 5 bytes || MR || SA-1 || ARITHMETIC RESULT [PRODUCT/QUOTIENT/ACCUMULATIVE SUM]&lt;br /&gt;
|-&lt;br /&gt;
| $230B || 1 bytes || OF || SA-1 || ARITHMETIC OVERFLOW FLAG&lt;br /&gt;
|-&lt;br /&gt;
| $230C || 2 bytes || VDP || SA-1 || VARIABLE-LENGTH DATA READ PORT&lt;br /&gt;
|-&lt;br /&gt;
| $230E || 1 byte || VC || SNES || VERSION CODE REGISTER (OPEN BUS)&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Register Details ===&lt;br /&gt;
&lt;br /&gt;
==== $2200 - SA-1 CPU CONTROL ====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== $2201 - SUPER NES CPU INT ENABLE ====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== $2202 - SUPER NES CPU INT CLEAR ====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== $2203 - SA-1 CPU RESET VECTOR ====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== $2205 - SA-1 CPU NMI VECTOR ====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== $2207 - SA-1 CPU IRQ VECTOR ====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== $2209 - SUPER NES CPU CONTROL ====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== $220A - SA-1 CPU INT ENABLE ====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== $220B - SA-1 CPU INT CLEAR ====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== $220C - SUPER NES CPU NMI VECTOR ====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== $220E - SUPER NES CPU IRQ VECTOR ====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== $2210 - H/V TIMER CONTROL ====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== $2211 - SA-1 CPU TIMER RESTART ====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== $2212 - SET H-COUNT ====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== $2214 - SET V-COUNT ====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== $2220-$2223 - SET SUPER MMC BANK C/D/E/F ====&lt;br /&gt;
{{32bit-reg|2220|2221|2222|2223&lt;br /&gt;
|CBM|0|0|0|0|CB2|CB1|CB0&lt;br /&gt;
|DBM|0|0|0|0|CB2|CB1|CB0&lt;br /&gt;
|EBM|0|0|0|0|CB2|CB1|CB0&lt;br /&gt;
|FBM|0|0|0|0|CB2|CB1|CB0}}&lt;br /&gt;
&lt;br /&gt;
CB2~CB0: Which megabyte of the ROM to map to $C0-$CF / $D0-$DF / $E0-$EF / $F0-$FF.&lt;br /&gt;
&lt;br /&gt;
CBM/DBM/EBM/FBM: If set, apply image projection to LoROM banks as well.&lt;br /&gt;
{|style=&amp;quot;width:auto&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Flag !! Bank Range&lt;br /&gt;
|-&lt;br /&gt;
| CBM || Apply to banks $00-$1F&lt;br /&gt;
|-&lt;br /&gt;
| DBM || Apply to banks $20-$3F&lt;br /&gt;
|-&lt;br /&gt;
| EBM || Apply to banks $80-$9F&lt;br /&gt;
|-&lt;br /&gt;
| FBM || Apply to banks $A0-$BF&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Registers are responsible for setting up the ROM bank mapping.&lt;br /&gt;
By default, the values { $00, $01, $02, $03 } are loaded on power up.&lt;br /&gt;
&lt;br /&gt;
Bits CBM/DBM/EBM/FBM determine if the mapping should apply to the LoROM banks as well, otherwise they will have the constant value of { $00, $01, $02, $03 } regardless of the ROM size. Given that, it&#039;s possible the entire 8 MB layout at once by storing values { $04, $05, $06, $07 } to the registers. Snes9x 1.53 and older always treated these flags as set, making the mapping always apply to the LoROM banks.&lt;br /&gt;
&lt;br /&gt;
{|style=&amp;quot;width:auto&amp;quot;&lt;br /&gt;
|+Common values&lt;br /&gt;
|-&lt;br /&gt;
! Register !! $2220 !! $2221 !! $2222 !! $2223 !! Comment&lt;br /&gt;
|-&lt;br /&gt;
| Value || $00 || $01 || $02 || $03 || Default values&lt;br /&gt;
|-&lt;br /&gt;
| Value || $04 || $05 || $06 || $07 || Maps the first 4 MB to banks $00-$3F and $80-$BF, with LoROM-like layout. The last 4 MB is mapped to $C0-$FF, with HiROM-like layout.&lt;br /&gt;
|-&lt;br /&gt;
| Value || $80 || $81 || $80 || $81 || Simulates the standard LoROM map with FastROM compatibility by mapping the first 2 MB to $00-$3F and $80-$BF.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The Super MMC register affects all memory maps, including SNES, SA-1, SA-1 DMA and SA-1 Variable Length Bit maps.&lt;br /&gt;
bsnes 0.7x does not apply the custom memory mapping to Variable Length Bit circuit.&lt;br /&gt;
&lt;br /&gt;
Hardware verification has shown that the unused bits has no effects to the chip pinout and therefore the maximum ROM size for the SA-1 without using a custom ROM controller outside the chip is 8 MB (megabytes).&lt;br /&gt;
&lt;br /&gt;
==== $2224 - SUPER NES CPU BW-RAM ADDRESS MAPPING ====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== $2225 - SA-1 CPU BW-RAM ADDRESS MAPPING ====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== $2226 - SUPER NES CPU BW-RAM WRITE ENABLE ====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== $2227 - SA-1 CPU BW-RAM WRITE ENABLE ====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== $2228 - BW-RAM WRITE-PROTECTED AREA ====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== $2229 - SA-1 I-RAM WRITE PROTECTION ====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== $222A - SA-1 I-RAM WRITE PROTECTION ====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== $2230 - DMA CONTROL ====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== $2231 - CHARACTER CONVERSION OMA PARAMETERS ====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== $2232 - DMA SOURCE DEVICE START ADDRESS ====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== $2235 - DMA DESTINATION START ADDRESS ====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== $2238 - DMA TERMINAL COUNTER ====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== $223F - BW-RAM BIT MAP FORMAT ====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== $2240 - BIT MAP REGISTER FILE ====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== $2250 - ARITHMETIC CONTROL ====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== $2251 - ARITHMETIC PARAMETERS: MULTIPLICAND/DIVIDEND ====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== $2253 - ARITHMETIC PARAMETERS: MULTIPLIER/DIVISOR ====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== $2258 - VARIABLE-LENGTH BIT PROCESSING ====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== $2259 - VARIABLE-LENGTH BIT GAME PAK ROM START ADDRESS ====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== $2300 - SUPER NES CPU FLAG READ ====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== $2301 - SA-1 CPU FLAG READ ====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== $2302 - H-COUNT READ ====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== $2304 - V-COUNT READ ====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== $2306 - ARITHMETIC RESULT [PRODUCT/QUOTIENT/ACCUMULATIVE SUM] ====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== $230B - ARITHMETIC OVERFLOW FLAG ====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== $230C - VARIABLE-LENGTH DATA READ PORT ====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== $230E - VERSION CODE REGISTER (OPEN BUS) ====&lt;br /&gt;
{{8bit-reg|230E|VC7|VC6|VC5|VC4|VC3|VC2|VC1|VC0}}&lt;br /&gt;
{| style=&amp;quot;width:auto&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Bits !! Meaning&lt;br /&gt;
|-&lt;br /&gt;
| VC0 ~ VC7 || SA-1 Device Version&lt;br /&gt;
|}&lt;br /&gt;
According the SNES Development Book II, this register was supposed to hold the SA-1 chip version code, however tests made on some real carts has shown that this register in particular is actually [[open bus]].&lt;br /&gt;
-----&lt;br /&gt;
&lt;br /&gt;
== Memory and Bus ==&lt;br /&gt;
&lt;br /&gt;
=== Memory Map ===&lt;br /&gt;
&lt;br /&gt;
==== SNES Side ====&lt;br /&gt;
&lt;br /&gt;
==== SA-1 Side ====&lt;br /&gt;
&lt;br /&gt;
==== Open Bus Behavior ====&lt;br /&gt;
&lt;br /&gt;
=== ROM ===&lt;br /&gt;
&lt;br /&gt;
=== I-RAM ===&lt;br /&gt;
&lt;br /&gt;
==== Write Protection ====&lt;br /&gt;
&lt;br /&gt;
=== BW-RAM ===&lt;br /&gt;
&lt;br /&gt;
==== Write Protection ====&lt;br /&gt;
&lt;br /&gt;
=== Virtual Bitmap Memory ===&lt;br /&gt;
&lt;br /&gt;
=== Super MMC ===&lt;br /&gt;
&lt;br /&gt;
=== Bus Conflicts ===&lt;br /&gt;
&lt;br /&gt;
== Direct Memory Access ==&lt;br /&gt;
&lt;br /&gt;
=== Character Conversion DMA ===&lt;br /&gt;
&lt;br /&gt;
=== Parallel DMA ===&lt;br /&gt;
&lt;br /&gt;
=== Interactions with SNES DMA ===&lt;br /&gt;
&lt;br /&gt;
=== Undefined Behavior ===&lt;br /&gt;
&lt;br /&gt;
== Variable Length Bit ==&lt;br /&gt;
&lt;br /&gt;
=== Fixed Mode ===&lt;br /&gt;
&lt;br /&gt;
=== Automatic Mode ===&lt;br /&gt;
&lt;br /&gt;
=== Mixed Mode ===&lt;br /&gt;
&lt;br /&gt;
== Arithmetic Operations ==&lt;br /&gt;
&lt;br /&gt;
=== Multiplication ===&lt;br /&gt;
&lt;br /&gt;
=== Division ===&lt;br /&gt;
&lt;br /&gt;
=== Cumulative Sum ===&lt;br /&gt;
&lt;br /&gt;
== Parallelism and I/O ==&lt;br /&gt;
&lt;br /&gt;
=== IRQ ===&lt;br /&gt;
&lt;br /&gt;
=== NMI ===&lt;br /&gt;
&lt;br /&gt;
=== FastROM Interactions ===&lt;br /&gt;
&lt;br /&gt;
[[Category:SNES Hardware]] [[Category:ASM]]&lt;/div&gt;</summary>
		<author><name>Vitor Vilela</name></author>
	</entry>
	<entry>
		<id>https://sneslab.net/mw/index.php?title=SnesLab:Staff&amp;diff=1078</id>
		<title>SnesLab:Staff</title>
		<link rel="alternate" type="text/html" href="https://sneslab.net/mw/index.php?title=SnesLab:Staff&amp;diff=1078"/>
		<updated>2020-01-12T21:58:24Z</updated>

		<summary type="html">&lt;p&gt;Vitor Vilela: New The Council Policy, cleaning up removed users.&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&#039;&#039;&#039;The SnesLab Staff Team&#039;&#039;&#039; is the administrative team responsible for developing, keeping, guarding, helping and maintaining SnesLab. They are split in several areas and have different degrees of power. &#039;&#039;&#039;All of them&#039;&#039;&#039; are voluntary roles and they are always open for new members, since they don&#039;t have a fixed member limit.&lt;br /&gt;
&lt;br /&gt;
The most important for the staff team in the first place is promoting a &#039;&#039;&#039;healthy&#039;&#039;&#039; and a &#039;&#039;&#039;developing&#039;&#039;&#039; ambience where people can keep learning and improving their skills that applies for both ROM hacking, gaming and real life competences. If &#039;&#039;&#039;you are interested&#039;&#039;&#039; in joining the team, message one of the Real Scientists for more information.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Active Areas ==&lt;br /&gt;
=== Real Scientists ===&lt;br /&gt;
Real Scientists are the SnesLab &#039;&#039;&#039;administrators&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Members:&#039;&#039;&#039;&lt;br /&gt;
* Tattletale&lt;br /&gt;
* Vitor Vilela (articulator/owner)&lt;br /&gt;
* Major Flare (inactive)&lt;br /&gt;
* Zexi (inactive)&lt;br /&gt;
* DiscoTheBat (inactive)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Former:&#039;&#039;&#039;&lt;br /&gt;
* Mirann (resigned, now Lab Manager)&lt;br /&gt;
&lt;br /&gt;
=== DevOps ===&lt;br /&gt;
DevOps is the group responsible for the technical aspects of the SnesLab website. It was created from the members that had an important participation from the Website Committee and had technical knowledge in creating and maintaining the server.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Members:&#039;&#039;&#039;&lt;br /&gt;
* Alcaro&lt;br /&gt;
* RanAS&lt;br /&gt;
* Vitor Vilela&lt;br /&gt;
* Tattletale (inactive)&lt;br /&gt;
&lt;br /&gt;
=== Lab Managers ===&lt;br /&gt;
Lab Managers are the Discord guardians (moderators). Responsible for keeping the good ambience of the community.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Members:&#039;&#039;&#039;&lt;br /&gt;
* Alcaro&lt;br /&gt;
* Catador&lt;br /&gt;
* LX5&lt;br /&gt;
* Mirann&lt;br /&gt;
* Ragey&lt;br /&gt;
* RanAS&lt;br /&gt;
* Shiny Ninetales&lt;br /&gt;
* Super Maks 64&lt;br /&gt;
* Tattletale&lt;br /&gt;
* Vitor Vilela&lt;br /&gt;
* JackTheSpades (inactive)&lt;br /&gt;
&lt;br /&gt;
=== Forum Committee ===&lt;br /&gt;
The Forum Committee is a temporary group where people are currently discussing the creation of SnesLab Forums.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Members:&#039;&#039;&#039;&lt;br /&gt;
* Daizo Dee Von&lt;br /&gt;
* MarioE&lt;br /&gt;
* Shiny Ninetales&lt;br /&gt;
* RanAS&lt;br /&gt;
* Vitor Vilela&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Incoming Areas ==&lt;br /&gt;
Areas that will be incoming when the SnesLab Board and SnesLab Hub are out:&lt;br /&gt;
&lt;br /&gt;
* Forum Moderators&lt;br /&gt;
* ASM Team&lt;br /&gt;
* Networking Team&lt;br /&gt;
* Music Team&lt;br /&gt;
* Graphics Team&lt;br /&gt;
* ROM Hacks Team&lt;br /&gt;
* Programming Team&lt;br /&gt;
* Projects Team&lt;br /&gt;
* Game-specific Team&lt;br /&gt;
&lt;br /&gt;
== Inactive/Archived Areas ==&lt;br /&gt;
Areas or groups that no longer exist or are inactive.&lt;br /&gt;
&lt;br /&gt;
=== Networking Area ===&lt;br /&gt;
The Networking Area is a group responsible for the website design, UX/UI experience and Public Relations. It&#039;s currently inactive but there are plans for reopening it with new members.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Members:&#039;&#039;&#039;&lt;br /&gt;
* Tob&lt;br /&gt;
* Luks&lt;br /&gt;
* Vitor Vilela&lt;br /&gt;
&lt;br /&gt;
=== Website Committee ===&lt;br /&gt;
Website Committee was a group for people discussing the creation of the SnesLab website, as well designing the website logo, identity, name, wiki and the technical challenges behind it.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Members:&#039;&#039;&#039;&lt;br /&gt;
* Aja&lt;br /&gt;
* Alcaro&lt;br /&gt;
* anonimzwx&lt;br /&gt;
* Daizo Dee Von&lt;br /&gt;
* Konata&lt;br /&gt;
* LadiesMan217&lt;br /&gt;
* Luks&lt;br /&gt;
* Masterlink&lt;br /&gt;
* mellonpizza&lt;br /&gt;
* Ragey&lt;br /&gt;
* RanAS&lt;br /&gt;
* randomdude999&lt;br /&gt;
* Shiny Ninetales&lt;br /&gt;
* Tattletale&lt;br /&gt;
* Ukyo&lt;br /&gt;
* Vitor Vilela&lt;br /&gt;
* WYE&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== The Council ==&lt;br /&gt;
The Council is a fixed and permanent group where people are invited to bring ideas, issues or concerns about SnesLab and SNES ROM hacking in general. They work as Real Scientists advisors. It was the first private channel created on the Discord server and people are occasionally invited to join them.&lt;br /&gt;
&lt;br /&gt;
If you would like to join it, please send a DM to Vitor Vilela.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Members:&#039;&#039;&#039;&lt;br /&gt;
* Akaginite&lt;br /&gt;
* Alcaro&lt;br /&gt;
* amHunter&lt;br /&gt;
* Bruno Lucius&lt;br /&gt;
* Bruno Visnadi&lt;br /&gt;
* BrunoValads&lt;br /&gt;
* Catador&lt;br /&gt;
* Daizo Dee Von&lt;br /&gt;
* DiscoTheBat&lt;br /&gt;
* FURiOUS&lt;br /&gt;
* FuSoYa&lt;br /&gt;
* JackTheSpades&lt;br /&gt;
* Kieran&lt;br /&gt;
* LX5&lt;br /&gt;
* LadiesMan217&lt;br /&gt;
* Lui37&lt;br /&gt;
* MarioE&lt;br /&gt;
* Masterlink&lt;br /&gt;
* Major Flare&lt;br /&gt;
* Mirann&lt;br /&gt;
* Nep-Enut&lt;br /&gt;
* Ragey&lt;br /&gt;
* RanAS&lt;br /&gt;
* Sariel&lt;br /&gt;
* Shiny Ninetales&lt;br /&gt;
* Skewer&lt;br /&gt;
* Super Maks 64&lt;br /&gt;
* Tattletale&lt;br /&gt;
* Vitor Vilela&lt;br /&gt;
* Zexi&lt;/div&gt;</summary>
		<author><name>Vitor Vilela</name></author>
	</entry>
	<entry>
		<id>https://sneslab.net/mw/index.php?title=SnesLab:Staff&amp;diff=1076</id>
		<title>SnesLab:Staff</title>
		<link rel="alternate" type="text/html" href="https://sneslab.net/mw/index.php?title=SnesLab:Staff&amp;diff=1076"/>
		<updated>2020-01-11T04:46:13Z</updated>

		<summary type="html">&lt;p&gt;Vitor Vilela: Aja, Sinc-X, Jimmy and Tob has been kicked from The Council for relaying confidential information to the SMW Central staff team.&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&#039;&#039;&#039;The SnesLab Staff Team&#039;&#039;&#039; is the administrative team responsible for developing, keeping, guarding, helping and maintaining SnesLab. They are split in several areas and have different degrees of power. &#039;&#039;&#039;All of them&#039;&#039;&#039; are voluntary roles and they are always open for new members, since they don&#039;t have a fixed member limit.&lt;br /&gt;
&lt;br /&gt;
The most important for the staff team in the first place is promoting a &#039;&#039;&#039;healthy&#039;&#039;&#039; and a &#039;&#039;&#039;developing&#039;&#039;&#039; ambience where people can keep learning and improving their skills that applies for both ROM hacking, gaming and real life competences. If &#039;&#039;&#039;you are interested&#039;&#039;&#039; in joining the team, message one of the Real Scientists for more information.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Active Areas ==&lt;br /&gt;
=== Real Scientists ===&lt;br /&gt;
Real Scientists are the SnesLab &#039;&#039;&#039;administrators&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Members:&#039;&#039;&#039;&lt;br /&gt;
* Tattletale&lt;br /&gt;
* Vitor Vilela (articulator/owner)&lt;br /&gt;
* Major Flare (inactive)&lt;br /&gt;
* Zexi (inactive)&lt;br /&gt;
* DiscoTheBat (inactive)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Former:&#039;&#039;&#039;&lt;br /&gt;
* Mirann (resigned, now Lab Manager)&lt;br /&gt;
&lt;br /&gt;
=== DevOps ===&lt;br /&gt;
DevOps is the group responsible for the technical aspects of the SnesLab website. It was created from the members that had an important participation from the Website Committee and had technical knowledge in creating and maintaining the server.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Members:&#039;&#039;&#039;&lt;br /&gt;
* Alcaro&lt;br /&gt;
* RanAS&lt;br /&gt;
* Vitor Vilela&lt;br /&gt;
* Tattletale (inactive)&lt;br /&gt;
&lt;br /&gt;
=== Lab Managers ===&lt;br /&gt;
Lab Managers are the Discord guardians (moderators). Responsible for keeping the good ambience of the community.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Members:&#039;&#039;&#039;&lt;br /&gt;
* Alcaro&lt;br /&gt;
* Catador&lt;br /&gt;
* LX5&lt;br /&gt;
* Mirann&lt;br /&gt;
* Ragey&lt;br /&gt;
* RanAS&lt;br /&gt;
* Shiny Ninetales&lt;br /&gt;
* Super Maks 64&lt;br /&gt;
* Tattletale&lt;br /&gt;
* Vitor Vilela&lt;br /&gt;
* JackTheSpades (inactive)&lt;br /&gt;
&lt;br /&gt;
=== Forum Committee ===&lt;br /&gt;
The Forum Committee is a temporary group where people are currently discussing the creation of SnesLab Forums.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Members:&#039;&#039;&#039;&lt;br /&gt;
* Daizo Dee Von&lt;br /&gt;
* MarioE&lt;br /&gt;
* Shiny Ninetales&lt;br /&gt;
* RanAS&lt;br /&gt;
* Vitor Vilela&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Incoming Areas ==&lt;br /&gt;
Areas that will be incoming when the SnesLab Board and SnesLab Hub are out:&lt;br /&gt;
&lt;br /&gt;
* Forum Moderators&lt;br /&gt;
* ASM Team&lt;br /&gt;
* Networking Team&lt;br /&gt;
* Music Team&lt;br /&gt;
* Graphics Team&lt;br /&gt;
* ROM Hacks Team&lt;br /&gt;
* Programming Team&lt;br /&gt;
* Projects Team&lt;br /&gt;
* Game-specific Team&lt;br /&gt;
&lt;br /&gt;
== Inactive/Archived Areas ==&lt;br /&gt;
Areas or groups that no longer exist or are inactive.&lt;br /&gt;
&lt;br /&gt;
=== Networking Area ===&lt;br /&gt;
The Networking Area is a group responsible for the website design, UX/UI experience and Public Relations. It&#039;s currently inactive but there are plans for reopening it with new members.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Members:&#039;&#039;&#039;&lt;br /&gt;
* Tob&lt;br /&gt;
* Luks&lt;br /&gt;
* Vitor Vilela&lt;br /&gt;
&lt;br /&gt;
=== Website Committee ===&lt;br /&gt;
Website Committee was a group for people discussing the creation of the SnesLab website, as well designing the website logo, identity, name, wiki and the technical challenges behind it.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Members:&#039;&#039;&#039;&lt;br /&gt;
* Aja&lt;br /&gt;
* Alcaro&lt;br /&gt;
* anonimzwx&lt;br /&gt;
* Daizo Dee Von&lt;br /&gt;
* Konata&lt;br /&gt;
* LadiesMan217&lt;br /&gt;
* Luks&lt;br /&gt;
* Masterlink&lt;br /&gt;
* mellonpizza&lt;br /&gt;
* Ragey&lt;br /&gt;
* RanAS&lt;br /&gt;
* randomdude999&lt;br /&gt;
* Shiny Ninetales&lt;br /&gt;
* Tattletale&lt;br /&gt;
* Ukyo&lt;br /&gt;
* Vitor Vilela&lt;br /&gt;
* WYE&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== The Council ==&lt;br /&gt;
The Council is a fixed and permanent group where people are invited to bring ideas, issues or concerns about SnesLab and SNES ROM hacking in general. They work as Real Scientists advisors. It was the first private channel created on the Discord server and people are occasionally invited to join them.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Members:&#039;&#039;&#039;&lt;br /&gt;
* aCrowned&lt;br /&gt;
* Akaginite&lt;br /&gt;
* Alcaro&lt;br /&gt;
* amHunter&lt;br /&gt;
* Amaraticando&lt;br /&gt;
* Anonimato&lt;br /&gt;
* Bruno Lucius&lt;br /&gt;
* Bruno Visnadi&lt;br /&gt;
* BrunoValads&lt;br /&gt;
* Catador&lt;br /&gt;
* Daizo Dee Von&lt;br /&gt;
* DiscoTheBat&lt;br /&gt;
* FURiOUS&lt;br /&gt;
* FuSoYa&lt;br /&gt;
* JackTheSpades&lt;br /&gt;
* K3fka&lt;br /&gt;
* Kieran&lt;br /&gt;
* LX5&lt;br /&gt;
* LadiesMan217&lt;br /&gt;
* Lui37&lt;br /&gt;
* Kaizoman&lt;br /&gt;
* MarioE&lt;br /&gt;
* Masterlink&lt;br /&gt;
* MaxodeX&lt;br /&gt;
* Major Flare&lt;br /&gt;
* Mirann&lt;br /&gt;
* Nep-Enut&lt;br /&gt;
* Ragey&lt;br /&gt;
* RanAS&lt;br /&gt;
* Sariel&lt;br /&gt;
* Shiny Ninetales&lt;br /&gt;
* Skewer&lt;br /&gt;
* Super Maks 64&lt;br /&gt;
* Tattletale&lt;br /&gt;
* TheMorganah&lt;br /&gt;
* TheRedhotbr&lt;br /&gt;
* Torchkas&lt;br /&gt;
* Ukyo&lt;br /&gt;
* Vitor Vilela&lt;br /&gt;
* WYE&lt;br /&gt;
* Wakana&lt;br /&gt;
* Zexi&lt;/div&gt;</summary>
		<author><name>Vitor Vilela</name></author>
	</entry>
	<entry>
		<id>https://sneslab.net/mw/index.php?title=SA-1_Pack&amp;diff=998</id>
		<title>SA-1 Pack</title>
		<link rel="alternate" type="text/html" href="https://sneslab.net/mw/index.php?title=SA-1_Pack&amp;diff=998"/>
		<updated>2019-12-01T16:15:42Z</updated>

		<summary type="html">&lt;p&gt;Vitor Vilela: Detach MaxTile page&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&#039;&#039;&#039;SA-1 Pack&#039;&#039;&#039; is a package of patches for activating and optimizing the [[SA-1]] system for [[Super Mario World]], with emphasis on eliminating slowdown, game limitations and accelerating the engine to the maximum possible. Unlike [[SA-1 Root]], SA-1 Pack is focused for [[ROM hacking]] and it includes several features for implementing new features for the game using the chip.&lt;br /&gt;
&lt;br /&gt;
Being the most complex patch made for Super Mario World, SA-1 Pack requires to all other ASM patches apply a [[RAM remap]] for warranting compatibility with the patch. However, without the RAM remap, it would have been impossible to accelerate the game because the SA-1 chip cannot access the S-CPU work memory (WRAM).&lt;br /&gt;
&lt;br /&gt;
For implementation details, see [[SA-1 Root]].&lt;br /&gt;
&lt;br /&gt;
== Features ==&lt;br /&gt;
* Makes the game run up to four times faster.&lt;br /&gt;
* Increase the maximum amount of sprites at once on screen to 22.&lt;br /&gt;
* Increase the maximum amount of sprites on a single sub-level to 255.&lt;br /&gt;
* Reduces loading time of all levels and maps.&lt;br /&gt;
* Increase the maximum ROM size to 8 MB.&lt;br /&gt;
* Offers enhanced bitmap and arithmetic capabilities for better graphics performance.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== MaxTile System ==&lt;br /&gt;
See main article: [[MaxTile System]]&lt;br /&gt;
&lt;br /&gt;
[[Category:Super Mario World]] [[Category:ASM]]&lt;/div&gt;</summary>
		<author><name>Vitor Vilela</name></author>
	</entry>
	<entry>
		<id>https://sneslab.net/mw/index.php?title=MaxTile_System&amp;diff=997</id>
		<title>MaxTile System</title>
		<link rel="alternate" type="text/html" href="https://sneslab.net/mw/index.php?title=MaxTile_System&amp;diff=997"/>
		<updated>2019-12-01T16:14:13Z</updated>

		<summary type="html">&lt;p&gt;Vitor Vilela: Create dedicated page for MaxTile system.&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&#039;&#039;&#039;MaxTile System&#039;&#039;&#039; or just &#039;&#039;&#039;MaxTile&#039;&#039;&#039; is a new feature introduced on SA-1 Pack v1.40 that fixes all known OAM issues involving the game, allowing custom sprites using both $0200 &amp;amp; $0300 area and implements a basic sprite priority system for custom resources interested in using the MaxTile API directly, while still keeping compatibility with regular and custom sprites that weren&#039;t designed for MaxTile.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
How it works:&lt;br /&gt;
* At the beginning of the frame, $7F:8000 is called and invalidates all OAM data.&lt;br /&gt;
* $0200 - $049F can be used normally on the game.&lt;br /&gt;
* When a sprite is executed, its OAM index is set to $0328.&lt;br /&gt;
* When the next sprite is executed, the previous OAM tiles are copied into a new buffer and the $0328+ is freed so the next sprite can use it.&lt;br /&gt;
* At the end of the frame, the entire OAM is scanned for other tiles and unused tiles are removed.&lt;br /&gt;
* During the process, any tile outside screen is automatically dropped as well, maximizing free OAM slots.&lt;br /&gt;
* The sprite buffer then is copied back to the OAM and all sprites are rendered to the screen.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
In practice however the process is a bit more complex:&lt;br /&gt;
* At the beginning of the frame:&lt;br /&gt;
** $7F:8000 is called and clears all SMW OAM&#039;s table.&lt;br /&gt;
** Reset SA-1&#039;s MaxTile internal pointer to $40:C000.&lt;br /&gt;
* During the frame:&lt;br /&gt;
** $0200 - $049F can be used normally on the game.&lt;br /&gt;
** When a new regular sprite asks for a OAM slot, SA-1 MaxTile will transfer all used tiles between $0328-$03FC to its internal buffer and give slot #$28 ($0328).&lt;br /&gt;
** Sprites made for MaxTile will be able to assign a priority number on its attribute and MaxTile will acknowledge the information at the end of the frame.&lt;br /&gt;
* At the end of the frame:&lt;br /&gt;
** MaxTile will iterate though $0200-$02FC and copy all tiles to its internal buffer and mark as &amp;quot;highest priority&amp;quot;.&lt;br /&gt;
** Copy $0300-$0324 to its internal buffer and mark as &amp;quot;high priority&amp;quot;.&lt;br /&gt;
** Copy $0328-$03FC to its internal buffer and mark as &amp;quot;standard priority&amp;quot;.&lt;br /&gt;
** MaxTile will iterate its internal buffer and will copy all tiles marked as &amp;quot;highest priority&amp;quot; starting at $0200, then will repeat the process of &amp;quot;high&amp;quot;, &amp;quot;standard&amp;quot; and &amp;quot;low&amp;quot; priority until it&#039;s over, gradually filling SMW&#039;s buffer with the sorted tiles.&lt;br /&gt;
** While iterating, MaxTile will analyze if each tile is inside or outside screen, discarding the ones outside screen for saving more slots.&lt;br /&gt;
** If it runs out of OAM slots, MaxTile will discard the lowest priority tiles and abort.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
To be questioned:&lt;br /&gt;
* What will happen if one of the Mode 7 bosses change the OAM low address?&lt;br /&gt;
* Is it really needed to analyze if each tile is inside or outside screen?&lt;br /&gt;
* What if a sprite stores to $0400-$041F directly?&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Priority system ==&lt;br /&gt;
When working with MaxTile, you can continue storing to $0200-$02FC directly for setting your own priority (but with static tile management), you can use $0328+ for using as standard sprite priority or you can use its built-in priority system that will automatically ensure that your tiles are placed on the requested order.&lt;br /&gt;
&lt;br /&gt;
The available priorities are:&lt;br /&gt;
# Maximum priority: store all tiles before the ones statically stored at $0200-$02FC. This is useful for sprite status bar or other status text.&lt;br /&gt;
# High priority: store all tiles before the ones statically stored at $0300-$0324. This is useful if you wanna make sprite appears in front of the player and yoshi like custom powerups or even additional players. It can also be useful for platforms and clouds.&lt;br /&gt;
# Standard priority: store all tiles in the same order as the sprites, so between $0328-$03FC. Useful for standard sprites that you don&#039;t really have to worry about the priority between them.&lt;br /&gt;
# Low priority: store all tiles after the ones normally written at $0328-$03FC. Useful for custom sprite backgrounds.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Some SMW sprites has hardcoded priorities and because of that they were adjusted to work with MaxTile&#039;s priority system. The following sprites are affected:&lt;br /&gt;
* Lakitu&#039;s cloud&lt;br /&gt;
* Yoshi&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Memory management ==&lt;br /&gt;
Although SA-1 Pack for Super Mario World has a considerable amount of free memory on SA-1 side, it&#039;s always on concern about memory use when you are talking about SMW hacking.&lt;br /&gt;
&lt;br /&gt;
The initial MaxTile idea would require only 384-400 free RAM bytes, but with the so-requested priority system, we ran into the following issue: although the OAM has only 128 sprite slots, we don&#039;t know how many slots will each priority take. It might sound impossible, but priority #2 or priority #4 can take almost all slots. Or vice-versa, priority #3 can take most of the slots or priority #1 can end up completely empty.&lt;br /&gt;
&lt;br /&gt;
The simplest approach would be letting each priority have all slots available: 512 bytes main table + 128 bytes attribute table. With four priorities available, you would end up spending 2560 bytes of RAM, plus the pointers of each one. Overkill considering there are only 128 free slots and in the end a good chunk of the RAM will end up unused.&lt;br /&gt;
&lt;br /&gt;
An alternative approach is making priority #2 and priority #4 reversed, so they will decrement the pointer and fill the previous priority buffer, but that would not allow custom sprites change priority by just swapping the pointer, requiring different graphics routines for each one.&lt;br /&gt;
&lt;br /&gt;
Another thought approach was instead of using 2560 bytes of RAM, is using 2048 bytes at $40:C000-$40:C7FF so it could be mapped to $6000-$7FFF using the $2224 and $2225 SA-1 registers. However, each there would be only enough free space for three OAM buffers for four different priorities, which we would be forced to have two or three profiles with less OAM slots available and different performance profiles would be needed to implement (one that gives more free slots to low priority, another that gives more free slots to high priority, etc.).&lt;br /&gt;
&lt;br /&gt;
The chosen approach was actually using the unused bits of properties table to define sprite priority (#$00 - normal, #$40 - low, #$80 - highest, #$C0 - high), reducing the amount of required memory to 512 + 128 (main draw buffer and properties) + pointers, keeping the cycle complexity somewhat similar (four table iterations).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Programming reference ==&lt;br /&gt;
* $6200-$63FF: SMW&#039;s OAM table. An Y value of #$F0 means the slot is empty.&lt;br /&gt;
* $6400-$641F: SMW&#039;s OAM attribute table. No sprite should ever modify this value directly, unless if the finish OAM write is not called (and therefore MaxTile won&#039;t run), like on the Nintendo presents screen.&lt;br /&gt;
* $6420-$649F: SMW&#039;s OAM expanded attribute table. Format: --OO --sH, where OO is priority (0-standard,1-low,2-maximum,3-high), s is the OAM tile size (8x8 or 16x16) and H is the X position most significant bit (9th).&lt;br /&gt;
* $40:C000-$40:C1FF: MaxTile&#039;s OAM table buffer.&lt;br /&gt;
* $40:C200-$40:C27F: MaxTile&#039;s OAM properties buffer. Format: ---- --sH.&lt;br /&gt;
* $40:C280-$40:C2FF: MaxTile&#039;s OAM priority buffer. Format: F-OO ---, where OO is priority and F is &amp;quot;force empty&amp;quot; flag.&lt;br /&gt;
* $40:C300-$40:C301: MaxTile&#039;s OAM pointer. Every frame it&#039;s reset to #$0000 and gradually incremented though the OAM tiles are copied to the buffer.&lt;br /&gt;
&lt;br /&gt;
[[Category:Super Mario World]] [[Category:ASM]]&lt;/div&gt;</summary>
		<author><name>Vitor Vilela</name></author>
	</entry>
	<entry>
		<id>https://sneslab.net/mw/index.php?title=SA-1_Pack&amp;diff=996</id>
		<title>SA-1 Pack</title>
		<link rel="alternate" type="text/html" href="https://sneslab.net/mw/index.php?title=SA-1_Pack&amp;diff=996"/>
		<updated>2019-12-01T16:09:30Z</updated>

		<summary type="html">&lt;p&gt;Vitor Vilela: /* Programming reference */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&#039;&#039;&#039;SA-1 Pack&#039;&#039;&#039; is a package of patches for activating and optimizing the [[SA-1]] system for [[Super Mario World]], with emphasis on eliminating slowdown, game limitations and accelerating the engine to the maximum possible. Unlike [[SA-1 Root]], SA-1 Pack is focused for [[ROM hacking]] and it includes several features for implementing new features for the game using the chip.&lt;br /&gt;
&lt;br /&gt;
Being the most complex patch made for Super Mario World, SA-1 Pack requires to all other ASM patches apply a [[RAM remap]] for warranting compatibility with the patch. However, without the RAM remap, it would have been impossible to accelerate the game because the SA-1 chip cannot access the S-CPU work memory (WRAM).&lt;br /&gt;
&lt;br /&gt;
For implementation details, see [[SA-1 Root]].&lt;br /&gt;
&lt;br /&gt;
== Features ==&lt;br /&gt;
* Makes the game run up to four times faster.&lt;br /&gt;
* Increase the maximum amount of sprites at once on screen to 22.&lt;br /&gt;
* Increase the maximum amount of sprites on a single sub-level to 255.&lt;br /&gt;
* Reduces loading time of all levels and maps.&lt;br /&gt;
* Increase the maximum ROM size to 8 MB.&lt;br /&gt;
* Offers enhanced bitmap and arithmetic capabilities for better graphics performance.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== MaxTile System ==&lt;br /&gt;
&#039;&#039;&#039;MaxTile System&#039;&#039;&#039; or just &#039;&#039;&#039;MaxTile&#039;&#039;&#039; is a new feature introduced on SA-1 Pack v1.40 that fixes all known OAM issues involving the game, allowing custom sprites using both $0200 &amp;amp; $0300 area and implements a basic sprite priority system for custom resources interested in using the MaxTile API directly, while still keeping compatibility with regular and custom sprites that weren&#039;t designed for MaxTile.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
How it works:&lt;br /&gt;
* At the beginning of the frame, $7F:8000 is called and invalidates all OAM data.&lt;br /&gt;
* $0200 - $049F can be used normally on the game.&lt;br /&gt;
* When a sprite is executed, its OAM index is set to $0328.&lt;br /&gt;
* When the next sprite is executed, the previous OAM tiles are copied into a new buffer and the $0328+ is freed so the next sprite can use it.&lt;br /&gt;
* At the end of the frame, the entire OAM is scanned for other tiles and unused tiles are removed.&lt;br /&gt;
* During the process, any tile outside screen is automatically dropped as well, maximizing free OAM slots.&lt;br /&gt;
* The sprite buffer then is copied back to the OAM and all sprites are rendered to the screen.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
In practice however the process is a bit more complex:&lt;br /&gt;
* At the beginning of the frame:&lt;br /&gt;
** $7F:8000 is called and clears all SMW OAM&#039;s table.&lt;br /&gt;
** Reset SA-1&#039;s MaxTile internal pointer to $40:C000.&lt;br /&gt;
* During the frame:&lt;br /&gt;
** $0200 - $049F can be used normally on the game.&lt;br /&gt;
** When a new regular sprite asks for a OAM slot, SA-1 MaxTile will transfer all used tiles between $0328-$03FC to its internal buffer and give slot #$28 ($0328).&lt;br /&gt;
** Sprites made for MaxTile will be able to assign a priority number on its attribute and MaxTile will acknowledge the information at the end of the frame.&lt;br /&gt;
* At the end of the frame:&lt;br /&gt;
** MaxTile will iterate though $0200-$02FC and copy all tiles to its internal buffer and mark as &amp;quot;highest priority&amp;quot;.&lt;br /&gt;
** Copy $0300-$0324 to its internal buffer and mark as &amp;quot;high priority&amp;quot;.&lt;br /&gt;
** Copy $0328-$03FC to its internal buffer and mark as &amp;quot;standard priority&amp;quot;.&lt;br /&gt;
** MaxTile will iterate its internal buffer and will copy all tiles marked as &amp;quot;highest priority&amp;quot; starting at $0200, then will repeat the process of &amp;quot;high&amp;quot;, &amp;quot;standard&amp;quot; and &amp;quot;low&amp;quot; priority until it&#039;s over, gradually filling SMW&#039;s buffer with the sorted tiles.&lt;br /&gt;
** While iterating, MaxTile will analyze if each tile is inside or outside screen, discarding the ones outside screen for saving more slots.&lt;br /&gt;
** If it runs out of OAM slots, MaxTile will discard the lowest priority tiles and abort.&lt;br /&gt;
&lt;br /&gt;
To be questioned:&lt;br /&gt;
* What will happen if one of the Mode 7 bosses change the OAM low address?&lt;br /&gt;
* Is it really needed to analyze if each tile is inside or outside screen?&lt;br /&gt;
* What if a sprite stores to $0400-$041F directly?&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Priority system ===&lt;br /&gt;
When working with MaxTile, you can continue storing to $0200-$02FC directly for setting your own priority (but with static tile management), you can use $0328+ for using as standard sprite priority or you can use its built-in priority system that will automatically ensure that your tiles are placed on the requested order.&lt;br /&gt;
&lt;br /&gt;
The available priorities are:&lt;br /&gt;
# Maximum priority: store all tiles before the ones statically stored at $0200-$02FC. This is useful for sprite status bar or other status text.&lt;br /&gt;
# High priority: store all tiles before the ones statically stored at $0300-$0324. This is useful if you wanna make sprite appears in front of the player and yoshi like custom powerups or even additional players. It can also be useful for platforms and clouds.&lt;br /&gt;
# Standard priority: store all tiles in the same order as the sprites, so between $0328-$03FC. Useful for standard sprites that you don&#039;t really have to worry about the priority between them.&lt;br /&gt;
# Low priority: store all tiles after the ones normally written at $0328-$03FC. Useful for custom sprite backgrounds.&lt;br /&gt;
&lt;br /&gt;
Some SMW sprites has hardcoded priorities and because of that they were adjusted to work with MaxTile&#039;s priority system. The following sprites are affected:&lt;br /&gt;
* Lakitu&#039;s cloud&lt;br /&gt;
* Yoshi&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Memory management ===&lt;br /&gt;
Although SA-1 Pack for Super Mario World has a considerable amount of free memory on SA-1 side, it&#039;s always on concern about memory use when you are talking about SMW hacking.&lt;br /&gt;
&lt;br /&gt;
The initial MaxTile idea would require only 384-400 free RAM bytes, but with the so-requested priority system, we ran into the following issue: although the OAM has only 128 sprite slots, we don&#039;t know how many slots will each priority take. It might sound impossible, but priority #2 or priority #4 can take almost all slots. Or vice-versa, priority #3 can take most of the slots or priority #1 can end up completely empty.&lt;br /&gt;
&lt;br /&gt;
The simplest approach would be letting each priority have all slots available: 512 bytes main table + 128 bytes attribute table. With four priorities available, you would end up spending 2560 bytes of RAM, plus the pointers of each one. Overkill considering there are only 128 free slots and in the end a good chunk of the RAM will end up unused.&lt;br /&gt;
&lt;br /&gt;
An alternative approach is making priority #2 and priority #4 reversed, so they will decrement the pointer and fill the previous priority buffer, but that would not allow custom sprites change priority by just swapping the pointer, requiring different graphics routines for each one.&lt;br /&gt;
&lt;br /&gt;
Another thought approach was instead of using 2560 bytes of RAM, is using 2048 bytes at $40:C000-$40:C7FF so it could be mapped to $6000-$7FFF using the $2224 and $2225 SA-1 registers. However, each there would be only enough free space for three OAM buffers for four different priorities, which we would be forced to have two or three profiles with less OAM slots available and different performance profiles would be needed to implement (one that gives more free slots to low priority, another that gives more free slots to high priority, etc.).&lt;br /&gt;
&lt;br /&gt;
The chosen approach was actually using the unused bits of properties table to define sprite priority (#$00 - normal, #$40 - low, #$80 - highest, #$C0 - high), reducing the amount of required memory to 512 + 128 (main draw buffer and properties) + pointers, keeping the cycle complexity somewhat similar (four table iterations).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Programming reference ===&lt;br /&gt;
&lt;br /&gt;
* $6200-$63FF: SMW&#039;s OAM table. An Y value of #$F0 means the slot is empty.&lt;br /&gt;
* $6400-$641F: SMW&#039;s OAM attribute table. No sprite should ever modify this value directly, unless if the finish OAM write is not called (and therefore MaxTile won&#039;t run), like on the Nintendo presents screen.&lt;br /&gt;
* $6420-$649F: SMW&#039;s OAM expanded attribute table. Format: --OO --sH, where OO is priority (0-standard,1-low,2-maximum,3-high), s is the OAM tile size (8x8 or 16x16) and H is the X position most significant bit (9th).&lt;br /&gt;
* $40:C000-$40:C1FF: MaxTile&#039;s OAM table buffer.&lt;br /&gt;
* $40:C200-$40:C27F: MaxTile&#039;s OAM properties buffer. Format: ---- --sH.&lt;br /&gt;
* $40:C280-$40:C2FF: MaxTile&#039;s OAM priority buffer. Format: F-OO ---, where OO is priority and F is &amp;quot;force empty&amp;quot; flag.&lt;br /&gt;
* $40:C300-$40:C301: MaxTile&#039;s OAM pointer. Every frame it&#039;s reset to #$0000 and gradually incremented though the OAM tiles are copied to the buffer.&lt;br /&gt;
&lt;br /&gt;
[[Category:Super Mario World]] [[Category:ASM]]&lt;/div&gt;</summary>
		<author><name>Vitor Vilela</name></author>
	</entry>
	<entry>
		<id>https://sneslab.net/mw/index.php?title=SA-1_Pack&amp;diff=995</id>
		<title>SA-1 Pack</title>
		<link rel="alternate" type="text/html" href="https://sneslab.net/mw/index.php?title=SA-1_Pack&amp;diff=995"/>
		<updated>2019-12-01T02:44:18Z</updated>

		<summary type="html">&lt;p&gt;Vitor Vilela: Programming reference of MaxTile.&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&#039;&#039;&#039;SA-1 Pack&#039;&#039;&#039; is a package of patches for activating and optimizing the [[SA-1]] system for [[Super Mario World]], with emphasis on eliminating slowdown, game limitations and accelerating the engine to the maximum possible. Unlike [[SA-1 Root]], SA-1 Pack is focused for [[ROM hacking]] and it includes several features for implementing new features for the game using the chip.&lt;br /&gt;
&lt;br /&gt;
Being the most complex patch made for Super Mario World, SA-1 Pack requires to all other ASM patches apply a [[RAM remap]] for warranting compatibility with the patch. However, without the RAM remap, it would have been impossible to accelerate the game because the SA-1 chip cannot access the S-CPU work memory (WRAM).&lt;br /&gt;
&lt;br /&gt;
For implementation details, see [[SA-1 Root]].&lt;br /&gt;
&lt;br /&gt;
== Features ==&lt;br /&gt;
* Makes the game run up to four times faster.&lt;br /&gt;
* Increase the maximum amount of sprites at once on screen to 22.&lt;br /&gt;
* Increase the maximum amount of sprites on a single sub-level to 255.&lt;br /&gt;
* Reduces loading time of all levels and maps.&lt;br /&gt;
* Increase the maximum ROM size to 8 MB.&lt;br /&gt;
* Offers enhanced bitmap and arithmetic capabilities for better graphics performance.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== MaxTile System ==&lt;br /&gt;
&#039;&#039;&#039;MaxTile System&#039;&#039;&#039; or just &#039;&#039;&#039;MaxTile&#039;&#039;&#039; is a new feature introduced on SA-1 Pack v1.40 that fixes all known OAM issues involving the game, allowing custom sprites using both $0200 &amp;amp; $0300 area and implements a basic sprite priority system for custom resources interested in using the MaxTile API directly, while still keeping compatibility with regular and custom sprites that weren&#039;t designed for MaxTile.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
How it works:&lt;br /&gt;
* At the beginning of the frame, $7F:8000 is called and invalidates all OAM data.&lt;br /&gt;
* $0200 - $049F can be used normally on the game.&lt;br /&gt;
* When a sprite is executed, its OAM index is set to $0328.&lt;br /&gt;
* When the next sprite is executed, the previous OAM tiles are copied into a new buffer and the $0328+ is freed so the next sprite can use it.&lt;br /&gt;
* At the end of the frame, the entire OAM is scanned for other tiles and unused tiles are removed.&lt;br /&gt;
* During the process, any tile outside screen is automatically dropped as well, maximizing free OAM slots.&lt;br /&gt;
* The sprite buffer then is copied back to the OAM and all sprites are rendered to the screen.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
In practice however the process is a bit more complex:&lt;br /&gt;
* At the beginning of the frame:&lt;br /&gt;
** $7F:8000 is called and clears all SMW OAM&#039;s table.&lt;br /&gt;
** Reset SA-1&#039;s MaxTile internal pointer to $40:C000.&lt;br /&gt;
* During the frame:&lt;br /&gt;
** $0200 - $049F can be used normally on the game.&lt;br /&gt;
** When a new regular sprite asks for a OAM slot, SA-1 MaxTile will transfer all used tiles between $0328-$03FC to its internal buffer and give slot #$28 ($0328).&lt;br /&gt;
** Sprites made for MaxTile will be able to assign a priority number on its attribute and MaxTile will acknowledge the information at the end of the frame.&lt;br /&gt;
* At the end of the frame:&lt;br /&gt;
** MaxTile will iterate though $0200-$02FC and copy all tiles to its internal buffer and mark as &amp;quot;highest priority&amp;quot;.&lt;br /&gt;
** Copy $0300-$0324 to its internal buffer and mark as &amp;quot;high priority&amp;quot;.&lt;br /&gt;
** Copy $0328-$03FC to its internal buffer and mark as &amp;quot;standard priority&amp;quot;.&lt;br /&gt;
** MaxTile will iterate its internal buffer and will copy all tiles marked as &amp;quot;highest priority&amp;quot; starting at $0200, then will repeat the process of &amp;quot;high&amp;quot;, &amp;quot;standard&amp;quot; and &amp;quot;low&amp;quot; priority until it&#039;s over, gradually filling SMW&#039;s buffer with the sorted tiles.&lt;br /&gt;
** While iterating, MaxTile will analyze if each tile is inside or outside screen, discarding the ones outside screen for saving more slots.&lt;br /&gt;
** If it runs out of OAM slots, MaxTile will discard the lowest priority tiles and abort.&lt;br /&gt;
&lt;br /&gt;
To be questioned:&lt;br /&gt;
* What will happen if one of the Mode 7 bosses change the OAM low address?&lt;br /&gt;
* Is it really needed to analyze if each tile is inside or outside screen?&lt;br /&gt;
* What if a sprite stores to $0400-$041F directly?&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Priority system ===&lt;br /&gt;
When working with MaxTile, you can continue storing to $0200-$02FC directly for setting your own priority (but with static tile management), you can use $0328+ for using as standard sprite priority or you can use its built-in priority system that will automatically ensure that your tiles are placed on the requested order.&lt;br /&gt;
&lt;br /&gt;
The available priorities are:&lt;br /&gt;
# Maximum priority: store all tiles before the ones statically stored at $0200-$02FC. This is useful for sprite status bar or other status text.&lt;br /&gt;
# High priority: store all tiles before the ones statically stored at $0300-$0324. This is useful if you wanna make sprite appears in front of the player and yoshi like custom powerups or even additional players. It can also be useful for platforms and clouds.&lt;br /&gt;
# Standard priority: store all tiles in the same order as the sprites, so between $0328-$03FC. Useful for standard sprites that you don&#039;t really have to worry about the priority between them.&lt;br /&gt;
# Low priority: store all tiles after the ones normally written at $0328-$03FC. Useful for custom sprite backgrounds.&lt;br /&gt;
&lt;br /&gt;
Some SMW sprites has hardcoded priorities and because of that they were adjusted to work with MaxTile&#039;s priority system. The following sprites are affected:&lt;br /&gt;
* Lakitu&#039;s cloud&lt;br /&gt;
* Yoshi&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Memory management ===&lt;br /&gt;
Although SA-1 Pack for Super Mario World has a considerable amount of free memory on SA-1 side, it&#039;s always on concern about memory use when you are talking about SMW hacking.&lt;br /&gt;
&lt;br /&gt;
The initial MaxTile idea would require only 384-400 free RAM bytes, but with the so-requested priority system, we ran into the following issue: although the OAM has only 128 sprite slots, we don&#039;t know how many slots will each priority take. It might sound impossible, but priority #2 or priority #4 can take almost all slots. Or vice-versa, priority #3 can take most of the slots or priority #1 can end up completely empty.&lt;br /&gt;
&lt;br /&gt;
The simplest approach would be letting each priority have all slots available: 512 bytes main table + 128 bytes attribute table. With four priorities available, you would end up spending 2560 bytes of RAM, plus the pointers of each one. Overkill considering there are only 128 free slots and in the end a good chunk of the RAM will end up unused.&lt;br /&gt;
&lt;br /&gt;
An alternative approach is making priority #2 and priority #4 reversed, so they will decrement the pointer and fill the previous priority buffer, but that would not allow custom sprites change priority by just swapping the pointer, requiring different graphics routines for each one.&lt;br /&gt;
&lt;br /&gt;
Another thought approach was instead of using 2560 bytes of RAM, is using 2048 bytes at $40:C000-$40:C7FF so it could be mapped to $6000-$7FFF using the $2224 and $2225 SA-1 registers. However, each there would be only enough free space for three OAM buffers for four different priorities, which we would be forced to have two or three profiles with less OAM slots available and different performance profiles would be needed to implement (one that gives more free slots to low priority, another that gives more free slots to high priority, etc.).&lt;br /&gt;
&lt;br /&gt;
The chosen approach was actually using the unused bits of properties table to define sprite priority (#$00 - normal, #$40 - low, #$80 - highest, #$C0 - high), reducing the amount of required memory to 512 + 128 (main draw buffer and properties) + pointers, keeping the cycle complexity somewhat similar (four table iterations).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Programming reference ===&lt;br /&gt;
&lt;br /&gt;
* $6200-$63FF: SMW&#039;s OAM table. An Y value of #$F0 means the slot is empty.&lt;br /&gt;
* $6400-$641F: SMW&#039;s OAM attribute table. No sprite should ever modify this value directly, unless if the finish OAM write is not called (and therefore MaxTile won&#039;t run), like on the Nintendo presents screen.&lt;br /&gt;
* $6420-$649F: SMW&#039;s OAM expanded attribute table. Format: --OO --sH, where OO is priority (0-standard,1-low,2-maximum,3-high), s is the OAM tile size (8x8 or 16x16) and H is the X position most significant bit (9th).&lt;br /&gt;
* $40:C000-$40:C1FF: MaxTile&#039;s OAM table buffer.&lt;br /&gt;
* $40:C200-$40:C27F: MaxTile&#039;s OAM properties buffer. Same format as $0420-$049F.&lt;br /&gt;
* $40:C280-$40:C281: MaxTile&#039;s OAM pointer. Every frame it&#039;s reset to #$0000 and gradually incremented though the OAM tiles are copied to the buffer.&lt;br /&gt;
&lt;br /&gt;
[[Category:Super Mario World]] [[Category:ASM]]&lt;/div&gt;</summary>
		<author><name>Vitor Vilela</name></author>
	</entry>
	<entry>
		<id>https://sneslab.net/mw/index.php?title=SA-1_Pack&amp;diff=994</id>
		<title>SA-1 Pack</title>
		<link rel="alternate" type="text/html" href="https://sneslab.net/mw/index.php?title=SA-1_Pack&amp;diff=994"/>
		<updated>2019-12-01T01:38:24Z</updated>

		<summary type="html">&lt;p&gt;Vitor Vilela: /* Priority system */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&#039;&#039;&#039;SA-1 Pack&#039;&#039;&#039; is a package of patches for activating and optimizing the [[SA-1]] system for [[Super Mario World]], with emphasis on eliminating slowdown, game limitations and accelerating the engine to the maximum possible. Unlike [[SA-1 Root]], SA-1 Pack is focused for [[ROM hacking]] and it includes several features for implementing new features for the game using the chip.&lt;br /&gt;
&lt;br /&gt;
Being the most complex patch made for Super Mario World, SA-1 Pack requires to all other ASM patches apply a [[RAM remap]] for warranting compatibility with the patch. However, without the RAM remap, it would have been impossible to accelerate the game because the SA-1 chip cannot access the S-CPU work memory (WRAM).&lt;br /&gt;
&lt;br /&gt;
For implementation details, see [[SA-1 Root]].&lt;br /&gt;
&lt;br /&gt;
== Features ==&lt;br /&gt;
* Makes the game run up to four times faster.&lt;br /&gt;
* Increase the maximum amount of sprites at once on screen to 22.&lt;br /&gt;
* Increase the maximum amount of sprites on a single sub-level to 255.&lt;br /&gt;
* Reduces loading time of all levels and maps.&lt;br /&gt;
* Increase the maximum ROM size to 8 MB.&lt;br /&gt;
* Offers enhanced bitmap and arithmetic capabilities for better graphics performance.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== MaxTile System ==&lt;br /&gt;
&#039;&#039;&#039;MaxTile System&#039;&#039;&#039; or just &#039;&#039;&#039;MaxTile&#039;&#039;&#039; is a new feature introduced on SA-1 Pack v1.40 that fixes all known OAM issues involving the game, allowing custom sprites using both $0200 &amp;amp; $0300 area and implements a basic sprite priority system for custom resources interested in using the MaxTile API directly, while still keeping compatibility with regular and custom sprites that weren&#039;t designed for MaxTile.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
How it works:&lt;br /&gt;
* At the beginning of the frame, $7F:8000 is called and invalidates all OAM data.&lt;br /&gt;
* $0200 - $049F can be used normally on the game.&lt;br /&gt;
* When a sprite is executed, its OAM index is set to $0328.&lt;br /&gt;
* When the next sprite is executed, the previous OAM tiles are copied into a new buffer and the $0328+ is freed so the next sprite can use it.&lt;br /&gt;
* At the end of the frame, the entire OAM is scanned for other tiles and unused tiles are removed.&lt;br /&gt;
* During the process, any tile outside screen is automatically dropped as well, maximizing free OAM slots.&lt;br /&gt;
* The sprite buffer then is copied back to the OAM and all sprites are rendered to the screen.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
In practice however the process is a bit more complex:&lt;br /&gt;
* At the beginning of the frame:&lt;br /&gt;
** $7F:8000 is called and clears all SMW OAM&#039;s table.&lt;br /&gt;
** Reset SA-1&#039;s MaxTile internal pointer to $40:C000.&lt;br /&gt;
* During the frame:&lt;br /&gt;
** $0200 - $049F can be used normally on the game.&lt;br /&gt;
** When a new regular sprite asks for a OAM slot, SA-1 MaxTile will transfer all used tiles between $0328-$03FC to its internal buffer and give slot #$28 ($0328).&lt;br /&gt;
** Sprites made for MaxTile will be able to assign a priority number on its attribute and MaxTile will acknowledge the information at the end of the frame.&lt;br /&gt;
* At the end of the frame:&lt;br /&gt;
** MaxTile will iterate though $0200-$02FC and copy all tiles to its internal buffer and mark as &amp;quot;highest priority&amp;quot;.&lt;br /&gt;
** Copy $0300-$0324 to its internal buffer and mark as &amp;quot;high priority&amp;quot;.&lt;br /&gt;
** Copy $0328-$03FC to its internal buffer and mark as &amp;quot;standard priority&amp;quot;.&lt;br /&gt;
** MaxTile will iterate its internal buffer and will copy all tiles marked as &amp;quot;highest priority&amp;quot; starting at $0200, then will repeat the process of &amp;quot;high&amp;quot;, &amp;quot;standard&amp;quot; and &amp;quot;low&amp;quot; priority until it&#039;s over, gradually filling SMW&#039;s buffer with the sorted tiles.&lt;br /&gt;
** While iterating, MaxTile will analyze if each tile is inside or outside screen, discarding the ones outside screen for saving more slots.&lt;br /&gt;
** If it runs out of OAM slots, MaxTile will discard the lowest priority tiles and abort.&lt;br /&gt;
&lt;br /&gt;
To be questioned:&lt;br /&gt;
* What will happen if one of the Mode 7 bosses change the OAM low address?&lt;br /&gt;
* Is it really needed to analyze if each tile is inside or outside screen?&lt;br /&gt;
* What if a sprite stores to $0400-$041F directly?&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Priority system ===&lt;br /&gt;
When working with MaxTile, you can continue storing to $0200-$02FC directly for setting your own priority (but with static tile management), you can use $0328+ for using as standard sprite priority or you can use its built-in priority system that will automatically ensure that your tiles are placed on the requested order.&lt;br /&gt;
&lt;br /&gt;
The available priorities are:&lt;br /&gt;
# Maximum priority: store all tiles before the ones statically stored at $0200-$02FC. This is useful for sprite status bar or other status text.&lt;br /&gt;
# High priority: store all tiles before the ones statically stored at $0300-$0324. This is useful if you wanna make sprite appears in front of the player and yoshi like custom powerups or even additional players. It can also be useful for platforms and clouds.&lt;br /&gt;
# Standard priority: store all tiles in the same order as the sprites, so between $0328-$03FC. Useful for standard sprites that you don&#039;t really have to worry about the priority between them.&lt;br /&gt;
# Low priority: store all tiles after the ones normally written at $0328-$03FC. Useful for custom sprite backgrounds.&lt;br /&gt;
&lt;br /&gt;
Some SMW sprites has hardcoded priorities and because of that they were adjusted to work with MaxTile&#039;s priority system. The following sprites are affected:&lt;br /&gt;
* Lakitu&#039;s cloud&lt;br /&gt;
* Yoshi&lt;br /&gt;
&lt;br /&gt;
=== Memory management ===&lt;br /&gt;
Although SA-1 Pack for Super Mario World has a considerable amount of free memory on SA-1 side, it&#039;s always on concern about memory use when you are talking about SMW hacking.&lt;br /&gt;
&lt;br /&gt;
The initial MaxTile idea would require only 384-400 free RAM bytes, but with the so-requested priority system, we ran into the following issue: although the OAM has only 128 sprite slots, we don&#039;t know how many slots will each priority take. It might sound impossible, but priority #2 or priority #4 can take almost all slots. Or vice-versa, priority #3 can take most of the slots or priority #1 can end up completely empty.&lt;br /&gt;
&lt;br /&gt;
The simplest approach would be letting each priority have all slots available: 512 bytes main table + 128 bytes attribute table. With four priorities available, you would end up spending 2560 bytes of RAM, plus the pointers of each one. Overkill considering there are only 128 free slots and in the end a good chunk of the RAM will end up unused.&lt;br /&gt;
&lt;br /&gt;
An alternative approach is making priority #2 and priority #4 reversed, so they will decrement the pointer and fill the previous priority buffer, but that would not allow custom sprites change priority by just swapping the pointer, requiring different graphics routines for each one.&lt;br /&gt;
&lt;br /&gt;
Another thought approach was instead of using 2560 bytes of RAM, is using 2048 bytes at $40:C000-$40:C7FF so it could be mapped to $6000-$7FFF using the $2224 and $2225 SA-1 registers. However, each there would be only enough free space for three OAM buffers for four different priorities, which we would be forced to have two or three profiles with less OAM slots available and different performance profiles would be needed to implement (one that gives more free slots to low priority, another that gives more free slots to high priority, etc.).&lt;br /&gt;
&lt;br /&gt;
The chosen approach was actually using the unused bits of properties table to define sprite priority (#$00 - normal, #$40 - low, #$80 - highest, #$C0 - high), reducing the amount of required memory to 512 + 128 (main draw buffer and properties) + pointers, keeping the cycle complexity somewhat similar (four table iterations).&lt;br /&gt;
&lt;br /&gt;
[[Category:Super Mario World]] [[Category:ASM]]&lt;/div&gt;</summary>
		<author><name>Vitor Vilela</name></author>
	</entry>
	<entry>
		<id>https://sneslab.net/mw/index.php?title=SA-1_Pack&amp;diff=993</id>
		<title>SA-1 Pack</title>
		<link rel="alternate" type="text/html" href="https://sneslab.net/mw/index.php?title=SA-1_Pack&amp;diff=993"/>
		<updated>2019-12-01T01:36:28Z</updated>

		<summary type="html">&lt;p&gt;Vitor Vilela: /* MaxTile System */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&#039;&#039;&#039;SA-1 Pack&#039;&#039;&#039; is a package of patches for activating and optimizing the [[SA-1]] system for [[Super Mario World]], with emphasis on eliminating slowdown, game limitations and accelerating the engine to the maximum possible. Unlike [[SA-1 Root]], SA-1 Pack is focused for [[ROM hacking]] and it includes several features for implementing new features for the game using the chip.&lt;br /&gt;
&lt;br /&gt;
Being the most complex patch made for Super Mario World, SA-1 Pack requires to all other ASM patches apply a [[RAM remap]] for warranting compatibility with the patch. However, without the RAM remap, it would have been impossible to accelerate the game because the SA-1 chip cannot access the S-CPU work memory (WRAM).&lt;br /&gt;
&lt;br /&gt;
For implementation details, see [[SA-1 Root]].&lt;br /&gt;
&lt;br /&gt;
== Features ==&lt;br /&gt;
* Makes the game run up to four times faster.&lt;br /&gt;
* Increase the maximum amount of sprites at once on screen to 22.&lt;br /&gt;
* Increase the maximum amount of sprites on a single sub-level to 255.&lt;br /&gt;
* Reduces loading time of all levels and maps.&lt;br /&gt;
* Increase the maximum ROM size to 8 MB.&lt;br /&gt;
* Offers enhanced bitmap and arithmetic capabilities for better graphics performance.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== MaxTile System ==&lt;br /&gt;
&#039;&#039;&#039;MaxTile System&#039;&#039;&#039; or just &#039;&#039;&#039;MaxTile&#039;&#039;&#039; is a new feature introduced on SA-1 Pack v1.40 that fixes all known OAM issues involving the game, allowing custom sprites using both $0200 &amp;amp; $0300 area and implements a basic sprite priority system for custom resources interested in using the MaxTile API directly, while still keeping compatibility with regular and custom sprites that weren&#039;t designed for MaxTile.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
How it works:&lt;br /&gt;
* At the beginning of the frame, $7F:8000 is called and invalidates all OAM data.&lt;br /&gt;
* $0200 - $049F can be used normally on the game.&lt;br /&gt;
* When a sprite is executed, its OAM index is set to $0328.&lt;br /&gt;
* When the next sprite is executed, the previous OAM tiles are copied into a new buffer and the $0328+ is freed so the next sprite can use it.&lt;br /&gt;
* At the end of the frame, the entire OAM is scanned for other tiles and unused tiles are removed.&lt;br /&gt;
* During the process, any tile outside screen is automatically dropped as well, maximizing free OAM slots.&lt;br /&gt;
* The sprite buffer then is copied back to the OAM and all sprites are rendered to the screen.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
In practice however the process is a bit more complex:&lt;br /&gt;
* At the beginning of the frame:&lt;br /&gt;
** $7F:8000 is called and clears all SMW OAM&#039;s table.&lt;br /&gt;
** Reset SA-1&#039;s MaxTile internal pointer to $40:C000.&lt;br /&gt;
* During the frame:&lt;br /&gt;
** $0200 - $049F can be used normally on the game.&lt;br /&gt;
** When a new regular sprite asks for a OAM slot, SA-1 MaxTile will transfer all used tiles between $0328-$03FC to its internal buffer and give slot #$28 ($0328).&lt;br /&gt;
** Sprites made for MaxTile will be able to assign a priority number on its attribute and MaxTile will acknowledge the information at the end of the frame.&lt;br /&gt;
* At the end of the frame:&lt;br /&gt;
** MaxTile will iterate though $0200-$02FC and copy all tiles to its internal buffer and mark as &amp;quot;highest priority&amp;quot;.&lt;br /&gt;
** Copy $0300-$0324 to its internal buffer and mark as &amp;quot;high priority&amp;quot;.&lt;br /&gt;
** Copy $0328-$03FC to its internal buffer and mark as &amp;quot;standard priority&amp;quot;.&lt;br /&gt;
** MaxTile will iterate its internal buffer and will copy all tiles marked as &amp;quot;highest priority&amp;quot; starting at $0200, then will repeat the process of &amp;quot;high&amp;quot;, &amp;quot;standard&amp;quot; and &amp;quot;low&amp;quot; priority until it&#039;s over, gradually filling SMW&#039;s buffer with the sorted tiles.&lt;br /&gt;
** While iterating, MaxTile will analyze if each tile is inside or outside screen, discarding the ones outside screen for saving more slots.&lt;br /&gt;
** If it runs out of OAM slots, MaxTile will discard the lowest priority tiles and abort.&lt;br /&gt;
&lt;br /&gt;
To be questioned:&lt;br /&gt;
* What will happen if one of the Mode 7 bosses change the OAM low address?&lt;br /&gt;
* Is it really needed to analyze if each tile is inside or outside screen?&lt;br /&gt;
* What if a sprite stores to $0400-$041F directly?&lt;br /&gt;
&lt;br /&gt;
=== Priority system ===&lt;br /&gt;
When working with MaxTile, you can continue storing to $0200-$02FC directly for setting your own priority (but with static tile management), you can use $0328+ for using as standard sprite priority or you can use its built-in priority system that will automatically ensure that your tiles are placed on the requested order.&lt;br /&gt;
&lt;br /&gt;
The available priorities are:&lt;br /&gt;
# Maximum priority: store all tiles before the ones statically stored at $0200-$02FC. This is useful for sprite status bar or other status text.&lt;br /&gt;
# High priority: store all tiles before the ones statically stored at $0300-$0324. This is useful if you wanna make sprite appears in front of the player and yoshi like custom powerups or even additional players. It can also be useful for platforms and clouds.&lt;br /&gt;
# Standard priority: store all tiles in the same order as the sprites, so between $0328-$03FC. Useful for standard sprites that you don&#039;t really have to worry about the priority between them.&lt;br /&gt;
# Low priority: store all tiles after the ones normally written at $0328-$03FC. Useful for custom sprite backgrounds.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Memory management ===&lt;br /&gt;
Although SA-1 Pack for Super Mario World has a considerable amount of free memory on SA-1 side, it&#039;s always on concern about memory use when you are talking about SMW hacking.&lt;br /&gt;
&lt;br /&gt;
The initial MaxTile idea would require only 384-400 free RAM bytes, but with the so-requested priority system, we ran into the following issue: although the OAM has only 128 sprite slots, we don&#039;t know how many slots will each priority take. It might sound impossible, but priority #2 or priority #4 can take almost all slots. Or vice-versa, priority #3 can take most of the slots or priority #1 can end up completely empty.&lt;br /&gt;
&lt;br /&gt;
The simplest approach would be letting each priority have all slots available: 512 bytes main table + 128 bytes attribute table. With four priorities available, you would end up spending 2560 bytes of RAM, plus the pointers of each one. Overkill considering there are only 128 free slots and in the end a good chunk of the RAM will end up unused.&lt;br /&gt;
&lt;br /&gt;
An alternative approach is making priority #2 and priority #4 reversed, so they will decrement the pointer and fill the previous priority buffer, but that would not allow custom sprites change priority by just swapping the pointer, requiring different graphics routines for each one.&lt;br /&gt;
&lt;br /&gt;
Another thought approach was instead of using 2560 bytes of RAM, is using 2048 bytes at $40:C000-$40:C7FF so it could be mapped to $6000-$7FFF using the $2224 and $2225 SA-1 registers. However, each there would be only enough free space for three OAM buffers for four different priorities, which we would be forced to have two or three profiles with less OAM slots available and different performance profiles would be needed to implement (one that gives more free slots to low priority, another that gives more free slots to high priority, etc.).&lt;br /&gt;
&lt;br /&gt;
The chosen approach was actually using the unused bits of properties table to define sprite priority (#$00 - normal, #$40 - low, #$80 - highest, #$C0 - high), reducing the amount of required memory to 512 + 128 (main draw buffer and properties) + pointers, keeping the cycle complexity somewhat similar (four table iterations).&lt;br /&gt;
&lt;br /&gt;
[[Category:Super Mario World]] [[Category:ASM]]&lt;/div&gt;</summary>
		<author><name>Vitor Vilela</name></author>
	</entry>
</feed>