<?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=MarioFanGamer</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=MarioFanGamer"/>
	<link rel="alternate" type="text/html" href="https://sneslab.net/wiki/Special:Contributions/MarioFanGamer"/>
	<updated>2026-09-16T19:52:41Z</updated>
	<subtitle>User contributions</subtitle>
	<generator>MediaWiki 1.39.5</generator>
	<entry>
		<id>https://sneslab.net/mw/index.php?title=FROM_(Super_FX)&amp;diff=18080</id>
		<title>FROM (Super FX)</title>
		<link rel="alternate" type="text/html" href="https://sneslab.net/mw/index.php?title=FROM_(Super_FX)&amp;diff=18080"/>
		<updated>2024-07-15T12:48:45Z</updated>

		<summary type="html">&lt;p&gt;MarioFanGamer: Added note on execution of MOVES.&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;float:right;clear:right;width:50%&amp;quot;&lt;br /&gt;
!colspan=&amp;quot;8&amp;quot;|Basic Info&lt;br /&gt;
|+&lt;br /&gt;
|&#039;&#039;&#039;Addressing Mode&#039;&#039;&#039;&lt;br /&gt;
|&#039;&#039;&#039;Opcode&#039;&#039;&#039;&lt;br /&gt;
|&#039;&#039;&#039;Length&#039;&#039;&#039;&lt;br /&gt;
|&#039;&#039;&#039;ROM Speed&#039;&#039;&#039;&lt;br /&gt;
|&#039;&#039;&#039;RAM Speed&#039;&#039;&#039;&lt;br /&gt;
|&#039;&#039;&#039;Cache Speed&#039;&#039;&#039;&lt;br /&gt;
|+&lt;br /&gt;
|[[Implied]] (type 1)&lt;br /&gt;
|Bn&lt;br /&gt;
|1 byte&lt;br /&gt;
|3 cycles&lt;br /&gt;
|3 cycles&lt;br /&gt;
|1 cycle&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;float:right;clear:right;width:30%&amp;quot;&lt;br /&gt;
!colspan=&amp;quot;9&amp;quot;|Flags Affected&lt;br /&gt;
|+&lt;br /&gt;
|[[B Flag|B]]&lt;br /&gt;
|[[ALT1]]&lt;br /&gt;
|[[ALT2]]&lt;br /&gt;
|[[O/V]]&lt;br /&gt;
|[[Sign Flag|S]]&lt;br /&gt;
|[[CY]]&lt;br /&gt;
|[[Zero Flag|Z]]&lt;br /&gt;
|+&lt;br /&gt;
|.&lt;br /&gt;
|.&lt;br /&gt;
|.&lt;br /&gt;
|.&lt;br /&gt;
|.&lt;br /&gt;
|.&lt;br /&gt;
|.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;FROM&#039;&#039;&#039; is a [[Super FX]] register prefix instruction that specifies the [[source register]]. The exception is when the [[B Flag]] is set (i.e. a [[WITH]] instruction is executed immediately before) in which case a [[MOVES]] is executed instead with FROM acting as the source and WTIH as the destination.&amp;lt;sup&amp;gt;[1]&amp;lt;/sup&amp;gt;&lt;br /&gt;
&lt;br /&gt;
No flags are affected.&lt;br /&gt;
&lt;br /&gt;
==== Syntax ====&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
FROM Rn&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Example ====&lt;br /&gt;
To set R&amp;lt;sub&amp;gt;2&amp;lt;/sub&amp;gt; as the source register, run:&lt;br /&gt;
 FROM R&amp;lt;sub&amp;gt;2&amp;lt;/sub&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== See Also ===&lt;br /&gt;
* [[TO (Super FX)]]&lt;br /&gt;
* [[WITH (Super FX)]]&lt;br /&gt;
* [[MOVES (Super FX)]]&lt;br /&gt;
&lt;br /&gt;
=== Notes ===&lt;br /&gt;
&amp;lt;sup&amp;gt;[1]&amp;lt;/sup&amp;gt; The information in the developer manual is actually contradictory. The description of FROM claims the transfer happens from R&amp;lt;sub&amp;gt;n&amp;lt;/sub&amp;gt; (set by FROM) to D&amp;lt;sub&amp;gt;reg&amp;lt;/sub&amp;gt; (set by WITH) whereas that of MOVES R&amp;lt;sub&amp;gt;n&amp;lt;/sub&amp;gt;, R&amp;lt;sub&amp;gt;n&amp;lt;/sub&amp;gt;&#039; claims to transfer from R&amp;lt;sub&amp;gt;n&amp;lt;/sub&amp;gt;&#039; (set by WITH) to R&amp;lt;sub&amp;gt;n&amp;lt;/sub&amp;gt; (set by FROM) instead. According to [[fullsnes]], it&#039;s the description of MOVES which is wrong.&lt;br /&gt;
&lt;br /&gt;
=== External Links ===&lt;br /&gt;
* Official Nintendo documentation on FROM: 9.34 on [https://archive.org/details/SNESDevManual/book2/page/n204 page 2-9-48 of Book II]&lt;br /&gt;
* Official Nintendo documentation on Register Prefixes: [https://archive.org/details/SNESDevManual/book2/page/n129 page 2-6-7 of Book II]&lt;br /&gt;
&lt;br /&gt;
[[Category:ASM]]&lt;br /&gt;
[[Category:Super FX]]&lt;br /&gt;
[[Category:Register Prefix Instructions]]&lt;br /&gt;
[[Category:One-byte Instructions]]&lt;/div&gt;</summary>
		<author><name>MarioFanGamer</name></author>
	</entry>
	<entry>
		<id>https://sneslab.net/mw/index.php?title=MOVE_(Super_FX)&amp;diff=18078</id>
		<title>MOVE (Super FX)</title>
		<link rel="alternate" type="text/html" href="https://sneslab.net/mw/index.php?title=MOVE_(Super_FX)&amp;diff=18078"/>
		<updated>2024-07-15T12:39:24Z</updated>

		<summary type="html">&lt;p&gt;MarioFanGamer: Added technical details and components of MOVE Rn, Rn&amp;#039;.&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;float:right;clear:right;width:50%&amp;quot;&lt;br /&gt;
!colspan=&amp;quot;8&amp;quot;|Basic Info&lt;br /&gt;
|+&lt;br /&gt;
|&#039;&#039;&#039;Addressing Mode&#039;&#039;&#039;&lt;br /&gt;
|&#039;&#039;&#039;Opcode&#039;&#039;&#039;&lt;br /&gt;
|&#039;&#039;&#039;Length&#039;&#039;&#039;&lt;br /&gt;
|&#039;&#039;&#039;ROM Speed&#039;&#039;&#039;&lt;br /&gt;
|&#039;&#039;&#039;RAM Speed&#039;&#039;&#039;&lt;br /&gt;
|&#039;&#039;&#039;Cache Speed&#039;&#039;&#039;&lt;br /&gt;
|+&lt;br /&gt;
|&lt;br /&gt;
|2n&#039;1n&lt;br /&gt;
|2 bytes&lt;br /&gt;
|6 cycles&lt;br /&gt;
|6 cycles&lt;br /&gt;
|2 cycles&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;float:right;clear:right;width:30%&amp;quot;&lt;br /&gt;
!colspan=&amp;quot;9&amp;quot;|Flags Affected&lt;br /&gt;
|+&lt;br /&gt;
|[[B Flag|B]]&lt;br /&gt;
|[[ALT1]]&lt;br /&gt;
|[[ALT2]]&lt;br /&gt;
|[[O/V]]&lt;br /&gt;
|[[Sign Flag|S]]&lt;br /&gt;
|[[CY]]&lt;br /&gt;
|[[Zero Flag|Z]]&lt;br /&gt;
|+&lt;br /&gt;
|0&lt;br /&gt;
|0&lt;br /&gt;
|0&lt;br /&gt;
|.&lt;br /&gt;
|.&lt;br /&gt;
|.&lt;br /&gt;
|.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MOVE&#039;&#039;&#039; is the name of a [[Super FX]] instruction and macro instructions that moves the value of a register or immediate value into another register or RAM.&lt;br /&gt;
&lt;br /&gt;
The [[ALT0]] state is restored.&lt;br /&gt;
&lt;br /&gt;
==== Syntax ====&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
MOVE Rn, Rn&#039;&lt;br /&gt;
MOVE Rn, #xx&lt;br /&gt;
MOVE Rn, (xx)&lt;br /&gt;
MOVE (xx), Rn&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== MOVE R&amp;lt;sub&amp;gt;n&amp;lt;/sub&amp;gt;, R&amp;lt;sub&amp;gt;n&#039;&amp;lt;/sub&amp;gt; ====&lt;br /&gt;
&lt;br /&gt;
MOVE R&amp;lt;sub&amp;gt;n&amp;lt;/sub&amp;gt;, R&amp;lt;sub&amp;gt;n&#039;&amp;lt;/sub&amp;gt; as a GSU instruction transfers the value from R&amp;lt;sub&amp;gt;n&#039;&amp;lt;/sub&amp;gt; to R&amp;lt;sub&amp;gt;n&amp;lt;/sub&amp;gt;. The opcode is strictly speaking an alterantive execution of [[TO]], namely when the [[B flag]] is set i.e. a TO is executed immediately after a [[WITH]]. The register of WITH R&amp;lt;sub&amp;gt;n&#039;&amp;lt;/sub&amp;gt; is the source and the register of TO R&amp;lt;sub&amp;gt;n&amp;lt;/sub&amp;gt; is the destination (for this reason, it is safe to assume that the transfer happens from S&amp;lt;sub&amp;gt;reg&amp;lt;/sub&amp;gt; to D&amp;lt;sub&amp;gt;reg&amp;lt;/sub&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
As such, the execution of both codes are identical:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
; R0 = 52BAh&lt;br /&gt;
WITH R0&lt;br /&gt;
TO R13&lt;br /&gt;
; R13 also is now 52BAh&lt;br /&gt;
&lt;br /&gt;
; R0 = 52BAh&lt;br /&gt;
WITH R13,R0&lt;br /&gt;
; R13 also is now 52BAh&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Example ====&lt;br /&gt;
Let:&lt;br /&gt;
 R&amp;lt;sub&amp;gt;14&amp;lt;/sub&amp;gt; = 4983h&lt;br /&gt;
 R&amp;lt;sub&amp;gt;8&amp;lt;/sub&amp;gt; = 9264h&lt;br /&gt;
when MOVE R&amp;lt;sub&amp;gt;8&amp;lt;/sub&amp;gt;, R&amp;lt;sub&amp;gt;14&amp;lt;/sub&amp;gt; is executed:&lt;br /&gt;
 R&amp;lt;sub&amp;gt;8&amp;lt;/sub&amp;gt; = 4983h&lt;br /&gt;
&lt;br /&gt;
=== See Also ===&lt;br /&gt;
* [[B flag]]&lt;br /&gt;
* [[MOVES]]&lt;br /&gt;
* [[MOVEW]]&lt;br /&gt;
* [[MOVEB]]&lt;br /&gt;
* [[LM]]&lt;br /&gt;
* [[LMS]]&lt;br /&gt;
&lt;br /&gt;
=== External Links ===&lt;br /&gt;
* Official Super Nintendo development manual on MOVE: 9.57 on [https://archive.org/details/SNESDevManual/book2/page/n237 page 2-9-81 of Book II]&lt;br /&gt;
* Official Super Nintendo development manual on TO: 9.57 on [https://archive.org/details/SNESDevManual/book2/page/n277 page 2-9-48 of Book II]&lt;br /&gt;
&lt;br /&gt;
[[Category:ASM]]&lt;br /&gt;
[[Category:Super FX]]&lt;br /&gt;
[[Category:Data Transfer Instructions]]&lt;br /&gt;
[[Category:Macro Instructions]]&lt;br /&gt;
[[Category:Two-byte Instructions]]&lt;/div&gt;</summary>
		<author><name>MarioFanGamer</name></author>
	</entry>
	<entry>
		<id>https://sneslab.net/mw/index.php?title=B_Flag_(Super_FX)&amp;diff=18069</id>
		<title>B Flag (Super FX)</title>
		<link rel="alternate" type="text/html" href="https://sneslab.net/mw/index.php?title=B_Flag_(Super_FX)&amp;diff=18069"/>
		<updated>2024-07-15T12:08:35Z</updated>

		<summary type="html">&lt;p&gt;MarioFanGamer: Specified which opcodes the B-flag affects.&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;The &#039;&#039;&#039;B flag&#039;&#039;&#039; is on the [[Super FX]], and is set when [[WITH]] runs.&lt;br /&gt;
&lt;br /&gt;
These instructions change their behaviour on the B flag:&lt;br /&gt;
&lt;br /&gt;
*  [[TO]] R&amp;lt;sub&amp;gt;n&#039;&amp;lt;/sub&amp;gt; as [[MOVE]] R&amp;lt;sub&amp;gt;n&amp;lt;/sub&amp;gt;,R&amp;lt;sub&amp;gt;n&#039;&amp;lt;/sub&amp;gt;&lt;br /&gt;
*  [[FROM]] R&amp;lt;sub&amp;gt;n&#039;&amp;lt;/sub&amp;gt; as [[MOVES]] R&amp;lt;sub&amp;gt;n&amp;lt;/sub&amp;gt;,R&amp;lt;sub&amp;gt;n&#039;&amp;lt;/sub&amp;gt;&lt;br /&gt;
&lt;br /&gt;
For both of them, the R&amp;lt;sub&amp;gt;n&amp;lt;/sub&amp;gt; is set by the preceeeding WITH R&amp;lt;sub&amp;gt;n&amp;lt;/sub&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Many instructions clear the B flag, including:&lt;br /&gt;
&lt;br /&gt;
*	[[GSU/ADC|ADC]] R&amp;lt;sub&amp;gt;n&amp;lt;/sub&amp;gt;&lt;br /&gt;
*	[[GSU/ADC|ADC]] #n&lt;br /&gt;
*	[[ADD]] R&amp;lt;sub&amp;gt;n&amp;lt;/sub&amp;gt;&lt;br /&gt;
*	[[ADD]] #n&lt;br /&gt;
*	[[GSU/AND|AND]] R&amp;lt;sub&amp;gt;n&amp;lt;/sub&amp;gt;&lt;br /&gt;
*	[[GSU/AND|AND]] #n&lt;br /&gt;
*	[[ASR]]&lt;br /&gt;
*	[[BIC]] R&amp;lt;sub&amp;gt;n&amp;lt;/sub&amp;gt;&lt;br /&gt;
*	[[BIC]] #n&lt;br /&gt;
*	[[CACHE]]&lt;br /&gt;
*	[[CMODE]]&lt;br /&gt;
*	[[GSU/CMP|CMP]] R&amp;lt;sub&amp;gt;n&amp;lt;/sub&amp;gt;&lt;br /&gt;
*	[[COLOR]]&lt;br /&gt;
*	[[GSU/DEC|DEC]] R&amp;lt;sub&amp;gt;n&amp;lt;/sub&amp;gt;&lt;br /&gt;
*	[[DIV2]]&lt;br /&gt;
*	[[FMULT]]&lt;br /&gt;
*	[[GETB]]&lt;br /&gt;
*	[[GETBH]]&lt;br /&gt;
*	[[GETBL]]&lt;br /&gt;
*	[[GETBS]]&lt;br /&gt;
*	[[GETC]]&lt;br /&gt;
*	[[HIB]]&lt;br /&gt;
*	[[IBT]] R&amp;lt;sub&amp;gt;n&amp;lt;/sub&amp;gt;, #pp&lt;br /&gt;
*	[[GSU/INC|INC]] R&amp;lt;sub&amp;gt;n&amp;lt;/sub&amp;gt;&lt;br /&gt;
*	[[IWT]] R&amp;lt;sub&amp;gt;n&amp;lt;/sub&amp;gt;, #xx&lt;br /&gt;
*	[[GSU/JMP|JMP]] R&amp;lt;sub&amp;gt;n&amp;lt;/sub&amp;gt;&lt;br /&gt;
*	[[LDB]] (R&amp;lt;sub&amp;gt;m&amp;lt;/sub&amp;gt;)&lt;br /&gt;
*	[[LDW]] (R&amp;lt;sub&amp;gt;m&amp;lt;/sub&amp;gt;)&lt;br /&gt;
*	[[LEA]] R&amp;lt;sub&amp;gt;n&amp;lt;/sub&amp;gt;, xx&lt;br /&gt;
*	[[LINK]] #n&lt;br /&gt;
*	[[LJMP]] R&amp;lt;sub&amp;gt;n&amp;lt;/sub&amp;gt;&lt;br /&gt;
*	[[LM]] R&amp;lt;sub&amp;gt;n&amp;lt;/sub&amp;gt;, (xx)&lt;br /&gt;
*	[[LMS]] R&amp;lt;sub&amp;gt;n&amp;lt;/sub&amp;gt;, (yy)&lt;br /&gt;
*	[[LMULT]]&lt;br /&gt;
*	[[LOB]]&lt;br /&gt;
*	[[LOOP]]&lt;br /&gt;
*	[[GSU/LSR|LSR]]&lt;br /&gt;
*	[[MERGE]]&lt;br /&gt;
*	[[MOVE]] R&amp;lt;sub&amp;gt;n&amp;lt;/sub&amp;gt;, R&amp;lt;sub&amp;gt;n&amp;lt;/sub&amp;gt;&#039;&lt;br /&gt;
*	[[MOVES]] R&amp;lt;sub&amp;gt;n&amp;lt;/sub&amp;gt;, R&amp;lt;sub&amp;gt;n&amp;lt;/sub&amp;gt;&#039;&lt;br /&gt;
*	[[MULT]] R&amp;lt;sub&amp;gt;n&amp;lt;/sub&amp;gt;&lt;br /&gt;
*	[[MULT]] #n&lt;br /&gt;
*	[[GSU/NOP|NOP]]&lt;br /&gt;
*	[[NOT]]&lt;br /&gt;
*	[[OR]] R&amp;lt;sub&amp;gt;n&amp;lt;/sub&amp;gt;&lt;br /&gt;
*	[[OR]] #n&lt;br /&gt;
*	[[PLOT]]&lt;br /&gt;
*	[[RAMB]]&lt;br /&gt;
*	[[GSU/ROL|ROL]]&lt;br /&gt;
*	[[ROMB]]&lt;br /&gt;
*	[[GSU/ROR|ROR]]&lt;br /&gt;
*	[[RPIX]]&lt;br /&gt;
*	[[GSU/SBC|SBC]] R&amp;lt;sub&amp;gt;n&amp;lt;/sub&amp;gt;&lt;br /&gt;
*	[[SBK]]&lt;br /&gt;
*	[[SEX]]&lt;br /&gt;
*	[[SM]] (xx), R&amp;lt;sub&amp;gt;n&amp;lt;/sub&amp;gt;&lt;br /&gt;
*	[[SMS]] (yy), R&amp;lt;sub&amp;gt;n&amp;lt;/sub&amp;gt;&lt;br /&gt;
*	[[STB]] (R&amp;lt;sub&amp;gt;m&amp;lt;/sub&amp;gt;)&lt;br /&gt;
*	[[STOP]]&lt;br /&gt;
*	[[STW]] (R&amp;lt;sub&amp;gt;m&amp;lt;/sub&amp;gt;)&lt;br /&gt;
*	[[SUB]] R&amp;lt;sub&amp;gt;n&amp;lt;/sub&amp;gt;&lt;br /&gt;
*	[[SUB]] #n&lt;br /&gt;
*	[[SWAP]]&lt;br /&gt;
*	[[UMULT]] R&amp;lt;sub&amp;gt;n&amp;lt;/sub&amp;gt;&lt;br /&gt;
*	and presumably UMULT #n too&lt;br /&gt;
&lt;br /&gt;
=== See Also ===&lt;br /&gt;
* [[Dither Flag]]&lt;br /&gt;
* [[Break Flag]]&lt;br /&gt;
* [[ALT1]]&lt;br /&gt;
* [[ALT2]]&lt;br /&gt;
&lt;br /&gt;
=== Reference ===&lt;br /&gt;
* [https://archive.org/details/SNESDevManual/book2/page/n158 page 2-9-2 of Book II] of the official Super Nintendo development manual&lt;br /&gt;
&lt;br /&gt;
[[Category:Flags]]&lt;br /&gt;
[[Category:Super FX]]&lt;br /&gt;
[[Category:ASM]]&lt;/div&gt;</summary>
		<author><name>MarioFanGamer</name></author>
	</entry>
	<entry>
		<id>https://sneslab.net/mw/index.php?title=WITH_(Super_FX)&amp;diff=16618</id>
		<title>WITH (Super FX)</title>
		<link rel="alternate" type="text/html" href="https://sneslab.net/mw/index.php?title=WITH_(Super_FX)&amp;diff=16618"/>
		<updated>2024-07-04T14:56:42Z</updated>

		<summary type="html">&lt;p&gt;MarioFanGamer: Added opcode information (opcode, size) from fullsnes and a note&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;float:right;clear:right;width:50%&amp;quot;&lt;br /&gt;
!colspan=&amp;quot;8&amp;quot;|Basic Info&lt;br /&gt;
|+&lt;br /&gt;
|&#039;&#039;&#039;Addressing Mode&#039;&#039;&#039;&lt;br /&gt;
|&#039;&#039;&#039;Opcode&#039;&#039;&#039;&lt;br /&gt;
|&#039;&#039;&#039;Length&#039;&#039;&#039;&lt;br /&gt;
|&#039;&#039;&#039;ROM Speed&#039;&#039;&#039;&lt;br /&gt;
|&#039;&#039;&#039;RAM Speed&#039;&#039;&#039;&lt;br /&gt;
|&#039;&#039;&#039;Cache Speed&#039;&#039;&#039;&lt;br /&gt;
|+&lt;br /&gt;
|&lt;br /&gt;
|2n&amp;lt;sup&amp;gt;[1]&amp;lt;/sup&amp;gt;&lt;br /&gt;
|1 byte&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;float:right;clear:right;width:30%&amp;quot;&lt;br /&gt;
!colspan=&amp;quot;9&amp;quot;|Flags Affected&lt;br /&gt;
|+&lt;br /&gt;
|[[B Flag|B]]&lt;br /&gt;
|[[ALT1]]&lt;br /&gt;
|[[ALT2]]&lt;br /&gt;
|[[O/V]]&lt;br /&gt;
|[[Sign Flag|S]]&lt;br /&gt;
|[[CY]]&lt;br /&gt;
|Z&lt;br /&gt;
|+&lt;br /&gt;
|1&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;WITH&#039;&#039;&#039; is an undocumented{{dubious}} (WITH is mentioned on pages 2-2-8 and 2-6-7 of Book II the Nintendo documentation) [[Super FX]] instruction that sets the register specified by the operand as both the [[source register]] and [[destination register]]. It also sets the B flag which makes it a prefix instruction, more specifically for [[TO]] and [[FROM]] which act like [[MOVE]] and [[MOVES]], respectively, with WITH carrying the source and the modified opcode the destination.&lt;br /&gt;
&lt;br /&gt;
=== Notes ===&lt;br /&gt;
&amp;lt;sup&amp;gt;[1]&amp;lt;/sup&amp;gt;The opcode lacks a dedicated description in the developer manual, this information comes from fullsnes instead. Furthermore, one can deduce that WITH is this opcode in that it&#039;s explicitely mentioned to be the first byte of the MOVE opcode which &#039;&#039;&#039;is&#039;&#039;&#039; documented in the manual.&lt;br /&gt;
&lt;br /&gt;
=== See Also ===&lt;br /&gt;
* [[TO (Super FX)]]&lt;br /&gt;
* [[FROM (Super FX)]]&lt;br /&gt;
* [[B Flag]]&lt;br /&gt;
* [[MOVE (Super FX)]]&lt;br /&gt;
* [[MOVES (Super FX)]]&lt;br /&gt;
&lt;br /&gt;
=== References ===&lt;br /&gt;
* &#039;&#039;Comprehensive Super FX ASM Guide&#039;&#039;, part C (Basic operations): https://www.smwcentral.net/?p=viewthread&amp;amp;t=81548&lt;br /&gt;
* Official Nintendo documentation on Register Prefixes: [https://archive.org/details/SNESDevManual/book2/page/n129 page 2-6-7 of Book II]&lt;br /&gt;
* fullsnes, SNES Cart GSU-n CPU JMP and Prefix Opcodes: https://problemkaputt.de/fullsnes.txt&lt;br /&gt;
&lt;br /&gt;
[[Category:ASM]]&lt;br /&gt;
[[Category:Super FX]]&lt;br /&gt;
[[Category:Register Prefix Instructions]]&lt;/div&gt;</summary>
		<author><name>MarioFanGamer</name></author>
	</entry>
	<entry>
		<id>https://sneslab.net/mw/index.php?title=GETB_(Super_FX)&amp;diff=16080</id>
		<title>GETB (Super FX)</title>
		<link rel="alternate" type="text/html" href="https://sneslab.net/mw/index.php?title=GETB_(Super_FX)&amp;diff=16080"/>
		<updated>2024-06-30T20:15:48Z</updated>

		<summary type="html">&lt;p&gt;MarioFanGamer: /* See Also */ Added other GET* opcopdes.&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;float:right;clear:right;width:50%&amp;quot;&lt;br /&gt;
!colspan=&amp;quot;8&amp;quot;|Basic Info&lt;br /&gt;
|+&lt;br /&gt;
|&#039;&#039;&#039;Opcode&#039;&#039;&#039;&lt;br /&gt;
|&#039;&#039;&#039;Length&#039;&#039;&#039;&lt;br /&gt;
|&#039;&#039;&#039;ROM Speed&#039;&#039;&#039;&lt;br /&gt;
|&#039;&#039;&#039;RAM Speed&#039;&#039;&#039;&lt;br /&gt;
|&#039;&#039;&#039;Cache Speed&#039;&#039;&#039;&lt;br /&gt;
|+&lt;br /&gt;
|EF&lt;br /&gt;
|1 byte&lt;br /&gt;
|3 to 8 cycles&lt;br /&gt;
|3 to 9 cycles&lt;br /&gt;
|1 to 6 cycle&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;float:right;clear:right;width:30%&amp;quot;&lt;br /&gt;
!colspan=&amp;quot;9&amp;quot;|Flags Affected&lt;br /&gt;
|+&lt;br /&gt;
|[[B Flag|B]]&lt;br /&gt;
|[[ALT1]]&lt;br /&gt;
|[[ALT2]]&lt;br /&gt;
|[[O/V]]&lt;br /&gt;
|S&lt;br /&gt;
|[[CY]]&lt;br /&gt;
|Z&lt;br /&gt;
|+&lt;br /&gt;
|0&lt;br /&gt;
|0&lt;br /&gt;
|0&lt;br /&gt;
|.&lt;br /&gt;
|.&lt;br /&gt;
|.&lt;br /&gt;
|.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;GETB&#039;&#039;&#039; (Get Byte) is a [[Super FX]] instruction that loads one byte from the [[ROM buffer]] into the low byte of the [[destination register]].  The high byte of the destination register is zeroed.&lt;br /&gt;
&lt;br /&gt;
=== See Also ===&lt;br /&gt;
* [[GETBH]]&lt;br /&gt;
* [[GETBL]]&lt;br /&gt;
* [[GETBS]]&lt;br /&gt;
* [[GETC]]&lt;br /&gt;
* [[ROMB]]&lt;br /&gt;
&lt;br /&gt;
=== External Links ===&lt;br /&gt;
* Official Super Nintendo development manual on GETB: 9.35 on [https://archive.org/details/SNESDevManual/book2/page/n205 Page 2-9-49 of Book II]&lt;br /&gt;
* example: [https://archive.org/details/SNESDevManual/book2/page/n206 page 2-9-50 of Book II], lbid&lt;br /&gt;
&lt;br /&gt;
[[Category:ASM]]&lt;br /&gt;
[[Category:Super FX]]&lt;br /&gt;
[[Category:Data Transfer Instructions]]&lt;br /&gt;
[[Category:One-byte Instructions]]&lt;/div&gt;</summary>
		<author><name>MarioFanGamer</name></author>
	</entry>
	<entry>
		<id>https://sneslab.net/mw/index.php?title=TO_(Super_FX)&amp;diff=16067</id>
		<title>TO (Super FX)</title>
		<link rel="alternate" type="text/html" href="https://sneslab.net/mw/index.php?title=TO_(Super_FX)&amp;diff=16067"/>
		<updated>2024-06-30T19:09:42Z</updated>

		<summary type="html">&lt;p&gt;MarioFanGamer: Removed code tags from sentence&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;float:right;clear:right;width:50%&amp;quot;&lt;br /&gt;
!colspan=&amp;quot;8&amp;quot;|Basic Info&lt;br /&gt;
|+&lt;br /&gt;
|&#039;&#039;&#039;Opcode&#039;&#039;&#039;&lt;br /&gt;
|&#039;&#039;&#039;Length&#039;&#039;&#039;&lt;br /&gt;
|&#039;&#039;&#039;ROM Speed&#039;&#039;&#039;&lt;br /&gt;
|&#039;&#039;&#039;RAM Speed&#039;&#039;&#039;&lt;br /&gt;
|&#039;&#039;&#039;Cache Speed&#039;&#039;&#039;&lt;br /&gt;
|+&lt;br /&gt;
|1n&lt;br /&gt;
|1 byte&lt;br /&gt;
|3 cycles&lt;br /&gt;
|3 cycles&lt;br /&gt;
|1 cycle&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;float:right;clear:right;width:30%&amp;quot;&lt;br /&gt;
!colspan=&amp;quot;9&amp;quot;|Flags Affected&lt;br /&gt;
|+&lt;br /&gt;
|B&lt;br /&gt;
|[[ALT1]]&lt;br /&gt;
|[[ALT2]]&lt;br /&gt;
|[[O/V]]&lt;br /&gt;
|S&lt;br /&gt;
|[[CY]]&lt;br /&gt;
|Z&lt;br /&gt;
|+&lt;br /&gt;
|.&lt;br /&gt;
|.&lt;br /&gt;
|.&lt;br /&gt;
|.&lt;br /&gt;
|.&lt;br /&gt;
|.&lt;br /&gt;
|.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;TO&#039;&#039;&#039; is a [[Super FX]] register prefix instruction that specifies the [[destination register]]. The exception is when the [[B Flag]] is set (i.e. a [[WITH]] instruction is executed immediately before) in which case a [[MOVE]] is executed instead with WITH acting as the source and TO as the destination.&lt;br /&gt;
&lt;br /&gt;
No flags are affected.&lt;br /&gt;
&lt;br /&gt;
=== See Also ===&lt;br /&gt;
* [[FROM (Super FX)]]&lt;br /&gt;
* [[WITH (Super FX)]]&lt;br /&gt;
* [[MOVE (Super FX)]]&lt;br /&gt;
&lt;br /&gt;
=== External Links ===&lt;br /&gt;
* Official Nintendo documentation on TO: [https://archive.org/details/SNESDevManual/book2/page/n277 page 2-9-121 of Book II]&lt;br /&gt;
* Official Nintendo documentation on Register Prefixes: [https://archive.org/details/SNESDevManual/book2/page/n129 page 2-6-7 of Book II]&lt;br /&gt;
&lt;br /&gt;
[[Category:ASM]]&lt;br /&gt;
[[Category:Super FX]]&lt;br /&gt;
[[Category:Register Prefix Instructions]]&lt;br /&gt;
[[Category:One-byte Instructions]]&lt;/div&gt;</summary>
		<author><name>MarioFanGamer</name></author>
	</entry>
	<entry>
		<id>https://sneslab.net/mw/index.php?title=FROM_(Super_FX)&amp;diff=16066</id>
		<title>FROM (Super FX)</title>
		<link rel="alternate" type="text/html" href="https://sneslab.net/mw/index.php?title=FROM_(Super_FX)&amp;diff=16066"/>
		<updated>2024-06-30T19:08:57Z</updated>

		<summary type="html">&lt;p&gt;MarioFanGamer: Added connection to the B Flag and MOVE.&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;float:right;clear:right;width:50%&amp;quot;&lt;br /&gt;
!colspan=&amp;quot;8&amp;quot;|Basic Info&lt;br /&gt;
|+&lt;br /&gt;
|&#039;&#039;&#039;Opcode&#039;&#039;&#039;&lt;br /&gt;
|&#039;&#039;&#039;Length&#039;&#039;&#039;&lt;br /&gt;
|&#039;&#039;&#039;ROM Speed&#039;&#039;&#039;&lt;br /&gt;
|&#039;&#039;&#039;RAM Speed&#039;&#039;&#039;&lt;br /&gt;
|&#039;&#039;&#039;Cache Speed&#039;&#039;&#039;&lt;br /&gt;
|+&lt;br /&gt;
|Bn&lt;br /&gt;
|1 byte&lt;br /&gt;
|3 cycles&lt;br /&gt;
|3 cycles&lt;br /&gt;
|1 cycle&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;float:right;clear:right;width:30%&amp;quot;&lt;br /&gt;
!colspan=&amp;quot;9&amp;quot;|Flags Affected&lt;br /&gt;
|+&lt;br /&gt;
|B&lt;br /&gt;
|[[ALT1]]&lt;br /&gt;
|[[ALT2]]&lt;br /&gt;
|[[O/V]]&lt;br /&gt;
|S&lt;br /&gt;
|[[CY]]&lt;br /&gt;
|Z&lt;br /&gt;
|+&lt;br /&gt;
|.&lt;br /&gt;
|.&lt;br /&gt;
|.&lt;br /&gt;
|.&lt;br /&gt;
|.&lt;br /&gt;
|.&lt;br /&gt;
|.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;FROM&#039;&#039;&#039; is a [[Super FX]] register prefix instruction that specifies the [[source register]]. The exception is when the [[B Flag]] is set (i.e. a [[WITH]] instruction is executed immediately before) in which case a [[MOVES]] is executed instead with WITH acting as the source and FROM as the destination.&lt;br /&gt;
&lt;br /&gt;
No flags are affected.&lt;br /&gt;
&lt;br /&gt;
=== See Also ===&lt;br /&gt;
* [[TO (Super FX)]]&lt;br /&gt;
* [[WITH (Super FX)]]&lt;br /&gt;
* [[MOVES (Super FX)]]&lt;br /&gt;
&lt;br /&gt;
=== External Links ===&lt;br /&gt;
* Official Nintendo documentation on FROM: [https://archive.org/details/SNESDevManual/book2/page/n204 Page 2-9-48 of Book II]&lt;br /&gt;
* Official Nintendo documentation on Register Prefixes: [https://archive.org/details/SNESDevManual/book2/page/n129 page 2-6-7 of Book II]&lt;br /&gt;
&lt;br /&gt;
[[Category:ASM]]&lt;br /&gt;
[[Category:Super FX]]&lt;br /&gt;
[[Category:Register Prefix Instructions]]&lt;br /&gt;
[[Category:One-byte Instructions]]&lt;/div&gt;</summary>
		<author><name>MarioFanGamer</name></author>
	</entry>
	<entry>
		<id>https://sneslab.net/mw/index.php?title=TO_(Super_FX)&amp;diff=16065</id>
		<title>TO (Super FX)</title>
		<link rel="alternate" type="text/html" href="https://sneslab.net/mw/index.php?title=TO_(Super_FX)&amp;diff=16065"/>
		<updated>2024-06-30T19:06:50Z</updated>

		<summary type="html">&lt;p&gt;MarioFanGamer: Added connection to the B Flag and MOVE.&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;float:right;clear:right;width:50%&amp;quot;&lt;br /&gt;
!colspan=&amp;quot;8&amp;quot;|Basic Info&lt;br /&gt;
|+&lt;br /&gt;
|&#039;&#039;&#039;Opcode&#039;&#039;&#039;&lt;br /&gt;
|&#039;&#039;&#039;Length&#039;&#039;&#039;&lt;br /&gt;
|&#039;&#039;&#039;ROM Speed&#039;&#039;&#039;&lt;br /&gt;
|&#039;&#039;&#039;RAM Speed&#039;&#039;&#039;&lt;br /&gt;
|&#039;&#039;&#039;Cache Speed&#039;&#039;&#039;&lt;br /&gt;
|+&lt;br /&gt;
|1n&lt;br /&gt;
|1 byte&lt;br /&gt;
|3 cycles&lt;br /&gt;
|3 cycles&lt;br /&gt;
|1 cycle&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;float:right;clear:right;width:30%&amp;quot;&lt;br /&gt;
!colspan=&amp;quot;9&amp;quot;|Flags Affected&lt;br /&gt;
|+&lt;br /&gt;
|B&lt;br /&gt;
|[[ALT1]]&lt;br /&gt;
|[[ALT2]]&lt;br /&gt;
|[[O/V]]&lt;br /&gt;
|S&lt;br /&gt;
|[[CY]]&lt;br /&gt;
|Z&lt;br /&gt;
|+&lt;br /&gt;
|.&lt;br /&gt;
|.&lt;br /&gt;
|.&lt;br /&gt;
|.&lt;br /&gt;
|.&lt;br /&gt;
|.&lt;br /&gt;
|.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;TO&#039;&#039;&#039; is a [[Super FX]] register prefix instruction that specifies the [[destination register]]. The exception is when the [[B Flag]] is set (i.e. a [[WITH]] instruction is executed immediately before) in which case a [[MOVE]] is executed instead with &amp;lt;code&amp;gt;WITH&amp;lt;/code&amp;gt; acting as the source and &amp;lt;code&amp;gt;TO&amp;lt;/code&amp;gt; as the destination.&lt;br /&gt;
&lt;br /&gt;
No flags are affected.&lt;br /&gt;
&lt;br /&gt;
=== See Also ===&lt;br /&gt;
* [[FROM (Super FX)]]&lt;br /&gt;
* [[WITH (Super FX)]]&lt;br /&gt;
* [[MOVE (Super FX)]]&lt;br /&gt;
&lt;br /&gt;
=== External Links ===&lt;br /&gt;
* Official Nintendo documentation on TO: [https://archive.org/details/SNESDevManual/book2/page/n277 page 2-9-121 of Book II]&lt;br /&gt;
* Official Nintendo documentation on Register Prefixes: [https://archive.org/details/SNESDevManual/book2/page/n129 page 2-6-7 of Book II]&lt;br /&gt;
&lt;br /&gt;
[[Category:ASM]]&lt;br /&gt;
[[Category:Super FX]]&lt;br /&gt;
[[Category:Register Prefix Instructions]]&lt;br /&gt;
[[Category:One-byte Instructions]]&lt;/div&gt;</summary>
		<author><name>MarioFanGamer</name></author>
	</entry>
	<entry>
		<id>https://sneslab.net/mw/index.php?title=WITH_(Super_FX)&amp;diff=16064</id>
		<title>WITH (Super FX)</title>
		<link rel="alternate" type="text/html" href="https://sneslab.net/mw/index.php?title=WITH_(Super_FX)&amp;diff=16064"/>
		<updated>2024-06-30T19:05:46Z</updated>

		<summary type="html">&lt;p&gt;MarioFanGamer: /* See Also */ Removed (Super FX) from B Flag&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;float:right;clear:right;width:30%&amp;quot;&lt;br /&gt;
!colspan=&amp;quot;9&amp;quot;|Flags Affected&lt;br /&gt;
|+&lt;br /&gt;
|B&lt;br /&gt;
|[[ALT1]]&lt;br /&gt;
|[[ALT2]]&lt;br /&gt;
|[[O/V]]&lt;br /&gt;
|S&lt;br /&gt;
|[[CY]]&lt;br /&gt;
|Z&lt;br /&gt;
|+&lt;br /&gt;
|1&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;WITH&#039;&#039;&#039; is an undocumented{{dubious}} (WITH is mentioned on pages 2-2-8 and 2-6-7 of Book II the Nintendo documentation) [[Super FX]] instruction that sets the register specified by the operand as both the [[source register]] and [[destination register]]. It also sets the B flag which makes it a prefix instruction, more specifically for [[TO]] and [[FROM]] which act like [[MOVE]] and [[MOVES]], respectively, with WITH carrying the source and the modified opcode the destination.&lt;br /&gt;
&lt;br /&gt;
=== See Also ===&lt;br /&gt;
* [[TO (Super FX)]]&lt;br /&gt;
* [[FROM (Super FX)]]&lt;br /&gt;
* [[B Flag]]&lt;br /&gt;
* [[MOVE (Super FX)]]&lt;br /&gt;
* [[MOVES (Super FX)]]&lt;br /&gt;
&lt;br /&gt;
=== References ===&lt;br /&gt;
* &#039;&#039;Comprehensive Super FX ASM Guide&#039;&#039;, part C (Basic operations): https://www.smwcentral.net/?p=viewthread&amp;amp;t=81548&lt;br /&gt;
* Official Nintendo documentation on Register Prefixes: [https://archive.org/details/SNESDevManual/book2/page/n129 page 2-6-7 of Book II]&lt;br /&gt;
&lt;br /&gt;
[[Category:ASM]]&lt;br /&gt;
[[Category:Super FX]]&lt;br /&gt;
[[Category:Register Prefix Instructions]]&lt;/div&gt;</summary>
		<author><name>MarioFanGamer</name></author>
	</entry>
	<entry>
		<id>https://sneslab.net/mw/index.php?title=WITH_(Super_FX)&amp;diff=16063</id>
		<title>WITH (Super FX)</title>
		<link rel="alternate" type="text/html" href="https://sneslab.net/mw/index.php?title=WITH_(Super_FX)&amp;diff=16063"/>
		<updated>2024-06-30T19:05:23Z</updated>

		<summary type="html">&lt;p&gt;MarioFanGamer: Added purpose as a register prefix.&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;float:right;clear:right;width:30%&amp;quot;&lt;br /&gt;
!colspan=&amp;quot;9&amp;quot;|Flags Affected&lt;br /&gt;
|+&lt;br /&gt;
|B&lt;br /&gt;
|[[ALT1]]&lt;br /&gt;
|[[ALT2]]&lt;br /&gt;
|[[O/V]]&lt;br /&gt;
|S&lt;br /&gt;
|[[CY]]&lt;br /&gt;
|Z&lt;br /&gt;
|+&lt;br /&gt;
|1&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;WITH&#039;&#039;&#039; is an undocumented{{dubious}} (WITH is mentioned on pages 2-2-8 and 2-6-7 of Book II the Nintendo documentation) [[Super FX]] instruction that sets the register specified by the operand as both the [[source register]] and [[destination register]]. It also sets the B flag which makes it a prefix instruction, more specifically for [[TO]] and [[FROM]] which act like [[MOVE]] and [[MOVES]], respectively, with WITH carrying the source and the modified opcode the destination.&lt;br /&gt;
&lt;br /&gt;
=== See Also ===&lt;br /&gt;
* [[TO (Super FX)]]&lt;br /&gt;
* [[FROM (Super FX)]]&lt;br /&gt;
* [[B Flag (Super FX)]]&lt;br /&gt;
* [[MOVE (Super FX)]]&lt;br /&gt;
* [[MOVES (Super FX)]]&lt;br /&gt;
&lt;br /&gt;
=== References ===&lt;br /&gt;
* &#039;&#039;Comprehensive Super FX ASM Guide&#039;&#039;, part C (Basic operations): https://www.smwcentral.net/?p=viewthread&amp;amp;t=81548&lt;br /&gt;
* Official Nintendo documentation on Register Prefixes: [https://archive.org/details/SNESDevManual/book2/page/n129 page 2-6-7 of Book II]&lt;br /&gt;
&lt;br /&gt;
[[Category:ASM]]&lt;br /&gt;
[[Category:Super FX]]&lt;br /&gt;
[[Category:Register Prefix Instructions]]&lt;/div&gt;</summary>
		<author><name>MarioFanGamer</name></author>
	</entry>
	<entry>
		<id>https://sneslab.net/mw/index.php?title=Super_FX&amp;diff=16060</id>
		<title>Super FX</title>
		<link rel="alternate" type="text/html" href="https://sneslab.net/mw/index.php?title=Super_FX&amp;diff=16060"/>
		<updated>2024-06-30T18:20:16Z</updated>

		<summary type="html">&lt;p&gt;MarioFanGamer: /* Status/Flag Register (SFR) */ Clarification that $3030 and $3031 refer to the CPU only.&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&#039;&#039;&#039;Super FX&#039;&#039;&#039; is a [[Super NES]] [[enhancement chip]] developed by [https://en.wikipedia.org/wiki/Argonaut_Games Argonaut Games] and [http://en.wikipedia.org/wiki/Nintendo Nintendo]. It&#039;s also known as the &amp;quot;Graphical Support Unit&amp;quot; (short for &amp;quot;GSU&amp;quot;) for its greater graphical capabilities compared to the S-CPU whereas its first revision, used for [[Star Fox]], uses the name &amp;quot;Mathematical, Argonaut, Rotation, &amp;amp; Input/Output&amp;quot; or short MARIO chip. It also is know for the use in &#039;&#039;[[Super Mario World 2: Yoshi&#039;s Island]]&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
During this article, GSU refers to Super FX whereas CPU refers to the Super NES CPU.&lt;br /&gt;
&lt;br /&gt;
== Features ==&lt;br /&gt;
This embedded co-processor has a base clock speed of &#039;&#039;&#039;10.74 MHz&#039;&#039;&#039; - four times as fast as the S-CPU, which uses a base block of 2.68 Mhz. Its features include but are not limited to:&lt;br /&gt;
* A RISC-like processor where most opcodes have an instruction size of one byte and are executed in a single cycle when in cache.&lt;br /&gt;
* 512 bytes of cache RAM for faster processing of instructions.&lt;br /&gt;
* A large memory capactiy, a total capacity of 8 MiB ROM, of which two MiB are shared by CPU and GSU, and 256 KiB RAM, of which 128 KiB are shared by CPU and GSU.&lt;br /&gt;
* A separate bus for ROM and RAM to handle memory in parallel&lt;br /&gt;
* Parallel processing with the CPU&lt;br /&gt;
* Fast Bitmap to Planar conversion&lt;br /&gt;
* Pipeline processing to fetch opcodes twice as fast, effectively increasing the processing speed to 21.48 MHz.&lt;br /&gt;
&lt;br /&gt;
= Technical Information =&lt;br /&gt;
&lt;br /&gt;
[[File:Super FX System Configuration.png|thumb]]&lt;br /&gt;
&lt;br /&gt;
== Hardware Registers ==&lt;br /&gt;
&lt;br /&gt;
Super FX comes with various hardware registers of various functions. Most (but not all) of the GSU hardware registers can be accessed from the CPU when the GSU is idling. They are located in the $3000-$3FFF region in banks $00-$3F and $80-$BF.&lt;br /&gt;
&lt;br /&gt;
=== General Registers (R0-R13) ===&lt;br /&gt;
&lt;br /&gt;
These registers are more or less equivalent to the A, X and Y registers on the [[65c816]]. They all are parameters to many opcodes, though not all of them are valid (e.g. R0 can&#039;t be a parameter for the logical operators), and are all 16-bit. Some of them come with a secondary use for certain opcodes. The CPU can directly read from and write to these registers $3000-$301B.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+A list of their addresses and their secondary functions&lt;br /&gt;
|-&lt;br /&gt;
! Name !! Address !! Secondary Function&lt;br /&gt;
|-&lt;br /&gt;
|  R0  ||  $3000  || Default source/destination register.&lt;br /&gt;
|-&lt;br /&gt;
|  R1  ||  $3002  || [[PLOT]] X position&lt;br /&gt;
|-&lt;br /&gt;
|  R2  ||  $3004  || [[PLOT]] Y position&lt;br /&gt;
|-&lt;br /&gt;
|  R3  ||  $3006  ||&lt;br /&gt;
|-&lt;br /&gt;
|  R4  ||  $3008  || Low word for [[LMULT]] result&lt;br /&gt;
|-&lt;br /&gt;
|  R5  ||  $300A  ||&lt;br /&gt;
|-&lt;br /&gt;
|  R6  ||  $300C  || Second input for [[LMULT]] and [[FMULT]]&lt;br /&gt;
|-&lt;br /&gt;
|  R7  ||  $300E  || [[MERGE]] source 1&lt;br /&gt;
|-&lt;br /&gt;
|  R8  ||  $3010  || [[MERGE]] source 2&lt;br /&gt;
|-&lt;br /&gt;
|  R9  ||  $3012  ||&lt;br /&gt;
|-&lt;br /&gt;
|  R10 ||  $3014  ||&lt;br /&gt;
|-&lt;br /&gt;
|  R11 ||  $3016  || [[LINK]] destination&lt;br /&gt;
|-&lt;br /&gt;
|  R12 ||  $3018  || [[LOOP]] counter&lt;br /&gt;
|-&lt;br /&gt;
|  R13 ||  $301A  || [[LOOP]] start&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Game Pak ROM Address Pointer (R14) ===&lt;br /&gt;
&lt;br /&gt;
R14 is the ROM Pointer register and is mapped to $301C-$301D on the SNES. It&#039;s the pointer for the [[GETB]] opcodes which allows the GSU to read from ROM.&lt;br /&gt;
It otherwise acts like any normal general register and is sometimes used as such.&lt;br /&gt;
&lt;br /&gt;
=== Program Counter (R15) ===&lt;br /&gt;
&lt;br /&gt;
R15 is the program counter and is mapped to $301E-$301F on the SNES. Unlike on the [[65c816]] processor, the program counter (excluding the bank) can be directly read or modified within code&lt;br /&gt;
as it acts like a general register. This makes it possible to e.g. jump to a certain address without the use of a dedicated opcode.&lt;br /&gt;
For example, &amp;lt;code&amp;gt;IWT R15, #xxxx&amp;lt;/code&amp;gt; on Super FX is equivalent to &amp;lt;code&amp;gt;JMP $xxxx&amp;lt;/code&amp;gt; on the 65c816.&lt;br /&gt;
&lt;br /&gt;
In addition, writing to $301E on the CPU side invokes the GSU.&lt;br /&gt;
&lt;br /&gt;
=== Status/Flag Register (SFR) ===&lt;br /&gt;
&lt;br /&gt;
Super FX comes with a 16-bit register of various flags, mostly from calculations (e.g. a carry flag) but also other flags like whether Super FX is currently running.&lt;br /&gt;
They can be read and written through $3030 and $3031 on the CPU side.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+Status/Flag Register bitwise&lt;br /&gt;
!       !! B7  !! B6 !! B5 !! B4 !! B3 !! B2 !!  B1  !!  B0&lt;br /&gt;
|-&lt;br /&gt;
| $3031 || IRQ || -  || -  || B  || IH || IL || ALT1 || ALT2&lt;br /&gt;
|-&lt;br /&gt;
| $3030 ||  -  || R  || G  || OV || S  || CY ||  Z   ||  -&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+Description of Flags&lt;br /&gt;
|-&lt;br /&gt;
! Flag !! Description&lt;br /&gt;
|-&lt;br /&gt;
|  Z   || Zero flag, set when result is zero.&lt;br /&gt;
|-&lt;br /&gt;
|  CY  || Carry flag, set at result overflow (unsigned).&lt;br /&gt;
|-&lt;br /&gt;
|  S   || Sign flag, set when number is negative.&lt;br /&gt;
|-&lt;br /&gt;
|  OV  || Overflow flag, set at result overflow (signed).&lt;br /&gt;
|-&lt;br /&gt;
|  G   || Go flag, set when GSU is running.&lt;br /&gt;
|-&lt;br /&gt;
|  R   || Set when reading from ROM.&lt;br /&gt;
|-&lt;br /&gt;
| ALT1 || Opcode modifier 1, set when executing [[ALT1]].&lt;br /&gt;
|-&lt;br /&gt;
| ALT2 || Opcode modifier 2, set when executing [[ALT2]].&lt;br /&gt;
|-&lt;br /&gt;
|  IL  || Immediate lower 8-bit flag.&lt;br /&gt;
|-&lt;br /&gt;
|  IH  || Immediate higher 8-bit flag.&lt;br /&gt;
|-&lt;br /&gt;
|  B   || Set when executing [[WITH]].&lt;br /&gt;
|-&lt;br /&gt;
| IRQ  || Interrupt flag, set when GSU stopped.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Program Bank Register (PBR) ===&lt;br /&gt;
&lt;br /&gt;
The program bank is the bank where GSU code is executed. It&#039;s a readable and writable 8-bit register which is mapped to $3034 on the CPU side.&lt;br /&gt;
Unlike R15, this can only be modified indirectly using [[LJMP]] on GSU side.&lt;br /&gt;
&lt;br /&gt;
=== Game Pak ROM Bank Register (ROMBR) ===&lt;br /&gt;
&lt;br /&gt;
This register controls the bank where ROM is read. It&#039;s set using the [[ROMB]] on the GSU side.&lt;br /&gt;
It&#039;s a readable only 8-bit register which is mapped to $3036 on the CPU side.&lt;br /&gt;
&lt;br /&gt;
=== Game Pak RAM Bank Register (RAMBR) ===&lt;br /&gt;
&lt;br /&gt;
This register is the RAM equivalent to ROMBR. It&#039;s set using the [[RAMB]] on the GSU side.&lt;br /&gt;
It&#039;s a readable only 1-bit register which is mapped to $303C on the CPU side.&lt;br /&gt;
&lt;br /&gt;
=== Cache Base Register (CBR) ===&lt;br /&gt;
&lt;br /&gt;
The Cache Base Register is the address where cache has been enabled through and tells the GSU where to run code in cache.&lt;br /&gt;
It&#039;s readable 16-bit register accessible through $303E and $303F from the CPU and written by the GSU with the [[CACHE]] and [[LJMP]] opcodes.&lt;br /&gt;
The lowest four bits of this register are open bus since cache is stored in 16-byte blocks.&lt;br /&gt;
&lt;br /&gt;
=== Screen Base Register (SCBR) ===&lt;br /&gt;
&lt;br /&gt;
The Screen Base Register is the high byte of the image buffer i.e. the plotting destination.&lt;br /&gt;
It&#039;s a writeable 8-bit register mapped to $3038 on the CPU side.&lt;br /&gt;
&lt;br /&gt;
=== Screen Mode Register (SCMR) ===&lt;br /&gt;
&lt;br /&gt;
The Screen Mode Register contains the settings for the image buffer (dimensions, bitdepth) but also access to ROM and RAM.&lt;br /&gt;
It&#039;s a writeable 8-bit register mapped to $303A on the CPU side.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+Screen Mode Register bitwise&lt;br /&gt;
! B7 !! B6 !! B5  !! B4  !! B3  !! B2  !! B1  !! B0&lt;br /&gt;
|-&lt;br /&gt;
| -  || -  || HT1 || ROM || RAN || HT0 || MD1 || MD0&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The image buffer dimensions are given by HT0 and HT1. They all are 256 pixels wide but have different heights.&lt;br /&gt;
A special case exists when both bits are 1 which enables OBJ mode which is used to plot single sprites like in &#039;&#039;[[Yoshi&#039;s Island]]&#039;&#039;.&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+Screen Dimensions&lt;br /&gt;
|-&lt;br /&gt;
! HT1 !! H00 !! Mode&lt;br /&gt;
|-&lt;br /&gt;
|  0  ||  0  || 256 by 128&lt;br /&gt;
|-&lt;br /&gt;
|  0  ||  1  || 256 by 160&lt;br /&gt;
|-&lt;br /&gt;
|  1  ||  0  || 256 by 192&lt;br /&gt;
|-&lt;br /&gt;
|  1  ||  1  || OBJ mode&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The bitdepth of the image buffer is set by the MD0 and MD1 bits:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+Screen Mode&lt;br /&gt;
|-&lt;br /&gt;
! MD1 !! MD0 !! Mode&lt;br /&gt;
|-&lt;br /&gt;
|  0  ||  0  || 4-color mode (2bpp)&lt;br /&gt;
|-&lt;br /&gt;
|  0  ||  1  || 16-color mode (4bpp)&lt;br /&gt;
|-&lt;br /&gt;
|  1  ||  0  || Not used&lt;br /&gt;
|-&lt;br /&gt;
|  1  ||  1  || 256-color mode (8bpp)&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The SCMR register also controls whether Game Pak ROM and RAM can be accessed by the CPU or GSU:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+Screen Mode&lt;br /&gt;
|-&lt;br /&gt;
! Bit !! Description&lt;br /&gt;
|-&lt;br /&gt;
| RON || Gives ROM access to the CPU when 0 and GSU when 1.&lt;br /&gt;
|-&lt;br /&gt;
| RAN || Gives RAM access to the CPU when 0 and GSU when 1.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Color Register (COLR) ===&lt;br /&gt;
&lt;br /&gt;
The Color Register contains the colour for the pixel which is to be plotted.&lt;br /&gt;
It&#039;s an 8-bit register which is set using the [[COLOR]] and [[GETC]] opcodes on the GSU. There is no access from the CPU.&lt;br /&gt;
&lt;br /&gt;
=== Plot Options Register (POR) ===&lt;br /&gt;
&lt;br /&gt;
The Color Register controls how the colours are loaded into the COLR register as well as how they&#039;re drawn onto the buffer.&lt;br /&gt;
It&#039;s an 8-bit register which is set using the [[CMODE]] opcode on the GSU. There is no access from the CPU.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+Screen Mode Register bitwise&lt;br /&gt;
! B7 !! B6 !! B5 !! B4  !! B3 !! B2 !! B1 !! B0&lt;br /&gt;
|-&lt;br /&gt;
| -  || -  || -  || OBJ || FH || HN || DT || TP&lt;br /&gt;
|}&lt;br /&gt;
Note that these abbreviations are inofficial and have been included for simplification.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+Description of Screen Mode Register&lt;br /&gt;
|-&lt;br /&gt;
! Bit !! Description&lt;br /&gt;
|-&lt;br /&gt;
| OBJ || [[OBJ Flag]]&lt;br /&gt;
|-&lt;br /&gt;
| FH  || [[Freeze High Flag]]&lt;br /&gt;
|-&lt;br /&gt;
| HN  || [[High Nibble Flag]]&lt;br /&gt;
|-&lt;br /&gt;
| DT  || [[Dither Flag]]&lt;br /&gt;
|-&lt;br /&gt;
| TP  || [[Transparent Flag]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Backup RAM Register (BRAMR) ===&lt;br /&gt;
&lt;br /&gt;
This controls whether Back-up RAM (not to be confused with Game Pak RAM) becomes “protected”.&amp;lt;sup&amp;gt;1&amp;lt;/sup&amp;gt;&lt;br /&gt;
It&#039;s a 1-bit register mapped to bit 0 of $3033 which can be written by the CPU.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;sup&amp;gt;1&amp;lt;/sup&amp;gt;The definition of “protected” isn&#039;t very clear, though it can be assumed that Back-up RAM can&#039;t be written when it&#039;s set to be protected.&lt;br /&gt;
&lt;br /&gt;
=== Version Code Register (VCR) ===&lt;br /&gt;
&lt;br /&gt;
The Version Code Register contains the version code of the Super FX chip.&lt;br /&gt;
It&#039;s an 8-bit read-only register and accessed $303B on the CPU side.&lt;br /&gt;
&lt;br /&gt;
=== Config Register (CFGR) ===&lt;br /&gt;
&lt;br /&gt;
The Config Register contains two flags:&lt;br /&gt;
The IRQ flag which allows the GSU to fire an interrupt to the CPU should it stop and&lt;br /&gt;
the MS0 which controls the speed of the multiplication.&lt;br /&gt;
It&#039;s mapped to bit 0 of $3039 and is writeable from the CPU.&lt;br /&gt;
&lt;br /&gt;
=== Clock Select Register (CLSR) ===&lt;br /&gt;
&lt;br /&gt;
This register sets the clock speed of Super FX and enables pipelining in the process. When clear, Super FX runs at 10.74 MHz, when set, at 21.48 MHz.&lt;br /&gt;
It&#039;s mapped to bit 0 of $3039 and is writeable from the CPU.&lt;br /&gt;
&lt;br /&gt;
Supposedly, the CLSR and MS0 flags must not be set 1 at the same time but no side effects are known.&lt;br /&gt;
&lt;br /&gt;
== Memory and Bus ==&lt;br /&gt;
&lt;br /&gt;
=== Memory Map ===&lt;br /&gt;
One advantage of Super FX is that it naturally supports ROMs with a size of up to 8 MiB. However, Super FX can only use the first two MiB of a ROM. Similarly, even though a single cartridge may have up to 256 KiB of SRAM, only half of them can be used by Super FX. As a result, there is a difference between the CPU and GSU mapping.&lt;br /&gt;
&lt;br /&gt;
This is how the ROM is mapped from the perspective of the CPU:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
!  Banks  !!   Address   !! Description&lt;br /&gt;
|-&lt;br /&gt;
|rowspan=&amp;quot;6&amp;quot;|$00-$3F&lt;br /&gt;
          || $0000-$1FFF || WRAM mirror&lt;br /&gt;
|-&lt;br /&gt;
|           $2100-$21FF || PPU registers&lt;br /&gt;
|-&lt;br /&gt;
|           $3000-$3FFF || Super FX registers&lt;br /&gt;
|-&lt;br /&gt;
|           $4200-$43FF || CPU registers&lt;br /&gt;
|-&lt;br /&gt;
|           $6000-$7FFF || SRAM mirror&lt;br /&gt;
|-&lt;br /&gt;
|           $8000-$FFFF || ROM (LoROM)&lt;br /&gt;
|-&lt;br /&gt;
| $40-$5F || $0000-$FFFF || Mirror of ROM in banks $00-$3F (HiROM)&lt;br /&gt;
|-&lt;br /&gt;
| $60-$6F || $0000-$FFFF || Unmapped&lt;br /&gt;
|-&lt;br /&gt;
| $70-$71 || $0000-$FFFF || SRAM&lt;br /&gt;
|-&lt;br /&gt;
| $7C-$7D || $0000-$FFFF || Backup RAM&lt;br /&gt;
|-&lt;br /&gt;
| $7E-$7F || $0000-$FFFF || WRAM&lt;br /&gt;
|-&lt;br /&gt;
|rowspan=&amp;quot;6&amp;quot;|$80-$BF&lt;br /&gt;
          || $0000-$1FFF || WRAM mirror&lt;br /&gt;
|-&lt;br /&gt;
|           $2100-$21FF || PPU registers&lt;br /&gt;
|-&lt;br /&gt;
|           $3000-$3FFF || Super FX registers&lt;br /&gt;
|-&lt;br /&gt;
|           $4200-$43FF || CPU registers&lt;br /&gt;
|-&lt;br /&gt;
|           $6000-$7FFF || SRAM mirror&lt;br /&gt;
|-&lt;br /&gt;
|           $8000-$FFFF || ROM (LoROM)&lt;br /&gt;
|-&lt;br /&gt;
| $C0-$FF || $8000-$FFFF || ROM (HiROM)&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The GSU memory map looks similar to the CPU mapping but only with access to ROM and SRAM as well as only access to 2 MiB of ROM and 128 KiB of SRAM. As a result, it looks more like this:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
!  Banks  !!   Address   !! Description&lt;br /&gt;
|-&lt;br /&gt;
|rowspan=&amp;quot;2&amp;quot;|$00-$3F&lt;br /&gt;
          || $0000-$7FFF || Unmapped&lt;br /&gt;
|-&lt;br /&gt;
|            $8000-$FFFF || ROM (LoROM)&lt;br /&gt;
|-&lt;br /&gt;
| $40-$5F || $0000-$FFFF || Mirror of ROM in banks $00-$3F (HiROM)&lt;br /&gt;
|-&lt;br /&gt;
| $60-$6F || $0000-$FFFF || Unmapped&lt;br /&gt;
|-&lt;br /&gt;
| $70-$71 || $0000-$FFFF || SRAM&lt;br /&gt;
|-&lt;br /&gt;
| $72-$7F || $0000-$FFFF || Unmapped&lt;br /&gt;
|-&lt;br /&gt;
| $80-$FF || $0000-$FFFF || Mirror of $00-$7F&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Finally, it should be noted that banks $40-$5F are HiROM mirrors of the LoROM banks $00-$3F interlaced so addresses such as $008000 and $400000 contain the same value.&lt;br /&gt;
&lt;br /&gt;
=== ROM ===&lt;br /&gt;
ROM on Super FX can be up to 8 MiB large. However, even though the size is theoretically doable, the largest published Super FX games had a ROM size of 2 MiBs. As a result, not many emulators (not even BSNES as of 2021) emulate this feature properly and such ROM sizes only exist in homebrewing and modding.&lt;br /&gt;
&lt;br /&gt;
Super FX has also has got limitations with ROM access. This first example is the ROM size. Even though a Super FX ROM can be as large as 8 MiB (in theory), the GSU&#039;s data bus is only connected to 2 MiB of it. Said portion of ROM which the processor can access is called GamePak ROM while the additional 6 MiB, called the Super NES ROM, can only be accessed by the CPU.&lt;br /&gt;
A second limitation is the clock speed. The GSU is clocked very fast at 10.74 Mhz (which can be doubled with pipelining) but ROM is clocked at 3.58 Mhz (unlike on [[SA-1]] where ROM is clocked at the same frequency as the coprocessor). As a result, all opcodes, when they are executed in ROM, take at least three cycles to process while reads from ROM are slow.&lt;br /&gt;
&lt;br /&gt;
To counteract against this limitation, the GSU uses a buffering system. In order to load a value from ROM, the bank must first be set in ROMBR (set by [[ROMB]] in the GSU code) while the address is set in register R14. Any write to R14 initiates the buffering process (it&#039;s also this reason it isn&#039;t considered a general purpose register even though it can be used as such). The value then can be retrieved with [[GETB]] and similar opcodes (referred to just &amp;lt;code&amp;gt;GETB&amp;lt;/code&amp;gt; from now on).&lt;br /&gt;
&lt;br /&gt;
The GSU doesn&#039;t wait during the process of fetching. As a result, it is possible to call &amp;lt;code&amp;gt;GETB&amp;lt;/code&amp;gt; some time after writing to R14. In fact, this is even recommend because calling &amp;lt;code&amp;gt;GETB&amp;lt;/code&amp;gt; during the process of fetching will cause the GSU to halt for up to five cycles for executing &amp;lt;code&amp;gt;GETB&amp;lt;/code&amp;gt;. Similarly, writing to &amp;lt;code&amp;gt;ROMB&amp;lt;/code&amp;gt; will halt the code as well until the data has been fetched and enabling cache during the process of fetching will mess up the loaded ROM value.&lt;br /&gt;
&lt;br /&gt;
=== RAM ===&lt;br /&gt;
&lt;br /&gt;
=== Cache ===&lt;br /&gt;
&lt;br /&gt;
In order to improve the speed of the processor, it includes a 512 byte large memory with the same frequency as the GSU as a cache. This allows Super FX to execute a single opcode with only a single cycle (i.e. three times as fast as in regular use). The cache is separated into 32 16-byte blocks, each with a flag which denotes that a block is used, and is indexed by the cache base register (CBR) which is used to keep track of where cache has been invoked. The cache flags and CBR are reset whenever a zero is written to the GO flag but simply halting or invoking the GSU preserves the content of the cache which in turn can be read by the CPU.&lt;br /&gt;
&lt;br /&gt;
Cache on the SNES is mapped to addresses $xx:3100-$xx:32FF ($xx = $00-$3F, $80-$BF), though the start of the cached code (see below) also is dependent on the CBR (start = $3100 + (CBR &amp;amp; 0x1FF)).&lt;br /&gt;
&lt;br /&gt;
There are two methods to fill the cache:&lt;br /&gt;
* Manual caching&lt;br /&gt;
* Automatic caching&lt;br /&gt;
&lt;br /&gt;
Manual caching involes using the CPU and transfer the code to cache. Keep in mind that Super FX will only execute the cache block which has been set to be used. That means, the code has to be transfered as a full 16 byte block, though strictly speaking, only the last byte of the block (address $XXXF) needs to be written to count the block as used.&lt;br /&gt;
In order to execute GSU code in cache, R15 has to be set to $0000-$01FF.&lt;br /&gt;
&lt;br /&gt;
Automatic caching is instead handled by the GSU itself. This is handled either by the dedicated [[CACHE]] opcode or by a [[LJMP]] opcode, the latter because of the lack of bank information for the cache. Both of them clear the cache flags and store the current PC with the lowest nibble masked out into the CBR (CBR = PC &amp;amp; 0xFFF0). Afterwards, each executed opcode will be written into cache starting from CBR &amp;amp; 0x1FF.&lt;br /&gt;
As a result, this use of cache is recommend for loops and the first loop will always run slower than the remaining loops. Should all the blocks be used, any remaining code will be left uncached and executed in the original memory.&lt;br /&gt;
&lt;br /&gt;
Another side effect is that cache is neither ROM nor GamePak RAM so any Super FX code in cache can run in parallel to the SNES even when access to ROM and RAM is given to the CPU instead of GSU.&lt;br /&gt;
&lt;br /&gt;
=== Pipeline Processing ===&lt;br /&gt;
&lt;br /&gt;
In order to boost the processing speed of the GSU, it uses a technique called &amp;quot;pipeline processing&amp;quot;. Pipelining exists to a lesser extend on the [[65c816]], where opcodes are prepared while the remaining bytes of the opcodes are fetched (this is notable on single byte opcodes such as [[INC]] which take two cycles to process, the same amount of cycles as &amp;lt;code&amp;gt;LDA #$xx&amp;lt;/code&amp;gt;, a two byte opcode) but the GSU takes it further by fetching the next opcode during the current opcode&#039;s execution.&lt;br /&gt;
This runs the code double as fast, virtually increasing the clock speed to 21.48 MHz at the cost of adding more care of the coder whenever R15 — the programm counter — is changed, either through branching or through direct writes to R15. In addition, internal processes such as multiplication and memory access can&#039;t take advantage of the virtual increment in clock speed.&lt;br /&gt;
&lt;br /&gt;
Pipelining is controlled with bit 0 of CLSR where clear means pipelining disabled and set means pipelining enabled. It&#039;s accessible on the CPU side at the address $3037.&lt;br /&gt;
&lt;br /&gt;
For the most part, having pipelining enabled doesn&#039;t change the code. The only exceptions are when R15 is modified outside of fetching opcodes i.e. the use of branches and writes to R15 (e.g. &amp;lt;code&amp;gt;IWT R15,#$8000&amp;lt;/code&amp;gt;) as well as halting the GSU such as with [[STOP]]. In these cases, the opcode following that instruction will be executed after the branch. A common solution for the unwanted opcode execution is to put a dummy [[NOP]] after the R15 modifying opcode such as in this example:&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;BCC SkipCode&lt;br /&gt;
NOP             ; Dummy NOP&lt;br /&gt;
...&lt;br /&gt;
SkipCode:&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This proves to be inefficient, though. Most Super FX opcodes are one byte large and take 3 or 1 cycles (depending on whether the code is executed in cache or not) to execute including &amp;lt;code&amp;gt;NOP&amp;lt;/code&amp;gt;. As a result, opcodes such as &amp;lt;code&amp;gt;SUB R0&amp;lt;/code&amp;gt; can be put as a dummy opcode in place of &amp;lt;code&amp;gt;NOP&amp;lt;/code&amp;gt;. The following example demonstrates it:&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;BCC SkipCode&lt;br /&gt;
;NOP            ; Redundant&lt;br /&gt;
SUB R0          ; Set R0 to zero&lt;br /&gt;
STW (R1)&lt;br /&gt;
SkipCode:&lt;br /&gt;
IWT R0,#$1234&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
In the above code, R0 gets overwritten by &amp;lt;code&amp;gt;SUB&amp;lt;/code&amp;gt; no matter whether the branch is taken. However, it later gets overwritten by &amp;lt;code&amp;gt;IWT&amp;lt;/code&amp;gt;. As a result, it doesn&#039;t matter whether the dummy opcode is a &amp;lt;code&amp;gt;NOP&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;SUB&amp;lt;/code&amp;gt; from the branch for the calculation. In fact, using a &amp;lt;code&amp;gt;NOP&amp;lt;/code&amp;gt; increases the code size by one byte which can matter when the code is executed in cache as well as increase the cycle count by 1 or 3 cycles each time the branch is executed, causing in total a minor speed penality.&lt;br /&gt;
&lt;br /&gt;
This doesn&#039;t work for every opcode, though. Opcodes such as &amp;lt;code&amp;gt;ADD #x&amp;lt;/code&amp;gt; (opcodes which are internally prefixed with &amp;lt;code&amp;gt;ALTn&amp;lt;/code&amp;gt;), &amp;lt;code&amp;gt;WITH&amp;lt;/code&amp;gt; (register prefixes which change which register is the source or destination), &amp;lt;code&amp;gt;BRA $10&amp;lt;/code&amp;gt; (branches which always use two bytes) and &amp;lt;code&amp;gt;IWT&amp;lt;/code&amp;gt; (immediate value transfers which use two or three bytes) can only be used as a dummy opcode in very specific circumstances. The latter two can even misalign the program counter not unlike executing &amp;lt;code&amp;gt;LDA #$12&amp;lt;/code&amp;gt; when A is in 16-bit mode on the 65816. The following example demonstrates it:&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;BCC SkipCode&lt;br /&gt;
BRA Error       ; Caution!&lt;br /&gt;
&lt;br /&gt;
SkipCode:&lt;br /&gt;
INC R1          ; Will instead be read with the BRA as &amp;quot;BRA $D1&amp;quot;.&lt;br /&gt;
...&lt;br /&gt;
&lt;br /&gt;
Error:&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
In addition, the dummy opcode after a &amp;lt;code&amp;gt;STOP&amp;lt;/code&amp;gt; &#039;&#039;&#039;must&#039;&#039;&#039; be a &amp;lt;code&amp;gt;NOP&amp;lt;/code&amp;gt; because putting the GSU in WAIT will not clear the opcode in the pipeline. Extra care should be taken when pipeliend code is executed and a &amp;lt;code&amp;gt;STOP&amp;lt;/code&amp;gt; is located at $XXXF in cache as the pipelined code may be located in unused cache and a value in ROM/RAM will be loaded instead.&lt;br /&gt;
&lt;br /&gt;
== Bus Conflicts ==&lt;br /&gt;
Between both processors, only one of them can acess Game Pak ROM and RAM at a time so memory access must be controlled. Access is set by the SCMR, by the RON and RAN bits with 0 meaning CPU access and 1 meaning GSU access.&lt;br /&gt;
&lt;br /&gt;
For the GSU, it&#039;s set to WAIT if it isn&#039;t granted access for the respective memory it tries to access (e.g. executing code in ROM, storing to RAM). Once it&#039;s granted access, the WAIT status is reset and execution resumes.&lt;br /&gt;
&lt;br /&gt;
For the CPU, illegal memory access is different as it lacks a WAIT state or a comparable feature. For this reason, the processor instead reads garbage values.&lt;br /&gt;
The specific values actually depend on the type of memory: For illegal RAM access, the CPU reads from open bus instead but for illegal ROM access, the memory bus provides a dummy byte whose value depends on the lowest nibble of the address instead:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
!    Address Low Nibble   !! Byte&lt;br /&gt;
|-&lt;br /&gt;
| 0x0, 0x2, 0x6, 0x8, 0xC || 0x00&lt;br /&gt;
|-&lt;br /&gt;
|            0x4          || 0x04&lt;br /&gt;
|-&lt;br /&gt;
|            0xA          || 0x08&lt;br /&gt;
|-&lt;br /&gt;
|            0xE          || 0x0C&lt;br /&gt;
|-&lt;br /&gt;
|           Other         || 0x01&lt;br /&gt;
|}&lt;br /&gt;
The main purpose of the dummy data is to handle interrupts where the CPU needs to read from ROM to execute code at the given address. This is why on Super FX ROMs, interrupts point to these specific addresses, all of which are in WRAM:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Address !! Interrupt&lt;br /&gt;
|-&lt;br /&gt;
| $000100 ||    BRK&lt;br /&gt;
|-&lt;br /&gt;
| $000104 ||    COP&lt;br /&gt;
|-&lt;br /&gt;
| $000108 ||    NMI&lt;br /&gt;
|-&lt;br /&gt;
| $00010C ||    IRQ&lt;br /&gt;
|}&lt;br /&gt;
The pointers are spaced to leave enough space for a single &amp;lt;code&amp;gt;JML $xxxxxx&amp;lt;/code&amp;gt; to jump to the actual interrupt code.&lt;br /&gt;
Relatedly, Super FX games upload their interrupt and invoke GSU codes into WRAM and execute them there to handle cases where e.g. an interrupt is fired during GSU execution.&lt;br /&gt;
&lt;br /&gt;
No control exists for cache, it&#039;s always assumed to be granted access to the GSU but can be safely accessed by the CPU if the former isn&#039;t running.&lt;br /&gt;
&lt;br /&gt;
This limitation specifically applies to Game Pak ROM and RAM; Super NES CPU ROM and Back-Up RAM, neither of which the GSU can access, are excluded from bus conflicts.&lt;br /&gt;
&lt;br /&gt;
== Bitmap Processing ==&lt;br /&gt;
&lt;br /&gt;
== External Links ==&lt;br /&gt;
&lt;br /&gt;
* Patent: https://patentimages.storage.googleapis.com/de/a2/7a/f07754f66f39d9/US5724497.pdf&lt;br /&gt;
&lt;br /&gt;
[[Category:SNES_Hardware]]&lt;br /&gt;
[[Category:Integrated Circuits]]&lt;br /&gt;
[[Category:Enhancement Chips]]&lt;br /&gt;
[[Category:Super FX]]&lt;/div&gt;</summary>
		<author><name>MarioFanGamer</name></author>
	</entry>
	<entry>
		<id>https://sneslab.net/mw/index.php?title=Super_FX&amp;diff=15223</id>
		<title>Super FX</title>
		<link rel="alternate" type="text/html" href="https://sneslab.net/mw/index.php?title=Super_FX&amp;diff=15223"/>
		<updated>2024-05-08T09:00:24Z</updated>

		<summary type="html">&lt;p&gt;MarioFanGamer: /* Memory Map */ Removed header cells in multi-row cells due to a misunderstanding in table syntax.&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&#039;&#039;&#039;Super FX&#039;&#039;&#039; is a [[Super NES]] [[enhancement chip]] developed by [https://en.wikipedia.org/wiki/Argonaut_Games Argonaut Games] and [http://en.wikipedia.org/wiki/Nintendo Nintendo]. It&#039;s also known as the &amp;quot;Graphical Support Unit&amp;quot; (short for &amp;quot;GSU&amp;quot;) for its greater graphical capabilities compared to the S-CPU whereas its first revision, used for [[Star Fox]], uses the name &amp;quot;Mathematical, Argonaut, Rotation, &amp;amp; Input/Output&amp;quot; or short MARIO chip. It also is know for the use in &#039;&#039;[[Super Mario World 2: Yoshi&#039;s Island]]&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
During this article, GSU refers to Super FX whereas CPU refers to the Super NES CPU.&lt;br /&gt;
&lt;br /&gt;
== Features ==&lt;br /&gt;
This embedded co-processor has a base clock speed of &#039;&#039;&#039;10.74 MHz&#039;&#039;&#039; - four times as fast as the S-CPU, which uses a base block of 2.68 Mhz. Its features include but are not limited to:&lt;br /&gt;
* A RISC-like processor where most opcodes have an instruction size of one byte and are executed in a single cycle when in cache.&lt;br /&gt;
* 512 bytes of cache RAM for faster processing of instructions.&lt;br /&gt;
* A large memory capactiy, a total capacity of 8 MiB ROM, of which two MiB are shared by CPU and GSU, and 256 KiB RAM, of which 128 KiB are shared by CPU and GSU.&lt;br /&gt;
* A separate bus for ROM and RAM to handle memory in parallel&lt;br /&gt;
* Parallel processing with the CPU&lt;br /&gt;
* Fast Bitmap to Planar conversion&lt;br /&gt;
* Pipeline processing to fetch opcodes twice as fast, effectively increasing the processing speed to 21.48 MHz.&lt;br /&gt;
&lt;br /&gt;
= Technical Information =&lt;br /&gt;
&lt;br /&gt;
[[File:Super FX System Configuration.png|thumb]]&lt;br /&gt;
&lt;br /&gt;
== Hardware Registers ==&lt;br /&gt;
&lt;br /&gt;
Super FX comes with various hardware registers of various functions. Most (but not all) of the GSU hardware registers can be accessed from the CPU when the GSU is idling. They are located in the $3000-$3FFF region in banks $00-$3F and $80-$BF.&lt;br /&gt;
&lt;br /&gt;
=== General Registers (R0-R13) ===&lt;br /&gt;
&lt;br /&gt;
These registers are more or less equivalent to the A, X and Y registers on the [[65c816]]. They all are parameters to many opcodes, though not all of them are valid (e.g. R0 can&#039;t be a parameter for the logical operators), and are all 16-bit. Some of them come with a secondary use for certain opcodes. The CPU can directly read from and write to these registers $3000-$301B.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+A list of their addresses and their secondary functions&lt;br /&gt;
|-&lt;br /&gt;
! Name !! Address !! Secondary Function&lt;br /&gt;
|-&lt;br /&gt;
|  R0  ||  $3000  || Default source/destination register.&lt;br /&gt;
|-&lt;br /&gt;
|  R1  ||  $3002  || [[PLOT]] X position&lt;br /&gt;
|-&lt;br /&gt;
|  R2  ||  $3004  || [[PLOT]] Y position&lt;br /&gt;
|-&lt;br /&gt;
|  R3  ||  $3006  ||&lt;br /&gt;
|-&lt;br /&gt;
|  R4  ||  $3008  || Low word for [[LMULT]] result&lt;br /&gt;
|-&lt;br /&gt;
|  R5  ||  $300A  ||&lt;br /&gt;
|-&lt;br /&gt;
|  R6  ||  $300C  || Second input for [[LMULT]] and [[FMULT]]&lt;br /&gt;
|-&lt;br /&gt;
|  R7  ||  $300E  || [[MERGE]] source 1&lt;br /&gt;
|-&lt;br /&gt;
|  R8  ||  $3010  || [[MERGE]] source 2&lt;br /&gt;
|-&lt;br /&gt;
|  R9  ||  $3012  ||&lt;br /&gt;
|-&lt;br /&gt;
|  R10 ||  $3014  ||&lt;br /&gt;
|-&lt;br /&gt;
|  R11 ||  $3016  || [[LINK]] destination&lt;br /&gt;
|-&lt;br /&gt;
|  R12 ||  $3018  || [[LOOP]] counter&lt;br /&gt;
|-&lt;br /&gt;
|  R13 ||  $301A  || [[LOOP]] start&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Game Pak ROM Address Pointer (R14) ===&lt;br /&gt;
&lt;br /&gt;
R14 is the ROM Pointer register and is mapped to $301C-$301D on the SNES. It&#039;s the pointer for the [[GETB]] opcodes which allows the GSU to read from ROM.&lt;br /&gt;
It otherwise acts like any normal general register and is sometimes used as such.&lt;br /&gt;
&lt;br /&gt;
=== Program Counter (R15) ===&lt;br /&gt;
&lt;br /&gt;
R15 is the program counter and is mapped to $301E-$301F on the SNES. Unlike on the [[65c816]] processor, the program counter (excluding the bank) can be directly read or modified within code&lt;br /&gt;
as it acts like a general register. This makes it possible to e.g. jump to a certain address without the use of a dedicated opcode.&lt;br /&gt;
For example, &amp;lt;code&amp;gt;IWT R15, #xxxx&amp;lt;/code&amp;gt; on Super FX is equivalent to &amp;lt;code&amp;gt;JMP $xxxx&amp;lt;/code&amp;gt; on the 65c816.&lt;br /&gt;
&lt;br /&gt;
In addition, writing to $301E on the CPU side invokes the GSU.&lt;br /&gt;
&lt;br /&gt;
=== Status/Flag Register (SFR) ===&lt;br /&gt;
&lt;br /&gt;
Super FX comes with a 16-bit register of various flags, mostly from calculations (e.g. a carry flag) but also other flags like whether Super FX is currently running.&lt;br /&gt;
They can be read and written through $3030 and $3031.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+Status/Flag Register bitwise&lt;br /&gt;
!       !! B7  !! B6 !! B5 !! B4 !! B3 !! B2 !!  B1  !!  B0&lt;br /&gt;
|-&lt;br /&gt;
| $3031 || IRQ || -  || -  || B  || IH || IL || ALT1 || ALT2&lt;br /&gt;
|-&lt;br /&gt;
| $3030 ||  -  || R  || G  || OV || S  || CY ||  Z   ||  -&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+Description of Flags&lt;br /&gt;
|-&lt;br /&gt;
! Flag !! Description&lt;br /&gt;
|-&lt;br /&gt;
|  Z   || Zero flag, set when result is zero.&lt;br /&gt;
|-&lt;br /&gt;
|  CY  || Carry flag, set at result overflow (unsigned).&lt;br /&gt;
|-&lt;br /&gt;
|  S   || Sign flag, set when number is negative.&lt;br /&gt;
|-&lt;br /&gt;
|  OV  || Overflow flag, set at result overflow (signed).&lt;br /&gt;
|-&lt;br /&gt;
|  G   || Go flag, set when GSU is running.&lt;br /&gt;
|-&lt;br /&gt;
|  R   || Set when reading from ROM.&lt;br /&gt;
|-&lt;br /&gt;
| ALT1 || Opcode modifier 1, set when executing [[ALT1]].&lt;br /&gt;
|-&lt;br /&gt;
| ALT2 || Opcode modifier 2, set when executing [[ALT2]].&lt;br /&gt;
|-&lt;br /&gt;
|  IL  || Immediate lower 8-bit flag.&lt;br /&gt;
|-&lt;br /&gt;
|  IH  || Immediate higher 8-bit flag.&lt;br /&gt;
|-&lt;br /&gt;
|  B   || Set when executing [[WITH]].&lt;br /&gt;
|-&lt;br /&gt;
| IRQ  || Interrupt flag, set when GSU stopped.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Program Bank Register (PBR) ===&lt;br /&gt;
&lt;br /&gt;
The program bank is the bank where GSU code is executed. It&#039;s a readable and writable 8-bit register which is mapped to $3034 on the CPU side.&lt;br /&gt;
Unlike R15, this can only be modified indirectly using [[LJMP]] on GSU side.&lt;br /&gt;
&lt;br /&gt;
=== Game Pak ROM Bank Register (ROMBR) ===&lt;br /&gt;
&lt;br /&gt;
This register controls the bank where ROM is read. It&#039;s set using the [[ROMB]] on the GSU side.&lt;br /&gt;
It&#039;s a readable only 8-bit register which is mapped to $3036 on the CPU side.&lt;br /&gt;
&lt;br /&gt;
=== Game Pak RAM Bank Register (RAMBR) ===&lt;br /&gt;
&lt;br /&gt;
This register is the RAM equivalent to ROMBR. It&#039;s set using the [[RAMB]] on the GSU side.&lt;br /&gt;
It&#039;s a readable only 1-bit register which is mapped to $303C on the CPU side.&lt;br /&gt;
&lt;br /&gt;
=== Cache Base Register (CBR) ===&lt;br /&gt;
&lt;br /&gt;
The Cache Base Register is the address where cache has been enabled through and tells the GSU where to run code in cache.&lt;br /&gt;
It&#039;s readable 16-bit register accessible through $303E and $303F from the CPU and written by the GSU with the [[CACHE]] and [[LJMP]] opcodes.&lt;br /&gt;
The lowest four bits of this register are open bus since cache is stored in 16-byte blocks.&lt;br /&gt;
&lt;br /&gt;
=== Screen Base Register (SCBR) ===&lt;br /&gt;
&lt;br /&gt;
The Screen Base Register is the high byte of the image buffer i.e. the plotting destination.&lt;br /&gt;
It&#039;s a writeable 8-bit register mapped to $3038 on the CPU side.&lt;br /&gt;
&lt;br /&gt;
=== Screen Mode Register (SCMR) ===&lt;br /&gt;
&lt;br /&gt;
The Screen Mode Register contains the settings for the image buffer (dimensions, bitdepth) but also access to ROM and RAM.&lt;br /&gt;
It&#039;s a writeable 8-bit register mapped to $303A on the CPU side.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+Screen Mode Register bitwise&lt;br /&gt;
! B7 !! B6 !! B5  !! B4  !! B3  !! B2  !! B1  !! B0&lt;br /&gt;
|-&lt;br /&gt;
| -  || -  || HT1 || ROM || RAN || HT0 || MD1 || MD0&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The image buffer dimensions are given by HT0 and HT1. They all are 256 pixels wide but have different heights.&lt;br /&gt;
A special case exists when both bits are 1 which enables OBJ mode which is used to plot single sprites like in &#039;&#039;[[Yoshi&#039;s Island]]&#039;&#039;.&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+Screen Dimensions&lt;br /&gt;
|-&lt;br /&gt;
! HT1 !! H00 !! Mode&lt;br /&gt;
|-&lt;br /&gt;
|  0  ||  0  || 256 by 128&lt;br /&gt;
|-&lt;br /&gt;
|  0  ||  1  || 256 by 160&lt;br /&gt;
|-&lt;br /&gt;
|  1  ||  0  || 256 by 192&lt;br /&gt;
|-&lt;br /&gt;
|  1  ||  1  || OBJ mode&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The bitdepth of the image buffer is set by the MD0 and MD1 bits:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+Screen Mode&lt;br /&gt;
|-&lt;br /&gt;
! MD1 !! MD0 !! Mode&lt;br /&gt;
|-&lt;br /&gt;
|  0  ||  0  || 4-color mode (2bpp)&lt;br /&gt;
|-&lt;br /&gt;
|  0  ||  1  || 16-color mode (4bpp)&lt;br /&gt;
|-&lt;br /&gt;
|  1  ||  0  || Not used&lt;br /&gt;
|-&lt;br /&gt;
|  1  ||  1  || 256-color mode (8bpp)&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The SCMR register also controls whether Game Pak ROM and RAM can be accessed by the CPU or GSU:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+Screen Mode&lt;br /&gt;
|-&lt;br /&gt;
! Bit !! Description&lt;br /&gt;
|-&lt;br /&gt;
| RON || Gives ROM access to the CPU when 0 and GSU when 1.&lt;br /&gt;
|-&lt;br /&gt;
| RAN || Gives RAM access to the CPU when 0 and GSU when 1.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Color Register (COLR) ===&lt;br /&gt;
&lt;br /&gt;
The Color Register contains the colour for the pixel which is to be plotted.&lt;br /&gt;
It&#039;s an 8-bit register which is set using the [[COLOR]] and [[GETC]] opcodes on the GSU. There is no access from the CPU.&lt;br /&gt;
&lt;br /&gt;
=== Plot Options Register (POR) ===&lt;br /&gt;
&lt;br /&gt;
The Color Register controls how the colours are loaded into the COLR register as well as how they&#039;re drawn onto the buffer.&lt;br /&gt;
It&#039;s an 8-bit register which is set using the [[CMODE]] opcode on the GSU. There is no access from the CPU.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+Screen Mode Register bitwise&lt;br /&gt;
! B7 !! B6 !! B5 !! B4  !! B3 !! B2 !! B1 !! B0&lt;br /&gt;
|-&lt;br /&gt;
| -  || -  || -  || OBJ || FH || HN || DT || TP&lt;br /&gt;
|}&lt;br /&gt;
Note that these abbreviations are inofficial and have been included for simplification.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+Description of Screen Mode Register&lt;br /&gt;
|-&lt;br /&gt;
! Bit !! Description&lt;br /&gt;
|-&lt;br /&gt;
| OBJ || [[OBJ Flag]]&lt;br /&gt;
|-&lt;br /&gt;
| FH  || [[Freeze High Flag]]&lt;br /&gt;
|-&lt;br /&gt;
| HN  || [[High Nibble Flag]]&lt;br /&gt;
|-&lt;br /&gt;
| DT  || [[Dither Flag]]&lt;br /&gt;
|-&lt;br /&gt;
| TP  || [[Transparent Flag]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Backup RAM Register (BRAMR) ===&lt;br /&gt;
&lt;br /&gt;
This controls whether Back-up RAM (not to be confused with Game Pak RAM) becomes “protected”.&amp;lt;sup&amp;gt;1&amp;lt;/sup&amp;gt;&lt;br /&gt;
It&#039;s a 1-bit register mapped to bit 0 of $3033 which can be written by the CPU.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;sup&amp;gt;1&amp;lt;/sup&amp;gt;The definition of “protected” isn&#039;t very clear, though it can be assumed that Back-up RAM can&#039;t be written when it&#039;s set to be protected.&lt;br /&gt;
&lt;br /&gt;
=== Version Code Register (VCR) ===&lt;br /&gt;
&lt;br /&gt;
The Version Code Register contains the version code of the Super FX chip.&lt;br /&gt;
It&#039;s an 8-bit read-only register and accessed $303B on the CPU side.&lt;br /&gt;
&lt;br /&gt;
=== Config Register (CFGR) ===&lt;br /&gt;
&lt;br /&gt;
The Config Register contains two flags:&lt;br /&gt;
The IRQ flag which allows the GSU to fire an interrupt to the CPU should it stop and&lt;br /&gt;
the MS0 which controls the speed of the multiplication.&lt;br /&gt;
It&#039;s mapped to bit 0 of $3039 and is writeable from the CPU.&lt;br /&gt;
&lt;br /&gt;
=== Clock Select Register (CLSR) ===&lt;br /&gt;
&lt;br /&gt;
This register sets the clock speed of Super FX and enables pipelining in the process. When clear, Super FX runs at 10.74 MHz, when set, at 21.48 MHz.&lt;br /&gt;
It&#039;s mapped to bit 0 of $3039 and is writeable from the CPU.&lt;br /&gt;
&lt;br /&gt;
Supposedly, the CLSR and MS0 flags must not be set 1 at the same time but no side effects are known.&lt;br /&gt;
&lt;br /&gt;
== Memory and Bus ==&lt;br /&gt;
&lt;br /&gt;
=== Memory Map ===&lt;br /&gt;
One advantage of Super FX is that it naturally supports ROMs with a size of up to 8 MiB. However, Super FX can only use the first two MiB of a ROM. Similarly, even though a single cartridge may have up to 256 KiB of SRAM, only half of them can be used by Super FX. As a result, there is a difference between the CPU and GSU mapping.&lt;br /&gt;
&lt;br /&gt;
This is how the ROM is mapped from the perspective of the CPU:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
!  Banks  !!   Address   !! Description&lt;br /&gt;
|-&lt;br /&gt;
|rowspan=&amp;quot;6&amp;quot;|$00-$3F&lt;br /&gt;
          || $0000-$1FFF || WRAM mirror&lt;br /&gt;
|-&lt;br /&gt;
|           $2100-$21FF || PPU registers&lt;br /&gt;
|-&lt;br /&gt;
|           $3000-$3FFF || Super FX registers&lt;br /&gt;
|-&lt;br /&gt;
|           $4200-$43FF || CPU registers&lt;br /&gt;
|-&lt;br /&gt;
|           $6000-$7FFF || SRAM mirror&lt;br /&gt;
|-&lt;br /&gt;
|           $8000-$FFFF || ROM (LoROM)&lt;br /&gt;
|-&lt;br /&gt;
| $40-$5F || $0000-$FFFF || Mirror of ROM in banks $00-$3F (HiROM)&lt;br /&gt;
|-&lt;br /&gt;
| $60-$6F || $0000-$FFFF || Unmapped&lt;br /&gt;
|-&lt;br /&gt;
| $70-$71 || $0000-$FFFF || SRAM&lt;br /&gt;
|-&lt;br /&gt;
| $7C-$7D || $0000-$FFFF || Backup RAM&lt;br /&gt;
|-&lt;br /&gt;
| $7E-$7F || $0000-$FFFF || WRAM&lt;br /&gt;
|-&lt;br /&gt;
|rowspan=&amp;quot;6&amp;quot;|$80-$BF&lt;br /&gt;
          || $0000-$1FFF || WRAM mirror&lt;br /&gt;
|-&lt;br /&gt;
|           $2100-$21FF || PPU registers&lt;br /&gt;
|-&lt;br /&gt;
|           $3000-$3FFF || Super FX registers&lt;br /&gt;
|-&lt;br /&gt;
|           $4200-$43FF || CPU registers&lt;br /&gt;
|-&lt;br /&gt;
|           $6000-$7FFF || SRAM mirror&lt;br /&gt;
|-&lt;br /&gt;
|           $8000-$FFFF || ROM (LoROM)&lt;br /&gt;
|-&lt;br /&gt;
| $C0-$FF || $8000-$FFFF || ROM (HiROM)&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The GSU memory map looks similar to the CPU mapping but only with access to ROM and SRAM as well as only access to 2 MiB of ROM and 128 KiB of SRAM. As a result, it looks more like this:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
!  Banks  !!   Address   !! Description&lt;br /&gt;
|-&lt;br /&gt;
|rowspan=&amp;quot;2&amp;quot;|$00-$3F&lt;br /&gt;
          || $0000-$7FFF || Unmapped&lt;br /&gt;
|-&lt;br /&gt;
|            $8000-$FFFF || ROM (LoROM)&lt;br /&gt;
|-&lt;br /&gt;
| $40-$5F || $0000-$FFFF || Mirror of ROM in banks $00-$3F (HiROM)&lt;br /&gt;
|-&lt;br /&gt;
| $60-$6F || $0000-$FFFF || Unmapped&lt;br /&gt;
|-&lt;br /&gt;
| $70-$71 || $0000-$FFFF || SRAM&lt;br /&gt;
|-&lt;br /&gt;
| $72-$7F || $0000-$FFFF || Unmapped&lt;br /&gt;
|-&lt;br /&gt;
| $80-$FF || $0000-$FFFF || Mirror of $00-$7F&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Finally, it should be noted that banks $40-$5F are HiROM mirrors of the LoROM banks $00-$3F interlaced so addresses such as $008000 and $400000 contain the same value.&lt;br /&gt;
&lt;br /&gt;
=== ROM ===&lt;br /&gt;
ROM on Super FX can be up to 8 MiB large. However, even though the size is theoretically doable, the largest published Super FX games had a ROM size of 2 MiBs. As a result, not many emulators (not even BSNES as of 2021) emulate this feature properly and such ROM sizes only exist in homebrewing and modding.&lt;br /&gt;
&lt;br /&gt;
Super FX has also has got limitations with ROM access. This first example is the ROM size. Even though a Super FX ROM can be as large as 8 MiB (in theory), the GSU&#039;s data bus is only connected to 2 MiB of it. Said portion of ROM which the processor can access is called GamePak ROM while the additional 6 MiB, called the Super NES ROM, can only be accessed by the CPU.&lt;br /&gt;
A second limitation is the clock speed. The GSU is clocked very fast at 10.74 Mhz (which can be doubled with pipelining) but ROM is clocked at 3.58 Mhz (unlike on [[SA-1]] where ROM is clocked at the same frequency as the coprocessor). As a result, all opcodes, when they are executed in ROM, take at least three cycles to process while reads from ROM are slow.&lt;br /&gt;
&lt;br /&gt;
To counteract against this limitation, the GSU uses a buffering system. In order to load a value from ROM, the bank must first be set in ROMBR (set by [[ROMB]] in the GSU code) while the address is set in register R14. Any write to R14 initiates the buffering process (it&#039;s also this reason it isn&#039;t considered a general purpose register even though it can be used as such). The value then can be retrieved with [[GETB]] and similar opcodes (referred to just &amp;lt;code&amp;gt;GETB&amp;lt;/code&amp;gt; from now on).&lt;br /&gt;
&lt;br /&gt;
The GSU doesn&#039;t wait during the process of fetching. As a result, it is possible to call &amp;lt;code&amp;gt;GETB&amp;lt;/code&amp;gt; some time after writing to R14. In fact, this is even recommend because calling &amp;lt;code&amp;gt;GETB&amp;lt;/code&amp;gt; during the process of fetching will cause the GSU to halt for up to five cycles for executing &amp;lt;code&amp;gt;GETB&amp;lt;/code&amp;gt;. Similarly, writing to &amp;lt;code&amp;gt;ROMB&amp;lt;/code&amp;gt; will halt the code as well until the data has been fetched and enabling cache during the process of fetching will mess up the loaded ROM value.&lt;br /&gt;
&lt;br /&gt;
=== RAM ===&lt;br /&gt;
&lt;br /&gt;
=== Cache ===&lt;br /&gt;
&lt;br /&gt;
In order to improve the speed of the processor, it includes a 512 byte large memory with the same frequency as the GSU as a cache. This allows Super FX to execute a single opcode with only a single cycle (i.e. three times as fast as in regular use). The cache is separated into 32 16-byte blocks, each with a flag which denotes that a block is used, and is indexed by the cache base register (CBR) which is used to keep track of where cache has been invoked. The cache flags and CBR are reset whenever a zero is written to the GO flag but simply halting or invoking the GSU preserves the content of the cache which in turn can be read by the CPU.&lt;br /&gt;
&lt;br /&gt;
Cache on the SNES is mapped to addresses $xx:3100-$xx:32FF ($xx = $00-$3F, $80-$BF), though the start of the cached code (see below) also is dependent on the CBR (start = $3100 + (CBR &amp;amp; 0x1FF)).&lt;br /&gt;
&lt;br /&gt;
There are two methods to fill the cache:&lt;br /&gt;
* Manual caching&lt;br /&gt;
* Automatic caching&lt;br /&gt;
&lt;br /&gt;
Manual caching involes using the CPU and transfer the code to cache. Keep in mind that Super FX will only execute the cache block which has been set to be used. That means, the code has to be transfered as a full 16 byte block, though strictly speaking, only the last byte of the block (address $XXXF) needs to be written to count the block as used.&lt;br /&gt;
In order to execute GSU code in cache, R15 has to be set to $0000-$01FF.&lt;br /&gt;
&lt;br /&gt;
Automatic caching is instead handled by the GSU itself. This is handled either by the dedicated [[CACHE]] opcode or by a [[LJMP]] opcode, the latter because of the lack of bank information for the cache. Both of them clear the cache flags and store the current PC with the lowest nibble masked out into the CBR (CBR = PC &amp;amp; 0xFFF0). Afterwards, each executed opcode will be written into cache starting from CBR &amp;amp; 0x1FF.&lt;br /&gt;
As a result, this use of cache is recommend for loops and the first loop will always run slower than the remaining loops. Should all the blocks be used, any remaining code will be left uncached and executed in the original memory.&lt;br /&gt;
&lt;br /&gt;
Another side effect is that cache is neither ROM nor GamePak RAM so any Super FX code in cache can run in parallel to the SNES even when access to ROM and RAM is given to the CPU instead of GSU.&lt;br /&gt;
&lt;br /&gt;
=== Pipeline Processing ===&lt;br /&gt;
&lt;br /&gt;
In order to boost the processing speed of the GSU, it uses a technique called &amp;quot;pipeline processing&amp;quot;. Pipelining exists to a lesser extend on the [[65c816]], where opcodes are prepared while the remaining bytes of the opcodes are fetched (this is notable on single byte opcodes such as [[INC]] which take two cycles to process, the same amount of cycles as &amp;lt;code&amp;gt;LDA #$xx&amp;lt;/code&amp;gt;, a two byte opcode) but the GSU takes it further by fetching the next opcode during the current opcode&#039;s execution.&lt;br /&gt;
This runs the code double as fast, virtually increasing the clock speed to 21.48 MHz at the cost of adding more care of the coder whenever R15 — the programm counter — is changed, either through branching or through direct writes to R15. In addition, internal processes such as multiplication and memory access can&#039;t take advantage of the virtual increment in clock speed.&lt;br /&gt;
&lt;br /&gt;
Pipelining is controlled with bit 0 of CLSR where clear means pipelining disabled and set means pipelining enabled. It&#039;s accessible on the CPU side at the address $3037.&lt;br /&gt;
&lt;br /&gt;
For the most part, having pipelining enabled doesn&#039;t change the code. The only exceptions are when R15 is modified outside of fetching opcodes i.e. the use of branches and writes to R15 (e.g. &amp;lt;code&amp;gt;IWT R15,#$8000&amp;lt;/code&amp;gt;) as well as halting the GSU such as with [[STOP]]. In these cases, the opcode following that instruction will be executed after the branch. A common solution for the unwanted opcode execution is to put a dummy [[NOP]] after the R15 modifying opcode such as in this example:&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;BCC SkipCode&lt;br /&gt;
NOP             ; Dummy NOP&lt;br /&gt;
...&lt;br /&gt;
SkipCode:&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This proves to be inefficient, though. Most Super FX opcodes are one byte large and take 3 or 1 cycles (depending on whether the code is executed in cache or not) to execute including &amp;lt;code&amp;gt;NOP&amp;lt;/code&amp;gt;. As a result, opcodes such as &amp;lt;code&amp;gt;SUB R0&amp;lt;/code&amp;gt; can be put as a dummy opcode in place of &amp;lt;code&amp;gt;NOP&amp;lt;/code&amp;gt;. The following example demonstrates it:&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;BCC SkipCode&lt;br /&gt;
;NOP            ; Redundant&lt;br /&gt;
SUB R0          ; Set R0 to zero&lt;br /&gt;
STW (R1)&lt;br /&gt;
SkipCode:&lt;br /&gt;
IWT R0,#$1234&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
In the above code, R0 gets overwritten by &amp;lt;code&amp;gt;SUB&amp;lt;/code&amp;gt; no matter whether the branch is taken. However, it later gets overwritten by &amp;lt;code&amp;gt;IWT&amp;lt;/code&amp;gt;. As a result, it doesn&#039;t matter whether the dummy opcode is a &amp;lt;code&amp;gt;NOP&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;SUB&amp;lt;/code&amp;gt; from the branch for the calculation. In fact, using a &amp;lt;code&amp;gt;NOP&amp;lt;/code&amp;gt; increases the code size by one byte which can matter when the code is executed in cache as well as increase the cycle count by 1 or 3 cycles each time the branch is executed, causing in total a minor speed penality.&lt;br /&gt;
&lt;br /&gt;
This doesn&#039;t work for every opcode, though. Opcodes such as &amp;lt;code&amp;gt;ADD #x&amp;lt;/code&amp;gt; (opcodes which are internally prefixed with &amp;lt;code&amp;gt;ALTn&amp;lt;/code&amp;gt;), &amp;lt;code&amp;gt;WITH&amp;lt;/code&amp;gt; (register prefixes which change which register is the source or destination), &amp;lt;code&amp;gt;BRA $10&amp;lt;/code&amp;gt; (branches which always use two bytes) and &amp;lt;code&amp;gt;IWT&amp;lt;/code&amp;gt; (immediate value transfers which use two or three bytes) can only be used as a dummy opcode in very specific circumstances. The latter two can even misalign the program counter not unlike executing &amp;lt;code&amp;gt;LDA #$12&amp;lt;/code&amp;gt; when A is in 16-bit mode on the 65816. The following example demonstrates it:&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;BCC SkipCode&lt;br /&gt;
BRA Error       ; Caution!&lt;br /&gt;
&lt;br /&gt;
SkipCode:&lt;br /&gt;
INC R1          ; Will instead be read with the BRA as &amp;quot;BRA $D1&amp;quot;.&lt;br /&gt;
...&lt;br /&gt;
&lt;br /&gt;
Error:&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
In addition, the dummy opcode after a &amp;lt;code&amp;gt;STOP&amp;lt;/code&amp;gt; &#039;&#039;&#039;must&#039;&#039;&#039; be a &amp;lt;code&amp;gt;NOP&amp;lt;/code&amp;gt; because putting the GSU in WAIT will not clear the opcode in the pipeline. Extra care should be taken when pipeliend code is executed and a &amp;lt;code&amp;gt;STOP&amp;lt;/code&amp;gt; is located at $XXXF in cache as the pipelined code may be located in unused cache and a value in ROM/RAM will be loaded instead.&lt;br /&gt;
&lt;br /&gt;
== Bus Conflicts ==&lt;br /&gt;
Between both processors, only one of them can acess Game Pak ROM and RAM at a time so memory access must be controlled. Access is set by the SCMR, by the RON and RAN bits with 0 meaning CPU access and 1 meaning GSU access.&lt;br /&gt;
&lt;br /&gt;
For the GSU, it&#039;s set to WAIT if it isn&#039;t granted access for the respective memory it tries to access (e.g. executing code in ROM, storing to RAM). Once it&#039;s granted access, the WAIT status is reset and execution resumes.&lt;br /&gt;
&lt;br /&gt;
For the CPU, illegal memory access is different as it lacks a WAIT state or a comparable feature. For this reason, the processor instead reads garbage values.&lt;br /&gt;
The specific values actually depend on the type of memory: For illegal RAM access, the CPU reads from open bus instead but for illegal ROM access, the memory bus provides a dummy byte whose value depends on the lowest nibble of the address instead:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
!    Address Low Nibble   !! Byte&lt;br /&gt;
|-&lt;br /&gt;
| 0x0, 0x2, 0x6, 0x8, 0xC || 0x00&lt;br /&gt;
|-&lt;br /&gt;
|            0x4          || 0x04&lt;br /&gt;
|-&lt;br /&gt;
|            0xA          || 0x08&lt;br /&gt;
|-&lt;br /&gt;
|            0xE          || 0x0C&lt;br /&gt;
|-&lt;br /&gt;
|           Other         || 0x01&lt;br /&gt;
|}&lt;br /&gt;
The main purpose of the dummy data is to handle interrupts where the CPU needs to read from ROM to execute code at the given address. This is why on Super FX ROMs, interrupts point to these specific addresses, all of which are in WRAM:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Address !! Interrupt&lt;br /&gt;
|-&lt;br /&gt;
| $000100 ||    BRK&lt;br /&gt;
|-&lt;br /&gt;
| $000104 ||    COP&lt;br /&gt;
|-&lt;br /&gt;
| $000108 ||    NMI&lt;br /&gt;
|-&lt;br /&gt;
| $00010C ||    IRQ&lt;br /&gt;
|}&lt;br /&gt;
The pointers are spaced to leave enough space for a single &amp;lt;code&amp;gt;JML $xxxxxx&amp;lt;/code&amp;gt; to jump to the actual interrupt code.&lt;br /&gt;
Relatedly, Super FX games upload their interrupt and invoke GSU codes into WRAM and execute them there to handle cases where e.g. an interrupt is fired during GSU execution.&lt;br /&gt;
&lt;br /&gt;
No control exists for cache, it&#039;s always assumed to be granted access to the GSU but can be safely accessed by the CPU if the former isn&#039;t running.&lt;br /&gt;
&lt;br /&gt;
This limitation specifically applies to Game Pak ROM and RAM; Super NES CPU ROM and Back-Up RAM, neither of which the GSU can access, are excluded from bus conflicts.&lt;br /&gt;
&lt;br /&gt;
== Bitmap Processing ==&lt;br /&gt;
&lt;br /&gt;
== External Links ==&lt;br /&gt;
&lt;br /&gt;
* Patent: https://patentimages.storage.googleapis.com/de/a2/7a/f07754f66f39d9/US5724497.pdf&lt;br /&gt;
&lt;br /&gt;
[[Category:SNES_Hardware]]&lt;br /&gt;
[[Category:Integrated Circuits]]&lt;br /&gt;
[[Category:Enhancement Chips]]&lt;br /&gt;
[[Category:Super FX]]&lt;/div&gt;</summary>
		<author><name>MarioFanGamer</name></author>
	</entry>
	<entry>
		<id>https://sneslab.net/mw/index.php?title=Cache_RAM&amp;diff=11599</id>
		<title>Cache RAM</title>
		<link rel="alternate" type="text/html" href="https://sneslab.net/mw/index.php?title=Cache_RAM&amp;diff=11599"/>
		<updated>2023-11-29T12:16:11Z</updated>

		<summary type="html">&lt;p&gt;MarioFanGamer: Added mapping on the CPU and Super FX category.&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&#039;&#039;&#039;Cache RAM&#039;&#039;&#039; is a region of 512 bytes on the [[Super FX]].  Access to it is six times faster than [[Game Pak ROM]] or [[Game Pak RAM]].&amp;lt;sup&amp;gt;1&amp;lt;/sup&amp;gt;  It is divided into 32 blocks, each block being 16 bytes.&amp;lt;sup&amp;gt;2&amp;lt;/sup&amp;gt;&lt;br /&gt;
&lt;br /&gt;
On the S-CPU, it is mapped to $xx:3100-$xx:32FF ($xx = $00-$3F, $80-$BF).&amp;lt;sup&amp;gt;3&amp;lt;/sup&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== See Also ===&lt;br /&gt;
* [[CACHE]]&lt;br /&gt;
* [[LJMP (Super FX)]]&lt;br /&gt;
&lt;br /&gt;
=== References ===&lt;br /&gt;
# [https://archive.org/details/SNESDevManual/book2/page/n131 page 2-6-9 of Book II] of the official Super Nintendo development manual&lt;br /&gt;
# [https://archive.org/details/SNESDevManual/book2/page/n132 page 2-6-10 of Book II] of the official Super Nintendo development manual&lt;br /&gt;
# Cache RAM Access From The Super NES.  [https://archive.org/details/SNESDevManual/book2/page/n133 page 2-6-12 of Book II] of the official Super Nintendo development manual&lt;br /&gt;
# Execution in Cache RAM.  [https://archive.org/details/SNESDevManual/book2/page/n123 page 2-6-1 of Book II] of the official Super Nintendo development manual&lt;br /&gt;
&lt;br /&gt;
[[Category:SNES Hardware]]&lt;br /&gt;
[[Category:Super FX]]&lt;br /&gt;
[[Category:Address Spaces]]&lt;/div&gt;</summary>
		<author><name>MarioFanGamer</name></author>
	</entry>
	<entry>
		<id>https://sneslab.net/mw/index.php?title=SBC_(Super_FX)&amp;diff=11598</id>
		<title>SBC (Super FX)</title>
		<link rel="alternate" type="text/html" href="https://sneslab.net/mw/index.php?title=SBC_(Super_FX)&amp;diff=11598"/>
		<updated>2023-11-29T12:10:55Z</updated>

		<summary type="html">&lt;p&gt;MarioFanGamer: Added details like carry flag and subtraction with a constand with carry (or lack thereof)&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;float:right;clear:right;width:40%&amp;quot;&lt;br /&gt;
!colspan=&amp;quot;8&amp;quot;|Basic Info&lt;br /&gt;
|+&lt;br /&gt;
|&#039;&#039;&#039;Opcode&#039;&#039;&#039;&lt;br /&gt;
|&#039;&#039;&#039;Length&#039;&#039;&#039;&lt;br /&gt;
|&#039;&#039;&#039;ROM Speed&#039;&#039;&#039;&lt;br /&gt;
|&#039;&#039;&#039;RAM Speed&#039;&#039;&#039;&lt;br /&gt;
|&#039;&#039;&#039;Cache Speed&#039;&#039;&#039;&lt;br /&gt;
|+&lt;br /&gt;
|3D6n&lt;br /&gt;
|2 bytes&lt;br /&gt;
|6 cycles&lt;br /&gt;
|6 cycles&lt;br /&gt;
|2 cycle&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;float:right;clear:right;width:30%&amp;quot;&lt;br /&gt;
!colspan=&amp;quot;9&amp;quot;|Flags Affected&lt;br /&gt;
|+&lt;br /&gt;
|B&lt;br /&gt;
|ALT1&lt;br /&gt;
|ALT2&lt;br /&gt;
|O/V&lt;br /&gt;
|S&lt;br /&gt;
|CY&lt;br /&gt;
|Z&lt;br /&gt;
|+&lt;br /&gt;
|0&lt;br /&gt;
|0&lt;br /&gt;
|0&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;SBC&#039;&#039;&#039; (SuBtract with Carry) is a [[Super FX]] instruction that performs a subtraction with regards to the [[CY|carry flag]].&lt;br /&gt;
Unlike [[ADD (Super FX)]], [[ADC (Super FX)]] and [[SUB (Super FX)]], this one can only be used with registers, not with constant values since since the ALT3 version of SUB is a [[CMP (Super FX)]] instead.&lt;br /&gt;
&lt;br /&gt;
=== See Also ===&lt;br /&gt;
* [[SBC]]&lt;br /&gt;
* [[ADC (Super FX)]]&lt;br /&gt;
* [[SUB (Super FX)]]&lt;br /&gt;
&lt;br /&gt;
=== Reference ===&lt;br /&gt;
* [https://archive.org/details/SNESDevManual/book2/page/n264 page 2-9-108 of Book II] of the official Super Nintendo development manual&lt;br /&gt;
&lt;br /&gt;
[[Category:ASM]]&lt;br /&gt;
[[Category:Super FX]]&lt;/div&gt;</summary>
		<author><name>MarioFanGamer</name></author>
	</entry>
	<entry>
		<id>https://sneslab.net/mw/index.php?title=SUB_(Super_FX)&amp;diff=11597</id>
		<title>SUB (Super FX)</title>
		<link rel="alternate" type="text/html" href="https://sneslab.net/mw/index.php?title=SUB_(Super_FX)&amp;diff=11597"/>
		<updated>2023-11-29T11:01:49Z</updated>

		<summary type="html">&lt;p&gt;MarioFanGamer: /* See Also */ Replaced SBK (not a subtraction) by CMP and SBC (ALT-opcodes).&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;float:right;clear:right;width:40%&amp;quot;&lt;br /&gt;
!colspan=&amp;quot;8&amp;quot;|Basic Info&lt;br /&gt;
|+&lt;br /&gt;
|&#039;&#039;&#039;Opcode&#039;&#039;&#039;&lt;br /&gt;
|&#039;&#039;&#039;Length&#039;&#039;&#039;&lt;br /&gt;
|&#039;&#039;&#039;ROM Speed&#039;&#039;&#039;&lt;br /&gt;
|&#039;&#039;&#039;RAM Speed&#039;&#039;&#039;&lt;br /&gt;
|&#039;&#039;&#039;Cache Speed&#039;&#039;&#039;&lt;br /&gt;
|+&lt;br /&gt;
|6n&lt;br /&gt;
|1 byte&lt;br /&gt;
|3 cycles&lt;br /&gt;
|3 cycles&lt;br /&gt;
|1 cycle&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;float:right;clear:right;width:30%&amp;quot;&lt;br /&gt;
!colspan=&amp;quot;9&amp;quot;|Flags Affected&lt;br /&gt;
|+&lt;br /&gt;
|B&lt;br /&gt;
|[[ALT1]]&lt;br /&gt;
|[[ALT2]]&lt;br /&gt;
|[[O/V]]&lt;br /&gt;
|S&lt;br /&gt;
|[[CY]]&lt;br /&gt;
|Z&lt;br /&gt;
|+&lt;br /&gt;
|0&lt;br /&gt;
|0&lt;br /&gt;
|0&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;SUB&#039;&#039;&#039; is a [[Super FX]] instruction that performs a subtraction.&lt;br /&gt;
&lt;br /&gt;
=== See Also ===&lt;br /&gt;
* [[ADD]]&lt;br /&gt;
* [[ADC (Super FX)]]&lt;br /&gt;
* [[ADC]]&lt;br /&gt;
* [[CMP (Super FX)]]&lt;br /&gt;
* [[SBC (Super FX)]]&lt;br /&gt;
&lt;br /&gt;
=== External Links ===&lt;br /&gt;
* Official Nintendo documentation on SUB: [https://archive.org/details/SNESDevManual/book2/page/n274 page 2-9-118 of Book II]&lt;br /&gt;
&lt;br /&gt;
[[Category:ASM]]&lt;br /&gt;
[[Category:Super FX]]&lt;br /&gt;
[[Category:Arithmetic Operation Instructions]]&lt;/div&gt;</summary>
		<author><name>MarioFanGamer</name></author>
	</entry>
	<entry>
		<id>https://sneslab.net/mw/index.php?title=ADC_(Super_FX)&amp;diff=11596</id>
		<title>ADC (Super FX)</title>
		<link rel="alternate" type="text/html" href="https://sneslab.net/mw/index.php?title=ADC_(Super_FX)&amp;diff=11596"/>
		<updated>2023-11-29T11:00:16Z</updated>

		<summary type="html">&lt;p&gt;MarioFanGamer: Fixed opcode for ADC Rn.&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;float:right;clear:right;width:60%&amp;quot;&lt;br /&gt;
!colspan=&amp;quot;8&amp;quot;|Basic Info&lt;br /&gt;
|+&lt;br /&gt;
|&#039;&#039;&#039;Addressing Mode&#039;&#039;&#039;&lt;br /&gt;
|&#039;&#039;&#039;Opcode&#039;&#039;&#039;&lt;br /&gt;
|&#039;&#039;&#039;Length&#039;&#039;&#039;&lt;br /&gt;
|&#039;&#039;&#039;ROM Speed&#039;&#039;&#039;&lt;br /&gt;
|&#039;&#039;&#039;RAM Speed&#039;&#039;&#039;&lt;br /&gt;
|&#039;&#039;&#039;Cache Speed&#039;&#039;&#039;&lt;br /&gt;
|+&lt;br /&gt;
|&lt;br /&gt;
|3D5n&lt;br /&gt;
|2 bytes&lt;br /&gt;
|6 cycles&lt;br /&gt;
|6 cycles&lt;br /&gt;
|2 cycle&lt;br /&gt;
|+&lt;br /&gt;
|[[Immediate]]&lt;br /&gt;
|3F5n&lt;br /&gt;
|2 bytes&lt;br /&gt;
|6 cycles&lt;br /&gt;
|6 cycles&lt;br /&gt;
|2 cycle&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;float:right;clear:right;width:30%&amp;quot;&lt;br /&gt;
!colspan=&amp;quot;9&amp;quot;|Flags Affected&lt;br /&gt;
|+&lt;br /&gt;
|B&lt;br /&gt;
|[[ALT1]]&lt;br /&gt;
|[[ALT2]]&lt;br /&gt;
|[[O/V]]&lt;br /&gt;
|S&lt;br /&gt;
|[[CY]]&lt;br /&gt;
|Z&lt;br /&gt;
|+&lt;br /&gt;
|0&lt;br /&gt;
|0&lt;br /&gt;
|0&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;ADC&#039;&#039;&#039; (Add with carry) is a [[Super FX]] instruction that performs an addition.  The [[source register]] is always the first addend.  The second addend may be any of the 16 R registers or an immediate value.  The third addend is [[CY]]. The sum is stored in the destination register. &lt;br /&gt;
&lt;br /&gt;
=== See Also ===&lt;br /&gt;
* [[ADD]]&lt;br /&gt;
* [[ADC]]&lt;br /&gt;
* [[SUB]]&lt;br /&gt;
&lt;br /&gt;
=== External Links ===&lt;br /&gt;
* Official Nintendo documentation on ADC: [https://archive.org/details/SNESDevManual/book2/page/n159 Page 2-9-3 of Book II]&lt;br /&gt;
&lt;br /&gt;
[[Category:ASM]]&lt;br /&gt;
[[Category:Super FX]]&lt;br /&gt;
[[Category:Arithmetic Operation Instructions]]&lt;/div&gt;</summary>
		<author><name>MarioFanGamer</name></author>
	</entry>
	<entry>
		<id>https://sneslab.net/mw/index.php?title=FMULT_(Super_FX)&amp;diff=11473</id>
		<title>FMULT (Super FX)</title>
		<link rel="alternate" type="text/html" href="https://sneslab.net/mw/index.php?title=FMULT_(Super_FX)&amp;diff=11473"/>
		<updated>2023-11-28T18:10:55Z</updated>

		<summary type="html">&lt;p&gt;MarioFanGamer: /* See Also */ Added link to LMULT.&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;float:right;clear:right;width:50%&amp;quot;&lt;br /&gt;
!colspan=&amp;quot;8&amp;quot;|Basic Info&lt;br /&gt;
|+&lt;br /&gt;
|&#039;&#039;&#039;Opcode&#039;&#039;&#039;&lt;br /&gt;
|&#039;&#039;&#039;Length&#039;&#039;&#039;&lt;br /&gt;
|&#039;&#039;&#039;ROM Speed&#039;&#039;&#039;&lt;br /&gt;
|&#039;&#039;&#039;RAM Speed&#039;&#039;&#039;&lt;br /&gt;
|&#039;&#039;&#039;Cache Speed&#039;&#039;&#039;&lt;br /&gt;
|+&lt;br /&gt;
|9F&lt;br /&gt;
|1 byte&lt;br /&gt;
|7 or 11 cycles&lt;br /&gt;
|7 or 11 cycles&lt;br /&gt;
|4 or 8 cycle&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;float:right;clear:right;width:30%&amp;quot;&lt;br /&gt;
!colspan=&amp;quot;9&amp;quot;|Flags Affected&lt;br /&gt;
|+&lt;br /&gt;
|B&lt;br /&gt;
|[[ALT1]]&lt;br /&gt;
|[[ALT2]]&lt;br /&gt;
|[[O/V]]&lt;br /&gt;
|S&lt;br /&gt;
|[[CY]]&lt;br /&gt;
|Z&lt;br /&gt;
|+&lt;br /&gt;
|0&lt;br /&gt;
|0&lt;br /&gt;
|0&lt;br /&gt;
|.&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;FMULT&#039;&#039;&#039; is a [[Super FX]] instruction that performs a signed multiplication.  The two factors are the [[source register]] and R6.  The upper 16 bits of the 32-bit product are stored in the [[destination register]].  Bit 15 of the product is stored in [[CY]].  The lower 15 bits of the product appear to be discarded.&lt;br /&gt;
&lt;br /&gt;
The exact speed depends on the state of the [[CFGR]] register.&lt;br /&gt;
&lt;br /&gt;
R4 cannot serve as the destination register.&lt;br /&gt;
&lt;br /&gt;
=== See Also ===&lt;br /&gt;
* [[LMULT]]&lt;br /&gt;
* [[UMULT]]&lt;br /&gt;
* [[MULT]]&lt;br /&gt;
&lt;br /&gt;
=== External Links ===&lt;br /&gt;
* Official Nintendo documentation on FMULT: [https://archive.org/details/SNESDevManual/book2/page/n202 Page 2-9-46 of Book II]&lt;br /&gt;
&lt;br /&gt;
[[Category:ASM]]&lt;br /&gt;
[[Category:Super FX]]&lt;br /&gt;
[[Category:Arithmetic Operation Instructions]]&lt;br /&gt;
[[Category:One-byte Instructions]]&lt;/div&gt;</summary>
		<author><name>MarioFanGamer</name></author>
	</entry>
	<entry>
		<id>https://sneslab.net/mw/index.php?title=Talk:WITH_(Super_FX)&amp;diff=11163</id>
		<title>Talk:WITH (Super FX)</title>
		<link rel="alternate" type="text/html" href="https://sneslab.net/mw/index.php?title=Talk:WITH_(Super_FX)&amp;diff=11163"/>
		<updated>2023-11-27T09:41:41Z</updated>

		<summary type="html">&lt;p&gt;MarioFanGamer: Detailed information about WITH and relation with MOVE(S).&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== &amp;lt;code&amp;gt;WITH&amp;lt;/code&amp;gt; affects &amp;lt;code&amp;gt;FROM&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;TO&amp;lt;/code&amp;gt; and is opcode 2x ==&lt;br /&gt;
Though it is missing in Description of Instruction, one can still identify which number &amp;lt;code&amp;gt;WITH&amp;lt;/code&amp;gt; is encoded thanks to information on page 2-6-7 (alongside 2-4-4 and 2-6-4 for completion): It mentions that &amp;lt;code&amp;gt;FROM&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;TO&amp;lt;/code&amp;gt; are executed as &amp;lt;code&amp;gt;MOVE&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;MOVES&amp;lt;/code&amp;gt;, respectively, if they follow a &amp;lt;code&amp;gt;WITH&amp;lt;/code&amp;gt; thanks to the fact that the former are affected by the B flag and the latter sets it.&lt;br /&gt;
Said information also is useful to update [[Super FX Opcode Matrices|GSU opcode matrix]] if with a footnote that you can only deduce it by looking at the binary representation of &amp;lt;code&amp;gt;MOVE&amp;lt;/code&amp;gt; and that &amp;lt;code&amp;gt;WITH&amp;lt;/code&amp;gt; acts as its prefix opcode (it also allows you to deduce that &amp;lt;code&amp;gt;WITH&amp;lt;/code&amp;gt; is the source and &amp;lt;code&amp;gt;FROM&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;TO&amp;lt;/code&amp;gt; the destination). --[[User:MarioFanGamer|MarioFanGamer]] ([[User talk:MarioFanGamer|talk]]) 09:41, 27 November 2023 (UTC)&lt;/div&gt;</summary>
		<author><name>MarioFanGamer</name></author>
	</entry>
	<entry>
		<id>https://sneslab.net/mw/index.php?title=Emulation_Mode_Flag&amp;diff=9926</id>
		<title>Emulation Mode Flag</title>
		<link rel="alternate" type="text/html" href="https://sneslab.net/mw/index.php?title=Emulation_Mode_Flag&amp;diff=9926"/>
		<updated>2023-11-17T20:39:43Z</updated>

		<summary type="html">&lt;p&gt;MarioFanGamer: Added relation about RESET and emulation mode.&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;The &#039;&#039;&#039;Emulation Mode flag&#039;&#039;&#039; controls whether the [[65c816]] is behaving like a 6502.&lt;br /&gt;
&lt;br /&gt;
When clear, the MPU is in 65c816 native mode.&lt;br /&gt;
&lt;br /&gt;
When set, the MPU is in 6502 emulation mode.&lt;br /&gt;
&lt;br /&gt;
This flag cannot be modified directly and is normally hidden from the programmer.  To modify it, use the [[XCE]] instruction to swap its value with the carry flag&#039;s value.&lt;br /&gt;
&lt;br /&gt;
The flag is set when a [[RESET]] interrupt is fired. In other words, the CPU always starts in emulation mode at boot and after a reset.&lt;br /&gt;
&lt;br /&gt;
[[Category:SNES Hardware]]&lt;br /&gt;
[[Category:ASM]]&lt;/div&gt;</summary>
		<author><name>MarioFanGamer</name></author>
	</entry>
	<entry>
		<id>https://sneslab.net/mw/index.php?title=forced_blank&amp;diff=9925</id>
		<title>forced blank</title>
		<link rel="alternate" type="text/html" href="https://sneslab.net/mw/index.php?title=forced_blank&amp;diff=9925"/>
		<updated>2023-11-17T20:17:58Z</updated>

		<summary type="html">&lt;p&gt;MarioFanGamer: Added redirect.&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;#REDIRECT [[Blanking]]&lt;/div&gt;</summary>
		<author><name>MarioFanGamer</name></author>
	</entry>
	<entry>
		<id>https://sneslab.net/mw/index.php?title=Offset_Change_Mode&amp;diff=9924</id>
		<title>Offset Change Mode</title>
		<link rel="alternate" type="text/html" href="https://sneslab.net/mw/index.php?title=Offset_Change_Mode&amp;diff=9924"/>
		<updated>2023-11-17T20:09:28Z</updated>

		<summary type="html">&lt;p&gt;MarioFanGamer: Corrected level number&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[File:touch fuzzy get dizzy still.png|thumb|offset change mode manipulating the ground background layer in stage 1-7 &amp;quot;Touch Fuzzy Get Dizzy&amp;quot; of &#039;&#039;Yoshi&#039;s Island&#039;&#039;]]&lt;br /&gt;
&lt;br /&gt;
The term &#039;&#039;&#039;Offset Change Mode&#039;&#039;&#039;, also known as &#039;&#039;&#039;Offset per Tile&#039;&#039;&#039;, describes an effect on the [[Super NES]] where the offset of each displayed column of a background tilemap can be overwritten by a different offset. Games such as &#039;&#039;Tetris Attack&#039;&#039; and &#039;&#039;Super Mario World 2: Yoshi&#039;s Island&#039;&#039; make use of it.&lt;br /&gt;
&lt;br /&gt;
== Function ==&lt;br /&gt;
The Super NES console has got eight modes, numbered from 0 to 7, for displaying background layers, three of them (background modes 2, 4 and 6) supporting Offset Change Mode. In these background modes, the offsets for almost every column can be overwritten by a new value. Said offsets can be applies for both visible background layers in the horizontal and vertical direction.&lt;br /&gt;
&lt;br /&gt;
In these background modes, the tilemap of background layer 3 is repurposed to contain offsets and not tile data. This is especially evident on Mode 2 which is otherwise identical to Mode 1: Two 4bpp backgrounds but only the latter has got three visible background layers. Furthermore, the Super NES is wired to always use background layer 3 for offsets even on Mode 6 which lacks layer 2.&lt;br /&gt;
&lt;br /&gt;
=== Reading an Offset ===&lt;br /&gt;
Because an actual background tilemap is used to get the offsets, reading an offset follows similar rules as reading a tile. The formula of the first offset on a 32x32 tilemap looks like this:&lt;br /&gt;
&amp;lt;code&amp;gt;(BG3SC &amp;amp; 0xFC &amp;lt;&amp;lt; 8) + (BG3VOFS &amp;amp; 0xF8 &amp;lt;&amp;lt; 2) + (BG3HOFS &amp;amp; 0xF8 &amp;gt;&amp;gt; 3)&amp;lt;/code&amp;gt;&lt;br /&gt;
where BG3SC is the value in $2109, BG3VOFS the value in $2112 and BG3HOFS the value in $2111. Because the offsets are affected by BG3VOFS and BG3HOFS, you can make use of a raster interrupt (i.e. [[IRQ]] and [[HDMA]]) to change the BG3 offsets and use a different offset for that portion of the screen.&lt;br /&gt;
&lt;br /&gt;
Furthermore, the Super NES reads from the offset data twice in background modes 2 and 6: First to get a horizontal offset and then again offset by 32 bytes (i.e. a single row of tiles) to get the vertical offset. Mode 4, on the other hand, only allows offsets in one direction, controlled by bit 15 of the offset data.&lt;br /&gt;
&lt;br /&gt;
=== Applying the Offset ===&lt;br /&gt;
The real difference comes in the tilemap data. Usually, the tiles use the &amp;lt;code&amp;gt;YXPCCCTT TTTTTTTT&amp;lt;/code&amp;gt; format but offsets use the &amp;lt;code&amp;gt;D21---OO OOOOOOOO&amp;lt;/code&amp;gt; format where D is the direction (0 = horizontal, 1 = vertical, only applicable in Mode 4), 2 and 1 are the affected background layers (0 = disabled, 1 = enabled) and the O bits are the offsets. Keep in mind that for horizontal offsets, the last three bytes are ignored and taken from the original background offset instead.&lt;br /&gt;
&lt;br /&gt;
== Limitations ==&lt;br /&gt;
Besides the limitation of horizontal offsets as well as Mode 4, Offset Change Mode isn&#039;t able to apply an offset to the leftmost displayed column. This is because even though Offset Change Mode can change offsets on 32 different columns, there are actually up to 33 columns onscreen. This can be fixed either by masking out the eight leftmost pixels of the screen or treat the original background offset as the 0th column.&lt;br /&gt;
&lt;br /&gt;
=== See Also ===&lt;br /&gt;
* [[Mosaic]]&lt;br /&gt;
&lt;br /&gt;
=== References ===&lt;br /&gt;
* Official Super Nintendo development manual on Offset Change Mode: [https://archive.org/details/SNESDevManual/book1/page/n77 Page 2-12-1 of Book I]&lt;br /&gt;
* [https://archive.org/details/SNESDevManual/book1/page/n207 Appendix 13] on Offset Change Mode&lt;br /&gt;
* https://problemkaputt.de/fullsnes.htm#snesppuoffsetpertilemode&lt;br /&gt;
&lt;br /&gt;
=== External Links ===&lt;br /&gt;
* Touch Fuzzy Get Dizzy example: https://youtu.be/Pus2I9aPUY4&lt;br /&gt;
&lt;br /&gt;
[[Category:Video]]&lt;/div&gt;</summary>
		<author><name>MarioFanGamer</name></author>
	</entry>
	<entry>
		<id>https://sneslab.net/mw/index.php?title=Super_FX&amp;diff=9813</id>
		<title>Super FX</title>
		<link rel="alternate" type="text/html" href="https://sneslab.net/mw/index.php?title=Super_FX&amp;diff=9813"/>
		<updated>2023-10-29T20:38:42Z</updated>

		<summary type="html">&lt;p&gt;MarioFanGamer: /* Bus Conflicts */ Added information about memory access and what happens if a processor isn&amp;#039;t granted it.&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&#039;&#039;&#039;Super FX&#039;&#039;&#039; is a [[Super NES]] [[enhancement chip]] developed by [https://en.wikipedia.org/wiki/Argonaut_Games Argonaut Games] and [http://en.wikipedia.org/wiki/Nintendo Nintendo]. It&#039;s also known as the &amp;quot;Graphical Support Unit&amp;quot; (short for &amp;quot;GSU&amp;quot;) for its greater graphical capabilities compared to the S-CPU whereas its first revision, used for [[Star Fox]], uses the name &amp;quot;Mathematical, Argonaut, Rotation, &amp;amp; Input/Output&amp;quot; or short MARIO chip. It also is know for the use in &#039;&#039;[[Super Mario World 2: Yoshi&#039;s Island]]&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
During this article, GSU refers to Super FX whereas CPU refers to the Super NES CPU.&lt;br /&gt;
&lt;br /&gt;
== Features ==&lt;br /&gt;
This embedded co-processor has a base clock speed of &#039;&#039;&#039;10.74 MHz&#039;&#039;&#039; - four times as fast as the S-CPU, which uses a base block of 2.68 Mhz. Its features include but are not limited to:&lt;br /&gt;
* A RISC-like processor where most opcodes have an instruction size of one byte and are executed in a single cycle when in cache.&lt;br /&gt;
* 512 bytes of cache RAM for faster processing of instructions.&lt;br /&gt;
* A large memory capactiy, a total capacity of 8 MiB ROM, of which two MiB are shared by CPU and GSU, and 256 KiB RAM, of which 128 KiB are shared by CPU and GSU.&lt;br /&gt;
* A separate bus for ROM and RAM to handle memory in parallel&lt;br /&gt;
* Parallel processing with the CPU&lt;br /&gt;
* Fast Bitmap to Planar conversion&lt;br /&gt;
* Pipeline processing to fetch opcodes twice as fast, effectively increasing the processing speed to 21.48 MHz.&lt;br /&gt;
&lt;br /&gt;
= Technical Information =&lt;br /&gt;
&lt;br /&gt;
== Hardware Registers ==&lt;br /&gt;
&lt;br /&gt;
Super FX comes with various hardware registers of various functions. Most (but not all) of the GSU hardware registers can be accessed from the CPU when the GSU is idling. They are located in the $3000-$3FFF region in banks $00-$3F and $80-$BF.&lt;br /&gt;
&lt;br /&gt;
=== General Registers (R0-R13) ===&lt;br /&gt;
&lt;br /&gt;
These registers are more or less equivalent to the A, X and Y registers on the [[65c816]]. They all are parameters to many opcodes, though not all of them are valid (e.g. R0 can&#039;t be a parameter for the logical operators), and are all 16-bit. Some of them come with a secondary use for certain opcodes. The CPU can directly read from and write to these registers $3000-$301B.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+A list of their addresses and their secondary functions&lt;br /&gt;
|-&lt;br /&gt;
! Name !! Address !! Secondary Function&lt;br /&gt;
|-&lt;br /&gt;
|  R0  ||  $3000  || Default source/destination register.&lt;br /&gt;
|-&lt;br /&gt;
|  R1  ||  $3002  || [[PLOT]] X position&lt;br /&gt;
|-&lt;br /&gt;
|  R2  ||  $3004  || [[PLOT]] Y position&lt;br /&gt;
|-&lt;br /&gt;
|  R3  ||  $3006  ||&lt;br /&gt;
|-&lt;br /&gt;
|  R4  ||  $3008  || Low word for [[LMULT]] result&lt;br /&gt;
|-&lt;br /&gt;
|  R5  ||  $300A  ||&lt;br /&gt;
|-&lt;br /&gt;
|  R6  ||  $300C  || Second input for [[LMULT]] and [[FMULT]]&lt;br /&gt;
|-&lt;br /&gt;
|  R7  ||  $300E  || [[MERGE]] source 1&lt;br /&gt;
|-&lt;br /&gt;
|  R8  ||  $3010  || [[MERGE]] source 2&lt;br /&gt;
|-&lt;br /&gt;
|  R9  ||  $3012  ||&lt;br /&gt;
|-&lt;br /&gt;
|  R10 ||  $3014  ||&lt;br /&gt;
|-&lt;br /&gt;
|  R11 ||  $3016  || [[LINK]] destination&lt;br /&gt;
|-&lt;br /&gt;
|  R12 ||  $3018  || [[LOOP]] counter&lt;br /&gt;
|-&lt;br /&gt;
|  R13 ||  $301A  || [[LOOP]] start&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Game Pak ROM Address Pointer (R14) ===&lt;br /&gt;
&lt;br /&gt;
R14 is the ROM Pointer register and is mapped to $301C-$301D on the SNES. It&#039;s the pointer for the [[GETB]] opcodes which allows the GSU to read from ROM.&lt;br /&gt;
It otherwise acts like any normal general register and is sometimes used as such.&lt;br /&gt;
&lt;br /&gt;
=== Program Counter (R15) ===&lt;br /&gt;
&lt;br /&gt;
R15 is the program counter and is mapped to $301E-$301F on the SNES. Unlike on the [[65c816]] processor, the program counter (excluding the bank) can be directly read or modified within code&lt;br /&gt;
as it acts like a general register. This makes it possible to e.g. jump to a certain address without the use of a dedicated opcode.&lt;br /&gt;
For example, &amp;lt;code&amp;gt;IWT R15, #xxxx&amp;lt;/code&amp;gt; on Super FX is equivalent to &amp;lt;code&amp;gt;JMP $xxxx&amp;lt;/code&amp;gt; on the 65c816.&lt;br /&gt;
&lt;br /&gt;
In addition, writing to $301E on the CPU side invokes the GSU.&lt;br /&gt;
&lt;br /&gt;
=== Status/Flag Register (SFR) ===&lt;br /&gt;
&lt;br /&gt;
Super FX comes with a 16-bit register of various flags, mostly from calculations (e.g. a carry flag) but also other flags like whether Super FX is currently running.&lt;br /&gt;
They can be read and written through $3030 and $3031.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+Status/Flag Register bitwise&lt;br /&gt;
!       !! B7  !! B6 !! B5 !! B4 !! B3 !! B2 !!  B1  !!  B0&lt;br /&gt;
|-&lt;br /&gt;
| $3031 || IRQ || -  || -  || B  || IH || IL || ALT1 || ALT2&lt;br /&gt;
|-&lt;br /&gt;
| $3030 ||  -  || R  || G  || OV || S  || CY ||  Z   ||  -&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+Description of Flags&lt;br /&gt;
|-&lt;br /&gt;
! Flag !! Description&lt;br /&gt;
|-&lt;br /&gt;
|  Z   || Zero flag, set when result is zero.&lt;br /&gt;
|-&lt;br /&gt;
|  CY  || Carry flag, set at result overflow (unsigned).&lt;br /&gt;
|-&lt;br /&gt;
|  S   || Sign flag, set when number is negative.&lt;br /&gt;
|-&lt;br /&gt;
|  OV  || Overflow flag, set at result overflow (signed).&lt;br /&gt;
|-&lt;br /&gt;
|  G   || Go flag, set when GSU is running.&lt;br /&gt;
|-&lt;br /&gt;
|  R   || Set when reading from ROM.&lt;br /&gt;
|-&lt;br /&gt;
| ALT1 || Opcode modifier 1, set when executing [[ALT1]].&lt;br /&gt;
|-&lt;br /&gt;
| ALT2 || Opcode modifier 2, set when executing [[ALT2]].&lt;br /&gt;
|-&lt;br /&gt;
|  IL  || Immediate lower 8-bit flag.&lt;br /&gt;
|-&lt;br /&gt;
|  IH  || Immediate higher 8-bit flag.&lt;br /&gt;
|-&lt;br /&gt;
|  B   || Set when executing [[WITH]].&lt;br /&gt;
|-&lt;br /&gt;
| IRQ  || Interrupt flag, set when GSU stopped.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Program Bank Register (PBR) ===&lt;br /&gt;
&lt;br /&gt;
The program bank is the bank where GSU code is executed. It&#039;s a readable and writable 8-bit register which is mapped to $3034 on the CPU side.&lt;br /&gt;
Unlike R15, this can only be modified indirectly using [[LJMP]] on GSU side.&lt;br /&gt;
&lt;br /&gt;
=== Game Pak ROM Bank Register (ROMBR) ===&lt;br /&gt;
&lt;br /&gt;
This register controls the bank where ROM is read. It&#039;s set using the [[ROMB]] on the GSU side.&lt;br /&gt;
It&#039;s a readable only 8-bit register which is mapped to $3036 on the CPU side.&lt;br /&gt;
&lt;br /&gt;
=== Game Pak RAM Bank Register (RAMBR) ===&lt;br /&gt;
&lt;br /&gt;
This register is the RAM equivalent to ROMBR. It&#039;s set using the [[RAMB]] on the GSU side.&lt;br /&gt;
It&#039;s a readable only 1-bit register which is mapped to $303C on the CPU side.&lt;br /&gt;
&lt;br /&gt;
=== Cache Base Register (CBR) ===&lt;br /&gt;
&lt;br /&gt;
The Cache Base Register is the address where cache has been enabled through and tells the GSU where to run code in cache.&lt;br /&gt;
It&#039;s readable 16-bit register accessible through $303E and $303F from the CPU and written by the GSU with the [[CACHE]] and [[LJMP]] opcodes.&lt;br /&gt;
The lowest four bits of this register are open bus since cache is stored in 16-byte blocks.&lt;br /&gt;
&lt;br /&gt;
=== Screen Base Register (SCBR) ===&lt;br /&gt;
&lt;br /&gt;
The Screen Base Register is the high byte of the image buffer i.e. the plotting destination.&lt;br /&gt;
It&#039;s a writeable 8-bit register mapped to $3038 on the CPU side.&lt;br /&gt;
&lt;br /&gt;
=== Screen Mode Register (SCMR) ===&lt;br /&gt;
&lt;br /&gt;
The Screen Mode Register contains the settings for the image buffer (dimensions, bitdepth) but also access to ROM and RAM.&lt;br /&gt;
It&#039;s a writeable 8-bit register mapped to $303A on the CPU side.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+Screen Mode Register bitwise&lt;br /&gt;
! B7 !! B6 !! B5  !! B4  !! B3  !! B2  !! B1  !! B0&lt;br /&gt;
|-&lt;br /&gt;
| -  || -  || HT1 || ROM || RAN || HT0 || MD1 || MD0&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The image buffer dimensions are given by HT0 and HT1. They all are 256 pixels wide but have different heights.&lt;br /&gt;
A special case exists when both bits are 1 which enables OBJ mode which is used to plot single sprites like in &#039;&#039;[[Yoshi&#039;s Island]]&#039;&#039;.&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+Screen Dimensions&lt;br /&gt;
|-&lt;br /&gt;
! HT1 !! H00 !! Mode&lt;br /&gt;
|-&lt;br /&gt;
|  0  ||  0  || 256 by 128&lt;br /&gt;
|-&lt;br /&gt;
|  0  ||  1  || 256 by 160&lt;br /&gt;
|-&lt;br /&gt;
|  1  ||  0  || 256 by 192&lt;br /&gt;
|-&lt;br /&gt;
|  1  ||  1  || OBJ mode&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The bitdepth of the image buffer is set by the MD0 and MD1 bits:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+Screen Mode&lt;br /&gt;
|-&lt;br /&gt;
! MD1 !! MD0 !! Mode&lt;br /&gt;
|-&lt;br /&gt;
|  0  ||  0  || 4-color mode (2bpp)&lt;br /&gt;
|-&lt;br /&gt;
|  0  ||  1  || 16-color mode (4bpp)&lt;br /&gt;
|-&lt;br /&gt;
|  1  ||  0  || Not used&lt;br /&gt;
|-&lt;br /&gt;
|  1  ||  1  || 256-color mode (8bpp)&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The SCMR register also controls whether Game Pak ROM and RAM can be accessed by the CPU or GSU:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+Screen Mode&lt;br /&gt;
|-&lt;br /&gt;
! Bit !! Description&lt;br /&gt;
|-&lt;br /&gt;
| RON || Gives ROM access to the CPU when 0 and GSU when 1.&lt;br /&gt;
|-&lt;br /&gt;
| RAN || Gives RAM access to the CPU when 0 and GSU when 1.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Color Register (COLR) ===&lt;br /&gt;
&lt;br /&gt;
The Color Register contains the colour for the pixel which is to be plotted.&lt;br /&gt;
It&#039;s an 8-bit register which is set using the [[COLOR]] and [[GETC]] opcodes on the GSU. There is no access from the CPU.&lt;br /&gt;
&lt;br /&gt;
=== Plot Options Register (POR) ===&lt;br /&gt;
&lt;br /&gt;
The Color Register controls how the colours are loaded into the COLR register as well as how they&#039;re drawn onto the buffer.&lt;br /&gt;
It&#039;s an 8-bit register which is set using the [[CMODE]] opcode on the GSU. There is no access from the CPU.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+Screen Mode Register bitwise&lt;br /&gt;
! B7 !! B6 !! B5 !! B4  !! B3 !! B2 !! B1 !! B0&lt;br /&gt;
|-&lt;br /&gt;
| -  || -  || -  || OBJ || FH || HN || DT || TP&lt;br /&gt;
|}&lt;br /&gt;
Note that these abbreviations are inofficial and have been included for simplification.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+Description of Screen Mode Register&lt;br /&gt;
|-&lt;br /&gt;
! Bit !! Description&lt;br /&gt;
|-&lt;br /&gt;
| OBJ || [[OBJ Flag]]&lt;br /&gt;
|-&lt;br /&gt;
| FH  || [[Freeze High Flag]]&lt;br /&gt;
|-&lt;br /&gt;
| HN  || [[High Nibble Flag]]&lt;br /&gt;
|-&lt;br /&gt;
| DT  || [[Dither Flag]]&lt;br /&gt;
|-&lt;br /&gt;
| TP  || [[Transparent Flag]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Backup RAM Register (BRAMR) ===&lt;br /&gt;
&lt;br /&gt;
This controls whether Back-up RAM (not to be confused with Game Pak RAM) becomes “protected”.&amp;lt;sup&amp;gt;1&amp;lt;/sup&amp;gt;&lt;br /&gt;
It&#039;s a 1-bit register mapped to bit 0 of $3033 which can be written by the CPU.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;sup&amp;gt;1&amp;lt;/sup&amp;gt;The definition of “protected” isn&#039;t very clear, though it can be assumed that Back-up RAM can&#039;t be written when it&#039;s set to be protected.&lt;br /&gt;
&lt;br /&gt;
=== Version Code Register (VCR) ===&lt;br /&gt;
&lt;br /&gt;
The Version Code Register contains the version code of the Super FX chip.&lt;br /&gt;
It&#039;s an 8-bit read-only register and accessed $303B on the CPU side.&lt;br /&gt;
&lt;br /&gt;
=== Config Register (CFGR) ===&lt;br /&gt;
&lt;br /&gt;
The Config Register contains two flags:&lt;br /&gt;
The IRQ flag which allows the GSU to fire an interrupt to the CPU should it stop and&lt;br /&gt;
the MS0 which controls the speed of the multiplication.&lt;br /&gt;
It&#039;s mapped to bit 0 of $3039 and is writeable from the CPU.&lt;br /&gt;
&lt;br /&gt;
=== Clock Select Register (CLSR) ===&lt;br /&gt;
&lt;br /&gt;
This register sets the clock speed of Super FX and enables pipelining in the process. When clear, Super FX runs at 10.74 MHz, when set, at 21.48 MHz.&lt;br /&gt;
It&#039;s mapped to bit 0 of $3039 and is writeable from the CPU.&lt;br /&gt;
&lt;br /&gt;
Supposedly, the CLSR and MS0 flags must not be set 1 at the same time but no side effects are known.&lt;br /&gt;
&lt;br /&gt;
== Memory and Bus ==&lt;br /&gt;
&lt;br /&gt;
=== Memory Map ===&lt;br /&gt;
One advantage of Super FX is that it naturally supports ROMs with a size of up to 8 MiB. However, Super FX can only use the first two MiB of a ROM. Similarly, even though a single cartridge may have up to 256 KiB of SRAM, only half of them can be used by Super FX. As a result, there is a difference between the CPU and GSU mapping.&lt;br /&gt;
&lt;br /&gt;
This is how the ROM is mapped from the perspective of the CPU:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
!  Banks  !!   Address   !! Description&lt;br /&gt;
|-&lt;br /&gt;
!rowspan=&amp;quot;6&amp;quot;|$00-$3F&lt;br /&gt;
          || $0000-$1FFF || WRAM mirror&lt;br /&gt;
|-&lt;br /&gt;
|           $2100-$21FF || PPU registers&lt;br /&gt;
|-&lt;br /&gt;
|           $3000-$3FFF || Super FX registers&lt;br /&gt;
|-&lt;br /&gt;
|           $4200-$43FF || CPU registers&lt;br /&gt;
|-&lt;br /&gt;
|           $6000-$7FFF || SRAM mirror&lt;br /&gt;
|-&lt;br /&gt;
|           $8000-$FFFF || ROM (LoROM)&lt;br /&gt;
|-&lt;br /&gt;
| $40-$5F || $0000-$FFFF || Mirror of ROM in banks $00-$3F (HiROM)&lt;br /&gt;
|-&lt;br /&gt;
| $60-$6F || $0000-$FFFF || Unmapped&lt;br /&gt;
|-&lt;br /&gt;
| $70-$71 || $0000-$FFFF || SRAM&lt;br /&gt;
|-&lt;br /&gt;
| $7C-$7D || $0000-$FFFF || Backup RAM&lt;br /&gt;
|-&lt;br /&gt;
| $7E-$7F || $0000-$FFFF || WRAM&lt;br /&gt;
|-&lt;br /&gt;
!rowspan=&amp;quot;6&amp;quot;|$80-$BF&lt;br /&gt;
          || $0000-$1FFF || WRAM mirror&lt;br /&gt;
|-&lt;br /&gt;
|           $2100-$21FF || PPU registers&lt;br /&gt;
|-&lt;br /&gt;
|           $3000-$3FFF || Super FX registers&lt;br /&gt;
|-&lt;br /&gt;
|           $4200-$43FF || CPU registers&lt;br /&gt;
|-&lt;br /&gt;
|           $6000-$7FFF || SRAM mirror&lt;br /&gt;
|-&lt;br /&gt;
|           $8000-$FFFF || ROM (LoROM)&lt;br /&gt;
|-&lt;br /&gt;
| $C0-$FF || $8000-$FFFF || ROM (HiROM)&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The GSU memory map looks similar to the CPU mapping but only with access to ROM and SRAM as well as only access to 2 MiB of ROM and 128 KiB of SRAM. As a result, it looks more like this:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
!  Banks  !!   Address   !! Description&lt;br /&gt;
|-&lt;br /&gt;
!rowspan=&amp;quot;2&amp;quot;|$00-$3F&lt;br /&gt;
          || $0000-$7FFF || Unmapped&lt;br /&gt;
|-&lt;br /&gt;
|            $8000-$FFFF || ROM (LoROM)&lt;br /&gt;
|-&lt;br /&gt;
| $40-$5F || $0000-$FFFF || Mirror of ROM in banks $00-$3F (HiROM)&lt;br /&gt;
|-&lt;br /&gt;
| $60-$6F || $0000-$FFFF || Unmapped&lt;br /&gt;
|-&lt;br /&gt;
| $70-$71 || $0000-$FFFF || SRAM&lt;br /&gt;
|-&lt;br /&gt;
| $72-$7F || $0000-$FFFF || Unmapped&lt;br /&gt;
|-&lt;br /&gt;
| $80-$FF || $0000-$FFFF || Mirror of $00-$7F&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Finally, it should be noted that banks $40-$5F are HiROM mirrors of the LoROM banks $00-$3F interlaced so addresses such as $008000 and $400000 contain the same value.&lt;br /&gt;
&lt;br /&gt;
=== ROM ===&lt;br /&gt;
ROM on Super FX can be up to 8 MiB large. However, even though the size is theoretically doable, the largest published Super FX games had a ROM size of 2 MiBs. As a result, not many emulators (not even BSNES as of 2021) emulate this feature properly and such ROM sizes only exist in homebrewing and modding.&lt;br /&gt;
&lt;br /&gt;
Super FX has also has got limitations with ROM access. This first example is the ROM size. Even though a Super FX ROM can be as large as 8 MiB (in theory), the GSU&#039;s data bus is only connected to 2 MiB of it. Said portion of ROM which the processor can access is called GamePak ROM while the additional 6 MiB, called the Super NES ROM, can only be accessed by the CPU.&lt;br /&gt;
A second limitation is the clock speed. The GSU is clocked very fast at 10.74 Mhz (which can be doubled with pipelining) but ROM is clocked at 3.58 Mhz (unlike on [[SA-1]] where ROM is clocked at the same frequency as the coprocessor). As a result, all opcodes, when they are executed in ROM, take at least three cycles to process while reads from ROM are slow.&lt;br /&gt;
&lt;br /&gt;
To counteract against this limitation, the GSU uses a buffering system. In order to load a value from ROM, the bank must first be set in ROMBR (set by [[ROMB]] in the GSU code) while the address is set in register R14. Any write to R14 initiates the buffering process (it&#039;s also this reason it isn&#039;t considered a general purpose register even though it can be used as such). The value then can be retrieved with [[GETB]] and similar opcodes (referred to just &amp;lt;code&amp;gt;GETB&amp;lt;/code&amp;gt; from now on).&lt;br /&gt;
&lt;br /&gt;
The GSU doesn&#039;t wait during the process of fetching. As a result, it is possible to call &amp;lt;code&amp;gt;GETB&amp;lt;/code&amp;gt; some time after writing to R14. In fact, this is even recommend because calling &amp;lt;code&amp;gt;GETB&amp;lt;/code&amp;gt; during the process of fetching will cause the GSU to halt for up to five cycles for executing &amp;lt;code&amp;gt;GETB&amp;lt;/code&amp;gt;. Similarly, writing to &amp;lt;code&amp;gt;ROMB&amp;lt;/code&amp;gt; will halt the code as well until the data has been fetched and enabling cache during the process of fetching will mess up the loaded ROM value.&lt;br /&gt;
&lt;br /&gt;
=== RAM ===&lt;br /&gt;
&lt;br /&gt;
=== Cache ===&lt;br /&gt;
&lt;br /&gt;
In order to improve the speed of the processor, it includes a 512 byte large memory with the same frequency as the GSU as a cache. This allows Super FX to execute a single opcode with only a single cycle (i.e. three times as fast as in regular use). The cache is separated into 32 16-byte blocks, each with a flag which denotes that a block is used, and is indexed by the cache base register (CBR) which is used to keep track of where cache has been invoked. The cache flags and CBR are reset whenever a zero is written to the GO flag but simply halting or invoking the GSU preserves the content of the cache which in turn can be read by the CPU.&lt;br /&gt;
&lt;br /&gt;
Cache on the SNES is mapped to addresses $xx:3100-$xx:32FF ($xx = $00-$3F, $80-$BF), though the start of the cached code (see below) also is dependent on the CBR (start = $3100 + (CBR &amp;amp; 0x1FF)).&lt;br /&gt;
&lt;br /&gt;
There are two methods to fill the cache:&lt;br /&gt;
* Manual caching&lt;br /&gt;
* Automatic caching&lt;br /&gt;
&lt;br /&gt;
Manual caching involes using the CPU and transfer the code to cache. Keep in mind that Super FX will only execute the cache block which has been set to be used. That means, the code has to be transfered as a full 16 byte block, though strictly speaking, only the last byte of the block (address $XXXF) needs to be written to count the block as used.&lt;br /&gt;
In order to execute GSU code in cache, R15 has to be set to $0000-$01FF.&lt;br /&gt;
&lt;br /&gt;
Automatic caching is instead handled by the GSU itself. This is handled either by the dedicated [[CACHE]] opcode or by a [[LJMP]] opcode, the latter because of the lack of bank information for the cache. Both of them clear the cache flags and store the current PC with the lowest nibble masked out into the CBR (CBR = PC &amp;amp; 0xFFF0). Afterwards, each executed opcode will be written into cache starting from CBR &amp;amp; 0x1FF.&lt;br /&gt;
As a result, this use of cache is recommend for loops and the first loop will always run slower than the remaining loops. Should all the blocks be used, any remaining code will be left uncached and executed in the original memory.&lt;br /&gt;
&lt;br /&gt;
Another side effect is that cache is neither ROM nor GamePak RAM so any Super FX code in cache can run in parallel to the SNES even when access to ROM and RAM is given to the CPU instead of GSU.&lt;br /&gt;
&lt;br /&gt;
=== Pipeline Processing ===&lt;br /&gt;
&lt;br /&gt;
In order to boost the processing speed of the GSU, it uses a technique called &amp;quot;pipeline processing&amp;quot;. Pipelining exists to a lesser extend on the [[65c816]], where opcodes are prepared while the remaining bytes of the opcodes are fetched (this is notable on single byte opcodes such as [[INC]] which take two cycles to process, the same amount of cycles as &amp;lt;code&amp;gt;LDA #$xx&amp;lt;/code&amp;gt;, a two byte opcode) but the GSU takes it further by fetching the next opcode during the current opcode&#039;s execution.&lt;br /&gt;
This runs the code double as fast, virtually increasing the clock speed to 21.48 MHz at the cost of adding more care of the coder whenever R15 — the programm counter — is changed, either through branching or through direct writes to R15. In addition, internal processes such as multiplication and memory access can&#039;t take advantage of the virtual increment in clock speed.&lt;br /&gt;
&lt;br /&gt;
Pipelining is controlled with bit 0 of CLSR where clear means pipelining disabled and set means pipelining enabled. It&#039;s accessible on the CPU side at the address $3037.&lt;br /&gt;
&lt;br /&gt;
For the most part, having pipelining enabled doesn&#039;t change the code. The only exceptions are when R15 is modified outside of fetching opcodes i.e. the use of branches and writes to R15 (e.g. &amp;lt;code&amp;gt;IWT R15,#$8000&amp;lt;/code&amp;gt;) as well as halting the GSU such as with [[STOP]]. In these cases, the opcode following that instruction will be executed after the branch. A common solution for the unwanted opcode execution is to put a dummy [[NOP]] after the R15 modifying opcode such as in this example:&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;BCC SkipCode&lt;br /&gt;
NOP             ; Dummy NOP&lt;br /&gt;
...&lt;br /&gt;
SkipCode:&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This proves to be inefficient, though. Most Super FX opcodes are one byte large and take 3 or 1 cycles (depending on whether the code is executed in cache or not) to execute including &amp;lt;code&amp;gt;NOP&amp;lt;/code&amp;gt;. As a result, opcodes such as &amp;lt;code&amp;gt;SUB R0&amp;lt;/code&amp;gt; can be put as a dummy opcode in place of &amp;lt;code&amp;gt;NOP&amp;lt;/code&amp;gt;. The following example demonstrates it:&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;BCC SkipCode&lt;br /&gt;
;NOP            ; Redundant&lt;br /&gt;
SUB R0          ; Set R0 to zero&lt;br /&gt;
STW (R1)&lt;br /&gt;
SkipCode:&lt;br /&gt;
IWT R0,#$1234&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
In the above code, R0 gets overwritten by &amp;lt;code&amp;gt;SUB&amp;lt;/code&amp;gt; no matter whether the branch is taken. However, it later gets overwritten by &amp;lt;code&amp;gt;IWT&amp;lt;/code&amp;gt;. As a result, it doesn&#039;t matter whether the dummy opcode is a &amp;lt;code&amp;gt;NOP&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;SUB&amp;lt;/code&amp;gt; from the branch for the calculation. In fact, using a &amp;lt;code&amp;gt;NOP&amp;lt;/code&amp;gt; increases the code size by one byte which can matter when the code is executed in cache as well as increase the cycle count by 1 or 3 cycles each time the branch is executed, causing in total a minor speed penality.&lt;br /&gt;
&lt;br /&gt;
This doesn&#039;t work for every opcode, though. Opcodes such as &amp;lt;code&amp;gt;ADD #x&amp;lt;/code&amp;gt; (opcodes which are internally prefixed with &amp;lt;code&amp;gt;ALTn&amp;lt;/code&amp;gt;), &amp;lt;code&amp;gt;WITH&amp;lt;/code&amp;gt; (register prefixes which change which register is the source or destination), &amp;lt;code&amp;gt;BRA $10&amp;lt;/code&amp;gt; (branches which always use two bytes) and &amp;lt;code&amp;gt;IWT&amp;lt;/code&amp;gt; (immediate value transfers which use two or three bytes) can only be used as a dummy opcode in very specific circumstances. The latter two can even misalign the program counter not unlike executing &amp;lt;code&amp;gt;LDA #$12&amp;lt;/code&amp;gt; when A is in 16-bit mode on the 65816. The following example demonstrates it:&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;BCC SkipCode&lt;br /&gt;
BRA Error       ; Caution!&lt;br /&gt;
&lt;br /&gt;
SkipCode:&lt;br /&gt;
INC R1          ; Will instead be read with the BRA as &amp;quot;BRA $D1&amp;quot;.&lt;br /&gt;
...&lt;br /&gt;
&lt;br /&gt;
Error:&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
In addition, the dummy opcode after a &amp;lt;code&amp;gt;STOP&amp;lt;/code&amp;gt; &#039;&#039;&#039;must&#039;&#039;&#039; be a &amp;lt;code&amp;gt;NOP&amp;lt;/code&amp;gt; because putting the GSU in WAIT will not clear the opcode in the pipeline. Extra care should be taken when pipeliend code is executed and a &amp;lt;code&amp;gt;STOP&amp;lt;/code&amp;gt; is located at $XXXF in cache as the pipelined code may be located in unused cache and a value in ROM/RAM will be loaded instead.&lt;br /&gt;
&lt;br /&gt;
== Bus Conflicts ==&lt;br /&gt;
Between both processors, only one of them can acess Game Pak ROM and RAM at a time so memory access must be controlled. Access is set by the SCMR, by the RON and RAN bits with 0 meaning CPU access and 1 meaning GSU access.&lt;br /&gt;
&lt;br /&gt;
For the GSU, it&#039;s set to WAIT if it isn&#039;t granted access for the respective memory it tries to access (e.g. executing code in ROM, storing to RAM). Once it&#039;s granted access, the WAIT status is reset and execution resumes.&lt;br /&gt;
&lt;br /&gt;
For the CPU, illegal memory access is different as it lacks a WAIT state or a comparable feature. For this reason, the processor instead reads garbage values.&lt;br /&gt;
The specific values actually depend on the type of memory: For illegal RAM access, the CPU reads from open bus instead but for illegal ROM access, the memory bus provides a dummy byte whose value depends on the lowest nibble of the address instead:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
!    Address Low Nibble   !! Byte&lt;br /&gt;
|-&lt;br /&gt;
| 0x0, 0x2, 0x6, 0x8, 0xC || 0x00&lt;br /&gt;
|-&lt;br /&gt;
|            0x4          || 0x04&lt;br /&gt;
|-&lt;br /&gt;
|            0xA          || 0x08&lt;br /&gt;
|-&lt;br /&gt;
|            0xE          || 0x0C&lt;br /&gt;
|-&lt;br /&gt;
|           Other         || 0x01&lt;br /&gt;
|}&lt;br /&gt;
The main purpose of the dummy data is to handle interrupts where the CPU needs to read from ROM to execute code at the given address. This is why on Super FX ROMs, interrupts point to these specific addresses, all of which are in WRAM:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Address !! Interrupt&lt;br /&gt;
|-&lt;br /&gt;
| $000100 ||    BRK&lt;br /&gt;
|-&lt;br /&gt;
| $000104 ||    COP&lt;br /&gt;
|-&lt;br /&gt;
| $000108 ||    NMI&lt;br /&gt;
|-&lt;br /&gt;
| $00010C ||    IRQ&lt;br /&gt;
|}&lt;br /&gt;
The pointers are spaced to leave enough space for a single &amp;lt;code&amp;gt;JML $xxxxxx&amp;lt;/code&amp;gt; to jump to the actual interrupt code.&lt;br /&gt;
Relatedly, Super FX games upload their interrupt and invoke GSU codes into WRAM and execute them there to handle cases where e.g. an interrupt is fired during GSU execution.&lt;br /&gt;
&lt;br /&gt;
No control exists for cache, it&#039;s always assumed to be granted access to the GSU but can be safely accessed by the CPU if the former isn&#039;t running.&lt;br /&gt;
&lt;br /&gt;
This limitation specifically applies to Game Pak ROM and RAM; Super NES CPU ROM and Back-Up RAM, neither of which the GSU can access, are excluded from bus conflicts.&lt;br /&gt;
&lt;br /&gt;
== Bitmap Processing ==&lt;br /&gt;
&lt;br /&gt;
== External Links ==&lt;br /&gt;
&lt;br /&gt;
* Patent: https://patentimages.storage.googleapis.com/de/a2/7a/f07754f66f39d9/US5724497.pdf&lt;br /&gt;
&lt;br /&gt;
[[Category:SNES_Hardware]]&lt;br /&gt;
[[Category:Integrated Circuits]]&lt;br /&gt;
[[Category:Enhancement Chips]]&lt;br /&gt;
[[Category:Super FX]]&lt;/div&gt;</summary>
		<author><name>MarioFanGamer</name></author>
	</entry>
	<entry>
		<id>https://sneslab.net/mw/index.php?title=Super_FX&amp;diff=9796</id>
		<title>Super FX</title>
		<link rel="alternate" type="text/html" href="https://sneslab.net/mw/index.php?title=Super_FX&amp;diff=9796"/>
		<updated>2023-10-20T07:00:14Z</updated>

		<summary type="html">&lt;p&gt;MarioFanGamer: /* Pipeline Processing */ Spelling and error fixes.&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&#039;&#039;&#039;Super FX&#039;&#039;&#039; is a [[Super NES]] [[enhancement chip]] developed by [https://en.wikipedia.org/wiki/Argonaut_Games Argonaut Games] and [http://en.wikipedia.org/wiki/Nintendo Nintendo]. It&#039;s also known as the &amp;quot;Graphical Support Unit&amp;quot; (short for &amp;quot;GSU&amp;quot;) for its greater graphical capabilities compared to the S-CPU whereas its first revision, used for [[Star Fox]], uses the name &amp;quot;Mathematical, Argonaut, Rotation, &amp;amp; Input/Output&amp;quot; or short MARIO chip. It also is know for the use in &#039;&#039;[[Super Mario World 2: Yoshi&#039;s Island]]&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
During this article, GSU refers to Super FX whereas CPU refers to the Super NES CPU.&lt;br /&gt;
&lt;br /&gt;
== Features ==&lt;br /&gt;
This embedded co-processor has a base clock speed of &#039;&#039;&#039;10.74 MHz&#039;&#039;&#039; - four times as fast as the S-CPU, which uses a base block of 2.68 Mhz. Its features include but are not limited to:&lt;br /&gt;
* A RISC-like processor where most opcodes have an instruction size of one byte and are executed in a single cycle when in cache.&lt;br /&gt;
* 512 bytes of cache RAM for faster processing of instructions.&lt;br /&gt;
* A large memory capactiy, a total capacity of 8 MiB ROM, of which two MiB are shared by CPU and GSU, and 256 KiB RAM, of which 128 KiB are shared by CPU and GSU.&lt;br /&gt;
* A separate bus for ROM and RAM to handle memory in parallel&lt;br /&gt;
* Parallel processing with the CPU&lt;br /&gt;
* Fast Bitmap to Planar conversion&lt;br /&gt;
* Pipeline processing to fetch opcodes twice as fast, effectively increasing the processing speed to 21.48 MHz.&lt;br /&gt;
&lt;br /&gt;
= Technical Information =&lt;br /&gt;
&lt;br /&gt;
== Hardware Registers ==&lt;br /&gt;
&lt;br /&gt;
Super FX comes with various hardware registers of various functions. Most (but not all) of the GSU hardware registers can be accessed from the CPU when the GSU is idling. They are located in the $3000-$3FFF region in banks $00-$3F and $80-$BF.&lt;br /&gt;
&lt;br /&gt;
=== General Registers (R0-R13) ===&lt;br /&gt;
&lt;br /&gt;
These registers are more or less equivalent to the A, X and Y registers on the [[65c816]]. They all are parameters to many opcodes, though not all of them are valid (e.g. R0 can&#039;t be a parameter for the logical operators), and are all 16-bit. Some of them come with a secondary use for certain opcodes. The CPU can directly read from and write to these registers $3000-$301B.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+A list of their addresses and their secondary functions&lt;br /&gt;
|-&lt;br /&gt;
! Name !! Address !! Secondary Function&lt;br /&gt;
|-&lt;br /&gt;
|  R0  ||  $3000  || Default source/destination register.&lt;br /&gt;
|-&lt;br /&gt;
|  R1  ||  $3002  || [[PLOT]] X position&lt;br /&gt;
|-&lt;br /&gt;
|  R2  ||  $3004  || [[PLOT]] Y position&lt;br /&gt;
|-&lt;br /&gt;
|  R3  ||  $3006  ||&lt;br /&gt;
|-&lt;br /&gt;
|  R4  ||  $3008  || Low word for [[LMULT]] result&lt;br /&gt;
|-&lt;br /&gt;
|  R5  ||  $300A  ||&lt;br /&gt;
|-&lt;br /&gt;
|  R6  ||  $300C  || Second input for [[LMULT]] and [[FMULT]]&lt;br /&gt;
|-&lt;br /&gt;
|  R7  ||  $300E  || [[MERGE]] source 1&lt;br /&gt;
|-&lt;br /&gt;
|  R8  ||  $3010  || [[MERGE]] source 2&lt;br /&gt;
|-&lt;br /&gt;
|  R9  ||  $3012  ||&lt;br /&gt;
|-&lt;br /&gt;
|  R10 ||  $3014  ||&lt;br /&gt;
|-&lt;br /&gt;
|  R11 ||  $3016  || [[LINK]] destination&lt;br /&gt;
|-&lt;br /&gt;
|  R12 ||  $3018  || [[LOOP]] counter&lt;br /&gt;
|-&lt;br /&gt;
|  R13 ||  $301A  || [[LOOP]] start&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Game Pak ROM Address Pointer (R14) ===&lt;br /&gt;
&lt;br /&gt;
R14 is the ROM Pointer register and is mapped to $301C-$301D on the SNES. It&#039;s the pointer for the [[GETB]] opcodes which allows the GSU to read from ROM.&lt;br /&gt;
It otherwise acts like any normal general register and is sometimes used as such.&lt;br /&gt;
&lt;br /&gt;
=== Program Counter (R15) ===&lt;br /&gt;
&lt;br /&gt;
R15 is the program counter and is mapped to $301E-$301F on the SNES. Unlike on the [[65c816]] processor, the program counter (excluding the bank) can be directly read or modified within code&lt;br /&gt;
as it acts like a general register. This makes it possible to e.g. jump to a certain address without the use of a dedicated opcode.&lt;br /&gt;
For example, &amp;lt;code&amp;gt;IWT R15, #xxxx&amp;lt;/code&amp;gt; on Super FX is equivalent to &amp;lt;code&amp;gt;JMP $xxxx&amp;lt;/code&amp;gt; on the 65c816.&lt;br /&gt;
&lt;br /&gt;
In addition, writing to $301E on the CPU side invokes the GSU.&lt;br /&gt;
&lt;br /&gt;
=== Status/Flag Register (SFR) ===&lt;br /&gt;
&lt;br /&gt;
Super FX comes with a 16-bit register of various flags, mostly from calculations (e.g. a carry flag) but also other flags like whether Super FX is currently running.&lt;br /&gt;
They can be read and written through $3030 and $3031.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+Status/Flag Register bitwise&lt;br /&gt;
!       !! B7  !! B6 !! B5 !! B4 !! B3 !! B2 !!  B1  !!  B0&lt;br /&gt;
|-&lt;br /&gt;
| $3031 || IRQ || -  || -  || B  || IH || IL || ALT1 || ALT2&lt;br /&gt;
|-&lt;br /&gt;
| $3030 ||  -  || R  || G  || OV || S  || CY ||  Z   ||  -&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+Description of Flags&lt;br /&gt;
|-&lt;br /&gt;
! Flag !! Description&lt;br /&gt;
|-&lt;br /&gt;
|  Z   || Zero flag, set when result is zero.&lt;br /&gt;
|-&lt;br /&gt;
|  CY  || Carry flag, set at result overflow (unsigned).&lt;br /&gt;
|-&lt;br /&gt;
|  S   || Sign flag, set when number is negative.&lt;br /&gt;
|-&lt;br /&gt;
|  OV  || Overflow flag, set at result overflow (signed).&lt;br /&gt;
|-&lt;br /&gt;
|  G   || Go flag, set when GSU is running.&lt;br /&gt;
|-&lt;br /&gt;
|  R   || Set when reading from ROM.&lt;br /&gt;
|-&lt;br /&gt;
| ALT1 || Opcode modifier 1, set when executing [[ALT1]].&lt;br /&gt;
|-&lt;br /&gt;
| ALT2 || Opcode modifier 2, set when executing [[ALT2]].&lt;br /&gt;
|-&lt;br /&gt;
|  IL  || Immediate lower 8-bit flag.&lt;br /&gt;
|-&lt;br /&gt;
|  IH  || Immediate higher 8-bit flag.&lt;br /&gt;
|-&lt;br /&gt;
|  B   || Set when executing [[WITH]].&lt;br /&gt;
|-&lt;br /&gt;
| IRQ  || Interrupt flag, set when GSU stopped.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Program Bank Register (PBR) ===&lt;br /&gt;
&lt;br /&gt;
The program bank is the bank where GSU code is executed. It&#039;s a readable and writable 8-bit register which is mapped to $3034 on the CPU side.&lt;br /&gt;
Unlike R15, this can only be modified indirectly using [[LJMP]] on GSU side.&lt;br /&gt;
&lt;br /&gt;
=== Game Pak ROM Bank Register (ROMBR) ===&lt;br /&gt;
&lt;br /&gt;
This register controls the bank where ROM is read. It&#039;s set using the [[ROMB]] on the GSU side.&lt;br /&gt;
It&#039;s a readable only 8-bit register which is mapped to $3036 on the CPU side.&lt;br /&gt;
&lt;br /&gt;
=== Game Pak RAM Bank Register (RAMBR) ===&lt;br /&gt;
&lt;br /&gt;
This register is the RAM equivalent to ROMBR. It&#039;s set using the [[RAMB]] on the GSU side.&lt;br /&gt;
It&#039;s a readable only 1-bit register which is mapped to $303C on the CPU side.&lt;br /&gt;
&lt;br /&gt;
=== Cache Base Register (CBR) ===&lt;br /&gt;
&lt;br /&gt;
The Cache Base Register is the address where cache has been enabled through and tells the GSU where to run code in cache.&lt;br /&gt;
It&#039;s readable 16-bit register accessible through $303E and $303F from the CPU and written by the GSU with the [[CACHE]] and [[LJMP]] opcodes.&lt;br /&gt;
The lowest four bits of this register are open bus since cache is stored in 16-byte blocks.&lt;br /&gt;
&lt;br /&gt;
=== Screen Base Register (SCBR) ===&lt;br /&gt;
&lt;br /&gt;
The Screen Base Register is the high byte of the image buffer i.e. the plotting destination.&lt;br /&gt;
It&#039;s a writeable 8-bit register mapped to $3038 on the CPU side.&lt;br /&gt;
&lt;br /&gt;
=== Screen Mode Register (SCMR) ===&lt;br /&gt;
&lt;br /&gt;
The Screen Mode Register contains the settings for the image buffer (dimensions, bitdepth) but also access to ROM and RAM.&lt;br /&gt;
It&#039;s a writeable 8-bit register mapped to $303A on the CPU side.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+Screen Mode Register bitwise&lt;br /&gt;
! B7 !! B6 !! B5  !! B4  !! B3  !! B2  !! B1  !! B0&lt;br /&gt;
|-&lt;br /&gt;
| -  || -  || HT1 || ROM || RAN || HT0 || MD1 || MD0&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The image buffer dimensions are given by HT0 and HT1. They all are 256 pixels wide but have different heights.&lt;br /&gt;
A special case exists when both bits are 1 which enables OBJ mode which is used to plot single sprites like in &#039;&#039;[[Yoshi&#039;s Island]]&#039;&#039;.&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+Screen Dimensions&lt;br /&gt;
|-&lt;br /&gt;
! HT1 !! H00 !! Mode&lt;br /&gt;
|-&lt;br /&gt;
|  0  ||  0  || 256 by 128&lt;br /&gt;
|-&lt;br /&gt;
|  0  ||  1  || 256 by 160&lt;br /&gt;
|-&lt;br /&gt;
|  1  ||  0  || 256 by 192&lt;br /&gt;
|-&lt;br /&gt;
|  1  ||  1  || OBJ mode&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The bitdepth of the image buffer is set by the MD0 and MD1 bits:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+Screen Mode&lt;br /&gt;
|-&lt;br /&gt;
! MD1 !! MD0 !! Mode&lt;br /&gt;
|-&lt;br /&gt;
|  0  ||  0  || 4-color mode (2bpp)&lt;br /&gt;
|-&lt;br /&gt;
|  0  ||  1  || 16-color mode (4bpp)&lt;br /&gt;
|-&lt;br /&gt;
|  1  ||  0  || Not used&lt;br /&gt;
|-&lt;br /&gt;
|  1  ||  1  || 256-color mode (8bpp)&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The SCMR register also controls whether Game Pak ROM and RAM can be accessed by the CPU or GSU:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+Screen Mode&lt;br /&gt;
|-&lt;br /&gt;
! Bit !! Description&lt;br /&gt;
|-&lt;br /&gt;
| RON || Gives ROM access to the CPU when 0 and GSU when 1.&lt;br /&gt;
|-&lt;br /&gt;
| RAN || Gives RAM access to the CPU when 0 and GSU when 1.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Color Register (COLR) ===&lt;br /&gt;
&lt;br /&gt;
The Color Register contains the colour for the pixel which is to be plotted.&lt;br /&gt;
It&#039;s an 8-bit register which is set using the [[COLOR]] and [[GETC]] opcodes on the GSU. There is no access from the CPU.&lt;br /&gt;
&lt;br /&gt;
=== Plot Options Register (POR) ===&lt;br /&gt;
&lt;br /&gt;
The Color Register controls how the colours are loaded into the COLR register as well as how they&#039;re drawn onto the buffer.&lt;br /&gt;
It&#039;s an 8-bit register which is set using the [[CMODE]] opcode on the GSU. There is no access from the CPU.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+Screen Mode Register bitwise&lt;br /&gt;
! B7 !! B6 !! B5 !! B4  !! B3 !! B2 !! B1 !! B0&lt;br /&gt;
|-&lt;br /&gt;
| -  || -  || -  || OBJ || FH || HN || DT || TP&lt;br /&gt;
|}&lt;br /&gt;
Note that these abbreviations are inofficial and have been included for simplification.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+Description of Screen Mode Register&lt;br /&gt;
|-&lt;br /&gt;
! Bit !! Description&lt;br /&gt;
|-&lt;br /&gt;
| OBJ || [[OBJ Flag]]&lt;br /&gt;
|-&lt;br /&gt;
| FH  || [[Freeze High Flag]]&lt;br /&gt;
|-&lt;br /&gt;
| HN  || [[High Nibble Flag]]&lt;br /&gt;
|-&lt;br /&gt;
| DT  || [[Dither Flag]]&lt;br /&gt;
|-&lt;br /&gt;
| TP  || [[Transparent Flag]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Backup RAM Register (BRAMR) ===&lt;br /&gt;
&lt;br /&gt;
This controls whether Back-up RAM (not to be confused with Game Pak RAM) becomes “protected”.&amp;lt;sup&amp;gt;1&amp;lt;/sup&amp;gt;&lt;br /&gt;
It&#039;s a 1-bit register mapped to bit 0 of $3033 which can be written by the CPU.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;sup&amp;gt;1&amp;lt;/sup&amp;gt;The definition of “protected” isn&#039;t very clear, though it can be assumed that Back-up RAM can&#039;t be written when it&#039;s set to be protected.&lt;br /&gt;
&lt;br /&gt;
=== Version Code Register (VCR) ===&lt;br /&gt;
&lt;br /&gt;
The Version Code Register contains the version code of the Super FX chip.&lt;br /&gt;
It&#039;s an 8-bit read-only register and accessed $303B on the CPU side.&lt;br /&gt;
&lt;br /&gt;
=== Config Register (CFGR) ===&lt;br /&gt;
&lt;br /&gt;
The Config Register contains two flags:&lt;br /&gt;
The IRQ flag which allows the GSU to fire an interrupt to the CPU should it stop and&lt;br /&gt;
the MS0 which controls the speed of the multiplication.&lt;br /&gt;
It&#039;s mapped to bit 0 of $3039 and is writeable from the CPU.&lt;br /&gt;
&lt;br /&gt;
=== Clock Select Register (CLSR) ===&lt;br /&gt;
&lt;br /&gt;
This register sets the clock speed of Super FX and enables pipelining in the process. When clear, Super FX runs at 10.74 MHz, when set, at 21.48 MHz.&lt;br /&gt;
It&#039;s mapped to bit 0 of $3039 and is writeable from the CPU.&lt;br /&gt;
&lt;br /&gt;
Supposedly, the CLSR and MS0 flags must not be set 1 at the same time but no side effects are known.&lt;br /&gt;
&lt;br /&gt;
== Memory and Bus ==&lt;br /&gt;
&lt;br /&gt;
=== Memory Map ===&lt;br /&gt;
One advantage of Super FX is that it naturally supports ROMs with a size of up to 8 MiB. However, Super FX can only use the first two MiB of a ROM. Similarly, even though a single cartridge may have up to 256 KiB of SRAM, only half of them can be used by Super FX. As a result, there is a difference between the CPU and GSU mapping.&lt;br /&gt;
&lt;br /&gt;
This is how the ROM is mapped from the perspective of the CPU:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
!  Banks  !!   Address   !! Description&lt;br /&gt;
|-&lt;br /&gt;
!rowspan=&amp;quot;6&amp;quot;|$00-$3F&lt;br /&gt;
          || $0000-$1FFF || WRAM mirror&lt;br /&gt;
|-&lt;br /&gt;
|           $2100-$21FF || PPU registers&lt;br /&gt;
|-&lt;br /&gt;
|           $3000-$3FFF || Super FX registers&lt;br /&gt;
|-&lt;br /&gt;
|           $4200-$43FF || CPU registers&lt;br /&gt;
|-&lt;br /&gt;
|           $6000-$7FFF || SRAM mirror&lt;br /&gt;
|-&lt;br /&gt;
|           $8000-$FFFF || ROM (LoROM)&lt;br /&gt;
|-&lt;br /&gt;
| $40-$5F || $0000-$FFFF || Mirror of ROM in banks $00-$3F (HiROM)&lt;br /&gt;
|-&lt;br /&gt;
| $60-$6F || $0000-$FFFF || Unmapped&lt;br /&gt;
|-&lt;br /&gt;
| $70-$71 || $0000-$FFFF || SRAM&lt;br /&gt;
|-&lt;br /&gt;
| $7C-$7D || $0000-$FFFF || Backup RAM&lt;br /&gt;
|-&lt;br /&gt;
| $7E-$7F || $0000-$FFFF || WRAM&lt;br /&gt;
|-&lt;br /&gt;
!rowspan=&amp;quot;6&amp;quot;|$80-$BF&lt;br /&gt;
          || $0000-$1FFF || WRAM mirror&lt;br /&gt;
|-&lt;br /&gt;
|           $2100-$21FF || PPU registers&lt;br /&gt;
|-&lt;br /&gt;
|           $3000-$3FFF || Super FX registers&lt;br /&gt;
|-&lt;br /&gt;
|           $4200-$43FF || CPU registers&lt;br /&gt;
|-&lt;br /&gt;
|           $6000-$7FFF || SRAM mirror&lt;br /&gt;
|-&lt;br /&gt;
|           $8000-$FFFF || ROM (LoROM)&lt;br /&gt;
|-&lt;br /&gt;
| $C0-$FF || $8000-$FFFF || ROM (HiROM)&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The GSU memory map looks similar to the CPU mapping but only with access to ROM and SRAM as well as only access to 2 MiB of ROM and 128 KiB of SRAM. As a result, it looks more like this:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
!  Banks  !!   Address   !! Description&lt;br /&gt;
|-&lt;br /&gt;
!rowspan=&amp;quot;2&amp;quot;|$00-$3F&lt;br /&gt;
          || $0000-$7FFF || Unmapped&lt;br /&gt;
|-&lt;br /&gt;
|            $8000-$FFFF || ROM (LoROM)&lt;br /&gt;
|-&lt;br /&gt;
| $40-$5F || $0000-$FFFF || Mirror of ROM in banks $00-$3F (HiROM)&lt;br /&gt;
|-&lt;br /&gt;
| $60-$6F || $0000-$FFFF || Unmapped&lt;br /&gt;
|-&lt;br /&gt;
| $70-$71 || $0000-$FFFF || SRAM&lt;br /&gt;
|-&lt;br /&gt;
| $72-$7F || $0000-$FFFF || Unmapped&lt;br /&gt;
|-&lt;br /&gt;
| $80-$FF || $0000-$FFFF || Mirror of $00-$7F&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Finally, it should be noted that banks $40-$5F are HiROM mirrors of the LoROM banks $00-$3F interlaced so addresses such as $008000 and $400000 contain the same value.&lt;br /&gt;
&lt;br /&gt;
=== ROM ===&lt;br /&gt;
ROM on Super FX can be up to 8 MiB large. However, even though the size is theoretically doable, the largest published Super FX games had a ROM size of 2 MiBs. As a result, not many emulators (not even BSNES as of 2021) emulate this feature properly and such ROM sizes only exist in homebrewing and modding.&lt;br /&gt;
&lt;br /&gt;
Super FX has also has got limitations with ROM access. This first example is the ROM size. Even though a Super FX ROM can be as large as 8 MiB (in theory), the GSU&#039;s data bus is only connected to 2 MiB of it. Said portion of ROM which the processor can access is called GamePak ROM while the additional 6 MiB, called the Super NES ROM, can only be accessed by the CPU.&lt;br /&gt;
A second limitation is the clock speed. The GSU is clocked very fast at 10.74 Mhz (which can be doubled with pipelining) but ROM is clocked at 3.58 Mhz (unlike on [[SA-1]] where ROM is clocked at the same frequence as the coprocessor). As a result, all opcodes, when they are executed in ROM, take at least three cycles to process while reads from ROM are slow.&lt;br /&gt;
&lt;br /&gt;
To counteract against this limitation, the GSU uses a buffering system. In order to load a value from ROM, the bank must first be set in ROMBR (set by [[ROMB]] in the GSU code) while the address is set in register R14. Any write to R14 initiates the buffering process (it&#039;s also this reason it isn&#039;t considered a general purpose register even though it can be used as such). The value then can be retrieved with [[GETB]] and similar opcodes (referred to just &amp;lt;code&amp;gt;GETB&amp;lt;/code&amp;gt; from now on).&lt;br /&gt;
&lt;br /&gt;
The GSU doesn&#039;t wait during the process of fetching. As a result, it is possible to call &amp;lt;code&amp;gt;GETB&amp;lt;/code&amp;gt; some time after writing to R14. In fact, this is even recommend because calling &amp;lt;code&amp;gt;GETB&amp;lt;/code&amp;gt; during the process of fetching will cause the GSU to halt for up to five cycles for executing &amp;lt;code&amp;gt;GETB&amp;lt;/code&amp;gt;. Similarly, writing to &amp;lt;code&amp;gt;ROMB&amp;lt;/code&amp;gt; will halt the code as well until the data has been fetched and enabling cache during the process of fetching will mess up the loaded ROM value.&lt;br /&gt;
&lt;br /&gt;
=== RAM ===&lt;br /&gt;
&lt;br /&gt;
=== Cache ===&lt;br /&gt;
&lt;br /&gt;
In order to improve the speed of the processor, it includes a 512 byte large memory with the same frequency as the GSU as a cache. This allows Super FX to execute a single opcode with only a single cycle (i.e. three times as fast as in regular use). The cache is separated into 32 16-byte blocks, each with a flag which denotes that a block is used, and is indexed by the cache base register (CBR) which is used to keep track of where cache has been invoked. The cache flags and CBR are reset whenever a zero is written to the GO flag but simply halting or invoking the GSU preserves the content of the cache which in turn can be read by the CPU.&lt;br /&gt;
&lt;br /&gt;
Cache on the SNES is mapped to addresses $xx:3100-$xx:32FF ($xx = $00-$3F, $80-$BF), though the start of the cached code (see below) also is dependent on the CBR (start = $3100 + (CBR &amp;amp; 0x1FF)).&lt;br /&gt;
&lt;br /&gt;
There are two methods to fill the cache:&lt;br /&gt;
* Manual caching&lt;br /&gt;
* Automatic caching&lt;br /&gt;
&lt;br /&gt;
Manual caching involes using the CPU and transfer the code to cache. Keep in mind that Super FX will only execute the cache block which has been set to be used. That means, the code has to be transfered as a full 16 byte block, though strictly speaking, only the last byte of the block (address $XXXF) needs to be written to count the block as used.&lt;br /&gt;
In order to execute GSU code in cache, R15 has to be set to $0000-$01FF.&lt;br /&gt;
&lt;br /&gt;
Automatic caching is instead handled by the GSU itself. This is handled either by the dedicated [[CACHE]] opcode or by a [[LJMP]] opcode, the latter because of the lack of bank information for the cache. Both of them clear the cache flags and store the current PC with the lowest nibble masked out into the CBR (CBR = PC &amp;amp; 0xFFF0). Afterwards, each executed opcode will be written into cache starting from CBR &amp;amp; 0x1FF.&lt;br /&gt;
As a result, this use of cache is recommend for loops and the first loop will always run slower than the remaining loops. Should all the blocks be used, any remaining code will be left uncached and executed in the original memory.&lt;br /&gt;
&lt;br /&gt;
Another side effect is that cache is neither ROM nor GamePak RAM so any Super FX code in cache can run in parallel to the SNES even when access to ROM and RAM is given to the CPU instead of GSU.&lt;br /&gt;
&lt;br /&gt;
=== Pipeline Processing ===&lt;br /&gt;
&lt;br /&gt;
In order to boost the processing speed of the GSU, it uses a technique called &amp;quot;pipeline processing&amp;quot;. Pipelining exists to a lesser extend on the [[65c816]], where opcodes are prepared while the remaining bytes of the opcodes are fetched (this is notable on single byte opcodes such as [[INC]] which take two cycles to process, the same amount of cycles as &amp;lt;code&amp;gt;LDA #$xx&amp;lt;/code&amp;gt;, a two byte opcode) but the GSU takes it further by fetching the next opcode during the current opcode&#039;s execution.&lt;br /&gt;
This runs the code double as fast, virtually increasing the clock speed to 21.48 MHz at the cost of adding more care of the coder whenever R15 — the programm counter — is changed, either through branching or through direct writes to R15. In addition, internal processes such as multiplication and memory access can&#039;t take advantage of the virtual increment in clock speed.&lt;br /&gt;
&lt;br /&gt;
Pipelining is controlled with bit 0 of CLSR where clear means pipelining disabled and set means pipelining enabled. It&#039;s accessible on the CPU side at the address $3037.&lt;br /&gt;
&lt;br /&gt;
For the most part, having pipelining enabled doesn&#039;t change the code. The only exceptions are when R15 is modified outside of fetching opcodes i.e. the use of branches and writes to R15 (e.g. &amp;lt;code&amp;gt;IWT R15,#$8000&amp;lt;/code&amp;gt;) as well as halting the GSU such as with [[STOP]]. In these cases, the opcode following that instruction will be executed after the branch. A common solution for the unwanted opcode execution is to put a dummy [[NOP]] after the R15 modifying opcode such as in this example:&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;BCC SkipCode&lt;br /&gt;
NOP             ; Dummy NOP&lt;br /&gt;
...&lt;br /&gt;
SkipCode:&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This proves to be inefficient, though. Most Super FX opcodes are one byte large and take 3 or 1 cycles (depending on whether the code is executed in cache or not) to execute including &amp;lt;code&amp;gt;NOP&amp;lt;/code&amp;gt;. As a result, opcodes such as &amp;lt;code&amp;gt;SUB R0&amp;lt;/code&amp;gt; can be put as a dummy opcode in place of &amp;lt;code&amp;gt;NOP&amp;lt;/code&amp;gt;. The following example demonstrates it:&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;BCC SkipCode&lt;br /&gt;
;NOP            ; Redundant&lt;br /&gt;
SUB R0          ; Set R0 to zero&lt;br /&gt;
STW (R1)&lt;br /&gt;
SkipCode:&lt;br /&gt;
IWT R0,#$1234&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
In the above code, R0 gets overwritten by &amp;lt;code&amp;gt;SUB&amp;lt;/code&amp;gt; no matter whether the branch is taken. However, it later gets overwritten by &amp;lt;code&amp;gt;IWT&amp;lt;/code&amp;gt;. As a result, it doesn&#039;t matter whether the dummy opcode is a &amp;lt;code&amp;gt;NOP&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;SUB&amp;lt;/code&amp;gt; from the branch for the calculation. In fact, using a &amp;lt;code&amp;gt;NOP&amp;lt;/code&amp;gt; increases the code size by one byte which can matter when the code is executed in cache as well as increase the cycle count by 1 or 3 cycles each time the branch is executed, causing in total a minor speed penality.&lt;br /&gt;
&lt;br /&gt;
This doesn&#039;t work for every opcode, though. Opcodes such as &amp;lt;code&amp;gt;ADD #x&amp;lt;/code&amp;gt; (opcodes which are internally prefixed with &amp;lt;code&amp;gt;ALTn&amp;lt;/code&amp;gt;), &amp;lt;code&amp;gt;WITH&amp;lt;/code&amp;gt; (register prefixes which change which register is the source or destination), &amp;lt;code&amp;gt;BRA $10&amp;lt;/code&amp;gt; (branches which always use two bytes) and &amp;lt;code&amp;gt;IWT&amp;lt;/code&amp;gt; (immediate value transfers which use two or three bytes) can only be used as a dummy opcode in very specific circumstances. The latter two can even misalign the program counter not unlike executing &amp;lt;code&amp;gt;LDA #$12&amp;lt;/code&amp;gt; when A is in 16-bit mode on the 65816. The following example demonstrates it:&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;BCC SkipCode&lt;br /&gt;
BRA Error       ; Caution!&lt;br /&gt;
&lt;br /&gt;
SkipCode:&lt;br /&gt;
INC R1          ; Will instead be read with the BRA as &amp;quot;BRA $D1&amp;quot;.&lt;br /&gt;
...&lt;br /&gt;
&lt;br /&gt;
Error:&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
In addition, the dummy opcode after a &amp;lt;code&amp;gt;STOP&amp;lt;/code&amp;gt; &#039;&#039;&#039;must&#039;&#039;&#039; be a &amp;lt;code&amp;gt;NOP&amp;lt;/code&amp;gt; because putting the GSU in WAIT will not clear the opcode in the pipeline. Extra care should be taken when pipeliend code is executed and a &amp;lt;code&amp;gt;STOP&amp;lt;/code&amp;gt; is located at $XXXF in cache as the pipelined code may be located in unused cache and a value in ROM/RAM will be loaded instead.&lt;br /&gt;
&lt;br /&gt;
== Bus Conflicts ==&lt;br /&gt;
&lt;br /&gt;
== Bitmap Processing ==&lt;br /&gt;
&lt;br /&gt;
== External Links ==&lt;br /&gt;
&lt;br /&gt;
* Patent: https://patentimages.storage.googleapis.com/de/a2/7a/f07754f66f39d9/US5724497.pdf&lt;br /&gt;
&lt;br /&gt;
[[Category:SNES_Hardware]]&lt;br /&gt;
[[Category:Integrated Circuits]]&lt;br /&gt;
[[Category:Enhancement Chips]]&lt;br /&gt;
[[Category:Super FX]]&lt;/div&gt;</summary>
		<author><name>MarioFanGamer</name></author>
	</entry>
	<entry>
		<id>https://sneslab.net/mw/index.php?title=Super_FX&amp;diff=9795</id>
		<title>Super FX</title>
		<link rel="alternate" type="text/html" href="https://sneslab.net/mw/index.php?title=Super_FX&amp;diff=9795"/>
		<updated>2023-10-20T06:51:29Z</updated>

		<summary type="html">&lt;p&gt;MarioFanGamer: /* ROM */ Spelling errors and details.&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&#039;&#039;&#039;Super FX&#039;&#039;&#039; is a [[Super NES]] [[enhancement chip]] developed by [https://en.wikipedia.org/wiki/Argonaut_Games Argonaut Games] and [http://en.wikipedia.org/wiki/Nintendo Nintendo]. It&#039;s also known as the &amp;quot;Graphical Support Unit&amp;quot; (short for &amp;quot;GSU&amp;quot;) for its greater graphical capabilities compared to the S-CPU whereas its first revision, used for [[Star Fox]], uses the name &amp;quot;Mathematical, Argonaut, Rotation, &amp;amp; Input/Output&amp;quot; or short MARIO chip. It also is know for the use in &#039;&#039;[[Super Mario World 2: Yoshi&#039;s Island]]&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
During this article, GSU refers to Super FX whereas CPU refers to the Super NES CPU.&lt;br /&gt;
&lt;br /&gt;
== Features ==&lt;br /&gt;
This embedded co-processor has a base clock speed of &#039;&#039;&#039;10.74 MHz&#039;&#039;&#039; - four times as fast as the S-CPU, which uses a base block of 2.68 Mhz. Its features include but are not limited to:&lt;br /&gt;
* A RISC-like processor where most opcodes have an instruction size of one byte and are executed in a single cycle when in cache.&lt;br /&gt;
* 512 bytes of cache RAM for faster processing of instructions.&lt;br /&gt;
* A large memory capactiy, a total capacity of 8 MiB ROM, of which two MiB are shared by CPU and GSU, and 256 KiB RAM, of which 128 KiB are shared by CPU and GSU.&lt;br /&gt;
* A separate bus for ROM and RAM to handle memory in parallel&lt;br /&gt;
* Parallel processing with the CPU&lt;br /&gt;
* Fast Bitmap to Planar conversion&lt;br /&gt;
* Pipeline processing to fetch opcodes twice as fast, effectively increasing the processing speed to 21.48 MHz.&lt;br /&gt;
&lt;br /&gt;
= Technical Information =&lt;br /&gt;
&lt;br /&gt;
== Hardware Registers ==&lt;br /&gt;
&lt;br /&gt;
Super FX comes with various hardware registers of various functions. Most (but not all) of the GSU hardware registers can be accessed from the CPU when the GSU is idling. They are located in the $3000-$3FFF region in banks $00-$3F and $80-$BF.&lt;br /&gt;
&lt;br /&gt;
=== General Registers (R0-R13) ===&lt;br /&gt;
&lt;br /&gt;
These registers are more or less equivalent to the A, X and Y registers on the [[65c816]]. They all are parameters to many opcodes, though not all of them are valid (e.g. R0 can&#039;t be a parameter for the logical operators), and are all 16-bit. Some of them come with a secondary use for certain opcodes. The CPU can directly read from and write to these registers $3000-$301B.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+A list of their addresses and their secondary functions&lt;br /&gt;
|-&lt;br /&gt;
! Name !! Address !! Secondary Function&lt;br /&gt;
|-&lt;br /&gt;
|  R0  ||  $3000  || Default source/destination register.&lt;br /&gt;
|-&lt;br /&gt;
|  R1  ||  $3002  || [[PLOT]] X position&lt;br /&gt;
|-&lt;br /&gt;
|  R2  ||  $3004  || [[PLOT]] Y position&lt;br /&gt;
|-&lt;br /&gt;
|  R3  ||  $3006  ||&lt;br /&gt;
|-&lt;br /&gt;
|  R4  ||  $3008  || Low word for [[LMULT]] result&lt;br /&gt;
|-&lt;br /&gt;
|  R5  ||  $300A  ||&lt;br /&gt;
|-&lt;br /&gt;
|  R6  ||  $300C  || Second input for [[LMULT]] and [[FMULT]]&lt;br /&gt;
|-&lt;br /&gt;
|  R7  ||  $300E  || [[MERGE]] source 1&lt;br /&gt;
|-&lt;br /&gt;
|  R8  ||  $3010  || [[MERGE]] source 2&lt;br /&gt;
|-&lt;br /&gt;
|  R9  ||  $3012  ||&lt;br /&gt;
|-&lt;br /&gt;
|  R10 ||  $3014  ||&lt;br /&gt;
|-&lt;br /&gt;
|  R11 ||  $3016  || [[LINK]] destination&lt;br /&gt;
|-&lt;br /&gt;
|  R12 ||  $3018  || [[LOOP]] counter&lt;br /&gt;
|-&lt;br /&gt;
|  R13 ||  $301A  || [[LOOP]] start&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Game Pak ROM Address Pointer (R14) ===&lt;br /&gt;
&lt;br /&gt;
R14 is the ROM Pointer register and is mapped to $301C-$301D on the SNES. It&#039;s the pointer for the [[GETB]] opcodes which allows the GSU to read from ROM.&lt;br /&gt;
It otherwise acts like any normal general register and is sometimes used as such.&lt;br /&gt;
&lt;br /&gt;
=== Program Counter (R15) ===&lt;br /&gt;
&lt;br /&gt;
R15 is the program counter and is mapped to $301E-$301F on the SNES. Unlike on the [[65c816]] processor, the program counter (excluding the bank) can be directly read or modified within code&lt;br /&gt;
as it acts like a general register. This makes it possible to e.g. jump to a certain address without the use of a dedicated opcode.&lt;br /&gt;
For example, &amp;lt;code&amp;gt;IWT R15, #xxxx&amp;lt;/code&amp;gt; on Super FX is equivalent to &amp;lt;code&amp;gt;JMP $xxxx&amp;lt;/code&amp;gt; on the 65c816.&lt;br /&gt;
&lt;br /&gt;
In addition, writing to $301E on the CPU side invokes the GSU.&lt;br /&gt;
&lt;br /&gt;
=== Status/Flag Register (SFR) ===&lt;br /&gt;
&lt;br /&gt;
Super FX comes with a 16-bit register of various flags, mostly from calculations (e.g. a carry flag) but also other flags like whether Super FX is currently running.&lt;br /&gt;
They can be read and written through $3030 and $3031.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+Status/Flag Register bitwise&lt;br /&gt;
!       !! B7  !! B6 !! B5 !! B4 !! B3 !! B2 !!  B1  !!  B0&lt;br /&gt;
|-&lt;br /&gt;
| $3031 || IRQ || -  || -  || B  || IH || IL || ALT1 || ALT2&lt;br /&gt;
|-&lt;br /&gt;
| $3030 ||  -  || R  || G  || OV || S  || CY ||  Z   ||  -&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+Description of Flags&lt;br /&gt;
|-&lt;br /&gt;
! Flag !! Description&lt;br /&gt;
|-&lt;br /&gt;
|  Z   || Zero flag, set when result is zero.&lt;br /&gt;
|-&lt;br /&gt;
|  CY  || Carry flag, set at result overflow (unsigned).&lt;br /&gt;
|-&lt;br /&gt;
|  S   || Sign flag, set when number is negative.&lt;br /&gt;
|-&lt;br /&gt;
|  OV  || Overflow flag, set at result overflow (signed).&lt;br /&gt;
|-&lt;br /&gt;
|  G   || Go flag, set when GSU is running.&lt;br /&gt;
|-&lt;br /&gt;
|  R   || Set when reading from ROM.&lt;br /&gt;
|-&lt;br /&gt;
| ALT1 || Opcode modifier 1, set when executing [[ALT1]].&lt;br /&gt;
|-&lt;br /&gt;
| ALT2 || Opcode modifier 2, set when executing [[ALT2]].&lt;br /&gt;
|-&lt;br /&gt;
|  IL  || Immediate lower 8-bit flag.&lt;br /&gt;
|-&lt;br /&gt;
|  IH  || Immediate higher 8-bit flag.&lt;br /&gt;
|-&lt;br /&gt;
|  B   || Set when executing [[WITH]].&lt;br /&gt;
|-&lt;br /&gt;
| IRQ  || Interrupt flag, set when GSU stopped.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Program Bank Register (PBR) ===&lt;br /&gt;
&lt;br /&gt;
The program bank is the bank where GSU code is executed. It&#039;s a readable and writable 8-bit register which is mapped to $3034 on the CPU side.&lt;br /&gt;
Unlike R15, this can only be modified indirectly using [[LJMP]] on GSU side.&lt;br /&gt;
&lt;br /&gt;
=== Game Pak ROM Bank Register (ROMBR) ===&lt;br /&gt;
&lt;br /&gt;
This register controls the bank where ROM is read. It&#039;s set using the [[ROMB]] on the GSU side.&lt;br /&gt;
It&#039;s a readable only 8-bit register which is mapped to $3036 on the CPU side.&lt;br /&gt;
&lt;br /&gt;
=== Game Pak RAM Bank Register (RAMBR) ===&lt;br /&gt;
&lt;br /&gt;
This register is the RAM equivalent to ROMBR. It&#039;s set using the [[RAMB]] on the GSU side.&lt;br /&gt;
It&#039;s a readable only 1-bit register which is mapped to $303C on the CPU side.&lt;br /&gt;
&lt;br /&gt;
=== Cache Base Register (CBR) ===&lt;br /&gt;
&lt;br /&gt;
The Cache Base Register is the address where cache has been enabled through and tells the GSU where to run code in cache.&lt;br /&gt;
It&#039;s readable 16-bit register accessible through $303E and $303F from the CPU and written by the GSU with the [[CACHE]] and [[LJMP]] opcodes.&lt;br /&gt;
The lowest four bits of this register are open bus since cache is stored in 16-byte blocks.&lt;br /&gt;
&lt;br /&gt;
=== Screen Base Register (SCBR) ===&lt;br /&gt;
&lt;br /&gt;
The Screen Base Register is the high byte of the image buffer i.e. the plotting destination.&lt;br /&gt;
It&#039;s a writeable 8-bit register mapped to $3038 on the CPU side.&lt;br /&gt;
&lt;br /&gt;
=== Screen Mode Register (SCMR) ===&lt;br /&gt;
&lt;br /&gt;
The Screen Mode Register contains the settings for the image buffer (dimensions, bitdepth) but also access to ROM and RAM.&lt;br /&gt;
It&#039;s a writeable 8-bit register mapped to $303A on the CPU side.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+Screen Mode Register bitwise&lt;br /&gt;
! B7 !! B6 !! B5  !! B4  !! B3  !! B2  !! B1  !! B0&lt;br /&gt;
|-&lt;br /&gt;
| -  || -  || HT1 || ROM || RAN || HT0 || MD1 || MD0&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The image buffer dimensions are given by HT0 and HT1. They all are 256 pixels wide but have different heights.&lt;br /&gt;
A special case exists when both bits are 1 which enables OBJ mode which is used to plot single sprites like in &#039;&#039;[[Yoshi&#039;s Island]]&#039;&#039;.&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+Screen Dimensions&lt;br /&gt;
|-&lt;br /&gt;
! HT1 !! H00 !! Mode&lt;br /&gt;
|-&lt;br /&gt;
|  0  ||  0  || 256 by 128&lt;br /&gt;
|-&lt;br /&gt;
|  0  ||  1  || 256 by 160&lt;br /&gt;
|-&lt;br /&gt;
|  1  ||  0  || 256 by 192&lt;br /&gt;
|-&lt;br /&gt;
|  1  ||  1  || OBJ mode&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The bitdepth of the image buffer is set by the MD0 and MD1 bits:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+Screen Mode&lt;br /&gt;
|-&lt;br /&gt;
! MD1 !! MD0 !! Mode&lt;br /&gt;
|-&lt;br /&gt;
|  0  ||  0  || 4-color mode (2bpp)&lt;br /&gt;
|-&lt;br /&gt;
|  0  ||  1  || 16-color mode (4bpp)&lt;br /&gt;
|-&lt;br /&gt;
|  1  ||  0  || Not used&lt;br /&gt;
|-&lt;br /&gt;
|  1  ||  1  || 256-color mode (8bpp)&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The SCMR register also controls whether Game Pak ROM and RAM can be accessed by the CPU or GSU:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+Screen Mode&lt;br /&gt;
|-&lt;br /&gt;
! Bit !! Description&lt;br /&gt;
|-&lt;br /&gt;
| RON || Gives ROM access to the CPU when 0 and GSU when 1.&lt;br /&gt;
|-&lt;br /&gt;
| RAN || Gives RAM access to the CPU when 0 and GSU when 1.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Color Register (COLR) ===&lt;br /&gt;
&lt;br /&gt;
The Color Register contains the colour for the pixel which is to be plotted.&lt;br /&gt;
It&#039;s an 8-bit register which is set using the [[COLOR]] and [[GETC]] opcodes on the GSU. There is no access from the CPU.&lt;br /&gt;
&lt;br /&gt;
=== Plot Options Register (POR) ===&lt;br /&gt;
&lt;br /&gt;
The Color Register controls how the colours are loaded into the COLR register as well as how they&#039;re drawn onto the buffer.&lt;br /&gt;
It&#039;s an 8-bit register which is set using the [[CMODE]] opcode on the GSU. There is no access from the CPU.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+Screen Mode Register bitwise&lt;br /&gt;
! B7 !! B6 !! B5 !! B4  !! B3 !! B2 !! B1 !! B0&lt;br /&gt;
|-&lt;br /&gt;
| -  || -  || -  || OBJ || FH || HN || DT || TP&lt;br /&gt;
|}&lt;br /&gt;
Note that these abbreviations are inofficial and have been included for simplification.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+Description of Screen Mode Register&lt;br /&gt;
|-&lt;br /&gt;
! Bit !! Description&lt;br /&gt;
|-&lt;br /&gt;
| OBJ || [[OBJ Flag]]&lt;br /&gt;
|-&lt;br /&gt;
| FH  || [[Freeze High Flag]]&lt;br /&gt;
|-&lt;br /&gt;
| HN  || [[High Nibble Flag]]&lt;br /&gt;
|-&lt;br /&gt;
| DT  || [[Dither Flag]]&lt;br /&gt;
|-&lt;br /&gt;
| TP  || [[Transparent Flag]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Backup RAM Register (BRAMR) ===&lt;br /&gt;
&lt;br /&gt;
This controls whether Back-up RAM (not to be confused with Game Pak RAM) becomes “protected”.&amp;lt;sup&amp;gt;1&amp;lt;/sup&amp;gt;&lt;br /&gt;
It&#039;s a 1-bit register mapped to bit 0 of $3033 which can be written by the CPU.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;sup&amp;gt;1&amp;lt;/sup&amp;gt;The definition of “protected” isn&#039;t very clear, though it can be assumed that Back-up RAM can&#039;t be written when it&#039;s set to be protected.&lt;br /&gt;
&lt;br /&gt;
=== Version Code Register (VCR) ===&lt;br /&gt;
&lt;br /&gt;
The Version Code Register contains the version code of the Super FX chip.&lt;br /&gt;
It&#039;s an 8-bit read-only register and accessed $303B on the CPU side.&lt;br /&gt;
&lt;br /&gt;
=== Config Register (CFGR) ===&lt;br /&gt;
&lt;br /&gt;
The Config Register contains two flags:&lt;br /&gt;
The IRQ flag which allows the GSU to fire an interrupt to the CPU should it stop and&lt;br /&gt;
the MS0 which controls the speed of the multiplication.&lt;br /&gt;
It&#039;s mapped to bit 0 of $3039 and is writeable from the CPU.&lt;br /&gt;
&lt;br /&gt;
=== Clock Select Register (CLSR) ===&lt;br /&gt;
&lt;br /&gt;
This register sets the clock speed of Super FX and enables pipelining in the process. When clear, Super FX runs at 10.74 MHz, when set, at 21.48 MHz.&lt;br /&gt;
It&#039;s mapped to bit 0 of $3039 and is writeable from the CPU.&lt;br /&gt;
&lt;br /&gt;
Supposedly, the CLSR and MS0 flags must not be set 1 at the same time but no side effects are known.&lt;br /&gt;
&lt;br /&gt;
== Memory and Bus ==&lt;br /&gt;
&lt;br /&gt;
=== Memory Map ===&lt;br /&gt;
One advantage of Super FX is that it naturally supports ROMs with a size of up to 8 MiB. However, Super FX can only use the first two MiB of a ROM. Similarly, even though a single cartridge may have up to 256 KiB of SRAM, only half of them can be used by Super FX. As a result, there is a difference between the CPU and GSU mapping.&lt;br /&gt;
&lt;br /&gt;
This is how the ROM is mapped from the perspective of the CPU:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
!  Banks  !!   Address   !! Description&lt;br /&gt;
|-&lt;br /&gt;
!rowspan=&amp;quot;6&amp;quot;|$00-$3F&lt;br /&gt;
          || $0000-$1FFF || WRAM mirror&lt;br /&gt;
|-&lt;br /&gt;
|           $2100-$21FF || PPU registers&lt;br /&gt;
|-&lt;br /&gt;
|           $3000-$3FFF || Super FX registers&lt;br /&gt;
|-&lt;br /&gt;
|           $4200-$43FF || CPU registers&lt;br /&gt;
|-&lt;br /&gt;
|           $6000-$7FFF || SRAM mirror&lt;br /&gt;
|-&lt;br /&gt;
|           $8000-$FFFF || ROM (LoROM)&lt;br /&gt;
|-&lt;br /&gt;
| $40-$5F || $0000-$FFFF || Mirror of ROM in banks $00-$3F (HiROM)&lt;br /&gt;
|-&lt;br /&gt;
| $60-$6F || $0000-$FFFF || Unmapped&lt;br /&gt;
|-&lt;br /&gt;
| $70-$71 || $0000-$FFFF || SRAM&lt;br /&gt;
|-&lt;br /&gt;
| $7C-$7D || $0000-$FFFF || Backup RAM&lt;br /&gt;
|-&lt;br /&gt;
| $7E-$7F || $0000-$FFFF || WRAM&lt;br /&gt;
|-&lt;br /&gt;
!rowspan=&amp;quot;6&amp;quot;|$80-$BF&lt;br /&gt;
          || $0000-$1FFF || WRAM mirror&lt;br /&gt;
|-&lt;br /&gt;
|           $2100-$21FF || PPU registers&lt;br /&gt;
|-&lt;br /&gt;
|           $3000-$3FFF || Super FX registers&lt;br /&gt;
|-&lt;br /&gt;
|           $4200-$43FF || CPU registers&lt;br /&gt;
|-&lt;br /&gt;
|           $6000-$7FFF || SRAM mirror&lt;br /&gt;
|-&lt;br /&gt;
|           $8000-$FFFF || ROM (LoROM)&lt;br /&gt;
|-&lt;br /&gt;
| $C0-$FF || $8000-$FFFF || ROM (HiROM)&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The GSU memory map looks similar to the CPU mapping but only with access to ROM and SRAM as well as only access to 2 MiB of ROM and 128 KiB of SRAM. As a result, it looks more like this:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
!  Banks  !!   Address   !! Description&lt;br /&gt;
|-&lt;br /&gt;
!rowspan=&amp;quot;2&amp;quot;|$00-$3F&lt;br /&gt;
          || $0000-$7FFF || Unmapped&lt;br /&gt;
|-&lt;br /&gt;
|            $8000-$FFFF || ROM (LoROM)&lt;br /&gt;
|-&lt;br /&gt;
| $40-$5F || $0000-$FFFF || Mirror of ROM in banks $00-$3F (HiROM)&lt;br /&gt;
|-&lt;br /&gt;
| $60-$6F || $0000-$FFFF || Unmapped&lt;br /&gt;
|-&lt;br /&gt;
| $70-$71 || $0000-$FFFF || SRAM&lt;br /&gt;
|-&lt;br /&gt;
| $72-$7F || $0000-$FFFF || Unmapped&lt;br /&gt;
|-&lt;br /&gt;
| $80-$FF || $0000-$FFFF || Mirror of $00-$7F&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Finally, it should be noted that banks $40-$5F are HiROM mirrors of the LoROM banks $00-$3F interlaced so addresses such as $008000 and $400000 contain the same value.&lt;br /&gt;
&lt;br /&gt;
=== ROM ===&lt;br /&gt;
ROM on Super FX can be up to 8 MiB large. However, even though the size is theoretically doable, the largest published Super FX games had a ROM size of 2 MiBs. As a result, not many emulators (not even BSNES as of 2021) emulate this feature properly and such ROM sizes only exist in homebrewing and modding.&lt;br /&gt;
&lt;br /&gt;
Super FX has also has got limitations with ROM access. This first example is the ROM size. Even though a Super FX ROM can be as large as 8 MiB (in theory), the GSU&#039;s data bus is only connected to 2 MiB of it. Said portion of ROM which the processor can access is called GamePak ROM while the additional 6 MiB, called the Super NES ROM, can only be accessed by the CPU.&lt;br /&gt;
A second limitation is the clock speed. The GSU is clocked very fast at 10.74 Mhz (which can be doubled with pipelining) but ROM is clocked at 3.58 Mhz (unlike on [[SA-1]] where ROM is clocked at the same frequence as the coprocessor). As a result, all opcodes, when they are executed in ROM, take at least three cycles to process while reads from ROM are slow.&lt;br /&gt;
&lt;br /&gt;
To counteract against this limitation, the GSU uses a buffering system. In order to load a value from ROM, the bank must first be set in ROMBR (set by [[ROMB]] in the GSU code) while the address is set in register R14. Any write to R14 initiates the buffering process (it&#039;s also this reason it isn&#039;t considered a general purpose register even though it can be used as such). The value then can be retrieved with [[GETB]] and similar opcodes (referred to just &amp;lt;code&amp;gt;GETB&amp;lt;/code&amp;gt; from now on).&lt;br /&gt;
&lt;br /&gt;
The GSU doesn&#039;t wait during the process of fetching. As a result, it is possible to call &amp;lt;code&amp;gt;GETB&amp;lt;/code&amp;gt; some time after writing to R14. In fact, this is even recommend because calling &amp;lt;code&amp;gt;GETB&amp;lt;/code&amp;gt; during the process of fetching will cause the GSU to halt for up to five cycles for executing &amp;lt;code&amp;gt;GETB&amp;lt;/code&amp;gt;. Similarly, writing to &amp;lt;code&amp;gt;ROMB&amp;lt;/code&amp;gt; will halt the code as well until the data has been fetched and enabling cache during the process of fetching will mess up the loaded ROM value.&lt;br /&gt;
&lt;br /&gt;
=== RAM ===&lt;br /&gt;
&lt;br /&gt;
=== Cache ===&lt;br /&gt;
&lt;br /&gt;
In order to improve the speed of the processor, it includes a 512 byte large memory with the same frequency as the GSU as a cache. This allows Super FX to execute a single opcode with only a single cycle (i.e. three times as fast as in regular use). The cache is separated into 32 16-byte blocks, each with a flag which denotes that a block is used, and is indexed by the cache base register (CBR) which is used to keep track of where cache has been invoked. The cache flags and CBR are reset whenever a zero is written to the GO flag but simply halting or invoking the GSU preserves the content of the cache which in turn can be read by the CPU.&lt;br /&gt;
&lt;br /&gt;
Cache on the SNES is mapped to addresses $xx:3100-$xx:32FF ($xx = $00-$3F, $80-$BF), though the start of the cached code (see below) also is dependent on the CBR (start = $3100 + (CBR &amp;amp; 0x1FF)).&lt;br /&gt;
&lt;br /&gt;
There are two methods to fill the cache:&lt;br /&gt;
* Manual caching&lt;br /&gt;
* Automatic caching&lt;br /&gt;
&lt;br /&gt;
Manual caching involes using the CPU and transfer the code to cache. Keep in mind that Super FX will only execute the cache block which has been set to be used. That means, the code has to be transfered as a full 16 byte block, though strictly speaking, only the last byte of the block (address $XXXF) needs to be written to count the block as used.&lt;br /&gt;
In order to execute GSU code in cache, R15 has to be set to $0000-$01FF.&lt;br /&gt;
&lt;br /&gt;
Automatic caching is instead handled by the GSU itself. This is handled either by the dedicated [[CACHE]] opcode or by a [[LJMP]] opcode, the latter because of the lack of bank information for the cache. Both of them clear the cache flags and store the current PC with the lowest nibble masked out into the CBR (CBR = PC &amp;amp; 0xFFF0). Afterwards, each executed opcode will be written into cache starting from CBR &amp;amp; 0x1FF.&lt;br /&gt;
As a result, this use of cache is recommend for loops and the first loop will always run slower than the remaining loops. Should all the blocks be used, any remaining code will be left uncached and executed in the original memory.&lt;br /&gt;
&lt;br /&gt;
Another side effect is that cache is neither ROM nor GamePak RAM so any Super FX code in cache can run in parallel to the SNES even when access to ROM and RAM is given to the CPU instead of GSU.&lt;br /&gt;
&lt;br /&gt;
=== Pipeline Processing ===&lt;br /&gt;
&lt;br /&gt;
In order to boost the processing speed of the GSU, it uses a technique called &amp;quot;pipeline processing&amp;quot;. Pipelining exists to a lesser extend on the [[65c816]], where opcodes are prepared while the remaining bytes of the opcodes are fetched (this is notable on single byte opcodes such as [[INC]] which take two cycles to process, the same amount of cycles as &amp;lt;code&amp;gt;LDA #$xx&amp;lt;/code&amp;gt;, a two byte opcode) but the GSU takes it further by fetching the next opcode during the current opcode&#039;s execution.&lt;br /&gt;
This runs the code double as fast, virtually increasing the clock speed to 21.48 MHz at the cost of adding more care of the coder whenever R15 — the programm counter — is changed, either through branching or through direct writes to R15. In addition, internal processes such as multiplication and memory access can&#039;t take advantage of the virtual increment in clock speed.&lt;br /&gt;
&lt;br /&gt;
Pipelining is controlled with bit 0 of CLSR, where clear means pipelining disabled and set means pipelining enabled. It&#039;s accessable on the CPU side with the address $3037.&lt;br /&gt;
&lt;br /&gt;
For the most part, having pipelining enabled doesn&#039;t change the code. The only exceptions are when R15 is modified outside of fetching opcodes i.e. the use of branches and writes to R15 (e.g. &amp;lt;code&amp;gt;IWT R15,#$8000&amp;lt;/code&amp;gt;) as well as halting the GSU such as with [[STOP]]. In these cases, the opcode following that instruction will be executed after the branch. A common solution for the unwanted opcode execution is to put a dummy [[NOP]] after the R15 modifying opcode such as in this example:&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;BCC SkipCode&lt;br /&gt;
NOP             ; Dummy NOP&lt;br /&gt;
...&lt;br /&gt;
SkipCode:&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This proves to be inefficient, though. Most Super FX opcodes are one byte larger and take 3 or 1 cycles (depending on whether the code is executed in cache or not) to execute including &amp;lt;code&amp;gt;NOP&amp;lt;/code&amp;gt;. As a result, opcodes such as &amp;lt;code&amp;gt;SUB R0&amp;lt;/code&amp;gt; can be put as a dummy opcode in place of &amp;lt;code&amp;gt;NOP&amp;lt;/code&amp;gt;. The following example demonstrates it:&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;BCC SkipCode&lt;br /&gt;
;NOP            ; Redundant&lt;br /&gt;
SUB R0          ; Set R0 to zero&lt;br /&gt;
STW (R1)&lt;br /&gt;
SkipCode:&lt;br /&gt;
IWT R0,#$1234&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
In the above code, R0 gets overwritten by &amp;lt;code&amp;gt;SUB&amp;lt;/code&amp;gt; no matter whether the branch is taken. However, it later gets overwritten by &amp;lt;code&amp;gt;IWT&amp;lt;/code&amp;gt;. As a result, it doesn&#039;t matter whether the dummy opcode is a &amp;lt;code&amp;gt;NOP&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;SUB&amp;lt;/code&amp;gt; from the branch for the calculation. In fact, using a &amp;lt;code&amp;gt;NOP&amp;lt;/code&amp;gt; increases the code size by one byte which can matter when the code is executed in cache as well as increase the cycle count by 1 or 3 cycles each time the branch is executed, causing in total a minor speed penality.&lt;br /&gt;
&lt;br /&gt;
This doesn&#039;t work for every opcode, though. Opcodes such as &amp;lt;code&amp;gt;ADD #x&amp;lt;/code&amp;gt; (which is internally prefixed with [[ALT2]]), &amp;lt;code&amp;gt;WITH&amp;lt;/code&amp;gt; (register prefixes which change which register is the source or destination), &amp;lt;code&amp;gt;BRA $10&amp;lt;/code&amp;gt; (branches which always use two bytes) and &amp;lt;code&amp;gt;IWT&amp;lt;/code&amp;gt; (immediate value transfers which use two or three bytes) can only be used as a dummy opcode in very specific circumstances. The latter two can even misalign the program counter not unlike executing &amp;lt;code&amp;gt;LDA #$12&amp;lt;/code&amp;gt; when A is in 16-bit mode on the 65816. The following example demonstrates it:&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;BCC SkipCode&lt;br /&gt;
BRA Error       ; Caution!&lt;br /&gt;
...&lt;br /&gt;
SkipCode:&lt;br /&gt;
...&lt;br /&gt;
Error:&lt;br /&gt;
INC R1          ; Will instead be read with the BRA as &amp;quot;BRA $D1&amp;quot;.&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
In addition, the dummy opcode after a &amp;lt;code&amp;gt;STOP&amp;lt;/code&amp;gt; &#039;&#039;&#039;must&#039;&#039;&#039; be a &amp;lt;code&amp;gt;NOP&amp;lt;/code&amp;gt; because putting the GSU in WAIT will not clear the opcode in the pipeline. Extra care should be taken when pipeliend code is executed and a &amp;lt;code&amp;gt;STOP&amp;lt;/code&amp;gt; is located at $XXXF in cache as the pipelined code may be located in unused cache and a value in ROM/RAM will be loaded instead.&lt;br /&gt;
&lt;br /&gt;
== Bus Conflicts ==&lt;br /&gt;
&lt;br /&gt;
== Bitmap Processing ==&lt;br /&gt;
&lt;br /&gt;
== External Links ==&lt;br /&gt;
&lt;br /&gt;
* Patent: https://patentimages.storage.googleapis.com/de/a2/7a/f07754f66f39d9/US5724497.pdf&lt;br /&gt;
&lt;br /&gt;
[[Category:SNES_Hardware]]&lt;br /&gt;
[[Category:Integrated Circuits]]&lt;br /&gt;
[[Category:Enhancement Chips]]&lt;br /&gt;
[[Category:Super FX]]&lt;/div&gt;</summary>
		<author><name>MarioFanGamer</name></author>
	</entry>
	<entry>
		<id>https://sneslab.net/mw/index.php?title=Mode_4&amp;diff=8872</id>
		<title>Mode 4</title>
		<link rel="alternate" type="text/html" href="https://sneslab.net/mw/index.php?title=Mode_4&amp;diff=8872"/>
		<updated>2023-07-19T18:49:18Z</updated>

		<summary type="html">&lt;p&gt;MarioFanGamer: Added another property of Mode 4.&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;float:right;clear:right;width:40%&amp;quot;&lt;br /&gt;
!colspan=&amp;quot;4&amp;quot;|Layers Available&lt;br /&gt;
|+&lt;br /&gt;
| [[Layer 2]] || [[Layer 1]]&lt;br /&gt;
|+&lt;br /&gt;
| 2bpp || 8bpp&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Mode 4&#039;&#039;&#039; supports [[Offset Change Mode]] and [[Direct Color]].&lt;br /&gt;
&lt;br /&gt;
=== See Also ===&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!colspan=&amp;quot;4&amp;quot;|Other Background Modes&lt;br /&gt;
|+&lt;br /&gt;
| [[Mode 0]] || [[Mode 1]] || [[Mode 2]] || [[Mode 3]]&lt;br /&gt;
|+&lt;br /&gt;
| [[Mode 4]] || [[Mode 5]] || [[Mode 6]] || [[Mode 7]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Reference ===&lt;br /&gt;
* https://nesdoug.com/2022/05/30/other-modes&lt;br /&gt;
&lt;br /&gt;
[[Category:Video]]&lt;/div&gt;</summary>
		<author><name>MarioFanGamer</name></author>
	</entry>
	<entry>
		<id>https://sneslab.net/mw/index.php?title=IBT&amp;diff=3585</id>
		<title>IBT</title>
		<link rel="alternate" type="text/html" href="https://sneslab.net/mw/index.php?title=IBT&amp;diff=3585"/>
		<updated>2023-05-06T09:57:09Z</updated>

		<summary type="html">&lt;p&gt;MarioFanGamer: Added description for high byte, added category.&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&#039;&#039;&#039;IBT&#039;&#039;&#039; is a [[Super FX]] instruction that loads an immediate value into a specified register. Its upper eight bits will be set to the same value as bit 7, effectively loading a signed 8-bit value.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;float:right;clear:right;width:30%&amp;quot;&lt;br /&gt;
!colspan=&amp;quot;9&amp;quot;|Flags Clobbered&lt;br /&gt;
|+&lt;br /&gt;
|B&lt;br /&gt;
|ALT1&lt;br /&gt;
|ALT2&lt;br /&gt;
|O/V&lt;br /&gt;
|S&lt;br /&gt;
|CY&lt;br /&gt;
|Z&lt;br /&gt;
|+&lt;br /&gt;
|0&lt;br /&gt;
|0&lt;br /&gt;
|0&lt;br /&gt;
|.&lt;br /&gt;
|.&lt;br /&gt;
|.&lt;br /&gt;
|.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== See Also ===&lt;br /&gt;
* [[IWT]]&lt;br /&gt;
* [[LDA]]&lt;br /&gt;
&lt;br /&gt;
[[Category:ASM]]&lt;br /&gt;
[[Category:Enhancement Chips]]&lt;br /&gt;
[[Category:GSU_Control_Instructions]]&lt;/div&gt;</summary>
		<author><name>MarioFanGamer</name></author>
	</entry>
	<entry>
		<id>https://sneslab.net/mw/index.php?title=BLT_(Super_FX)&amp;diff=3584</id>
		<title>BLT (Super FX)</title>
		<link rel="alternate" type="text/html" href="https://sneslab.net/mw/index.php?title=BLT_(Super_FX)&amp;diff=3584"/>
		<updated>2023-05-06T09:40:48Z</updated>

		<summary type="html">&lt;p&gt;MarioFanGamer: Removed redirect, added proper description.&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&#039;&#039;&#039;BLT&#039;&#039;&#039; (Branch if Less Than ) is a [[Super FX]] opcode that performs a jump if the [[negative flag]] is unequal to the [[O/V]] flag, effectively checking for a signed less-than comparison (compare [[BCC]] which is an unsigned less-than comparison).&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;float:right;clear:right;width:40%&amp;quot;&lt;br /&gt;
!colspan=&amp;quot;8&amp;quot;|Basic Info&lt;br /&gt;
|+&lt;br /&gt;
|&#039;&#039;&#039;Opcode&#039;&#039;&#039;&lt;br /&gt;
|&#039;&#039;&#039;Length&#039;&#039;&#039;&lt;br /&gt;
|&#039;&#039;&#039;ROM Speed&#039;&#039;&#039;&lt;br /&gt;
|&#039;&#039;&#039;RAM Speed&#039;&#039;&#039;&lt;br /&gt;
|&#039;&#039;&#039;Cache Speed&#039;&#039;&#039;&lt;br /&gt;
|+&lt;br /&gt;
|06&lt;br /&gt;
|2 bytes&lt;br /&gt;
|6 cycles&lt;br /&gt;
|6 cycles&lt;br /&gt;
|2 cycles&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;float:right;clear:right;width:30%&amp;quot;&lt;br /&gt;
!colspan=&amp;quot;9&amp;quot;|Flags Clobbered&lt;br /&gt;
|+&lt;br /&gt;
|B&lt;br /&gt;
|ALT1&lt;br /&gt;
|ALT2&lt;br /&gt;
|O/V&lt;br /&gt;
|S&lt;br /&gt;
|CY&lt;br /&gt;
|Z&lt;br /&gt;
|+&lt;br /&gt;
|0&lt;br /&gt;
|0&lt;br /&gt;
|0&lt;br /&gt;
|.&lt;br /&gt;
|.&lt;br /&gt;
|.&lt;br /&gt;
|.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== See also ===&lt;br /&gt;
* [[BGE]]&lt;br /&gt;
* [[BCC]]&lt;br /&gt;
&lt;br /&gt;
[[Category:ASM]]&lt;br /&gt;
[[Category:Super FX]]&lt;br /&gt;
[[Category:GSU Control Instructions]]&lt;/div&gt;</summary>
		<author><name>MarioFanGamer</name></author>
	</entry>
	<entry>
		<id>https://sneslab.net/mw/index.php?title=BGE_(Super_FX)&amp;diff=3583</id>
		<title>BGE (Super FX)</title>
		<link rel="alternate" type="text/html" href="https://sneslab.net/mw/index.php?title=BGE_(Super_FX)&amp;diff=3583"/>
		<updated>2023-05-06T09:39:25Z</updated>

		<summary type="html">&lt;p&gt;MarioFanGamer: Removed redirect, added proper description.&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&#039;&#039;&#039;BGE&#039;&#039;&#039; (Branch if Greater or Equal) is a [[Super FX]] opcode that performs a jump if the [[negative flag]] is equal to the [[O/V]] flag, effectively checking for a signed greater-equal comparison (compare [[BCS]] which is an unsigned greater-equal comparison).&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;float:right;clear:right;width:40%&amp;quot;&lt;br /&gt;
!colspan=&amp;quot;8&amp;quot;|Basic Info&lt;br /&gt;
|+&lt;br /&gt;
|&#039;&#039;&#039;Opcode&#039;&#039;&#039;&lt;br /&gt;
|&#039;&#039;&#039;Length&#039;&#039;&#039;&lt;br /&gt;
|&#039;&#039;&#039;ROM Speed&#039;&#039;&#039;&lt;br /&gt;
|&#039;&#039;&#039;RAM Speed&#039;&#039;&#039;&lt;br /&gt;
|&#039;&#039;&#039;Cache Speed&#039;&#039;&#039;&lt;br /&gt;
|+&lt;br /&gt;
|07&lt;br /&gt;
|2 bytes&lt;br /&gt;
|6 cycles&lt;br /&gt;
|6 cycles&lt;br /&gt;
|2 cycles&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;float:right;clear:right;width:30%&amp;quot;&lt;br /&gt;
!colspan=&amp;quot;9&amp;quot;|Flags Clobbered&lt;br /&gt;
|+&lt;br /&gt;
|B&lt;br /&gt;
|ALT1&lt;br /&gt;
|ALT2&lt;br /&gt;
|O/V&lt;br /&gt;
|S&lt;br /&gt;
|CY&lt;br /&gt;
|Z&lt;br /&gt;
|+&lt;br /&gt;
|0&lt;br /&gt;
|0&lt;br /&gt;
|0&lt;br /&gt;
|.&lt;br /&gt;
|.&lt;br /&gt;
|.&lt;br /&gt;
|.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== See also ===&lt;br /&gt;
* [[BLT]]&lt;br /&gt;
* [[BCS]]&lt;br /&gt;
&lt;br /&gt;
[[Category:ASM]]&lt;br /&gt;
[[Category:Super FX]]&lt;br /&gt;
[[Category:GSU Control Instructions]]&lt;/div&gt;</summary>
		<author><name>MarioFanGamer</name></author>
	</entry>
	<entry>
		<id>https://sneslab.net/mw/index.php?title=SMW_level_data_format&amp;diff=3568</id>
		<title>SMW level data format</title>
		<link rel="alternate" type="text/html" href="https://sneslab.net/mw/index.php?title=SMW_level_data_format&amp;diff=3568"/>
		<updated>2023-05-06T07:12:42Z</updated>

		<summary type="html">&lt;p&gt;MarioFanGamer: Fixed more formatting and turned text-tables into Wiki tables.&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This article contains information about how levels are stored in [[Super Mario World]].&lt;br /&gt;
&lt;br /&gt;
== Pointer tables ==&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
!     Address    !!      Usage   !!    Amount    !! Bytes per level !! Total bytes&lt;br /&gt;
|-&lt;br /&gt;
| x2E200/$05E000 || Layer 1 data || 0x200 levels || 3   bytes       || 1,536 bytes&lt;br /&gt;
|-&lt;br /&gt;
| x2E800/$05E600 || Layer 2 data || 0x200 levels || 3*  bytes       || 1,536 bytes&lt;br /&gt;
|-&lt;br /&gt;
| x2EE00/$05EC00 || Sprite data  || 0x200 levels || 2** bytes       || 1,024 bytes&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;nowiki&amp;gt;*)&amp;lt;/nowiki&amp;gt;  Layer 2 BG only uses the two lower bytes. The upper byte should be FF. The backgrounds are stored in bank 0C.&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;nowiki&amp;gt;**)&amp;lt;/nowiki&amp;gt; The sprite data is located in bank 07.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Primary level header ==&lt;br /&gt;
&lt;br /&gt;
The first five bytes of the Layer 1 data is the primary level header.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
!   First  !!  Second  !!   Third  !!  Fourth  !!   Last&lt;br /&gt;
|-&lt;br /&gt;
| BBBLLLLL || CCCOOOOO || 3MMMSSSS || TTPPPFFF || IIVVZZZZ&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
!  Bits !! Description&lt;br /&gt;
|-&lt;br /&gt;
| BBB   || BG palette&lt;br /&gt;
|-&lt;br /&gt;
| LLLLL || Length of level (amount of screens)&lt;br /&gt;
|-&lt;br /&gt;
| CCC   || BG color&lt;br /&gt;
|-&lt;br /&gt;
| OOOOO || Level mode&lt;br /&gt;
|-&lt;br /&gt;
| 3     || Layer 3 Priority&lt;br /&gt;
|-&lt;br /&gt;
| MMM   || Music&lt;br /&gt;
|-&lt;br /&gt;
| SSSS  || Sprite set&lt;br /&gt;
|-&lt;br /&gt;
| TT    || Time&lt;br /&gt;
|-&lt;br /&gt;
| PPP   || Sprite palette&lt;br /&gt;
|-&lt;br /&gt;
| FFF   || FG palette&lt;br /&gt;
|-&lt;br /&gt;
| II    || Item memory&lt;br /&gt;
|-&lt;br /&gt;
| VV    || Vertical scroll&lt;br /&gt;
|-&lt;br /&gt;
| ZZZZ  || Tile set&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Secondary level header ==&lt;br /&gt;
&lt;br /&gt;
The secondary level header consists of four bytes (These four bytes are not stored together):&lt;br /&gt;
* Location of Byte 1: x2F200/$05F000 + level number&lt;br /&gt;
* Location of Byte 2: x2F400/$05F200 + level number&lt;br /&gt;
* Location of Byte 3: x2F600/$05F400 + level number&lt;br /&gt;
* Location of Byte 4: x2F800/$05F600 + level number&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
!  Byte 1  !!  Byte 2  !!  Byte 3  !!  Byte 4&lt;br /&gt;
|-&lt;br /&gt;
| SSSSYYYY || 33TTTXXX || MMMMFFBB || IUVEEEEE&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
!  Bits !! Description&lt;br /&gt;
|-&lt;br /&gt;
| SSSS  || Layer 2 scroll settings&lt;br /&gt;
|-&lt;br /&gt;
| YYYY  || Level entrance Y position&lt;br /&gt;
|-&lt;br /&gt;
| 33    || Layer 3 settings&lt;br /&gt;
|-&lt;br /&gt;
| TTT   || Level entrance type&lt;br /&gt;
|-&lt;br /&gt;
| XXX   || Level entrance X position&lt;br /&gt;
|-&lt;br /&gt;
| MMMM  || Level entrance midway screen&lt;br /&gt;
|-&lt;br /&gt;
| FF    || Level entrance FG init position&lt;br /&gt;
|-&lt;br /&gt;
| BB    || Level entrance BG init position&lt;br /&gt;
|-&lt;br /&gt;
| I     || Disable no-Yoshi intro flag&lt;br /&gt;
|-&lt;br /&gt;
| U     || Unknown vertical position flag&lt;br /&gt;
|-&lt;br /&gt;
| V     || Vertical positioning flag&lt;br /&gt;
|-&lt;br /&gt;
| EEEEE || Level entrance screen number&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Sprite header ===&lt;br /&gt;
&lt;br /&gt;
The sprite header is the first byte of sprite data.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Byte&lt;br /&gt;
|-&lt;br /&gt;
| SBMMMMMM&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
!  Bits  !! Header text&lt;br /&gt;
|-&lt;br /&gt;
| S      || Sprite buoyancy&lt;br /&gt;
|-&lt;br /&gt;
| B      || Sprite buoyancy (no sprite-L2 interaction)&lt;br /&gt;
|-&lt;br /&gt;
| MMMMMM || Sprite memory*&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;nowiki&amp;gt;*)&amp;lt;/nowiki&amp;gt; Values up to 0x3F are possible, but only up to 0x12 are valid according to Lunar Magic.&lt;br /&gt;
&lt;br /&gt;
== Layer 1 ==&lt;br /&gt;
&lt;br /&gt;
(Note that Direct Map16 is not documented, as it&#039;s a feature added by Lunar Magic)&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
The Layer 1 data begins with the primary level header, followed by the actual Layer 1 data. Each block is three bytes long, with the exception of the screen exit objects.&lt;br /&gt;
&lt;br /&gt;
=== Standard objects ===&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
!   First  !!  Second  !!   Last&lt;br /&gt;
|-&lt;br /&gt;
| NBBYYYYY || bbbbXXXX || SSSSSSSS&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
!   Bits   !! Descripton&lt;br /&gt;
|-&lt;br /&gt;
| N        || New Screen flag&lt;br /&gt;
|-&lt;br /&gt;
| BBbbbb   || Object number&lt;br /&gt;
|-&lt;br /&gt;
| YYYYY    || Y position&lt;br /&gt;
|-&lt;br /&gt;
| XXXX     || X position&lt;br /&gt;
|-&lt;br /&gt;
| SSSSSSSS || Settings byte&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
(Note: The first byte being FF marks the end of the data)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Num !!       Descripton        ||      Settings Byte&lt;br /&gt;
|-&lt;br /&gt;
| 00  || (Extended Objects)      || Extended object number&lt;br /&gt;
|-&lt;br /&gt;
| 01  || Water (Blue)            || {Height},{Width}&lt;br /&gt;
|-&lt;br /&gt;
| 02  || Invisible coin blocks   || {Height},{Width}&lt;br /&gt;
|-&lt;br /&gt;
| 03  || Invisible note blocks   || {Height},{Width}&lt;br /&gt;
|-&lt;br /&gt;
| 04  || Invisible POW coins     || {Height},{Width}&lt;br /&gt;
|-&lt;br /&gt;
| 05  || Coins                   || {Height},{Width}&lt;br /&gt;
|-&lt;br /&gt;
| 06  || Walk-through dirt       || {Height},{Width}&lt;br /&gt;
|-&lt;br /&gt;
| 07  || Water (Other color)     || {Height},{Width}&lt;br /&gt;
|-&lt;br /&gt;
| 08  || Note blocks             || {Height},{Width}&lt;br /&gt;
|-&lt;br /&gt;
| 09  || Turn blocks             || {Height},{Width}&lt;br /&gt;
|-&lt;br /&gt;
| 0A  || Coin ? blocks           || {Height},{Width}&lt;br /&gt;
|-&lt;br /&gt;
| 0B  || Throw blocks            || {Height},{Width}&lt;br /&gt;
|-&lt;br /&gt;
| 0C  || Black piranha plants    || {Height},{Width}&lt;br /&gt;
|-&lt;br /&gt;
| 0D  || Cement blocks           || {Height},{Width}&lt;br /&gt;
|-&lt;br /&gt;
| 0E  || Brown blocks            || {Height},{Width}&lt;br /&gt;
|-&lt;br /&gt;
| 0F  || Vertical pipes          || {Height},{Type}&lt;br /&gt;
|-&lt;br /&gt;
| 10  || Horizontal pipes        || {Type},{Width}&lt;br /&gt;
|-&lt;br /&gt;
| 11  || Bullet shooter          || {Height},{Unused}&lt;br /&gt;
|-&lt;br /&gt;
| 12  || Slopes                  || {Height},{Type}&lt;br /&gt;
|-&lt;br /&gt;
| 13  || Ledge edges             || {Height},{Type}&lt;br /&gt;
|-&lt;br /&gt;
| 14  || Ground ledge            || {Height},{Width}&lt;br /&gt;
|-&lt;br /&gt;
| 15  || Midway/Goal point       || {Height},{Type}&lt;br /&gt;
|-&lt;br /&gt;
| 16  || Blue coins              || {Height},{Width}&lt;br /&gt;
|-&lt;br /&gt;
| 17  || Rope/Clouds             || {Type},{Width}&lt;br /&gt;
|-&lt;br /&gt;
| 18  || Water surface (ani)     || {Height},{Width}&lt;br /&gt;
|-&lt;br /&gt;
| 19  || Water surface (not ani) || {Height},{Width}&lt;br /&gt;
|-&lt;br /&gt;
| 1A  || Lava surface (ani)      || {Height},{Width}&lt;br /&gt;
|-&lt;br /&gt;
| 1B  || Net top edge            || {Height},{Width}&lt;br /&gt;
|-&lt;br /&gt;
| 1C  || Donut bridge            || {Unused},{Width}&lt;br /&gt;
|-&lt;br /&gt;
| 1D  || Net bottom edge         || {Height},{Width}&lt;br /&gt;
|-&lt;br /&gt;
| 1E  || Net vertical edge       || {Height},{Type}&lt;br /&gt;
|-&lt;br /&gt;
| 1F  || Vert. Pipe/Bone/Log     || {Height},{Unused}&lt;br /&gt;
|-&lt;br /&gt;
| 20  || Horiz. Pipe/Bone/Log    || {Unused},{Width}&lt;br /&gt;
|-&lt;br /&gt;
| 21  || Long ground ledge       || Width&lt;br /&gt;
|-&lt;br /&gt;
| 22  || Special - Used by LM    ||&lt;br /&gt;
|-&lt;br /&gt;
| 23  || Special - Used by LM    ||&lt;br /&gt;
|-&lt;br /&gt;
| 24  || Special - Used by LM    ||&lt;br /&gt;
|-&lt;br /&gt;
| 25  || Special - Used by LM    ||&lt;br /&gt;
|-&lt;br /&gt;
| 26  || Special - Used by LM    ||&lt;br /&gt;
|-&lt;br /&gt;
| 27  || Special - Used by LM    ||&lt;br /&gt;
|-&lt;br /&gt;
| 28  || Special - Used by LM    ||&lt;br /&gt;
|-&lt;br /&gt;
| 29  || Special - Reserved      ||&lt;br /&gt;
|-&lt;br /&gt;
| 2A  || Special - Reserved      ||&lt;br /&gt;
|-&lt;br /&gt;
| 2B  || Special - Reserved      ||&lt;br /&gt;
|-&lt;br /&gt;
| 2C  || Special - Reserved      ||&lt;br /&gt;
|-&lt;br /&gt;
| 2D  || Special - Used by LM    ||&lt;br /&gt;
|-&lt;br /&gt;
| 2E  || Tileset Specific 1      ||&lt;br /&gt;
|-&lt;br /&gt;
| 2F  || Tileset Specific 2      ||&lt;br /&gt;
|-&lt;br /&gt;
| 30  || Tileset Specific 3      ||&lt;br /&gt;
|-&lt;br /&gt;
| 31  || Tileset Specific 4      ||&lt;br /&gt;
|-&lt;br /&gt;
| 32  || Tileset Specific 5      ||&lt;br /&gt;
|-&lt;br /&gt;
| 33  || Tileset Specific 6      ||&lt;br /&gt;
|-&lt;br /&gt;
| 34  || Tileset Specific 7      ||&lt;br /&gt;
|-&lt;br /&gt;
| 35  || Tileset Specific 8      ||&lt;br /&gt;
|-&lt;br /&gt;
| 36  || Tileset Specific 9      ||&lt;br /&gt;
|-&lt;br /&gt;
| 37  || Tileset Specific 10     ||&lt;br /&gt;
|-&lt;br /&gt;
| 38  || Tileset Specific 11     ||&lt;br /&gt;
|-&lt;br /&gt;
| 39  || Tileset Specific 12     ||&lt;br /&gt;
|-&lt;br /&gt;
| 3A  || Tileset Specific 13     ||&lt;br /&gt;
|-&lt;br /&gt;
| 3B  || Tileset Specific 14     ||&lt;br /&gt;
|-&lt;br /&gt;
| 3C  || Tileset Specific 15     ||&lt;br /&gt;
|-&lt;br /&gt;
| 3D  || Tileset Specific 16     ||&lt;br /&gt;
|-&lt;br /&gt;
| 3E  || Tileset Specific 17     ||&lt;br /&gt;
|-&lt;br /&gt;
| 3F  || Tileset Specific 18     ||&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Note: Most objects separate their nibbles into upper and lower bytes with separate functions. They&#039;re specified as {Upper Nibble},{Lower Nibble} in this table.&lt;br /&gt;
&lt;br /&gt;
=== Extended objects ===&lt;br /&gt;
&lt;br /&gt;
(Standard object 00)&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
!   First  !!  Second  !!   Last&lt;br /&gt;
|-&lt;br /&gt;
| N00YYYYY || 0000XXXX || BBBBBBBB&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
!   Bits   !! Description&lt;br /&gt;
|-&lt;br /&gt;
| N        || New Screen flag&lt;br /&gt;
|-&lt;br /&gt;
| YYYYY    || Y position&lt;br /&gt;
|-&lt;br /&gt;
| XXXX     || X position&lt;br /&gt;
|-&lt;br /&gt;
| BBBBBBBB || Extended object number&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
!  Num  || Desc&lt;br /&gt;
|-&lt;br /&gt;
| 00    ||Special - Screen Exit&lt;br /&gt;
|-&lt;br /&gt;
| 01    || Special - Screen Jump&lt;br /&gt;
|-&lt;br /&gt;
| 02-0F || Unused?&lt;br /&gt;
|-&lt;br /&gt;
| 10    || Small door&lt;br /&gt;
|-&lt;br /&gt;
| 11    || Invisible ? block (1-UP)&lt;br /&gt;
|-&lt;br /&gt;
| 12    || Invisible note block&lt;br /&gt;
|-&lt;br /&gt;
| 13    || Top left corner edge tile 1&lt;br /&gt;
|-&lt;br /&gt;
| 14    || Top right corner edge tile 1&lt;br /&gt;
|-&lt;br /&gt;
| 15    || Small POW door&lt;br /&gt;
|-&lt;br /&gt;
| 16    || Invisible POW ? block&lt;br /&gt;
|-&lt;br /&gt;
| 17    || Green star block&lt;br /&gt;
|-&lt;br /&gt;
| 18    || 3-UP moon&lt;br /&gt;
|-&lt;br /&gt;
| 19    || Invisible 1-UP #1&lt;br /&gt;
|-&lt;br /&gt;
| 1A    || Invisible 1-UP #2&lt;br /&gt;
|-&lt;br /&gt;
| 1B    || Invisible 1-UP #3&lt;br /&gt;
|-&lt;br /&gt;
| 1C    || Invisible 1-UP #4&lt;br /&gt;
|-&lt;br /&gt;
| 1D    || Red berry&lt;br /&gt;
|-&lt;br /&gt;
| 1E    || Pink berry&lt;br /&gt;
|-&lt;br /&gt;
| 1F    || Green berry&lt;br /&gt;
|-&lt;br /&gt;
| 20    || Always turning block&lt;br /&gt;
|-&lt;br /&gt;
| 21    || Bottom right of midway point (unused)&lt;br /&gt;
|-&lt;br /&gt;
| 22    || Bottom right of midway point (unused)&lt;br /&gt;
|-&lt;br /&gt;
| 23    || Note block (flower/feather/star)&lt;br /&gt;
|-&lt;br /&gt;
| 24    || ON/OFF block&lt;br /&gt;
|-&lt;br /&gt;
| 25    || Direction coins ? block&lt;br /&gt;
|-&lt;br /&gt;
| 26    || Note block&lt;br /&gt;
|-&lt;br /&gt;
| 27    || Note block, bounce on all sides&lt;br /&gt;
|-&lt;br /&gt;
| 28    || Turn block (Flower)&lt;br /&gt;
|-&lt;br /&gt;
| 29    || Turn block (Feather)&lt;br /&gt;
|-&lt;br /&gt;
| 2A    || Turn block (Star)&lt;br /&gt;
|-&lt;br /&gt;
| 2B    || Turn block (Star 2/1-UP/Vine)&lt;br /&gt;
|-&lt;br /&gt;
| 2C    || Turn block (Multiple coins)&lt;br /&gt;
|-&lt;br /&gt;
| 2D    || Turn block (Coin)&lt;br /&gt;
|-&lt;br /&gt;
| 2E    || Turn block (Nothing)&lt;br /&gt;
|-&lt;br /&gt;
| 2F    || Turn block (POW)&lt;br /&gt;
|-&lt;br /&gt;
| 30    || ? block (Flower)&lt;br /&gt;
|-&lt;br /&gt;
| 31    || ? block (Feather)&lt;br /&gt;
|-&lt;br /&gt;
| 32    || ? block (Star)&lt;br /&gt;
|-&lt;br /&gt;
| 33    || ? block (Star 2)&lt;br /&gt;
|-&lt;br /&gt;
| 34    || ? block (Multiple coins)&lt;br /&gt;
|-&lt;br /&gt;
| 35    || ? block (Key/Wings/Balloon/Shell)&lt;br /&gt;
|-&lt;br /&gt;
| 36    || ? block (Yoshi)&lt;br /&gt;
|-&lt;br /&gt;
| 37    || ? block (Shell)&lt;br /&gt;
|-&lt;br /&gt;
| 38    || ? block (Shell)&lt;br /&gt;
|-&lt;br /&gt;
| 39    || Turn block, unbreakable (Feather)&lt;br /&gt;
|-&lt;br /&gt;
| 3A    || Top left corner edge tile 2&lt;br /&gt;
|-&lt;br /&gt;
| 3B    || Top right corner edge tile 2&lt;br /&gt;
|-&lt;br /&gt;
| 3C    || Top left corner edge tile 3&lt;br /&gt;
|-&lt;br /&gt;
| 3D    || Top right corner edge tile 3&lt;br /&gt;
|-&lt;br /&gt;
| 3E    || Top left corner edge tile 4&lt;br /&gt;
|-&lt;br /&gt;
| 3F    || Top right corner edge tile 4&lt;br /&gt;
|-&lt;br /&gt;
| 40    || Transculent block&lt;br /&gt;
|-&lt;br /&gt;
| 41    || Yoshi Coin&lt;br /&gt;
|-&lt;br /&gt;
| 42    || Top left slope&lt;br /&gt;
|-&lt;br /&gt;
| 43    || Top right slope&lt;br /&gt;
|-&lt;br /&gt;
| 44    || Purple triangle, left&lt;br /&gt;
|-&lt;br /&gt;
| 45    || Purple triangle, right&lt;br /&gt;
|-&lt;br /&gt;
| 46    || Midway point rope&lt;br /&gt;
|-&lt;br /&gt;
| 47    || Door&lt;br /&gt;
|-&lt;br /&gt;
| 48    || Invisible POW door&lt;br /&gt;
|-&lt;br /&gt;
| 49    || Ghost house exit&lt;br /&gt;
|-&lt;br /&gt;
| 4A    || Climbing net door&lt;br /&gt;
|-&lt;br /&gt;
| 4B    || Conveyor end tile 1&lt;br /&gt;
|-&lt;br /&gt;
| 4C    || Conveyor end tile 2&lt;br /&gt;
|-&lt;br /&gt;
| 4D    || Line guide, top left 1/4 large circle&lt;br /&gt;
|-&lt;br /&gt;
| 4E    || Line guide, top right 1/4 large circle&lt;br /&gt;
|-&lt;br /&gt;
| 4F    || Line guide, bottom left 1/4 large circle&lt;br /&gt;
|-&lt;br /&gt;
| 50    || Line guide, bottom right 1/4 large circle&lt;br /&gt;
|-&lt;br /&gt;
| 51    || Line guide, top left 1/4 small circle&lt;br /&gt;
|-&lt;br /&gt;
| 52    || Line guide, top right 1/4 small circle&lt;br /&gt;
|-&lt;br /&gt;
| 53    || Line guide, bottom left 1/4 small circle&lt;br /&gt;
|-&lt;br /&gt;
| 54    || Line guide, bottom right 1/4 small circle&lt;br /&gt;
|-&lt;br /&gt;
| 55    || Line guide end, for horizontal line&lt;br /&gt;
|-&lt;br /&gt;
| 56    || Line guide end, for vertical line&lt;br /&gt;
|-&lt;br /&gt;
| 57    || Switch palace bottom right corner tile&lt;br /&gt;
|-&lt;br /&gt;
| 58    || Switch palace bottom left corner tile&lt;br /&gt;
|-&lt;br /&gt;
| 59    || Switch palace top right corner tile&lt;br /&gt;
|-&lt;br /&gt;
| 5A    || Switch palace top left corner tile&lt;br /&gt;
|-&lt;br /&gt;
| 5B    || Bit of brick background tile 1&lt;br /&gt;
|-&lt;br /&gt;
| 5C    || Bit of brick background tile 2&lt;br /&gt;
|-&lt;br /&gt;
| 5D    || Bit of brick background tile 3&lt;br /&gt;
|-&lt;br /&gt;
| 5E    || Bit of brick background tile 4&lt;br /&gt;
|-&lt;br /&gt;
| 5F    || Large background area&lt;br /&gt;
|-&lt;br /&gt;
| 60    || Lava/mud top right corner edge&lt;br /&gt;
|-&lt;br /&gt;
| 61    || Ghost house clock&lt;br /&gt;
|-&lt;br /&gt;
| 62    || Ghost house top left to bottom right beam 1&lt;br /&gt;
|-&lt;br /&gt;
| 63    || Ghost house top right to bottom left beam 1&lt;br /&gt;
|-&lt;br /&gt;
| 64    || Ghost house cobweb, top right&lt;br /&gt;
|-&lt;br /&gt;
| 65    || Ghost house cobweb, top left&lt;br /&gt;
|-&lt;br /&gt;
| 66    || Ghost house top right to bottom left beam 2&lt;br /&gt;
|-&lt;br /&gt;
| 67    || Ghost house top left to bottom right beam 2&lt;br /&gt;
|-&lt;br /&gt;
| 68    || Cloud fringe, bottom and right edge&lt;br /&gt;
|-&lt;br /&gt;
| 69    || Cloud fringe, bottom and left edge&lt;br /&gt;
|-&lt;br /&gt;
| 6A    || Cloud fringe, bottom right&lt;br /&gt;
|-&lt;br /&gt;
| 6B    || Cloud fringe, bottom left&lt;br /&gt;
|-&lt;br /&gt;
| 6C    || Cloud fringe on white, bottom and right edge&lt;br /&gt;
|-&lt;br /&gt;
| 6D    || Cloud fringe on white, bottom and left edge&lt;br /&gt;
|-&lt;br /&gt;
| 6E    || Cloud fringe on white, bottom right&lt;br /&gt;
|-&lt;br /&gt;
| 6F    || Cloud fringe on white, bottom left&lt;br /&gt;
|-&lt;br /&gt;
| 70    || Bit of canvass 1&lt;br /&gt;
|-&lt;br /&gt;
| 71    || Canvass 1&lt;br /&gt;
|-&lt;br /&gt;
| 72    || Canvass 2&lt;br /&gt;
|-&lt;br /&gt;
| 73    || Canvass 3&lt;br /&gt;
|-&lt;br /&gt;
| 74    || Canvass 4&lt;br /&gt;
|-&lt;br /&gt;
| 75    || Canvass tile 1&lt;br /&gt;
|-&lt;br /&gt;
| 76    || Canvass tile 2&lt;br /&gt;
|-&lt;br /&gt;
| 77    || Canvass tile 3&lt;br /&gt;
|-&lt;br /&gt;
| 78    || Canvass tile 4&lt;br /&gt;
|-&lt;br /&gt;
| 79    || Canvass tile 5&lt;br /&gt;
|-&lt;br /&gt;
| 7A    || Canvass tile 6&lt;br /&gt;
|-&lt;br /&gt;
| 7B    || Canvass tile 7&lt;br /&gt;
|-&lt;br /&gt;
| 7C    || Bit of canvas 2&lt;br /&gt;
|-&lt;br /&gt;
| 7D    || Bit of canvas 3&lt;br /&gt;
|-&lt;br /&gt;
| 7E    || Bit of canvas 4&lt;br /&gt;
|-&lt;br /&gt;
| 7F    || Torpedo launcher&lt;br /&gt;
|-&lt;br /&gt;
| 80    || Ghost house entrance&lt;br /&gt;
|-&lt;br /&gt;
| 81    || Water weed&lt;br /&gt;
|-&lt;br /&gt;
| 82    || Big bush 1&lt;br /&gt;
|-&lt;br /&gt;
| 83    || Big bush 2&lt;br /&gt;
|-&lt;br /&gt;
| 84    || Castle entrance&lt;br /&gt;
|-&lt;br /&gt;
| 85    || Yoshi&#039;s house&lt;br /&gt;
|-&lt;br /&gt;
| 86    || Arrow sign&lt;br /&gt;
|-&lt;br /&gt;
| 87    || ! block, green&lt;br /&gt;
|-&lt;br /&gt;
| 88    || Tree branch, left&lt;br /&gt;
|-&lt;br /&gt;
| 89    || Tree branch, right&lt;br /&gt;
|-&lt;br /&gt;
| 8A    || Switch, green&lt;br /&gt;
|-&lt;br /&gt;
| 8B    || Switch, yellow&lt;br /&gt;
|-&lt;br /&gt;
| 8C    || Switch, blue&lt;br /&gt;
|-&lt;br /&gt;
| 8D    || Switch, red&lt;br /&gt;
|-&lt;br /&gt;
| 8E    || ! block, yellow&lt;br /&gt;
|-&lt;br /&gt;
| 8F    || Ghost house window&lt;br /&gt;
|-&lt;br /&gt;
| 90    || Boss door&lt;br /&gt;
|-&lt;br /&gt;
| 91    || Steep left slope (vert. lev.)&lt;br /&gt;
|-&lt;br /&gt;
| 92    || Steep right slope (vert. lev.)&lt;br /&gt;
|-&lt;br /&gt;
| 93    || Normal left slope (vert. lev.)&lt;br /&gt;
|-&lt;br /&gt;
| 94    || Normal right slope (vert. lev.)&lt;br /&gt;
|-&lt;br /&gt;
| 95    || Very steep left slope (vert. lev.)&lt;br /&gt;
|-&lt;br /&gt;
| 96    || Very steep right slope (vert. lev.)&lt;br /&gt;
|-&lt;br /&gt;
| 97    || Switch palace right and bottom edge tile&lt;br /&gt;
|-&lt;br /&gt;
| 98-FF || Unused?&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Screen exits ===&lt;br /&gt;
&lt;br /&gt;
(Extended object 00)&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
!   First  !!  Second  !!   Third  !!   Last&lt;br /&gt;
|-&lt;br /&gt;
| 000PPPPP || 0000WUSH || 00000000 || DDDDDDDD&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
!   Bits   !! Page number&lt;br /&gt;
|-&lt;br /&gt;
| PPPPP    || Example&lt;br /&gt;
|-&lt;br /&gt;
| W        || Water (secondary exit)&lt;br /&gt;
|-&lt;br /&gt;
| U        || Secondary Exit? *&lt;br /&gt;
|-&lt;br /&gt;
| S        || Secondary Exit&lt;br /&gt;
|-&lt;br /&gt;
| H        || Unused **&lt;br /&gt;
|-&lt;br /&gt;
| DDDDDDDD || Lower 8 bits of destination level&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Creates a screen exit. Should be placed right before the end of the level.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;nowiki&amp;gt;*)&amp;lt;/nowiki&amp;gt;  Used by a Lunar Magic ASM hack: If set, the H bit will be used&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;nowiki&amp;gt;**)&amp;lt;/nowiki&amp;gt; Used by a Lunar Magic ASM hack: High bit of destination level (only if the U bit is set)&lt;br /&gt;
&lt;br /&gt;
=== Screen jump ===&lt;br /&gt;
&lt;br /&gt;
(Extended object 01)&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
!   First  !!  Second  !!   Last&lt;br /&gt;
|-&lt;br /&gt;
| 000PPPPP || 0000???? || 00000001&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
!  Bit  !!   Description&lt;br /&gt;
|-&lt;br /&gt;
| PPPPP || Page to jump to&lt;br /&gt;
|-&lt;br /&gt;
| ????  || Unused?&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The loading routine jumps to another screen.&lt;br /&gt;
&lt;br /&gt;
== Layer 2 ==&lt;br /&gt;
=== Background ===&lt;br /&gt;
&lt;br /&gt;
Layer 2 backgrounds are compressed using a simple RLE system.&lt;br /&gt;
&lt;br /&gt;
A background consists of any number of &amp;quot;lines&amp;quot;. There are two types: Normal line and RLE line&lt;br /&gt;
&lt;br /&gt;
Each line begins with a start byte. The highest bit decides what kind of line it is (0 = Normal, 1 = RLE). The other 7 bits are the &amp;quot;length&amp;quot; setting, which is the amount of tiles in the line minus 1.&lt;br /&gt;
&lt;br /&gt;
A normal line is then followed by (length+1) bytes, each being a tile in the background. An RLE line is only followed by a single byte which is repeated (length+1) times.&lt;br /&gt;
&lt;br /&gt;
The entire left half of the background is stored first, followed by the entire right half.&lt;br /&gt;
&lt;br /&gt;
The line &amp;quot;FFFF&amp;quot; marks the end of the data.&lt;br /&gt;
&lt;br /&gt;
=== Level ===&lt;br /&gt;
&lt;br /&gt;
Layer 2 levels are stored in exactly the same way as Layer 1. The five byte header is there as well, but doesn&#039;t seem to be used.&lt;br /&gt;
&lt;br /&gt;
== Sprites ==&lt;br /&gt;
&lt;br /&gt;
The first byte of the sprite data is the sprite header. Each sprite is three bytes long.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
!   First  !!  Second  !!   Last&lt;br /&gt;
|-&lt;br /&gt;
| YYYYEEsy || XXXXSSSS || NNNNNNNN&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
!   Bits   !!  Description&lt;br /&gt;
|-&lt;br /&gt;
! yYYYY    || Y position&lt;br /&gt;
|-&lt;br /&gt;
| EE       || Extra bits&lt;br /&gt;
|-&lt;br /&gt;
| XXXX     || X position&lt;br /&gt;
|-&lt;br /&gt;
| sSSSS    || Screen number&lt;br /&gt;
|-&lt;br /&gt;
| NNNNNNNN || Enemy number&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
(Note: The first byte being FF marks the end of the data)&lt;br /&gt;
&lt;br /&gt;
== Secondary entrances ==&lt;br /&gt;
&lt;br /&gt;
(Not yet documented.)&lt;br /&gt;
&lt;br /&gt;
[[Category:Super Mario World]]&lt;/div&gt;</summary>
		<author><name>MarioFanGamer</name></author>
	</entry>
	<entry>
		<id>https://sneslab.net/mw/index.php?title=SMW_level_data_format&amp;diff=3455</id>
		<title>SMW level data format</title>
		<link rel="alternate" type="text/html" href="https://sneslab.net/mw/index.php?title=SMW_level_data_format&amp;diff=3455"/>
		<updated>2023-05-05T18:50:12Z</updated>

		<summary type="html">&lt;p&gt;MarioFanGamer: Added table formatting to most tables, removed some unwanted formattings.&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This article contains information about how levels are stored in [[Super Mario World]].&lt;br /&gt;
&lt;br /&gt;
== Pointer tables ==&lt;br /&gt;
&lt;br /&gt;
x2E200/$05E000	Layer 1 data	0x200 levels, 3   bytes each. (1,536 bytes)&lt;br /&gt;
x2E800/$05E600	Layer 2 data	0x200 levels, 3*  bytes each. (1,536 bytes)&lt;br /&gt;
x2EE00/$05EC00	Sprite data	0x200 levels, 2** bytes each. (1,024 bytes)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;nowiki&amp;gt;*)&amp;lt;/nowiki&amp;gt;  Layer 2 BG only uses the two lower bytes. The upper byte should be FF.&lt;br /&gt;
    The backgrounds are stored in bank 0C.&lt;br /&gt;
&amp;lt;nowiki&amp;gt;**)&amp;lt;/nowiki&amp;gt; The sprite data is located in bank 07.&lt;br /&gt;
&lt;br /&gt;
== Primary level header ==&lt;br /&gt;
&lt;br /&gt;
The first five bytes of the Layer 1 data is the primary level header.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
!   First  !!  Second  !!   Third  !!  Fourth  !!   Last&lt;br /&gt;
|-&lt;br /&gt;
| BBBLLLLL || CCCOOOOO || 3MMMSSSS || TTPPPFFF || IIVVZZZZ&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
BBB   =BG palette&lt;br /&gt;
LLLLL =Length of level (amount of screens)&lt;br /&gt;
CCC   =BG color&lt;br /&gt;
OOOOO =Level mode&lt;br /&gt;
3     =Layer 3 Priority&lt;br /&gt;
MMM   =Music&lt;br /&gt;
SSSS  =Sprite set&lt;br /&gt;
TT    =Time&lt;br /&gt;
PPP   =Sprite palette&lt;br /&gt;
FFF   =FG palette&lt;br /&gt;
II    =Item memory&lt;br /&gt;
VV    =Vertical scroll&lt;br /&gt;
ZZZZ  =Tile set&lt;br /&gt;
&lt;br /&gt;
== Secondary level header ==&lt;br /&gt;
&lt;br /&gt;
The secondary level header consists of four bytes.&lt;br /&gt;
(These four bytes are not stored together)&lt;br /&gt;
Location of Byte 1: x2F200/$05F000 + level number&lt;br /&gt;
Location of Byte 2: x2F400/$05F200 + level number&lt;br /&gt;
Location of Byte 3: x2F600/$05F400 + level number&lt;br /&gt;
Location of Byte 4: x2F800/$05F600 + level number&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
!  Byte 1  !!  Byte 2  !!  Byte 3  !!  Byte 4&lt;br /&gt;
|-&lt;br /&gt;
| SSSSYYYY || 33TTTXXX || MMMMFFBB || IUVEEEEE&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
S = Layer 2 scroll settings&lt;br /&gt;
Y = Level entrance Y position&lt;br /&gt;
3 = Layer 3 settings&lt;br /&gt;
T = Level entrance type&lt;br /&gt;
X = Level entrance X position&lt;br /&gt;
M = Level entrance midway screen&lt;br /&gt;
F = Level entrance FG init position&lt;br /&gt;
B = Level entrance BG init position&lt;br /&gt;
I = Disable no-Yoshi intro flag&lt;br /&gt;
U = Unknown vertical position flag&lt;br /&gt;
V = Vertical positioning flag&lt;br /&gt;
E = Level entrance screen number&lt;br /&gt;
&lt;br /&gt;
=== Sprite header ===&lt;br /&gt;
&lt;br /&gt;
The sprite header is the first byte of sprite data.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Byte&lt;br /&gt;
|-&lt;br /&gt;
| SBMMMMMM&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
S      = Sprite buoyancy&lt;br /&gt;
B      = Sprite buoyancy (no sprite-L2 interaction)&lt;br /&gt;
MMMMMM = Sprite memory*&lt;br /&gt;
&lt;br /&gt;
&amp;lt;nowiki&amp;gt;*)&amp;lt;/nowiki&amp;gt; Values up to 0x3F are possible, but only up to 0x12 are valid according to Lunar Magic.&lt;br /&gt;
&lt;br /&gt;
== Layer 1 ==&lt;br /&gt;
&lt;br /&gt;
(Note that MAP16 is not documented, as it&#039;s a feature added by Lunar Magic)&lt;br /&gt;
The Layer 1 data begins with the primary level header, followed by the actual Layer 1 data.&lt;br /&gt;
Each block is three bytes long, with the exception of the screen exit objects.&lt;br /&gt;
&lt;br /&gt;
=== Standard objects ===&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
!   First  !!  Second  !!   Last&lt;br /&gt;
|-&lt;br /&gt;
| NBBYYYYY || bbbbXXXX || SSSSSSSS&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
N        = New Screen flag&lt;br /&gt;
BBbbbb   = Object number&lt;br /&gt;
YYYYY    = Y position&lt;br /&gt;
XXXX     = X position&lt;br /&gt;
SSSSSSSS = Settings byte&lt;br /&gt;
&lt;br /&gt;
(Note: The first byte being FF marks the end of the data)&lt;br /&gt;
&lt;br /&gt;
				    Settings byte&lt;br /&gt;
Num	Desc			Upper 4	       Lower 4&lt;br /&gt;
------------------------------------------------------&lt;br /&gt;
00	(Extended Objects)	Extended object number&lt;br /&gt;
01	Water (Blue)		Height		Width&lt;br /&gt;
02	Invisible coin blocks	Height		Width&lt;br /&gt;
03	Invisible note blocks	Height		Width&lt;br /&gt;
04	Invisible POW coins	Height		Width&lt;br /&gt;
05	Coins			Height		Width&lt;br /&gt;
06	Walk-through dirt	Height		Width&lt;br /&gt;
07	Water (Other color)	Height		Width&lt;br /&gt;
08	Note blocks		Height		Width&lt;br /&gt;
09	Turn blocks		Height		Width&lt;br /&gt;
0A	Coin ? blocks		Height		Width&lt;br /&gt;
0B	Throw blocks		Height		Width&lt;br /&gt;
0C	Black piranha plants	Height		Width&lt;br /&gt;
0D	Cement blocks		Height		Width&lt;br /&gt;
0E	Brown blocks		Height		Width&lt;br /&gt;
0F	Vertical pipes		Height		Type&lt;br /&gt;
10	Horizontal pipes	Type		Width&lt;br /&gt;
11	Bullet shooter		Height		Unused&lt;br /&gt;
12	Slopes			Height		Type&lt;br /&gt;
13	Ledge edges		Height		Type&lt;br /&gt;
14	Ground ledge		Height		Width&lt;br /&gt;
15	Midway/Goal point	Height		Type&lt;br /&gt;
16	Blue coins		Height		Width&lt;br /&gt;
17	Rope/Clouds		Type		Width&lt;br /&gt;
18	Water surface (ani)	Height		Width&lt;br /&gt;
19	Water surface (not ani)	Height		Width&lt;br /&gt;
1A	Lava surface (ani)	Height		Width&lt;br /&gt;
1B	Net top edge		Height		Width&lt;br /&gt;
1C	Donut bridge		Unused		Width&lt;br /&gt;
1D	Net bottom edge		Height		Width&lt;br /&gt;
1E	Net vertical edge	Height		Type&lt;br /&gt;
1F	Vert. Pipe/Bone/Log	Height		Unused&lt;br /&gt;
20	Horiz. Pipe/Bone/Log	Unused		Width&lt;br /&gt;
21	Long ground ledge	        Width&lt;br /&gt;
22	Special - Used by LM&lt;br /&gt;
23	Special - Used by LM&lt;br /&gt;
24	Special - Used by LM&lt;br /&gt;
25	Special - Used by LM&lt;br /&gt;
26	Special - Used by LM&lt;br /&gt;
27	Special - Used by LM&lt;br /&gt;
28	Special - Used by LM&lt;br /&gt;
29	Special - Reserved&lt;br /&gt;
2A	Special - Reserved&lt;br /&gt;
2B	Special - Reserved&lt;br /&gt;
2C	Special - Reserved&lt;br /&gt;
2D	Special - Used by LM&lt;br /&gt;
2E	Tileset Specific 1&lt;br /&gt;
2F	Tileset Specific 2&lt;br /&gt;
30	Tileset Specific 3&lt;br /&gt;
31	Tileset Specific 4&lt;br /&gt;
32	Tileset Specific 5&lt;br /&gt;
33	Tileset Specific 6&lt;br /&gt;
34	Tileset Specific 7&lt;br /&gt;
35	Tileset Specific 8&lt;br /&gt;
36	Tileset Specific 9&lt;br /&gt;
37	Tileset Specific 10&lt;br /&gt;
38	Tileset Specific 11&lt;br /&gt;
39	Tileset Specific 12&lt;br /&gt;
3A	Tileset Specific 13&lt;br /&gt;
3B	Tileset Specific 14&lt;br /&gt;
3C	Tileset Specific 15&lt;br /&gt;
3D	Tileset Specific 16&lt;br /&gt;
3E	Tileset Specific 17&lt;br /&gt;
3F	Tileset Specific 18&lt;br /&gt;
&lt;br /&gt;
=== Extended objects ===&lt;br /&gt;
&lt;br /&gt;
(Standard object 00)&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
!   First  !!  Second  !!   Last&lt;br /&gt;
|-&lt;br /&gt;
| N00YYYYY || 0000XXXX || BBBBBBBB&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
N        = New Screen flag&lt;br /&gt;
YYYYY    = Y position&lt;br /&gt;
XXXX     = X position&lt;br /&gt;
BBBBBBBB = Extended object number&lt;br /&gt;
&lt;br /&gt;
Num	Desc&lt;br /&gt;
----------------------------------------------------&lt;br /&gt;
00	Special - Screen Exit&lt;br /&gt;
01	Special - Screen Jump&lt;br /&gt;
02-0F	Unused?&lt;br /&gt;
10	Small door&lt;br /&gt;
11	Invisible ? block (1-UP)&lt;br /&gt;
12	Invisible note block&lt;br /&gt;
13	Top left corner edge tile 1&lt;br /&gt;
14	Top right corner edge tile 1&lt;br /&gt;
15	Small POW door&lt;br /&gt;
16	Invisible POW ? block&lt;br /&gt;
17	Green star block&lt;br /&gt;
18	3-UP moon&lt;br /&gt;
19	Invisible 1-UP #1&lt;br /&gt;
1A	Invisible 1-UP #2&lt;br /&gt;
1B	Invisible 1-UP #3&lt;br /&gt;
1C	Invisible 1-UP #4&lt;br /&gt;
1D	Red berry&lt;br /&gt;
1E	Pink berry&lt;br /&gt;
1F	Green berry&lt;br /&gt;
20	Always turning block&lt;br /&gt;
21	Bottom right of midway point (unused)&lt;br /&gt;
22	Bottom right of midway point (unused)&lt;br /&gt;
23	Note block (flower/feather/star)&lt;br /&gt;
24	ON/OFF block&lt;br /&gt;
25	Direction coins ? block&lt;br /&gt;
26	Note block&lt;br /&gt;
27	Note block, bounce on all sides&lt;br /&gt;
28	Turn block (Flower)&lt;br /&gt;
29	Turn block (Feather)&lt;br /&gt;
2A	Turn block (Star)&lt;br /&gt;
2B	Turn block (Star 2/1-UP/Vine)&lt;br /&gt;
2C	Turn block (Multiple coins)&lt;br /&gt;
2D	Turn block (Coin)&lt;br /&gt;
2E	Turn block (Nothing)&lt;br /&gt;
2F	Turn block (POW)&lt;br /&gt;
30	? block (Flower)&lt;br /&gt;
31	? block (Feather)&lt;br /&gt;
32	? block (Star)&lt;br /&gt;
33	? block (Star 2)&lt;br /&gt;
34	? block (Multiple coins)&lt;br /&gt;
35	? block (Key/Wings/Balloon/Shell)&lt;br /&gt;
36	? block (Yoshi)&lt;br /&gt;
37	? block (Shell)&lt;br /&gt;
38	? block (Shell)&lt;br /&gt;
39	Turn block, unbreakable (Feather)&lt;br /&gt;
3A	Top left corner edge tile 2&lt;br /&gt;
3B	Top right corner edge tile 2&lt;br /&gt;
3C	Top left corner edge tile 3&lt;br /&gt;
3D	Top right corner edge tile 3&lt;br /&gt;
3E	Top left corner edge tile 4&lt;br /&gt;
3F	Top right corner edge tile 4&lt;br /&gt;
40	Transculent block&lt;br /&gt;
41	Yoshi Coin&lt;br /&gt;
42	Top left slope&lt;br /&gt;
43	Top right slope&lt;br /&gt;
44	Purple triangle, left&lt;br /&gt;
45	Purple triangle, right&lt;br /&gt;
46	Midway point rope&lt;br /&gt;
47	Door&lt;br /&gt;
48	Invisible POW door&lt;br /&gt;
49	Ghost house exit&lt;br /&gt;
4A	Climbing net door&lt;br /&gt;
4B	Conveyor end tile 1&lt;br /&gt;
4C	Conveyor end tile 2&lt;br /&gt;
4D	Line guide, top left 1/4 large circle&lt;br /&gt;
4E	Line guide, top right 1/4 large circle&lt;br /&gt;
4F	Line guide, bottom left 1/4 large circle&lt;br /&gt;
50	Line guide, bottom right 1/4 large circle&lt;br /&gt;
51	Line guide, top left 1/4 small circle&lt;br /&gt;
52	Line guide, top right 1/4 small circle&lt;br /&gt;
53	Line guide, bottom left 1/4 small circle&lt;br /&gt;
54	Line guide, bottom right 1/4 small circle&lt;br /&gt;
55	Line guide end, for horizontal line&lt;br /&gt;
56	Line guide end, for vertical line&lt;br /&gt;
57	Switch palace bottom right corner tile&lt;br /&gt;
58	Switch palace bottom left corner tile&lt;br /&gt;
59	Switch palace top right corner tile&lt;br /&gt;
5A	Switch palace top left corner tile&lt;br /&gt;
5B	Bit of brick background tile 1&lt;br /&gt;
5C	Bit of brick background tile 2&lt;br /&gt;
5D	Bit of brick background tile 3&lt;br /&gt;
5E	Bit of brick background tile 4&lt;br /&gt;
5F	Large background area&lt;br /&gt;
60	Lava/mud top right corner edge&lt;br /&gt;
61	Ghost house clock&lt;br /&gt;
62	Ghost house top left to bottom right beam 1&lt;br /&gt;
63	Ghost house top right to bottom left beam 1&lt;br /&gt;
64	Ghost house cobweb, top right&lt;br /&gt;
65	Ghost house cobweb, top left&lt;br /&gt;
66	Ghost house top right to bottom left beam 2&lt;br /&gt;
67	Ghost house top left to bottom right beam 2&lt;br /&gt;
68	Cloud fringe, bottom and right edge&lt;br /&gt;
69	Cloud fringe, bottom and left edge&lt;br /&gt;
6A	Cloud fringe, bottom right&lt;br /&gt;
6B	Cloud fringe, bottom left&lt;br /&gt;
6C	Cloud fringe on white, bottom and right edge&lt;br /&gt;
6D	Cloud fringe on white, bottom and left edge&lt;br /&gt;
6E	Cloud fringe on white, bottom right&lt;br /&gt;
6F	Cloud fringe on white, bottom left&lt;br /&gt;
70	Bit of canvass 1&lt;br /&gt;
71	Canvass 1&lt;br /&gt;
72	Canvass 2&lt;br /&gt;
73	Canvass 3&lt;br /&gt;
74	Canvass 4&lt;br /&gt;
75	Canvass tile 1&lt;br /&gt;
76	Canvass tile 2&lt;br /&gt;
77	Canvass tile 3&lt;br /&gt;
78	Canvass tile 4&lt;br /&gt;
79	Canvass tile 5&lt;br /&gt;
7A	Canvass tile 6&lt;br /&gt;
7B	Canvass tile 7&lt;br /&gt;
7C	Bit of canvas 2&lt;br /&gt;
7D	Bit of canvas 3&lt;br /&gt;
7E	Bit of canvas 4&lt;br /&gt;
7F	Torpedo launcher&lt;br /&gt;
80	Ghost house entrance&lt;br /&gt;
81	Water weed&lt;br /&gt;
82	Big bush 1&lt;br /&gt;
83	Big bush 2&lt;br /&gt;
84	Castle entrance&lt;br /&gt;
85	Yoshi&#039;s house&lt;br /&gt;
86	Arrow sign&lt;br /&gt;
87	! block, green&lt;br /&gt;
88	Tree branch, left&lt;br /&gt;
89	Tree branch, right&lt;br /&gt;
8A	Switch, green&lt;br /&gt;
8B	Switch, yellow&lt;br /&gt;
8C	Switch, blue&lt;br /&gt;
8D	Switch, red&lt;br /&gt;
8E	! block, yellow&lt;br /&gt;
8F	Ghost house window&lt;br /&gt;
90	Boss door&lt;br /&gt;
91	Steep left slope (vert. lev.)&lt;br /&gt;
92	Steep right slope (vert. lev.)&lt;br /&gt;
93	Normal left slope (vert. lev.)&lt;br /&gt;
94	Normal right slope (vert. lev.)&lt;br /&gt;
95	Very steep left slope (vert. lev.)&lt;br /&gt;
96	Very steep right slope (vert. lev.)&lt;br /&gt;
97	Switch palace right and bottom edge tile&lt;br /&gt;
98-FF	Unused?&lt;br /&gt;
&lt;br /&gt;
=== Screen exits ===&lt;br /&gt;
&lt;br /&gt;
(Extended object 00)&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
!   First  !!  Second  !!   Third  !!   Last&lt;br /&gt;
|-&lt;br /&gt;
| 000PPPPP || 0000WUSH || 00000000 || DDDDDDDD&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
PPPPP    = Page number&lt;br /&gt;
W        = Water (secondary exit)&lt;br /&gt;
U        = Secondary Exit? *&lt;br /&gt;
S        = Secondary Exit&lt;br /&gt;
H        = Unused **&lt;br /&gt;
DDDDDDDD = Lower 8 bits of destination level&lt;br /&gt;
&lt;br /&gt;
Creates a screen exit. Should be placed right before the end of the level.&lt;br /&gt;
&lt;br /&gt;
*)  Used by a Lunar Magic ASM hack: If set, the H bit will be used&lt;br /&gt;
**) Used by a Lunar Magic ASM hack: High bit of destination level (only if the U bit is set)&lt;br /&gt;
&lt;br /&gt;
Screen jump&lt;br /&gt;
&lt;br /&gt;
(Extended object 01)&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
!   First  !!  Second  !!   Last&lt;br /&gt;
|-&lt;br /&gt;
| 000PPPPP || 0000???? || 00000001&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
PPPPP    = Page to jump to&lt;br /&gt;
????     = Unused?&lt;br /&gt;
&lt;br /&gt;
The loading routine jumps to another screen.&lt;br /&gt;
&lt;br /&gt;
== Layer 2 ==&lt;br /&gt;
=== Background ===&lt;br /&gt;
&lt;br /&gt;
Layer 2 backgrounds are compressed using a simple RLE system.&lt;br /&gt;
&lt;br /&gt;
A background consists of any number of &amp;quot;lines&amp;quot;. There are two types: Normal line and RLE line&lt;br /&gt;
&lt;br /&gt;
Each line begins with a start byte. The highest bit decides what kind of line it is.&lt;br /&gt;
(0 = Normal, 1 = RLE)&lt;br /&gt;
The other 7 bits are the &amp;quot;length&amp;quot; setting, which is the amount of tiles in the line minus 1.&lt;br /&gt;
&lt;br /&gt;
A normal line is then followed by (length+1) bytes, each being a tile in the background.&lt;br /&gt;
An RLE line is only followed by a single byte which is repeated (length+1) times.&lt;br /&gt;
&lt;br /&gt;
The entire left half of the background is stored first, followed by the entire right half.&lt;br /&gt;
&lt;br /&gt;
The line &amp;quot;FFFF&amp;quot; marks the end of the data.&lt;br /&gt;
&lt;br /&gt;
=== Level ===&lt;br /&gt;
&lt;br /&gt;
Layer 2 levels are stored in exactly the same way as Layer 1.&lt;br /&gt;
The five byte header is there as well, but doesn&#039;t seem to be used.&lt;br /&gt;
&lt;br /&gt;
== Sprites ==&lt;br /&gt;
&lt;br /&gt;
The first byte of the sprite data is the sprite header.&lt;br /&gt;
Each sprite is three bytes long.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
!   First  !!  Second  !!   Last&lt;br /&gt;
|-&lt;br /&gt;
| YYYYEEsy || XXXXSSSS || NNNNNNNN&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
yYYYY    = Y position&lt;br /&gt;
EE       = Extra bits&lt;br /&gt;
XXXX     = X position&lt;br /&gt;
sSSSS    = Screen number&lt;br /&gt;
NNNNNNNN = Enemy number&lt;br /&gt;
&lt;br /&gt;
(Note: The first byte being FF marks the end of the data)&lt;br /&gt;
&lt;br /&gt;
== Secondary entrances ==&lt;br /&gt;
&lt;br /&gt;
(Not yet documented.)&lt;br /&gt;
&lt;br /&gt;
[[Category:Super Mario World]]&lt;/div&gt;</summary>
		<author><name>MarioFanGamer</name></author>
	</entry>
	<entry>
		<id>https://sneslab.net/mw/index.php?title=Super_FX&amp;diff=3454</id>
		<title>Super FX</title>
		<link rel="alternate" type="text/html" href="https://sneslab.net/mw/index.php?title=Super_FX&amp;diff=3454"/>
		<updated>2023-05-05T15:04:02Z</updated>

		<summary type="html">&lt;p&gt;MarioFanGamer: Added links to most mentionings of opcodes, refined certain sentences.&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&#039;&#039;&#039;Super FX&#039;&#039;&#039; is a [[Super NES]] [[enhancement chip]] developed by [https://en.wikipedia.org/wiki/Argonaut_Games Argonaut Games] and [http://en.wikipedia.org/wiki/Nintendo Nintendo]. It&#039;s also known as the &amp;quot;Graphical Support Unit&amp;quot; (short for &amp;quot;GSU&amp;quot;) for its greater graphical capabilities compared to the S-CPU whereas its first revision, used for [[Star Fox]], uses the name &amp;quot;Mathematical, Argonaut, Rotation, &amp;amp; Input/Output&amp;quot; or short MARIO chip. It also is know for the use in [[Super Mario World 2: Yoshi&#039;s Island]].&lt;br /&gt;
&lt;br /&gt;
During this article, GSU refers to Super FX whereas CPU refers to the Super NES CPU.&lt;br /&gt;
&lt;br /&gt;
== Features ==&lt;br /&gt;
The embedded co-processor has got a base clock speed of &#039;&#039;&#039;10.74 MHz&#039;&#039;&#039; which is four times as fast as the S-CPU which uses a base block of 2.68 Mhz. Its features includes but not limited to:&lt;br /&gt;
* A RISC-like processor where most opcodes have an instruction size of one byte and are executed in a single cycle when in cache.&lt;br /&gt;
* 512 bytes of cache RAM for faster processing of instructions.&lt;br /&gt;
* A large memory capactiy, a total capacity of 8 MiB ROM, of which two MiB are shared by CPU and GSU, and 256 KiB RAM, of which 128 KiB are shared by CPU and GSU.&lt;br /&gt;
* A separate bus for ROM and RAM to handle memory in parallel&lt;br /&gt;
* Paralell processing with the CPU&lt;br /&gt;
* Fast Bitmap to Planar conversion&lt;br /&gt;
* Pipeline processing to fetch opcodes twice as fast, effectively increasing the processing speed to 21.48 MHz.&lt;br /&gt;
&lt;br /&gt;
= Technical Information =&lt;br /&gt;
&lt;br /&gt;
== Hardware Registers ==&lt;br /&gt;
&lt;br /&gt;
Super FX comes with various hardware registers of various functions. Most (but not all) of the GSU hardware registers can be accessed from the CPU when the GSU is idling. They are located in the $3000-$3FFF region in banks $00-$3F and $80-$BF.&lt;br /&gt;
&lt;br /&gt;
=== General Registers (R0-R13) ===&lt;br /&gt;
&lt;br /&gt;
These registers are more or less equivalent to the A, X and Y registers on the [[65c816]]. They all are parameters to many opcodes, though not all of them are valid (e.g. R0 can&#039;t be a parameter for the logical operators), and are all 16-bit. Some of them come with a secondary use for certain opcodes. The CPU can directly read from and write to these registers $3000-$301B.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+A list of their addresses and their secondary functions&lt;br /&gt;
|-&lt;br /&gt;
! Name !! Address !! Secondary Function&lt;br /&gt;
|-&lt;br /&gt;
|  R0  ||  $3000  || Default source/destination register.&lt;br /&gt;
|-&lt;br /&gt;
|  R1  ||  $3002  || [[PLOT]] X position&lt;br /&gt;
|-&lt;br /&gt;
|  R2  ||  $3004  || [[PLOT&amp;lt;]] Y position&lt;br /&gt;
|-&lt;br /&gt;
|  R3  ||  $3006  ||&lt;br /&gt;
|-&lt;br /&gt;
|  R4  ||  $3008  || Low word for [[LMULT]] result&lt;br /&gt;
|-&lt;br /&gt;
|  R5  ||  $300A  ||&lt;br /&gt;
|-&lt;br /&gt;
|  R6  ||  $300C  || Second input for [[LMULT]] and [[FMULT]]&lt;br /&gt;
|-&lt;br /&gt;
|  R7  ||  $300E  || [[MERGE]] source 1&lt;br /&gt;
|-&lt;br /&gt;
|  R8  ||  $3010  || [[MERGE]] source 2&lt;br /&gt;
|-&lt;br /&gt;
|  R9  ||  $3012  ||&lt;br /&gt;
|-&lt;br /&gt;
|  R10 ||  $3014  ||&lt;br /&gt;
|-&lt;br /&gt;
|  R11 ||  $3016  || [[LINK]] destination&lt;br /&gt;
|-&lt;br /&gt;
|  R12 ||  $3018  || [[LOOP]] counter&lt;br /&gt;
|-&lt;br /&gt;
|  R13 ||  $301A  || [[LOOP]] start&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Game Pak ROM Address Pointer (R14) ===&lt;br /&gt;
&lt;br /&gt;
R14 is the ROM Pointer register and is mapped to $301C-$301D on the SNES. It&#039;s the pointer for the [[GETB]] opcodes which allows the GSU to read from ROM.&lt;br /&gt;
It otherwise acts like any normal general register and is sometimes used as such.&lt;br /&gt;
&lt;br /&gt;
=== Program Counter (R15) ===&lt;br /&gt;
&lt;br /&gt;
R15 is the program counter and is mapped to $301E-$301F on the SNES. Unlike on the [[65c816]] processor, the program counter (excluding the bank) can be directly read or modified within code&lt;br /&gt;
as it acts like a general register. This makes it possible to e.g. jump to a certain address without the use of a dedicated opcode.&lt;br /&gt;
For example, &amp;lt;code&amp;gt;IWT R15, #xxxx&amp;lt;/code&amp;gt; on Super FX is equivalent to &amp;lt;code&amp;gt;JMP $xxxx&amp;lt;/code&amp;gt; on the 65c816.&lt;br /&gt;
&lt;br /&gt;
In addition, writing to $301E on the CPU side invokes the GSU.&lt;br /&gt;
&lt;br /&gt;
=== Status/Flag Register (SFR) ===&lt;br /&gt;
&lt;br /&gt;
Super FX comes with a 16-bit register of various flags, mostly from calculations (e.g. a carry flag) but also other flags like whether Super FX is currently running.&lt;br /&gt;
They can be read and written through $3030 and $3031.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+Status/Flag Register bitwise&lt;br /&gt;
!       !! B7  !! B6 !! B5 !! B4 !! B3 !! B2 !!  B1  !!  B0&lt;br /&gt;
|-&lt;br /&gt;
| $3031 || IRQ || -  || -  || B  || IH || IL || ALT1 || ALT2&lt;br /&gt;
|-&lt;br /&gt;
| $3030 ||  -  || R  || G  || OV || S  || CY ||  Z   ||  -&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+Description of Flags&lt;br /&gt;
|-&lt;br /&gt;
! Flag !! Description&lt;br /&gt;
|-&lt;br /&gt;
|  Z   || Zero flag, set when result is zero.&lt;br /&gt;
|-&lt;br /&gt;
|  CY  || Carry flag, set at result overflow (unsigned).&lt;br /&gt;
|-&lt;br /&gt;
|  S   || Sign flag, set when number is negative.&lt;br /&gt;
|-&lt;br /&gt;
|  OV  || Overflow flag, set at result overflow (signed).&lt;br /&gt;
|-&lt;br /&gt;
|  G   || Go flag, set when GSU is running.&lt;br /&gt;
|-&lt;br /&gt;
|  R   || Set when reading from ROM.&lt;br /&gt;
|-&lt;br /&gt;
| ALT1 || Opcode modifier 1, set when executing [[ALT1]].&lt;br /&gt;
|-&lt;br /&gt;
| ALT2 || Opcode modifier 2, set when executing [[ALT2]].&lt;br /&gt;
|-&lt;br /&gt;
|  IL  || Immediate lower 8-bit flag.&lt;br /&gt;
|-&lt;br /&gt;
|  IH  || Immediate higher 8-bit flag.&lt;br /&gt;
|-&lt;br /&gt;
|  B   || Set when executing [[WITH]].&lt;br /&gt;
|-&lt;br /&gt;
| IRQ  || Interrupt flag, set when GSU stopped.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Program Bank Register (PBR) ===&lt;br /&gt;
&lt;br /&gt;
The program bank is the bank where GSU code is executed. It&#039;s a readable and writable 8-bit register which is mapped to $3034 on the CPU side.&lt;br /&gt;
Unlike R15, this can only be modified indirectly using [[LJMP]] on GSU side.&lt;br /&gt;
&lt;br /&gt;
=== Game Pak ROM Bank Register (ROMBR) ===&lt;br /&gt;
&lt;br /&gt;
This register controls the bank where ROM is read. It&#039;s set using the [[ROMB]] on the GSU side.&lt;br /&gt;
It&#039;s a readable only 8-bit register which is mapped to $3036 on the CPU side.&lt;br /&gt;
&lt;br /&gt;
=== Game Pak RAM Bank Register (RAMBR) ===&lt;br /&gt;
&lt;br /&gt;
This register is the RAM equivalent to ROMBR. It&#039;s set using the [[RAMB]] on the GSU side.&lt;br /&gt;
It&#039;s a readable only 1-bit register which is mapped to $303C on the CPU side.&lt;br /&gt;
&lt;br /&gt;
=== Cache Base Register (CBR) ===&lt;br /&gt;
&lt;br /&gt;
The Cache Base Register is the address where cache has been enabled through and tells the GSU where to run code in cache.&lt;br /&gt;
It&#039;s readable 16-bit register accessible through $303E and $303F from the CPU and written by the GSU with the [[CACHE]] and [[LJMP]] opcodes.&lt;br /&gt;
The lowest four bits of this register are open bus since cache is stored in 16-byte blocks.&lt;br /&gt;
&lt;br /&gt;
=== Screen Base Register (SCBR) ===&lt;br /&gt;
&lt;br /&gt;
The Screen Base Register is the high byte of the image buffer i.e. the plotting destination.&lt;br /&gt;
It&#039;s a writeable 8-bit register mapped to $3038 on the CPU side.&lt;br /&gt;
&lt;br /&gt;
=== Screen Mode Register (SCMR) ===&lt;br /&gt;
&lt;br /&gt;
The Screen Mode Register contains the settings for the image buffer (dimensions, bitdepth) but also access to ROM and RAM.&lt;br /&gt;
It&#039;s a writeable 8-bit register mapped to $303A on the CPU side.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+Screen Mode Register bitwise&lt;br /&gt;
! B7 !! B6 !! B5  !! B4  !! B3  !! B2  !! B1  !! B0&lt;br /&gt;
|-&lt;br /&gt;
| -  || -  || HT1 || ROM || RAN || HT0 || MD1 || MD0&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The image buffer dimensions are given by HT0 and HT1. They all are 256 pixels wide but have different heights.&lt;br /&gt;
A special case exists when both bits are 1 which enables OBJ mode which is used to plot single sprites like in Yoshi&#039;s Island.&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+Screen Dimensions&lt;br /&gt;
|-&lt;br /&gt;
! HT1 !! H00 !! Mode&lt;br /&gt;
|-&lt;br /&gt;
|  0  ||  0  || 256 by 128&lt;br /&gt;
|-&lt;br /&gt;
|  0  ||  1  || 256 by 160&lt;br /&gt;
|-&lt;br /&gt;
|  1  ||  0  || 256 by 192&lt;br /&gt;
|-&lt;br /&gt;
|  1  ||  1  || OBJ mode&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The bitdepth of the image buffer is set by the MD0 and MD1 bits:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+Screen Mode&lt;br /&gt;
|-&lt;br /&gt;
! MD1 !! MD0 !! Mode&lt;br /&gt;
|-&lt;br /&gt;
|  0  ||  0  || 4-color mode (2bpp)&lt;br /&gt;
|-&lt;br /&gt;
|  0  ||  1  || 16-color mode (4bpp)&lt;br /&gt;
|-&lt;br /&gt;
|  1  ||  0  || Not used&lt;br /&gt;
|-&lt;br /&gt;
|  1  ||  1  || 256-color mode (8bpp)&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The SCMR register also controls whether Game Pak ROM and RAM can be accessed by the CPU or GSU:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+Screen Mode&lt;br /&gt;
|-&lt;br /&gt;
! Bit !! Description&lt;br /&gt;
|-&lt;br /&gt;
| RON || Gives ROM access to the CPU when 0 and GSU when 1.&lt;br /&gt;
|-&lt;br /&gt;
| RAN || Gives RAM access to the CPU when 0 and GSU when 1.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Color Register (COLR) ===&lt;br /&gt;
&lt;br /&gt;
The Color Register contains the colour for the pixel which is to be plotted.&lt;br /&gt;
It&#039;s an 8-bit register which is set using the [[COLOR]] and [[GETC]] opcodes on the GSU. There is no access from the CPU.&lt;br /&gt;
&lt;br /&gt;
=== Plot Option Register (POR) ===&lt;br /&gt;
&lt;br /&gt;
The Color Register controls how the colours are loaded into the COLR register as well as how they&#039;re drawn onto the buffer.&lt;br /&gt;
It&#039;s an 8-bit register which is set using the [[CMODE]] opcode on the GSU. There is no access from the CPU.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+Screen Mode Register bitwise&lt;br /&gt;
! B7 !! B6 !! B5 !! B4  !! B3 !! B2 !! B1 !! B0&lt;br /&gt;
|-&lt;br /&gt;
| -  || -  || -  || OBJ || FH || HN || DT || TP&lt;br /&gt;
|}&lt;br /&gt;
Note that these abbreviations are inofficial and have been included for simplification.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+Description of Screen Mode Register&lt;br /&gt;
|-&lt;br /&gt;
! Bit !! Description&lt;br /&gt;
|-&lt;br /&gt;
| OBJ || OBJ Flag&lt;br /&gt;
|-&lt;br /&gt;
| FH  || Freeze High Flag&lt;br /&gt;
|-&lt;br /&gt;
| HN  || High Nibble Flag&lt;br /&gt;
|-&lt;br /&gt;
| DT  || Dither Flag&lt;br /&gt;
|-&lt;br /&gt;
| TP  || Transparent Flag&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Backup RAM Register (BRAMR) ===&lt;br /&gt;
&lt;br /&gt;
This controls whether Back-up RAM (not to be confused with Game Pak RAM) becomes “protected”.&amp;lt;sup&amp;gt;1&amp;lt;/sup&amp;gt;&lt;br /&gt;
It&#039;s a 1-bit register mapped to bit 0 of $3033 which can be written by the CPU.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;sup&amp;gt;1&amp;lt;/sup&amp;gt;The definition of “protected” isn&#039;t very clear, though it can be assumed that Back-up RAM can&#039;t be written when it&#039;s set to be protected.&lt;br /&gt;
&lt;br /&gt;
=== Version Code Register (VCR) ===&lt;br /&gt;
&lt;br /&gt;
The Version Code Register contains the version code of the Super FX chip.&lt;br /&gt;
It&#039;s an 8-bit read-only register and accessed $303B on the CPU side.&lt;br /&gt;
&lt;br /&gt;
=== Config Register (CFGR) ===&lt;br /&gt;
&lt;br /&gt;
The Config Register contains two flags:&lt;br /&gt;
The IRQ flag which allows the GSU to fire an interrupt to the CPU should it stop and&lt;br /&gt;
the MS0 which controls the speed of the multiplication.&lt;br /&gt;
It&#039;s mapped to bit 0 of $3039 and is writeable from the CPU.&lt;br /&gt;
&lt;br /&gt;
=== Clock Select Register (CLSR) ===&lt;br /&gt;
&lt;br /&gt;
This register sets the clock speed of Super FX and enables pipelining in the process. When clear, Super FX runs at 10.74 MHz, when set, at 21.48 MHz.&lt;br /&gt;
It&#039;s mapped to bit 0 of $3039 and is writeable from the CPU.&lt;br /&gt;
&lt;br /&gt;
Supposedly, the CLSR and MS0 flags must not be set 1 at the same time but no side effects are known.&lt;br /&gt;
&lt;br /&gt;
== Memory and Bus ==&lt;br /&gt;
&lt;br /&gt;
=== Memory Map ===&lt;br /&gt;
One advantage of Super FX is that it naturally supports ROMs with a size of up to 8 MiB. However, Super FX can only use the first two MiB of a ROM. Similarly, even though a single cartridge may have up to 256 KiB of SRAM, only half of them can be used by Super FX. As a result, there is a difference between the CPU and GSU mapping.&lt;br /&gt;
&lt;br /&gt;
This is how the ROM is mapped from the perspective of the CPU:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
!  Banks  !!   Address   !! Description&lt;br /&gt;
|-&lt;br /&gt;
!rowspan=&amp;quot;6&amp;quot;|$00-$3F&lt;br /&gt;
          || $0000-$1FFF || WRAM mirror&lt;br /&gt;
|-&lt;br /&gt;
|           $2100-$21FF || PPU registers&lt;br /&gt;
|-&lt;br /&gt;
|           $3000-$3FFF || Super FX registers&lt;br /&gt;
|-&lt;br /&gt;
|           $4200-$43FF || CPU registers&lt;br /&gt;
|-&lt;br /&gt;
|           $6000-$7FFF || SRAM mirror&lt;br /&gt;
|-&lt;br /&gt;
|           $8000-$FFFF || ROM (LoROM)&lt;br /&gt;
|-&lt;br /&gt;
| $40-$5F || $0000-$FFFF || Mirror of ROM in banks $00-$3F (HiROM)&lt;br /&gt;
|-&lt;br /&gt;
| $60-$6F || $0000-$FFFF || Unmapped&lt;br /&gt;
|-&lt;br /&gt;
| $70-$71 || $0000-$FFFF || SRAM&lt;br /&gt;
|-&lt;br /&gt;
| $7C-$7D || $0000-$FFFF || Backup RAM&lt;br /&gt;
|-&lt;br /&gt;
| $7E-$7F || $0000-$FFFF || WRAM&lt;br /&gt;
|-&lt;br /&gt;
!rowspan=&amp;quot;6&amp;quot;|$80-$BF&lt;br /&gt;
          || $0000-$1FFF || WRAM mirror&lt;br /&gt;
|-&lt;br /&gt;
|           $2100-$21FF || PPU registers&lt;br /&gt;
|-&lt;br /&gt;
|           $3000-$3FFF || Super FX registers&lt;br /&gt;
|-&lt;br /&gt;
|           $4200-$43FF || CPU registers&lt;br /&gt;
|-&lt;br /&gt;
|           $6000-$7FFF || SRAM mirror&lt;br /&gt;
|-&lt;br /&gt;
|           $8000-$FFFF || ROM (LoROM)&lt;br /&gt;
|-&lt;br /&gt;
| $C0-$FF || $8000-$FFFF || ROM (HiROM)&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The GSU memory map looks similar to the CPU mapping but only with access to ROM and SRAM as well as only access to 2 MiB of ROM and 128 KiB of SRAM. As a result, it looks more like this:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
!  Banks  !!   Address   !! Description&lt;br /&gt;
|-&lt;br /&gt;
!rowspan=&amp;quot;2&amp;quot;|$00-$3F&lt;br /&gt;
          || $0000-$7FFF || Unmapped&lt;br /&gt;
|-&lt;br /&gt;
|            $8000-$FFFF || ROM (LoROM)&lt;br /&gt;
|-&lt;br /&gt;
| $40-$5F || $0000-$FFFF || Mirror of ROM in banks $00-$3F (HiROM)&lt;br /&gt;
|-&lt;br /&gt;
| $60-$6F || $0000-$FFFF || Unmapped&lt;br /&gt;
|-&lt;br /&gt;
| $70-$71 || $0000-$FFFF || SRAM&lt;br /&gt;
|-&lt;br /&gt;
| $72-$7F || $0000-$FFFF || Unmapped&lt;br /&gt;
|-&lt;br /&gt;
| $80-$FF || $0000-$FFFF || Mirror of $00-$7F&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Finally, it should be noted that banks $40-$5F are HiROM mirrors of the LoROM banks $00-$3F interlaced so addresses such as $008000 and $400000 contain the same value.&lt;br /&gt;
&lt;br /&gt;
=== ROM ===&lt;br /&gt;
ROM on Super FX can be up to 8 MiB large. However, even though the size is theoretically doable, the largest published Super FX games had a ROM size of 2 MiBs. As a result, not many emulators (not even BSNES as of 2021) emulate this feature properly and such ROM sizes only exist in homebrewing and modding.&lt;br /&gt;
&lt;br /&gt;
Super FX has also has got limitations with ROM access. This first example is the ROM size. Even though a Super FX ROM can be as large as 8 MiB (in theory), the GSU&#039;s data bus is only connected to 2 MiB of it. Said portion of ROM which the processor can access is called GamePak ROM while the additional 6 MiB, called the Super NES ROM, can only be accessed by the CPU.&lt;br /&gt;
A second limitation is the clock speed. The GSU is clocked very fast at 10,74 Mhz (which can be doubled with pipelining) but ROM is clocked at 3,58 Mhz (unlike on [[SA-1]] where ROM is clocked at the same frequence the coprocessor). As a result, all opcodes, when they are executed in ROM, take at least three cycles to process while reads from ROM are very slow.&lt;br /&gt;
&lt;br /&gt;
To counteract against this limitation, the GSU uses a buffering system. In order to load a value from ROM, the bank must first be set in ROMBR (set by [[ROMB]] in the GSU code) while the address is set in register R14. Any write to R14 initiates the buffering process. The value then can be retrieved with [[GETB]] and similar opcodes (referred to just &amp;lt;code&amp;gt;GETB&amp;lt;/code&amp;gt; from now on).&lt;br /&gt;
&lt;br /&gt;
The GSU doesn&#039;t wait during the process of fetching. As a result, it is possible to call &amp;lt;code&amp;gt;GETB&amp;lt;/code&amp;gt; some time after writing to R14. In fact, this is even recommend because calling &amp;lt;code&amp;gt;GETB&amp;lt;/code&amp;gt; during the process of fetching will cause the GSU to halt up five cycles for executing &amp;lt;code&amp;gt;GETB&amp;lt;/code&amp;gt;. Similarly, writing to &amp;lt;code&amp;gt;ROMB&amp;lt;/code&amp;gt; will halt the code as well until the data has been fetched enabling cache during the process of fetching will mess up the ROM value instead.&lt;br /&gt;
&lt;br /&gt;
=== RAM ===&lt;br /&gt;
&lt;br /&gt;
=== Cache ===&lt;br /&gt;
&lt;br /&gt;
In order to improve the speed of the processor, it includes a 512 byte large memory with the same frequency as the GSU as a cache. This allows Super FX to execute a single opcode with only a single cycle (i.e. three times as fast as in regular use). The cache is separated into 32 16-byte blocks, each with a flag which denotes that a block is used, and is indexed by the cache base register (CBR) which is used to keep track of where cache has been invoked. The cache flags and CBR are reset whenever a zero is written to the GO flag but simply halting or invoking the GSU preserves the content of the cache which in turn can be read by the CPU.&lt;br /&gt;
&lt;br /&gt;
Cache on the SNES is mapped to addresses $xx:3100-$xx:32FF ($xx = $00-$3F, $80-$BF), though the start of the cached code (see below) also is dependent on the CBR (start = $3100 + (CBR &amp;amp; 0x1FF)).&lt;br /&gt;
&lt;br /&gt;
There are two methods to fill the cache:&lt;br /&gt;
* Manual caching&lt;br /&gt;
* Automatic caching&lt;br /&gt;
&lt;br /&gt;
Manual caching involes using the CPU and transfer the code to cache. Keep in mind that Super FX will only execute the cache block which has been set to be used. That means, the code has to be transfered as a full 16 byte block, though strictly speaking, only the last byte of the block (address $XXXF) needs to be written to count the block as used.&lt;br /&gt;
In order to execute GSU code in cache, R15 has to be set to $0000-$01FF.&lt;br /&gt;
&lt;br /&gt;
Automatic caching is instead handled by the GSU itself. This is handled either by the dedicated [[CACHE]] opcode or by a [[LJMP]] opcode, the latter because of the lack of bank information for the cache. Both of them clear the cache flags and store the current PC with the lowest nibble masked out into the CBR (CBR = PC &amp;amp; 0xFFF0). Afterwards, each executed opcode will be written into cache starting from CBR &amp;amp; 0x1FF.&lt;br /&gt;
As a result, this use of cache is recommend for loops and the first loop will always run slower than the remaining loops. Should all the blocks be used, any remaining code will be left uncached and executed in the original memory.&lt;br /&gt;
&lt;br /&gt;
Another side effect is that cache is neither ROM nor GamePak RAM so any Super FX code in cache can run in parallel to the SNES even when access to ROM and RAM is given to the CPU instead of GSU.&lt;br /&gt;
&lt;br /&gt;
=== Pipeline Processing ===&lt;br /&gt;
&lt;br /&gt;
In order to boost the processing speed of the GSU, it uses a technique called &amp;quot;pipeline processing&amp;quot;. Pipelining exists to a lesser extend on the [[65c816]], where opcodes are prepared while the remaining bytes of the opcodes are fetched (this is notable on single byte opcodes such as [[INC]] which take two cycles to process, the same amount of cycles as &amp;lt;code&amp;gt;LDA #$xx&amp;lt;/code&amp;gt;, a two byte opcode) but the GSU takes it further by fetching the next opcode during the current opcode&#039;s execution.&lt;br /&gt;
This runs the code double as fast, virtually increasing the clock speed to 21.48 MHz at the cost of adding more care of the coder whenever R15 — the programm counter — is changed, either through branching or through direct writes to R15. In addition, internal processes such as multiplication and memory access can&#039;t take advantage of the virtual increment in clock speed.&lt;br /&gt;
&lt;br /&gt;
Pipelining is controlled with bit 0 of CLSR, where clear means pipelining disabled and set means pipelining enabled. It&#039;s accessable on the CPU side with the address $3037.&lt;br /&gt;
&lt;br /&gt;
For the most part, having pipelining enabled doesn&#039;t change the code. The only exceptions are when R15 is modified outside of fetching opcodes i.e. the use of branches and writes to R15 (e.g. &amp;lt;code&amp;gt;IWT R15,#$8000&amp;lt;/code&amp;gt;) as well as halting the GSU such as with [[STOP]]. In these cases, the opcode following that instruction will be executed after the branch. A common solution for the unwanted opcode execution is to put a dummy [[NOP]] after the R15 modifying opcode such as in this example:&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;BCC SkipCode&lt;br /&gt;
NOP             ; Dummy NOP&lt;br /&gt;
...&lt;br /&gt;
SkipCode:&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This proves to be inefficient, though. Most Super FX opcodes are one byte larger and take 3 or 1 cycles (depending on whether the code is executed in cache or not) to execute including &amp;lt;code&amp;gt;NOP&amp;lt;/code&amp;gt;. As a result, opcodes such as &amp;lt;code&amp;gt;SUB R0&amp;lt;/code&amp;gt; can be put as a dummy opcode in place of &amp;lt;code&amp;gt;NOP&amp;lt;/code&amp;gt;. The following example demonstrates it:&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;BCC SkipCode&lt;br /&gt;
;NOP            ; Redundant&lt;br /&gt;
SUB R0          ; Set R0 to zero&lt;br /&gt;
STW (R1)&lt;br /&gt;
SkipCode:&lt;br /&gt;
IWT R0,#$1234&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
In the above code, R0 gets overwritten by &amp;lt;code&amp;gt;SUB&amp;lt;/code&amp;gt; no matter whether the branch is taken. However, it later gets overwritten by &amp;lt;code&amp;gt;IWT&amp;lt;/code&amp;gt;. As a result, it doesn&#039;t matter whether the dummy opcode is a &amp;lt;code&amp;gt;NOP&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;SUB&amp;lt;/code&amp;gt; from the branch for the calculation. In fact, using a &amp;lt;code&amp;gt;NOP&amp;lt;/code&amp;gt; increases the code size by one byte which can matter when the code is executed in cache as well as increase the cycle count by 1 or 3 cycles each time the branch is executed, causing in total a minor speed penality.&lt;br /&gt;
&lt;br /&gt;
This doesn&#039;t work for every opcode, though. Opcodes such as &amp;lt;code&amp;gt;ADD #x&amp;lt;/code&amp;gt; (which is internally prefixed with [[ALT2]]), &amp;lt;code&amp;gt;WITH&amp;lt;/code&amp;gt; (register prefixes which change which register is the source or destination), &amp;lt;code&amp;gt;BRA $10&amp;lt;/code&amp;gt; (branches which always use two bytes) and &amp;lt;code&amp;gt;IWT&amp;lt;/code&amp;gt; (immediate value transfers which use two or three bytes) can only be used as a dummy opcode in very specific circumstances. The latter two can even misalign the program counter not unlike executing &amp;lt;code&amp;gt;LDA #$12&amp;lt;/code&amp;gt; when A is in 16-bit mode on the 65816. The following example demonstrates it:&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;BCC SkipCode&lt;br /&gt;
BRA Error       ; Caution!&lt;br /&gt;
...&lt;br /&gt;
SkipCode:&lt;br /&gt;
...&lt;br /&gt;
Error:&lt;br /&gt;
INC R1          ; Will instead be read with the BRA as &amp;quot;BRA $D1&amp;quot;.&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
In addition, the dummy opcode after a &amp;lt;code&amp;gt;STOP&amp;lt;/code&amp;gt; &#039;&#039;&#039;must&#039;&#039;&#039; be a &amp;lt;code&amp;gt;NOP&amp;lt;/code&amp;gt; because putting the GSU in WAIT will not clear the opcode in the pipeline. Extra care should be taken when pipeliend code is executed and a &amp;lt;code&amp;gt;STOP&amp;lt;/code&amp;gt; is located at $XXXF in cache as the pipelined code may be located in unused cache and a value in ROM/RAM will be loaded instead.&lt;br /&gt;
&lt;br /&gt;
== Bus Conflicts ==&lt;br /&gt;
&lt;br /&gt;
== Bitmap Processing ==&lt;br /&gt;
&lt;br /&gt;
[[Category:SNES_Hardware]]&lt;br /&gt;
[[Category:Integrated Circuits]]&lt;br /&gt;
[[Category:Enhancement Chips]]&lt;/div&gt;</summary>
		<author><name>MarioFanGamer</name></author>
	</entry>
	<entry>
		<id>https://sneslab.net/mw/index.php?title=DIV2_(Super_FX)&amp;diff=3450</id>
		<title>DIV2 (Super FX)</title>
		<link rel="alternate" type="text/html" href="https://sneslab.net/mw/index.php?title=DIV2_(Super_FX)&amp;diff=3450"/>
		<updated>2023-05-05T14:43:14Z</updated>

		<summary type="html">&lt;p&gt;MarioFanGamer: Added links to other bitshift operators, explanation to most significant bit and differenciation to ASR.&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&#039;&#039;&#039;DIV2&#039;&#039;&#039; (DIVide by 2)  is a [[Super FX]] instruction that shifts a register&#039;s bits one place to the right while also leaving the most significant bit unchanged. Unlike [[ASR]], the output becomes zero if the input is 0xFFFF.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;float:right;clear:right;width:30%&amp;quot;&lt;br /&gt;
!colspan=&amp;quot;9&amp;quot;|Flags Clobbered&lt;br /&gt;
|+&lt;br /&gt;
|B&lt;br /&gt;
|ALT1&lt;br /&gt;
|ALT2&lt;br /&gt;
|O/V&lt;br /&gt;
|S&lt;br /&gt;
|CY&lt;br /&gt;
|Z&lt;br /&gt;
|+&lt;br /&gt;
|0&lt;br /&gt;
|0&lt;br /&gt;
|0&lt;br /&gt;
|.&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== See Also ===&lt;br /&gt;
* [[ASL]]&lt;br /&gt;
* [[ASR]]&lt;br /&gt;
* [[LSR]]&lt;br /&gt;
&lt;br /&gt;
[[Category:ASM]]&lt;br /&gt;
[[Category:Enhancement Chips]]&lt;/div&gt;</summary>
		<author><name>MarioFanGamer</name></author>
	</entry>
	<entry>
		<id>https://sneslab.net/mw/index.php?title=ASR_(Super_FX)&amp;diff=3448</id>
		<title>ASR (Super FX)</title>
		<link rel="alternate" type="text/html" href="https://sneslab.net/mw/index.php?title=ASR_(Super_FX)&amp;diff=3448"/>
		<updated>2023-05-05T14:40:10Z</updated>

		<summary type="html">&lt;p&gt;MarioFanGamer: Added link to similar DIV2 as well as explanation to most significant.&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&#039;&#039;&#039;ASR&#039;&#039;&#039; (Arithmetic Shift Right) is a [[Super FX]] instruction that shifts all bits to the right while also leaving the most significant bit unchanged.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;float:right;clear:right;width:30%&amp;quot;&lt;br /&gt;
!colspan=&amp;quot;9&amp;quot;|Flags Clobbered&lt;br /&gt;
|+&lt;br /&gt;
|B&lt;br /&gt;
|ALT1&lt;br /&gt;
|ALT2&lt;br /&gt;
|O/V&lt;br /&gt;
|S&lt;br /&gt;
|CY&lt;br /&gt;
|Z&lt;br /&gt;
|+&lt;br /&gt;
|0&lt;br /&gt;
|0&lt;br /&gt;
|0&lt;br /&gt;
|.&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== See Also ===&lt;br /&gt;
* [[ASL]]&lt;br /&gt;
* [[LSR]]&lt;br /&gt;
* [[DIV2]]&lt;br /&gt;
&lt;br /&gt;
[[Category:ASM]]&lt;br /&gt;
[[Category:Enhancement Chips]]&lt;/div&gt;</summary>
		<author><name>MarioFanGamer</name></author>
	</entry>
	<entry>
		<id>https://sneslab.net/mw/index.php?title=Yoshi%27s_Island&amp;diff=2578</id>
		<title>Yoshi&#039;s Island</title>
		<link rel="alternate" type="text/html" href="https://sneslab.net/mw/index.php?title=Yoshi%27s_Island&amp;diff=2578"/>
		<updated>2023-04-27T07:14:19Z</updated>

		<summary type="html">&lt;p&gt;MarioFanGamer: Fixed redirection.&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;#REDIRECT [[Super Mario World 2: Yoshi&#039;s Island]]&lt;/div&gt;</summary>
		<author><name>MarioFanGamer</name></author>
	</entry>
	<entry>
		<id>https://sneslab.net/mw/index.php?title=Super_Metroid&amp;diff=2574</id>
		<title>Super Metroid</title>
		<link rel="alternate" type="text/html" href="https://sneslab.net/mw/index.php?title=Super_Metroid&amp;diff=2574"/>
		<updated>2023-04-27T07:01:26Z</updated>

		<summary type="html">&lt;p&gt;MarioFanGamer: Created page.&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Super Metroid, also known as Metroid 3, is the third enty of the Metroid series, being famously known for codifying the Metroidvania genre (alongside Castlevania: Symphony of the Night).&lt;br /&gt;
&lt;br /&gt;
[[Category:Games]]&lt;/div&gt;</summary>
		<author><name>MarioFanGamer</name></author>
	</entry>
	<entry>
		<id>https://sneslab.net/mw/index.php?title=Final_Fantasy_Mystic_Quest&amp;diff=2571</id>
		<title>Final Fantasy Mystic Quest</title>
		<link rel="alternate" type="text/html" href="https://sneslab.net/mw/index.php?title=Final_Fantasy_Mystic_Quest&amp;diff=2571"/>
		<updated>2023-04-27T06:53:42Z</updated>

		<summary type="html">&lt;p&gt;MarioFanGamer: Added category.&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&#039;&#039;&#039;Final Fantasy Mystic Quest&#039;&#039;&#039; is a JRPG developed by Square.&lt;br /&gt;
&lt;br /&gt;
== Easter Eggs ==&lt;br /&gt;
&lt;br /&gt;
FFMQ provides a convenient way to discover your SNES&#039; chip revisions.  When in the pause menu, press Start and Select simultaneously, and the revisions for the CPU, PPU1, and PPU2 will be displayed.&lt;br /&gt;
&lt;br /&gt;
[[File:FFMQ chipset.png|thumb|Pause menu displaying some of the SNES chipset]]&lt;br /&gt;
&lt;br /&gt;
[[Category:Games]]&lt;/div&gt;</summary>
		<author><name>MarioFanGamer</name></author>
	</entry>
	<entry>
		<id>https://sneslab.net/mw/index.php?title=Seiken_Densetsu_3&amp;diff=2570</id>
		<title>Seiken Densetsu 3</title>
		<link rel="alternate" type="text/html" href="https://sneslab.net/mw/index.php?title=Seiken_Densetsu_3&amp;diff=2570"/>
		<updated>2023-04-27T06:53:06Z</updated>

		<summary type="html">&lt;p&gt;MarioFanGamer: Added category.&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&#039;&#039;Seiken Densetsu 3&#039;&#039; is a 1995 JRPG developed by Squaresoft.&lt;br /&gt;
&lt;br /&gt;
It was fan-translated into English by Neill Corlett, and later received an offical English translation.&lt;br /&gt;
&lt;br /&gt;
[[Category:Games]]&lt;/div&gt;</summary>
		<author><name>MarioFanGamer</name></author>
	</entry>
	<entry>
		<id>https://sneslab.net/mw/index.php?title=F-Zero&amp;diff=2569</id>
		<title>F-Zero</title>
		<link rel="alternate" type="text/html" href="https://sneslab.net/mw/index.php?title=F-Zero&amp;diff=2569"/>
		<updated>2023-04-27T06:52:37Z</updated>

		<summary type="html">&lt;p&gt;MarioFanGamer: Added category.&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&#039;&#039;&#039;F-Zero&#039;&#039;&#039; is a racing game.&lt;br /&gt;
&lt;br /&gt;
[[Category:Games]]&lt;/div&gt;</summary>
		<author><name>MarioFanGamer</name></author>
	</entry>
	<entry>
		<id>https://sneslab.net/mw/index.php?title=The_Legend_of_Zelda:_A_Link_to_the_Past&amp;diff=2568</id>
		<title>The Legend of Zelda: A Link to the Past</title>
		<link rel="alternate" type="text/html" href="https://sneslab.net/mw/index.php?title=The_Legend_of_Zelda:_A_Link_to_the_Past&amp;diff=2568"/>
		<updated>2023-04-27T06:51:35Z</updated>

		<summary type="html">&lt;p&gt;MarioFanGamer: Added category.&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&#039;&#039;The Legend of Zelda: A Link to the Past&#039;&#039; is the third entry in the Zelda series.  It returned gameplay to an overhead perspective.&lt;br /&gt;
&lt;br /&gt;
[[Category:Games]]&lt;/div&gt;</summary>
		<author><name>MarioFanGamer</name></author>
	</entry>
	<entry>
		<id>https://sneslab.net/mw/index.php?title=Category:Compression_Formats&amp;diff=2319</id>
		<title>Category:Compression Formats</title>
		<link rel="alternate" type="text/html" href="https://sneslab.net/mw/index.php?title=Category:Compression_Formats&amp;diff=2319"/>
		<updated>2023-03-24T19:53:18Z</updated>

		<summary type="html">&lt;p&gt;MarioFanGamer: Create category.&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Informations about common compression formats used on the SNES.&lt;/div&gt;</summary>
		<author><name>MarioFanGamer</name></author>
	</entry>
	<entry>
		<id>https://sneslab.net/mw/index.php?title=Super_FX&amp;diff=2318</id>
		<title>Super FX</title>
		<link rel="alternate" type="text/html" href="https://sneslab.net/mw/index.php?title=Super_FX&amp;diff=2318"/>
		<updated>2023-03-24T19:52:03Z</updated>

		<summary type="html">&lt;p&gt;MarioFanGamer: Added category.&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&#039;&#039;&#039;Super FX&#039;&#039;&#039; is a [[Super NES]] [[enhancement chip]] developed by [https://en.wikipedia.org/wiki/Argonaut_Games Argonaut Games] and [http://en.wikipedia.org/wiki/Nintendo Nintendo]. It&#039;s also known as the &amp;quot;Graphical Support Unit&amp;quot; (short for &amp;quot;GSU&amp;quot;) for its greater graphical capabilities compared to the S-CPU whereas its first revision, used for [[Star Fox]], uses the name &amp;quot;Mathematical, Argonaut, Rotation, &amp;amp; Input/Output&amp;quot; or short MARIO chip. It also is know for the use in [[Super Mario World 2: Yoshi&#039;s Island]].&lt;br /&gt;
&lt;br /&gt;
During this article, GSU refers to Super FX whereas CPU refers to the Super NES CPU.&lt;br /&gt;
&lt;br /&gt;
== Features ==&lt;br /&gt;
The embedded co-processor has got a base clock speed of &#039;&#039;&#039;10.74 MHz&#039;&#039;&#039; which is four times as fast as the S-CPU which uses a base block of 2.68 Mhz. Its features includes but not limited to:&lt;br /&gt;
* A RISC-like processor where most opcodes have an instruction size of one byte and are executed in a single cycle when in cache.&lt;br /&gt;
* 512 bytes of cache RAM for faster processing of instructions.&lt;br /&gt;
* A large memory capactiy, a total capacity of 8 MiB ROM, of which two MiB are shared by CPU and GSU, and 256 KiB RAM, of which 128 KiB are shared by CPU and GSU.&lt;br /&gt;
* A separate bus for ROM and RAM to handle memory in parallel&lt;br /&gt;
* Paralell processing with the CPU&lt;br /&gt;
* Fast Bitmap to Planar conversion&lt;br /&gt;
* Pipeline processing to fetch opcodes twice as fast, effectively increasing the processing speed to 21.48 MHz.&lt;br /&gt;
&lt;br /&gt;
= Technical Information =&lt;br /&gt;
&lt;br /&gt;
== Hardware Registers ==&lt;br /&gt;
&lt;br /&gt;
Super FX comes with various hardware registers of various functions. Most (but not all) of the GSU hardware registers can be accessed from the CPU when the GSU is idling. They are located in the $3000-$3FFF region in banks $00-$3F and $80-$BF.&lt;br /&gt;
&lt;br /&gt;
=== General Registers (R0-R13) ===&lt;br /&gt;
&lt;br /&gt;
These registers are more or less equivalent to the A, X and Y registers on the [[65c816]]. They all are parameters to many opcodes, though not all of them are valid (e.g. R0 can&#039;t be a parameter for the logical operators), and are all 16-bit. Some of them come with a secondary use for certain opcodes. The CPU can directly read from and write to these registers $3000-$301B.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+A list of their addresses and their secondary functions&lt;br /&gt;
|-&lt;br /&gt;
! Name !! Address !! Secondary Function&lt;br /&gt;
|-&lt;br /&gt;
|  R0  ||  $3000  || Default source/destination register.&lt;br /&gt;
|-&lt;br /&gt;
|  R1  ||  $3002  || &amp;lt;code&amp;gt;PLOT&amp;lt;/code&amp;gt; X position&lt;br /&gt;
|-&lt;br /&gt;
|  R2  ||  $3004  || &amp;lt;code&amp;gt;PLOT&amp;lt;/code&amp;gt; Y position&lt;br /&gt;
|-&lt;br /&gt;
|  R3  ||  $3006  ||&lt;br /&gt;
|-&lt;br /&gt;
|  R4  ||  $3008  || Low word for &amp;lt;code&amp;gt;LMULT&amp;lt;/code&amp;gt; result&lt;br /&gt;
|-&lt;br /&gt;
|  R5  ||  $300A  ||&lt;br /&gt;
|-&lt;br /&gt;
|  R6  ||  $300C  || Second input for &amp;lt;code&amp;gt;LMULT&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;FMULT&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|  R7  ||  $300E  || &amp;lt;code&amp;gt;MERGE&amp;lt;/code&amp;gt; source 1&lt;br /&gt;
|-&lt;br /&gt;
|  R8  ||  $3010  || &amp;lt;code&amp;gt;MERGE&amp;lt;/code&amp;gt; source 2&lt;br /&gt;
|-&lt;br /&gt;
|  R9  ||  $3012  ||&lt;br /&gt;
|-&lt;br /&gt;
|  R10 ||  $3014  ||&lt;br /&gt;
|-&lt;br /&gt;
|  R11 ||  $3016  || &amp;lt;code&amp;gt;LINK&amp;lt;/code&amp;gt; destination&lt;br /&gt;
|-&lt;br /&gt;
|  R12 ||  $3018  || &amp;lt;code&amp;gt;LOOP&amp;lt;/code&amp;gt; counter&lt;br /&gt;
|-&lt;br /&gt;
|  R13 ||  $301A  || &amp;lt;code&amp;gt;LOOP&amp;lt;/code&amp;gt; start&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Game Pak ROM Address Pointer (R14) ===&lt;br /&gt;
&lt;br /&gt;
R14 is the ROM Pointer register and is mapped to $301C-$301D on the SNES. It&#039;s the pointer for the &amp;lt;code&amp;gt;GETB&amp;lt;/code&amp;gt; opcodes which allows the GSU to read from ROM.&lt;br /&gt;
It otherwise acts like any normal general register and is sometimes used as such.&lt;br /&gt;
&lt;br /&gt;
=== Program Counter (R15) ===&lt;br /&gt;
&lt;br /&gt;
R15 is the program counter and is mapped to $301E-$301F on the SNES. Unlike on the [[65c816]] processor, the program counter (excluding the bank) can be directly read or modified within code&lt;br /&gt;
as it acts like a general register. This makes it possible to e.g. jump to a certain address without the use of a dedicated opcode.&lt;br /&gt;
For example, &amp;lt;code&amp;gt;IWT R15, #xxxx&amp;lt;/code&amp;gt; on Super FX is equivalent to &amp;lt;code&amp;gt;JMP $xxxx&amp;lt;/code&amp;gt; on the 65c816.&lt;br /&gt;
&lt;br /&gt;
In addition, writing to $301E on the CPU side invokes the GSU.&lt;br /&gt;
&lt;br /&gt;
=== Status/Flag Register (SFR) ===&lt;br /&gt;
&lt;br /&gt;
Super FX comes with a 16-bit register of various flags, mostly from calculations (e.g. a carry flag) but also other flags like whether Super FX is currently running.&lt;br /&gt;
They can be read and written through $3030 and $3031.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+Status/Flag Register bitwise&lt;br /&gt;
!       !! B7  !! B6 !! B5 !! B4 !! B3 !! B2 !!  B1  !!  B0&lt;br /&gt;
|-&lt;br /&gt;
| $3031 || IRQ || -  || -  || B  || IH || IL || ALT1 || ALT2&lt;br /&gt;
|-&lt;br /&gt;
| $3030 ||  -  || R  || G  || OV || S  || CY ||  Z   ||  -&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+Description of Flags&lt;br /&gt;
|-&lt;br /&gt;
! Flag !! Description&lt;br /&gt;
|-&lt;br /&gt;
|  Z   || Zero flag, set when result is zero.&lt;br /&gt;
|-&lt;br /&gt;
|  CY  || Carry flag, set at result overflow (unsigned).&lt;br /&gt;
|-&lt;br /&gt;
|  S   || Sign flag, set when number is negative.&lt;br /&gt;
|-&lt;br /&gt;
|  OV  || Overflow flag, set at result overflow (signed).&lt;br /&gt;
|-&lt;br /&gt;
|  G   || Go flag, set when GSU is running.&lt;br /&gt;
|-&lt;br /&gt;
|  R   || Set when reading from ROM.&lt;br /&gt;
|-&lt;br /&gt;
| ALT1 || Opcode modifier 1, set when executing &amp;lt;code&amp;gt;ALT1&amp;lt;/code&amp;gt;.&lt;br /&gt;
|-&lt;br /&gt;
| ALT2 || Opcode modifier 2, set when executing &amp;lt;code&amp;gt;ALT2&amp;lt;/code&amp;gt;.&lt;br /&gt;
|-&lt;br /&gt;
|  IL  || Immediate lower 8-bit flag.&lt;br /&gt;
|-&lt;br /&gt;
|  IH  || Immediate higher 8-bit flag.&lt;br /&gt;
|-&lt;br /&gt;
|  B   || Set when executing &amp;lt;code&amp;gt;WITH&amp;lt;/code&amp;gt;.&lt;br /&gt;
|-&lt;br /&gt;
| IRQ  || Interrupt flag, set when GSU stopped.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Program Bank Register (PBR) ===&lt;br /&gt;
&lt;br /&gt;
The program bank is the bank where GSU code is executed. It&#039;s a readable and writable 8-bit register which is mapped to $3034 on the CPU side.&lt;br /&gt;
Unlike R15, this can only be modified indirectly using &amp;lt;code&amp;gt;LJMP&amp;lt;/code&amp;gt; on GSU side.&lt;br /&gt;
&lt;br /&gt;
=== Game Pak ROM Bank Register (ROMBR) ===&lt;br /&gt;
&lt;br /&gt;
This register controls the bank where ROM is read. It&#039;s set using the &amp;lt;code&amp;gt;ROMB&amp;lt;/code&amp;gt; on the GSU side.&lt;br /&gt;
It&#039;s a readable only 8-bit register which is mapped to $3036 on the CPU side.&lt;br /&gt;
&lt;br /&gt;
=== Game Pak RAM Bank Register (RAMBR) ===&lt;br /&gt;
&lt;br /&gt;
This register is the RAM equivalent to ROMBR. It&#039;s set using the &amp;lt;code&amp;gt;RAMB&amp;lt;/code&amp;gt; on the GSU side.&lt;br /&gt;
It&#039;s a readable only 1-bit register which is mapped to $303C on the CPU side.&lt;br /&gt;
&lt;br /&gt;
=== Cache Base Register (CBR) ===&lt;br /&gt;
&lt;br /&gt;
The Cache Base Register is the address where cache has been enabled through and tells the GSU where to run code in cache.&lt;br /&gt;
It&#039;s readable 16-bit register accessible through $303E and $303F from the CPU and written by the GSU with the &amp;lt;code&amp;gt;CACHE&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;LJMP&amp;lt;/code&amp;gt; opcodes.&lt;br /&gt;
The lowest four bits of this register are open bus since cache is stored in 16-byte blocks.&lt;br /&gt;
&lt;br /&gt;
=== Screen Base Register (SCBR) ===&lt;br /&gt;
&lt;br /&gt;
The Screen Base Register is the high byte of the image buffer i.e. the plotting destination.&lt;br /&gt;
It&#039;s a writeable 8-bit register mapped to $3038 on the CPU side.&lt;br /&gt;
&lt;br /&gt;
=== Screen Mode Register (SCMR) ===&lt;br /&gt;
&lt;br /&gt;
The Screen Mode Register contains the settings for the image buffer (dimensions, bitdepth) but also access to ROM and RAM.&lt;br /&gt;
It&#039;s a writeable 8-bit register mapped to $303A on the CPU side.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+Screen Mode Register bitwise&lt;br /&gt;
! B7 !! B6 !! B5  !! B4  !! B3  !! B2  !! B1  !! B0&lt;br /&gt;
|-&lt;br /&gt;
| -  || -  || HT1 || ROM || RAN || HT0 || MD1 || MD0&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The image buffer dimensions are given by HT0 and HT1. They all are 256 pixels wide but have different heights.&lt;br /&gt;
A special case exists when both bits are 1 which enables OBJ mode which is used to plot single sprites like in Yoshi&#039;s Island.&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+Screen Dimensions&lt;br /&gt;
|-&lt;br /&gt;
! HT1 !! H00 !! Mode&lt;br /&gt;
|-&lt;br /&gt;
|  0  ||  0  || 256 by 128&lt;br /&gt;
|-&lt;br /&gt;
|  0  ||  1  || 256 by 160&lt;br /&gt;
|-&lt;br /&gt;
|  1  ||  0  || 256 by 192&lt;br /&gt;
|-&lt;br /&gt;
|  1  ||  1  || OBJ mode&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The bitdepth of the image buffer is set by the MD0 and MD1 bits:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+Screen Mode&lt;br /&gt;
|-&lt;br /&gt;
! MD1 !! MD0 !! Mode&lt;br /&gt;
|-&lt;br /&gt;
|  0  ||  0  || 4-color mode (2bpp)&lt;br /&gt;
|-&lt;br /&gt;
|  0  ||  1  || 16-color mode (4bpp)&lt;br /&gt;
|-&lt;br /&gt;
|  1  ||  0  || Not used&lt;br /&gt;
|-&lt;br /&gt;
|  1  ||  1  || 256-color mode (8bpp)&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The SCMR register also controls whether Game Pak ROM and RAM can be accessed by the CPU or GSU:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+Screen Mode&lt;br /&gt;
|-&lt;br /&gt;
! Bit !! Description&lt;br /&gt;
|-&lt;br /&gt;
| RON || Gives ROM access to the CPU when 0 and GSU when 1.&lt;br /&gt;
|-&lt;br /&gt;
| RAN || Gives RAM access to the CPU when 0 and GSU when 1.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Color Register (COLR) ===&lt;br /&gt;
&lt;br /&gt;
The Color Register contains the colour for the pixel which is to be plotted.&lt;br /&gt;
It&#039;s an 8-bit register which is set using the &amp;lt;code&amp;gt;COLOR&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;GETC&amp;lt;/code&amp;gt; opcodes on the GSU. There is no access from the CPU.&lt;br /&gt;
&lt;br /&gt;
=== Plot Option Register (POR) ===&lt;br /&gt;
&lt;br /&gt;
The Color Register controls how the colours are loaded into the COLR register as well as .&lt;br /&gt;
It&#039;s an 8-bit register which is set using the &amp;lt;code&amp;gt;CMODE&amp;lt;/code&amp;gt; opcode on the GSU. There is no access from the CPU.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+Screen Mode Register bitwise&lt;br /&gt;
! B7 !! B6 !! B5 !! B4  !! B3 !! B2 !! B1 !! B0&lt;br /&gt;
|-&lt;br /&gt;
| -  || -  || -  || OBJ || FH || HN || DT || TP&lt;br /&gt;
|}&lt;br /&gt;
Note that these abbreviations are inofficial and have been included for simplification.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+Description of Screen Mode Register&lt;br /&gt;
|-&lt;br /&gt;
! Bit !! Description&lt;br /&gt;
|-&lt;br /&gt;
| OBJ || OBJ Flag&lt;br /&gt;
|-&lt;br /&gt;
| FH  || Freeze High Flag&lt;br /&gt;
|-&lt;br /&gt;
| HN  || High Nibble Flag&lt;br /&gt;
|-&lt;br /&gt;
| DT  || Dither Flag&lt;br /&gt;
|-&lt;br /&gt;
| TP  || Transparent Flag&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Backup RAM Register (BRAMR) ===&lt;br /&gt;
&lt;br /&gt;
This controls whether Back-up RAM (not to be confused with Game Pak RAM) becomes “protected”.&amp;lt;sup&amp;gt;1&amp;lt;/sup&amp;gt;&lt;br /&gt;
It&#039;s a 1-bit register mapped to bit 0 of $3033 which can be written by the CPU.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;sup&amp;gt;1&amp;lt;/sup&amp;gt;The definition of “protected” isn&#039;t very clear, though it can be assumed that Back-up RAM can&#039;t be written when it&#039;s set to be protected.&lt;br /&gt;
&lt;br /&gt;
=== Version Code Register (VCR) ===&lt;br /&gt;
&lt;br /&gt;
The Version Code Register contains the version code of the Super FX chip.&lt;br /&gt;
It&#039;s an 8-bit read-only register and accessed $303B on the CPU side.&lt;br /&gt;
&lt;br /&gt;
=== Config Register (CFGR) ===&lt;br /&gt;
&lt;br /&gt;
The Config Register contains two flags:&lt;br /&gt;
The IRQ flag which allows the GSU to fire an interrupt to the CPU should it stop and&lt;br /&gt;
the MS0 which controls the speed of the multiplication.&lt;br /&gt;
It&#039;s mapped to bit 0 of $3039 and is writeable from the CPU.&lt;br /&gt;
&lt;br /&gt;
=== Clock Select Register (CLSR) ===&lt;br /&gt;
&lt;br /&gt;
This register sets the clock speed of Super FX and enables pipelining in the process. When clear, Super FX runs at 10.74 MHz, when set, at 21.48 MHz.&lt;br /&gt;
It&#039;s mapped to bit 0 of $3039 and is writeable from the CPU.&lt;br /&gt;
&lt;br /&gt;
Supposedly, the CLSR and MS0 flags must not be set 1 at the same time but no side effects are known.&lt;br /&gt;
&lt;br /&gt;
== Memory and Bus ==&lt;br /&gt;
&lt;br /&gt;
=== Memory Map ===&lt;br /&gt;
One advantage of Super FX is that it naturally supports ROMs with a size of up to 8 MiB. However, Super FX can only use the first two MiB of a ROM. Similarly, even though a single cartridge may have up to 256 KiB of SRAM, only half of them can be used by Super FX. As a result, there is a difference between the CPU and GSU mapping.&lt;br /&gt;
&lt;br /&gt;
This is how the ROM is mapped from the perspective of the CPU:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
!  Banks  !!   Address   !! Description&lt;br /&gt;
|-&lt;br /&gt;
!rowspan=&amp;quot;6&amp;quot;|$00-$3F&lt;br /&gt;
          || $0000-$1FFF || WRAM mirror&lt;br /&gt;
|-&lt;br /&gt;
|           $2100-$21FF || PPU registers&lt;br /&gt;
|-&lt;br /&gt;
|           $3000-$3FFF || Super FX registers&lt;br /&gt;
|-&lt;br /&gt;
|           $4200-$43FF || CPU registers&lt;br /&gt;
|-&lt;br /&gt;
|           $6000-$7FFF || SRAM mirror&lt;br /&gt;
|-&lt;br /&gt;
|           $8000-$FFFF || ROM (LoROM)&lt;br /&gt;
|-&lt;br /&gt;
| $40-$5F || $0000-$FFFF || Mirror of ROM in banks $00-$3F (HiROM)&lt;br /&gt;
|-&lt;br /&gt;
| $60-$6F || $0000-$FFFF || Unmapped&lt;br /&gt;
|-&lt;br /&gt;
| $70-$71 || $0000-$FFFF || SRAM&lt;br /&gt;
|-&lt;br /&gt;
| $7C-$7D || $0000-$FFFF || Backup RAM&lt;br /&gt;
|-&lt;br /&gt;
| $7E-$7F || $0000-$FFFF || WRAM&lt;br /&gt;
|-&lt;br /&gt;
!rowspan=&amp;quot;6&amp;quot;|$80-$BF&lt;br /&gt;
          || $0000-$1FFF || WRAM mirror&lt;br /&gt;
|-&lt;br /&gt;
|           $2100-$21FF || PPU registers&lt;br /&gt;
|-&lt;br /&gt;
|           $3000-$3FFF || Super FX registers&lt;br /&gt;
|-&lt;br /&gt;
|           $4200-$43FF || CPU registers&lt;br /&gt;
|-&lt;br /&gt;
|           $6000-$7FFF || SRAM mirror&lt;br /&gt;
|-&lt;br /&gt;
|           $8000-$FFFF || ROM (LoROM)&lt;br /&gt;
|-&lt;br /&gt;
| $C0-$FF || $8000-$FFFF || ROM (HiROM)&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The GSU memory map looks similar to the CPU mapping but only with access to ROM and SRAM as well as only access to 2 MiB of ROM and 128 KiB of SRAM. As a result, it looks more like this:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
!  Banks  !!   Address   !! Description&lt;br /&gt;
|-&lt;br /&gt;
!rowspan=&amp;quot;2&amp;quot;|$00-$3F&lt;br /&gt;
          || $0000-$7FFF || Unmapped&lt;br /&gt;
|-&lt;br /&gt;
|            $8000-$FFFF || ROM (LoROM)&lt;br /&gt;
|-&lt;br /&gt;
| $40-$5F || $0000-$FFFF || Mirror of ROM in banks $00-$3F (HiROM)&lt;br /&gt;
|-&lt;br /&gt;
| $60-$6F || $0000-$FFFF || Unmapped&lt;br /&gt;
|-&lt;br /&gt;
| $70-$71 || $0000-$FFFF || SRAM&lt;br /&gt;
|-&lt;br /&gt;
| $72-$7F || $0000-$FFFF || Unmapped&lt;br /&gt;
|-&lt;br /&gt;
| $80-$FF || $0000-$FFFF || Mirror of $00-$7F&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Finally, it should be noted that banks $40-$5F are HiROM mirrors of the LoROM banks $00-$3F interlaced so addresses such as $008000 and $400000 contain the same value.&lt;br /&gt;
&lt;br /&gt;
=== ROM ===&lt;br /&gt;
ROM on Super FX can be up to 8 MiB large. However, even though the size is theoretically doable, the largest published Super FX games had a ROM size of 2 MiBs. As a result, not many emulators (not even BSNES as of 2021) emulate this feature properly and such ROM sizes only exist in homebrewing and modding.&lt;br /&gt;
&lt;br /&gt;
Super FX has also has got limitations with ROM access. This first example is the ROM size. Even though a Super FX ROM can be as large as 8 MiB (in theory), the GSU&#039;s data bus is only connected to 2 MiB of it. Said portion of ROM which the processor can access is called GamePak ROM while the additional 6 MiB, called the Super NES ROM, can only be accessed by the CPU.&lt;br /&gt;
A second limitation is the clock speed. The GSU is clocked very fast at 10,74 Mhz (which can be doubled with pipelining) but ROM is clocked at 3,58 Mhz (unlike on [[SA-1]] where ROM is clocked at the same frequence the coprocessor). As a result, all opcodes, when they are executed in ROM, take at least three cycles to process while reads from ROM are very slow.&lt;br /&gt;
&lt;br /&gt;
To counteract against this limitation, the GSU uses a buffering system. In order to load a value from ROM, the bank must first be set in ROMBR (set by &amp;lt;code&amp;gt;ROMB&amp;lt;/code&amp;gt; in the GSU code) while the address is set in register R14. Any write to R14 initiates the buffering process. The value then can be retrieved with &amp;lt;code&amp;gt;GETB&amp;lt;/code&amp;gt; and similar opcodes (referred to just &amp;lt;code&amp;gt;GETB&amp;lt;/code&amp;gt; from now on).&lt;br /&gt;
&lt;br /&gt;
The GSU doesn&#039;t wait during the process of fetching. As a result, it is possible to call &amp;lt;code&amp;gt;GETB&amp;lt;/code&amp;gt; some time after writing to R14. In fact, this is even recommend because calling &amp;lt;code&amp;gt;GETB&amp;lt;/code&amp;gt; during the process of fetching will cause the GSU to halt up five cycles for executing &amp;lt;code&amp;gt;GETB&amp;lt;/code&amp;gt;. Similarly, writing to &amp;lt;code&amp;gt;ROMB&amp;lt;/code&amp;gt; will halt the code as well until the data has been fetched enabling cache during the process of fetching will mess up the ROM value instead.&lt;br /&gt;
&lt;br /&gt;
=== RAM ===&lt;br /&gt;
&lt;br /&gt;
=== Cache ===&lt;br /&gt;
&lt;br /&gt;
In order to improve the speed of the processor, it includes a 512 byte large memory with the same frequency as the GSU as a cache. This allows Super FX to execute a single opcode with only a single cycle (i.e. three times as fast as in regular use). The cache is separated into 32 16-byte blocks, each with a flag which denotes that a block is used, and is indexed by the cache base register (CBR) which is used to keep track of where cache has been invoked. The cache flags and CBR are reset whenever a zero is written to the GO flag but simply halting or invoking the GSU preserves the content of the cache which in turn can be read by the CPU.&lt;br /&gt;
&lt;br /&gt;
Cache on the SNES is mapped to addresses $xx:3100-$xx:32FF ($xx = $00-$3F, $80-$BF), though the start of the cached code (see below) also is dependent on the CBR (start = $3100 + (CBR &amp;amp; 0x1FF)).&lt;br /&gt;
&lt;br /&gt;
There are two methods to fill the cache:&lt;br /&gt;
* Manual caching&lt;br /&gt;
* Automatic caching&lt;br /&gt;
&lt;br /&gt;
Manual caching involes using the CPU and transfer the code to cache. Keep in mind that Super FX will only execute the cache block which has been set to be used. That means, the code has to be transfered as a full 16 byte block, though strictly speaking, only the last byte of the block (address $XXXF) needs to be written to count the block as used.&lt;br /&gt;
In order to execute GSU code in cache, R15 has to be set to $0000-$01FF.&lt;br /&gt;
&lt;br /&gt;
Automatic caching is instead handled by the GSU itself. This is handled either by the dedicated &amp;lt;code&amp;gt;CACHE&amp;lt;/code&amp;gt; opcode or by a &amp;lt;code&amp;gt;LJMP&amp;lt;/code&amp;gt; opcode, the latter because of the lack of bank information for the cache. Both of them clear the cache flags and store the current PC with the lowest nibble masked out into the CBR (CBR = PC &amp;amp; 0xFFF0). Afterwards, each executed opcode will be written into cache starting from CBR &amp;amp; 0x1FF.&lt;br /&gt;
As a result, this use of cache is recommend for loops and the first loop will always run slower than the remaining loops. Should all the blocks be used, any remaining code will be left uncached and executed in the original memory.&lt;br /&gt;
&lt;br /&gt;
Another side effect is that cache is neither ROM nor GamePak RAM so any Super FX code in cache can run in parallel to the SNES even when access to ROM and RAM is given to the CPU instead of GSU.&lt;br /&gt;
&lt;br /&gt;
=== Pipeline Processing ===&lt;br /&gt;
&lt;br /&gt;
In order to boost the processing speed of the GSU, it uses a technique called &amp;quot;pipeline processing&amp;quot;. Pipelining exists to a lesser extend on the [[65c816]], where opcodes are prepared while the remaining bytes of the opcodes are fetched (this is notable on single byte opcodes such as &amp;lt;code&amp;gt;INC&amp;lt;/code&amp;gt; which take two cycles to process, the same amount of cycles as &amp;lt;code&amp;gt;LDA #$xx&amp;lt;/code&amp;gt;, a two byte opcode) but the GSU takes it further by fetching the next opcode during the current opcode&#039;s execution.&lt;br /&gt;
This runs the code double as fast, virtually increasing the clock speed to 21.48 MHz at the cost of adding more care of the coder whenever R15 — the programm counter — is changed, either through branching or through direct writes to R15. In addition, internal processes such as multiplication and memory access can&#039;t take advantage of the virtual increment in clock speed.&lt;br /&gt;
&lt;br /&gt;
Pipelining is controlled with bit 0 of CLSR, where clear means pipelining disabled and set means pipelining enabled. It&#039;s accessable on the CPU side with the address $3037.&lt;br /&gt;
&lt;br /&gt;
For the most part, having pipelining enabled doesn&#039;t change the code. The only exceptions are when R15 is modified outside of fetching opcodes i.e. the use of branches and writes to R15 (e.g. &amp;lt;code&amp;gt;IWT R15,#$8000&amp;lt;/code&amp;gt;) as well as halting the GSU such as with &amp;lt;code&amp;gt;STOP&amp;lt;/code&amp;gt;. In these cases, the opcode following that instruction will be executed after the branch. A common solution for the unwanted opcode execution is to put a dummy &amp;lt;code&amp;gt;NOP&amp;lt;/code&amp;gt; after the R15 modifying opcode such as in this example:&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;BCC SkipCode&lt;br /&gt;
NOP             ; Dummy NOP&lt;br /&gt;
...&lt;br /&gt;
SkipCode:&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This proves to be inefficient, though. Most Super FX opcodes are one byte larger and take 3 or 1 cycles (depending on whether the code is executed in cache or not) to execute including &amp;lt;code&amp;gt;NOP&amp;lt;/code&amp;gt;. As a result, opcodes such as &amp;lt;code&amp;gt;SUB R0&amp;lt;/code&amp;gt; can be put as a dummy opcode in place of &amp;lt;code&amp;gt;NOP&amp;lt;/code&amp;gt;. The following example demonstrates it:&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;BCC SkipCode&lt;br /&gt;
;NOP            ; Redundant&lt;br /&gt;
SUB R0          ; Set R0 to zero&lt;br /&gt;
STW (R1)&lt;br /&gt;
SkipCode:&lt;br /&gt;
IWT R0,#$1234&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
In the above code, R0 gets overwritten by &amp;lt;code&amp;gt;SUB&amp;lt;/code&amp;gt; no matter whether the branch is taken. However, it later gets overwritten by &amp;lt;code&amp;gt;IWT&amp;lt;/code&amp;gt;. As a result, it doesn&#039;t matter whether the dummy opcode is a &amp;lt;code&amp;gt;NOP&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;SUB&amp;lt;/code&amp;gt; from the branch for the calculation. In fact, using a &amp;lt;code&amp;gt;NOP&amp;lt;/code&amp;gt; increases the code size by one byte which can matter when the code is executed in cache as well as increase the cycle count by 1 or 3 cycles each time the branch is executed, causing in total a minor speed penality.&lt;br /&gt;
&lt;br /&gt;
This doesn&#039;t work for every opcode, though. Opcodes such as &amp;lt;code&amp;gt;ADD #x&amp;lt;/code&amp;gt; (which is internally prefixed with &amp;lt;code&amp;gt;ALT2&amp;lt;/code&amp;gt;), &amp;lt;code&amp;gt;WITH&amp;lt;/code&amp;gt; (register prefixes which change which register is the source or destination), &amp;lt;code&amp;gt;BRA $10&amp;lt;/code&amp;gt; (branches which always use two bytes) and &amp;lt;code&amp;gt;IWT&amp;lt;/code&amp;gt; (immediate value transfers which use two or three bytes) can only be used as a dummy opcode in very specific circumstances. The latter two can even misalign the program counter not unlike executing &amp;lt;code&amp;gt;LDA #$12&amp;lt;/code&amp;gt; when A is in 16-bit mode on the 65816. The following example demonstrates it:&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;BCC SkipCode&lt;br /&gt;
BRA Error       ; Caution!&lt;br /&gt;
...&lt;br /&gt;
SkipCode:&lt;br /&gt;
...&lt;br /&gt;
Error:&lt;br /&gt;
INC R1          ; Will instead be read with the BRA as &amp;quot;BRA $D1&amp;quot;.&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
In addition, the dummy opcode after a &amp;lt;code&amp;gt;STOP&amp;lt;/code&amp;gt; &#039;&#039;&#039;must&#039;&#039;&#039; be a &amp;lt;code&amp;gt;NOP&amp;lt;/code&amp;gt; because putting the GSU in WAIT will not clear the opcode in the pipeline. Extra care should be taken when pipeliend code is executed and a &amp;lt;code&amp;gt;STOP&amp;lt;/code&amp;gt; is located at $XXXF in cache as the pipelined code may be located in unused cache and a value in RAM will be loaded instead.&lt;br /&gt;
&lt;br /&gt;
== Bus Conflicts ==&lt;br /&gt;
&lt;br /&gt;
== Bitmap Processing ==&lt;br /&gt;
&lt;br /&gt;
[[Category:SNES_Hardware]]&lt;/div&gt;</summary>
		<author><name>MarioFanGamer</name></author>
	</entry>
	<entry>
		<id>https://sneslab.net/mw/index.php?title=LZ5&amp;diff=2317</id>
		<title>LZ5</title>
		<link rel="alternate" type="text/html" href="https://sneslab.net/mw/index.php?title=LZ5&amp;diff=2317"/>
		<updated>2023-03-24T19:50:49Z</updated>

		<summary type="html">&lt;p&gt;MarioFanGamer: Added category.&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;LZ5 or LC_LZ5, as named by Lunar Compress, is a lossless data compression format, used by [[Super Mario Kart]] to compress graphics and other data. The LZ5 compression format is a slight enhancement of the [[LZ2]] compression format, due to new commands.&lt;br /&gt;
&lt;br /&gt;
== Compression ==&lt;br /&gt;
&lt;br /&gt;
The compressed data consists of &amp;quot;chunks&amp;quot;, each with a header:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
bits&lt;br /&gt;
76543210&lt;br /&gt;
CCCLLLLL&lt;br /&gt;
CCC:   Command bits&lt;br /&gt;
LLLLL: Length&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If the header byte is $FF, the end of the compressed data has been reached, and decompression will be aborted.&lt;br /&gt;
&lt;br /&gt;
The commands mostly remain their LC_LZ2 commands. However, there are new commands too. Here is a list of commands bits which the LC_LZ5 decompression function can use during the decompression:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
000    &amp;quot;Direct Copy&amp;quot;&lt;br /&gt;
       Followed by (L+1) bytes of data&lt;br /&gt;
001    &amp;quot;Byte Fill&amp;quot;&lt;br /&gt;
       Followed by one byte to be repeated (L+1) times&lt;br /&gt;
010    &amp;quot;Word Fill&amp;quot;&lt;br /&gt;
       Followed by two bytes. Output first byte, then second, then first,&lt;br /&gt;
       then second, etc. until (L+1) bytes has been outputted&lt;br /&gt;
011    &amp;quot;Increasing Fill&amp;quot;&lt;br /&gt;
       Followed by one byte to be repeated (L+1) times, but the byte is&lt;br /&gt;
       increased by 1 after each write&lt;br /&gt;
100    &amp;quot;Repeat&amp;quot;&lt;br /&gt;
       Followed by a word (little-endian) containing address relative &lt;br /&gt;
       to the output buffer&#039;s first byte to copy (L+1) bytes from.&lt;br /&gt;
       Basically it&#039;s this math: (Output buffer offset + word value)&lt;br /&gt;
101    &amp;quot;XOR Repeat&amp;quot;&lt;br /&gt;
       Same concept as above, except all the copied bytes are getting&lt;br /&gt;
       XOR&#039;d by the value $FF.&lt;br /&gt;
110    &amp;quot;Negative Repeat&amp;quot;, followed by a byte subtracted by the CURRENT index&lt;br /&gt;
       to the output buffer, to copy (L+1) bytes from.&lt;br /&gt;
       Basically it&#039;s this math: (Output buffer offset&#039;s index - byte value)&lt;br /&gt;
111    &amp;quot;Long length&amp;quot;&lt;br /&gt;
       This command has got a two-byte header:&lt;br /&gt;
       111CCCLL LLLLLLLL&lt;br /&gt;
       CCC:        Real command&lt;br /&gt;
       LLLLLLLLLL: Length&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Long Length-exclusive command&lt;br /&gt;
111    &amp;quot;Negative XOR repeat&amp;quot;&lt;br /&gt;
       Same concept as &amp;quot;Negative Repeat&amp;quot;, except all the copied bytes&lt;br /&gt;
       are getting XOR&#039;d by the value $FF.&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Seeing that the long length command uses ten bits for its length, the maximum length is 1024 bytes/1kB, while the normal length is 32 bytes.&lt;br /&gt;
&lt;br /&gt;
== Decompression ==&lt;br /&gt;
&lt;br /&gt;
During the decompression, the decompressed chunks are outputted into a buffer which is either [[RAM]] or [[SRAM]].&lt;br /&gt;
&lt;br /&gt;
== Usage ==&lt;br /&gt;
&lt;br /&gt;
You can use the LZ5 compression to mainly compress graphics and data. Technically you can compress anything with this format.&lt;br /&gt;
&lt;br /&gt;
[[Category:Compression Formats]]&lt;/div&gt;</summary>
		<author><name>MarioFanGamer</name></author>
	</entry>
	<entry>
		<id>https://sneslab.net/mw/index.php?title=LC_LZ2&amp;diff=2316</id>
		<title>LC LZ2</title>
		<link rel="alternate" type="text/html" href="https://sneslab.net/mw/index.php?title=LC_LZ2&amp;diff=2316"/>
		<updated>2023-03-24T19:50:21Z</updated>

		<summary type="html">&lt;p&gt;MarioFanGamer: Added category.&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{DISPLAYTITLE:LC_LZ2}}&lt;br /&gt;
LZ2 or LC_LZ2, as named by [[Lunar Compress]], is a lossless data compression format, used by [[Super Mario World]] to compress graphics. It is also used by [[Super Mario World 2: Yoshi&#039;s Island]].&lt;br /&gt;
&lt;br /&gt;
== Compression ==&lt;br /&gt;
&lt;br /&gt;
The compressed data consists of &amp;quot;chunks&amp;quot;, each with a header:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
bits&lt;br /&gt;
76543210&lt;br /&gt;
CCCLLLLL&lt;br /&gt;
&lt;br /&gt;
CCC:   Command bits&lt;br /&gt;
LLLLL: Length&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If the header byte is $FF, the end of the compressed data has been reached, and decompression will be aborted.&lt;br /&gt;
&lt;br /&gt;
Here is a list of commands bits which the LC_LZ2 decompression function can use during the decompression:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
000    &amp;quot;Direct Copy&amp;quot;&lt;br /&gt;
       Followed by (L+1) bytes of data&lt;br /&gt;
001    &amp;quot;Byte Fill&amp;quot;&lt;br /&gt;
       Followed by one byte to be repeated (L+1) times&lt;br /&gt;
010    &amp;quot;Word Fill&amp;quot;&lt;br /&gt;
       Followed by two bytes. Output first byte, then second, then first,&lt;br /&gt;
       then second, etc. until (L+1) bytes has been outputted&lt;br /&gt;
011    &amp;quot;Increasing Fill&amp;quot;&lt;br /&gt;
       Followed by one byte to be repeated (L+1) times, but the byte is&lt;br /&gt;
       increased by 1 after each write&lt;br /&gt;
100    &amp;quot;Repeat&amp;quot;&lt;br /&gt;
       Followed by two bytes (big endian byte order) containing address (in the&lt;br /&gt;
       output buffer) to copy (L+1) bytes from&lt;br /&gt;
101    (Unused command)&lt;br /&gt;
110    (Unused command)&lt;br /&gt;
111    &amp;quot;Long length&amp;quot;&lt;br /&gt;
       This command has got a two-byte header:&lt;br /&gt;
       111CCCLL LLLLLLLL&lt;br /&gt;
       CCC:        Real command&lt;br /&gt;
       LLLLLLLLLL: Length&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Decompression ==&lt;br /&gt;
&lt;br /&gt;
During the decompression, the decompressed chunks are outputted into a buffer which is either RAM or SRAM. SMW uses the RAM address $7E:AD00 as its decompression buffer.&lt;br /&gt;
&lt;br /&gt;
== Usage ==&lt;br /&gt;
&lt;br /&gt;
You can use the LC_LZ2 compression to mainly compress graphics. Technically you can compress anything with this format, but graphics is preferred due to their big size. Seeing the SNES isn&#039;t fast, the decompression takes a while to finish, so whenever you overuse the compression the loading time will increase.&lt;br /&gt;
&lt;br /&gt;
== Other ==&lt;br /&gt;
&lt;br /&gt;
You can see an LC_LZ2 decompression routine setup at SNES $00:B888. The decompression routine itself is located at SNES $00:B8DE.&lt;br /&gt;
&lt;br /&gt;
== External links ==&lt;br /&gt;
&lt;br /&gt;
[https://fusoya.eludevisibility.org/lc/index.html Lunar Compress], a library by [[FuSoYa]] made to handle loading various game graphics format, including LZ2.&lt;br /&gt;
&lt;br /&gt;
[[Category:Compression Formats]]&lt;/div&gt;</summary>
		<author><name>MarioFanGamer</name></author>
	</entry>
	<entry>
		<id>https://sneslab.net/mw/index.php?title=RLE2&amp;diff=2315</id>
		<title>RLE2</title>
		<link rel="alternate" type="text/html" href="https://sneslab.net/mw/index.php?title=RLE2&amp;diff=2315"/>
		<updated>2023-03-24T19:50:04Z</updated>

		<summary type="html">&lt;p&gt;MarioFanGamer: Added category.&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;RLE2 or LC_RLE2, as named by [[Lunar Compress]], is a lossless data compression format, used by [[Super Mario World]] to compress the entire overworld layer 2 tilemap.&lt;br /&gt;
&lt;br /&gt;
== Compression ==&lt;br /&gt;
&lt;br /&gt;
The compression is a simple run-length encoding format. However, this one is two-dimensional, which means the decompressed data gets stored every other byte in the output buffer unlike LC_RLE1. Therefore, the decompression routine needs to be run entirely two times. Also, there are two compressed tables.&lt;br /&gt;
&lt;br /&gt;
The compressed data consists of &amp;quot;chunks&amp;quot;, each with a header:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
bits&lt;br /&gt;
76543210&lt;br /&gt;
CLLLLLLL&lt;br /&gt;
C:       Command bit&lt;br /&gt;
LLLLLLL: Length&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Here&#039;s a list of the command bit values the LC_RLE2 routine can use during decompression:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
0    &amp;quot;Direct Copy&amp;quot;&lt;br /&gt;
     Followed by (L+1) bytes of data&lt;br /&gt;
1    &amp;quot;RLE&amp;quot;&lt;br /&gt;
     Followed by one byte to be repeated (L+1) times&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
There is no byte which marks the end of the compressed data. You have to specify the length of the original, decompressed data so the decompression goes without any problems.&lt;br /&gt;
&lt;br /&gt;
== Two tables and decompression ==&lt;br /&gt;
&lt;br /&gt;
The decompressed data gets written to the output buffer every other byte. This means that the bytes are stored as [XX] [YY] [XX] [YY] [XX] [YY] [..]. The XX bytes are from table 1, the YY bytes are from table 2. Technically, when the compressed data is read, the index to the compressed data increases by one, while the index to the output buffer increases by two, which causes this effect. The tables&#039; original decompressed length should be half of the original, decompressed data altogether. So if you specify the length as $4000 bytes, table 1&#039;s output should be $2000 bytes, and table 2&#039;s output should be $2000 bytes too.&lt;br /&gt;
&lt;br /&gt;
== Usage ==&lt;br /&gt;
&lt;br /&gt;
You can use the LC_RLE2 compression to mainly compress raw [[VRAM]] tilemap. Technically you can compress anything with this format, but raw VRAM tilemaps are preferred due to the often-occuring repeating every-other bytes.&lt;br /&gt;
&lt;br /&gt;
== Other ==&lt;br /&gt;
&lt;br /&gt;
You can see an LC_RLE2 decompression routine setup at SNES $04:DC6F (SMW). The decompression routine itself is located at SNES $04:DABA. The decompression routine does not support data which crosses bank boundaries. Therefore, you will have to take care of that.&lt;br /&gt;
&lt;br /&gt;
[[Category:Compression Formats]]&lt;/div&gt;</summary>
		<author><name>MarioFanGamer</name></author>
	</entry>
	<entry>
		<id>https://sneslab.net/mw/index.php?title=LZ3&amp;diff=2314</id>
		<title>LZ3</title>
		<link rel="alternate" type="text/html" href="https://sneslab.net/mw/index.php?title=LZ3&amp;diff=2314"/>
		<updated>2023-03-24T19:49:49Z</updated>

		<summary type="html">&lt;p&gt;MarioFanGamer: Added category.&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;LZ3 or LC_LZ3, as named by Lunar Compress, is a lossless data compression format, used by Pokemon Gold/Silver to compress graphics and other data. The LZ3 compression format is similar the [[LZ2]] compression format.&lt;br /&gt;
&lt;br /&gt;
== Compression ==&lt;br /&gt;
&lt;br /&gt;
The compressed data consists of &amp;quot;chunks&amp;quot;, each with a header:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
bits&lt;br /&gt;
76543210&lt;br /&gt;
CCCLLLLL&lt;br /&gt;
CCC:   Command bits&lt;br /&gt;
LLLLL: Length&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If the header byte is $FF, the end of the compressed data has been reached, and decompression will be aborted.&lt;br /&gt;
&lt;br /&gt;
Here is a list of commands bits which the LC_LZ3 decompression function can use during the decompression:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
000    &amp;quot;Direct Copy&amp;quot;&lt;br /&gt;
       Followed by (L+1) bytes of data&lt;br /&gt;
001    &amp;quot;Byte Fill&amp;quot;&lt;br /&gt;
       Followed by one byte to be repeated (L+1) times&lt;br /&gt;
010    &amp;quot;Word Fill&amp;quot;&lt;br /&gt;
       Followed by two bytes. Output first byte, then second, then first,&lt;br /&gt;
       then second, etc. until (L+1) bytes has been outputted&lt;br /&gt;
011    &amp;quot;Zero Fill&amp;quot;&lt;br /&gt;
       Repeat a $00 (L+1) times&lt;br /&gt;
100    &amp;quot;Repeat&amp;quot;&lt;br /&gt;
       Followed by one or two bytes. The first byte is AYYYYYYY.&lt;br /&gt;
       If bit A is set, (L+1) bytes are copied from the current&lt;br /&gt;
       address in the output buffer minus (Y+1)&lt;br /&gt;
       If bit A is reset, a second byte ZZZZZZZZ is read, and&lt;br /&gt;
       (L+1) bytes are copied from the address (Y*0x100)+Z&lt;br /&gt;
       relative to the first byte in the output buffer&lt;br /&gt;
101    &amp;quot;Bit-Reverse Repeat&amp;quot;&lt;br /&gt;
       Same concept as above, except all the copied bytes are&lt;br /&gt;
       reversed in bit order. ($AF = %10101111 -&amp;gt; $F5 = %11110101)&lt;br /&gt;
110    &amp;quot;Backwards Repeat&amp;quot;&lt;br /&gt;
       Same concept as &amp;quot;Repeat&amp;quot;, except the bytes are copied in&lt;br /&gt;
       reversed order. The address points to the first byte to be copied,&lt;br /&gt;
       and it decrements as each byte is copied.&lt;br /&gt;
111    &amp;quot;Long length&amp;quot;&lt;br /&gt;
       This command has got a two-byte header:&lt;br /&gt;
       111CCCLL LLLLLLLL&lt;br /&gt;
       CCC:        Real command&lt;br /&gt;
       LLLLLLLLLL: Length&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Seeing that the long length command uses ten bits for its length, the maximum length is 1024 bytes/1kB, while the normal length is 32 bytes.&lt;br /&gt;
&lt;br /&gt;
== Decompression ==&lt;br /&gt;
&lt;br /&gt;
During the decompression, the decompressed chunks are outputted into a buffer in the RAM.&lt;br /&gt;
&lt;br /&gt;
== Usage ==&lt;br /&gt;
&lt;br /&gt;
You can use the LC_LZ3 compression to mainly compress graphics and data. Technically you can compress anything with this format.&lt;br /&gt;
&lt;br /&gt;
[[Category:Compression Formats]]&lt;/div&gt;</summary>
		<author><name>MarioFanGamer</name></author>
	</entry>
	<entry>
		<id>https://sneslab.net/mw/index.php?title=LZ1&amp;diff=2313</id>
		<title>LZ1</title>
		<link rel="alternate" type="text/html" href="https://sneslab.net/mw/index.php?title=LZ1&amp;diff=2313"/>
		<updated>2023-03-24T19:49:27Z</updated>

		<summary type="html">&lt;p&gt;MarioFanGamer: Added category.&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{DISPLAYTITLE:LZ1}}&lt;br /&gt;
LZ1 or LC_LZ1, as named by [[Lunar Compress]], is a lossless data compression format, used by [[A Link to the Past]] to compress graphics. It is also used by [[Super Mario World]] &amp;lt;sup&amp;gt;japanese version only&amp;lt;/sup&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Compression ==&lt;br /&gt;
&lt;br /&gt;
The compressed data consists of &amp;quot;chunks&amp;quot;, each with a header:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
bits&lt;br /&gt;
76543210&lt;br /&gt;
CCCLLLLL&lt;br /&gt;
&lt;br /&gt;
CCC:   Command bits&lt;br /&gt;
LLLLL: Length&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If the header byte is $FF, the end of the compressed data has been reached, and decompression will be aborted.&lt;br /&gt;
&lt;br /&gt;
Here is a list of commands bits which the LZ1 decompression function can use during the decompression:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
000    &amp;quot;Direct Copy&amp;quot;&lt;br /&gt;
       Followed by (L+1) bytes of data&lt;br /&gt;
001    &amp;quot;Byte Fill&amp;quot;&lt;br /&gt;
       Followed by one byte to be repeated (L+1) times&lt;br /&gt;
010    &amp;quot;Word Fill&amp;quot;&lt;br /&gt;
       Followed by two bytes. Output first byte, then second, then first,&lt;br /&gt;
       then second, etc. until (L+1) bytes has been outputted&lt;br /&gt;
011    &amp;quot;Increasing Fill&amp;quot;&lt;br /&gt;
       Followed by one byte to be repeated (L+1) times, but the byte is&lt;br /&gt;
       increased by 1 after each write&lt;br /&gt;
100    &amp;quot;Repeat&amp;quot;&lt;br /&gt;
       Followed by two bytes (small endian byte order, this being the only difference between LZ1 and LZ2) containing address (in the&lt;br /&gt;
       output buffer) to copy (L+1) bytes from&lt;br /&gt;
101    (Unused command)&lt;br /&gt;
110    (Unused command)&lt;br /&gt;
111    &amp;quot;Long length&amp;quot;&lt;br /&gt;
       This command has got a two-byte header:&lt;br /&gt;
       111CCCLL LLLLLLLL&lt;br /&gt;
       CCC:        Real command&lt;br /&gt;
       LLLLLLLLLL: Length&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
== Decompression ==&lt;br /&gt;
During the decompression, the decompressed chunks are outputted into a buffer in the RAM.&lt;br /&gt;
&lt;br /&gt;
== Usage ==&lt;br /&gt;
&lt;br /&gt;
You can use the LZ1 compression to mainly compress graphics. Technically you can compress anything with this format, but graphics is preferred due to their big size. Seeing the SNES isn&#039;t fast, the decompression takes a while to finish, so whenever you overuse the compression the loading time will increase.&lt;br /&gt;
&lt;br /&gt;
== External links ==&lt;br /&gt;
&lt;br /&gt;
[https://fusoya.eludevisibility.org/lc/index.html Lunar Compress], a library by [[FuSoYa]] made to handle loading various game graphics format, including LZ1.&lt;br /&gt;
&lt;br /&gt;
[[Category:Compression Formats]]&lt;/div&gt;</summary>
		<author><name>MarioFanGamer</name></author>
	</entry>
	<entry>
		<id>https://sneslab.net/mw/index.php?title=RLE1&amp;diff=2312</id>
		<title>RLE1</title>
		<link rel="alternate" type="text/html" href="https://sneslab.net/mw/index.php?title=RLE1&amp;diff=2312"/>
		<updated>2023-03-24T19:48:45Z</updated>

		<summary type="html">&lt;p&gt;MarioFanGamer: Added category.&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;RLE1 or LC_RLE1, as named by [[Lunar Compress]], is a lossless data compression format, used by [[Super Mario World]] to compress the overworld layer 2 event data&#039;s tilemap properties.&lt;br /&gt;
&lt;br /&gt;
== Compression ==&lt;br /&gt;
&lt;br /&gt;
The compression is a simple run-length encoding format. It&#039;s one-dimensional, which means the decompressed data gets stored normally in the output buffer unlike LC_RLE2.&lt;br /&gt;
&lt;br /&gt;
The compressed data consists of &amp;quot;chunks&amp;quot;, each with a header:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
bits&lt;br /&gt;
76543210&lt;br /&gt;
CLLLLLLL&lt;br /&gt;
C:       Command bit&lt;br /&gt;
LLLLLLL: Length&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Here&#039;s a list of the command bit values the LC_RLE1 routine can use during decompression:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
0    &amp;quot;Direct Copy&amp;quot;&lt;br /&gt;
     Followed by (L+1) bytes of data&lt;br /&gt;
1    &amp;quot;RLE&amp;quot;&lt;br /&gt;
     Followed by one byte to be repeated (L+1) times&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The end of the decompression data is reached when the header byte and the following byte both are $FF. This means that the compression does not support 128 bytes of $FF compressed (because the result will be $FF $FF, which aborts the decompression). However, you can compress 127 bytes instead so that the result becomes $FE $FF)&lt;br /&gt;
&lt;br /&gt;
== Decompression ==&lt;br /&gt;
&lt;br /&gt;
During the decompression, the decompressed chunks can be outputted into a buffer which is either RAM or SRAM. SMW uses the RAM address $7F:0000 as its decompression buffer. The maximum RLE decompression length is 128 bytes.&lt;br /&gt;
&lt;br /&gt;
== Usage ==&lt;br /&gt;
&lt;br /&gt;
You can use the LC_RLE1 compression to mainly compress things like tilemap. Technically you can compress anything with this format, but tilemaps are preferred due to the often-occuring consecutive repeating bytes.&lt;br /&gt;
&lt;br /&gt;
== Other ==&lt;br /&gt;
&lt;br /&gt;
You can see an LC_RLE1 decompression routine setup at SNES $04:DD40 (SMW). The decompression routine itself is located at SNES $04:DD57. The decompression routine does not support data which crosses bank boundaries. Therefore, you will have to take care of that.&lt;br /&gt;
&lt;br /&gt;
[[Category:Compression Formats]]&lt;/div&gt;</summary>
		<author><name>MarioFanGamer</name></author>
	</entry>
	<entry>
		<id>https://sneslab.net/mw/index.php?title=List_of_SNES_ROM_hacking_tools&amp;diff=2284</id>
		<title>List of SNES ROM hacking tools</title>
		<link rel="alternate" type="text/html" href="https://sneslab.net/mw/index.php?title=List_of_SNES_ROM_hacking_tools&amp;diff=2284"/>
		<updated>2023-03-12T06:26:36Z</updated>

		<summary type="html">&lt;p&gt;MarioFanGamer: /* Emulators/Debuggers */ Replaced Mesen-S with Mesen2.&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== General ==&lt;br /&gt;
=== ASM patchers ===&lt;br /&gt;
* [https://github.com/RPGHacker/asar Asar]&lt;br /&gt;
* [https://byuu.org/tool/bass bass]&lt;br /&gt;
* [https://www.smwcentral.net/?p=section&amp;amp;a=details&amp;amp;id=4615 xkas] (legacy, but very known)&lt;br /&gt;
&lt;br /&gt;
=== Binary patchers ===&lt;br /&gt;
* [https://github.com/Alcaro/Flips FLIPS] (.bps, .ips) -- Windows binary: https://sneslab.net/tools/floating.zip&lt;br /&gt;
* [https://fusoya.eludevisibility.org/lips/index.html Lunar IPS] (.ips)&lt;br /&gt;
&lt;br /&gt;
=== Emulators ===&lt;br /&gt;
* [https://byuu.org/emulation/bsnes/ bsnes]&lt;br /&gt;
* [https://github.com/snes9xgit/snes9x Snes9x]&lt;br /&gt;
* [https://zsnes.com/ ZSNES] (inaccurate, but fast and used to be very popular)&lt;br /&gt;
&lt;br /&gt;
=== Emulators/Debuggers ===&lt;br /&gt;
* [https://github.com/devinacker/bsnes-plus bsnes-plus]&lt;br /&gt;
* [https://github.com/SourMesen/Mesen2 Mesen]&lt;br /&gt;
&lt;br /&gt;
== SMW Hacking ==&lt;br /&gt;
=== Editors ===&lt;br /&gt;
* [https://fusoya.eludevisibility.org/lm/index.html Lunar Magic]&lt;br /&gt;
&lt;br /&gt;
=== Inserters ===&lt;br /&gt;
* [https://github.com/VitorVilela7/UberASMTool UberASM Tool]&lt;br /&gt;
* [https://github.com/JackTheSpades/SpriteToolSuperDelux PIXI]&lt;br /&gt;
* [https://smwc.me/1491239 GIEPY]&lt;br /&gt;
* [https://www.smwcentral.net/?p=section&amp;amp;a=details&amp;amp;id=17546 AddmusicK]&lt;br /&gt;
&lt;br /&gt;
=== Converters ===&lt;br /&gt;
* [https://github.com/VitorVilela7/SPCtoMML SPCtoMML]&lt;br /&gt;
* [https://github.com/VitorVilela7/SnesGFX SnesGFX]&lt;br /&gt;
&lt;br /&gt;
== YI Hacking ==&lt;br /&gt;
=== Editors ===&lt;br /&gt;
* [https://www.smwcentral.net/?p=section&amp;amp;a=details&amp;amp;id=4645 Golden Egg]&lt;br /&gt;
&lt;br /&gt;
=== Inserters ===&lt;br /&gt;
* [https://dl.dropbox.com/s/oqsnu42mg76runs/AddMusicY%20Beta.zip AddmusicY]&lt;/div&gt;</summary>
		<author><name>MarioFanGamer</name></author>
	</entry>
	<entry>
		<id>https://sneslab.net/mw/index.php?title=Super_FX&amp;diff=2280</id>
		<title>Super FX</title>
		<link rel="alternate" type="text/html" href="https://sneslab.net/mw/index.php?title=Super_FX&amp;diff=2280"/>
		<updated>2023-02-27T07:07:53Z</updated>

		<summary type="html">&lt;p&gt;MarioFanGamer: /* Hardware Registers */ Described all Super FX registers. TODO: Add links for further references.&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&#039;&#039;&#039;Super FX&#039;&#039;&#039; is a [[Super NES]] [[enhancement chip]] developed by [https://en.wikipedia.org/wiki/Argonaut_Games Argonaut Games] and [http://en.wikipedia.org/wiki/Nintendo Nintendo]. It&#039;s also known as the &amp;quot;Graphical Support Unit&amp;quot; (short for &amp;quot;GSU&amp;quot;) for its greater graphical capabilities compared to the S-CPU whereas its first revision, used for [[Star Fox]], uses the name &amp;quot;Mathematical, Argonaut, Rotation, &amp;amp; Input/Output&amp;quot; or short MARIO chip. It also is know for the use in [[Super Mario World 2: Yoshi&#039;s Island]].&lt;br /&gt;
&lt;br /&gt;
During this article, GSU refers to Super FX whereas CPU refers to the Super NES CPU.&lt;br /&gt;
&lt;br /&gt;
== Features ==&lt;br /&gt;
The embedded co-processor has got a base clock speed of &#039;&#039;&#039;10.74 MHz&#039;&#039;&#039; which is four times as fast as the S-CPU which uses a base block of 2.68 Mhz. Its features includes but not limited to:&lt;br /&gt;
* A RISC-like processor where most opcodes have an instruction size of one byte and are executed in a single cycle when in cache.&lt;br /&gt;
* 512 bytes of cache RAM for faster processing of instructions.&lt;br /&gt;
* A large memory capactiy, a total capacity of 8 MiB ROM, of which two MiB are shared by CPU and GSU, and 256 KiB RAM, of which 128 KiB are shared by CPU and GSU.&lt;br /&gt;
* A separate bus for ROM and RAM to handle memory in parallel&lt;br /&gt;
* Paralell processing with the CPU&lt;br /&gt;
* Fast Bitmap to Planar conversion&lt;br /&gt;
* Pipeline processing to fetch opcodes twice as fast, effectively increasing the processing speed to 21.48 MHz.&lt;br /&gt;
&lt;br /&gt;
= Technical Information =&lt;br /&gt;
&lt;br /&gt;
== Hardware Registers ==&lt;br /&gt;
&lt;br /&gt;
Super FX comes with various hardware registers of various functions. Most (but not all) of the GSU hardware registers can be accessed from the CPU when the GSU is idling. They are located in the $3000-$3FFF region in banks $00-$3F and $80-$BF.&lt;br /&gt;
&lt;br /&gt;
=== General Registers (R0-R13) ===&lt;br /&gt;
&lt;br /&gt;
These registers are more or less equivalent to the A, X and Y registers on the [[65c816]]. They all are parameters to many opcodes, though not all of them are valid (e.g. R0 can&#039;t be a parameter for the logical operators), and are all 16-bit. Some of them come with a secondary use for certain opcodes. The CPU can directly read from and write to these registers $3000-$301B.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+A list of their addresses and their secondary functions&lt;br /&gt;
|-&lt;br /&gt;
! Name !! Address !! Secondary Function&lt;br /&gt;
|-&lt;br /&gt;
|  R0  ||  $3000  || Default source/destination register.&lt;br /&gt;
|-&lt;br /&gt;
|  R1  ||  $3002  || &amp;lt;code&amp;gt;PLOT&amp;lt;/code&amp;gt; X position&lt;br /&gt;
|-&lt;br /&gt;
|  R2  ||  $3004  || &amp;lt;code&amp;gt;PLOT&amp;lt;/code&amp;gt; Y position&lt;br /&gt;
|-&lt;br /&gt;
|  R3  ||  $3006  ||&lt;br /&gt;
|-&lt;br /&gt;
|  R4  ||  $3008  || Low word for &amp;lt;code&amp;gt;LMULT&amp;lt;/code&amp;gt; result&lt;br /&gt;
|-&lt;br /&gt;
|  R5  ||  $300A  ||&lt;br /&gt;
|-&lt;br /&gt;
|  R6  ||  $300C  || Second input for &amp;lt;code&amp;gt;LMULT&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;FMULT&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|  R7  ||  $300E  || &amp;lt;code&amp;gt;MERGE&amp;lt;/code&amp;gt; source 1&lt;br /&gt;
|-&lt;br /&gt;
|  R8  ||  $3010  || &amp;lt;code&amp;gt;MERGE&amp;lt;/code&amp;gt; source 2&lt;br /&gt;
|-&lt;br /&gt;
|  R9  ||  $3012  ||&lt;br /&gt;
|-&lt;br /&gt;
|  R10 ||  $3014  ||&lt;br /&gt;
|-&lt;br /&gt;
|  R11 ||  $3016  || &amp;lt;code&amp;gt;LINK&amp;lt;/code&amp;gt; destination&lt;br /&gt;
|-&lt;br /&gt;
|  R12 ||  $3018  || &amp;lt;code&amp;gt;LOOP&amp;lt;/code&amp;gt; counter&lt;br /&gt;
|-&lt;br /&gt;
|  R13 ||  $301A  || &amp;lt;code&amp;gt;LOOP&amp;lt;/code&amp;gt; start&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Game Pak ROM Address Pointer (R14) ===&lt;br /&gt;
&lt;br /&gt;
R14 is the ROM Pointer register and is mapped to $301C-$301D on the SNES. It&#039;s the pointer for the &amp;lt;code&amp;gt;GETB&amp;lt;/code&amp;gt; opcodes which allows the GSU to read from ROM.&lt;br /&gt;
It otherwise acts like any normal general register and is sometimes used as such.&lt;br /&gt;
&lt;br /&gt;
=== Program Counter (R15) ===&lt;br /&gt;
&lt;br /&gt;
R15 is the program counter and is mapped to $301E-$301F on the SNES. Unlike on the [[65c816]] processor, the program counter (excluding the bank) can be directly read or modified within code&lt;br /&gt;
as it acts like a general register. This makes it possible to e.g. jump to a certain address without the use of a dedicated opcode.&lt;br /&gt;
For example, &amp;lt;code&amp;gt;IWT R15, #xxxx&amp;lt;/code&amp;gt; on Super FX is equivalent to &amp;lt;code&amp;gt;JMP $xxxx&amp;lt;/code&amp;gt; on the 65c816.&lt;br /&gt;
&lt;br /&gt;
In addition, writing to $301E on the CPU side invokes the GSU.&lt;br /&gt;
&lt;br /&gt;
=== Status/Flag Register (SFR) ===&lt;br /&gt;
&lt;br /&gt;
Super FX comes with a 16-bit register of various flags, mostly from calculations (e.g. a carry flag) but also other flags like whether Super FX is currently running.&lt;br /&gt;
They can be read and written through $3030 and $3031.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+Status/Flag Register bitwise&lt;br /&gt;
!       !! B7  !! B6 !! B5 !! B4 !! B3 !! B2 !!  B1  !!  B0&lt;br /&gt;
|-&lt;br /&gt;
| $3031 || IRQ || -  || -  || B  || IH || IL || ALT1 || ALT2&lt;br /&gt;
|-&lt;br /&gt;
| $3030 ||  -  || R  || G  || OV || S  || CY ||  Z   ||  -&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+Description of Flags&lt;br /&gt;
|-&lt;br /&gt;
! Flag !! Description&lt;br /&gt;
|-&lt;br /&gt;
|  Z   || Zero flag, set when result is zero.&lt;br /&gt;
|-&lt;br /&gt;
|  CY  || Carry flag, set at result overflow (unsigned).&lt;br /&gt;
|-&lt;br /&gt;
|  S   || Sign flag, set when number is negative.&lt;br /&gt;
|-&lt;br /&gt;
|  OV  || Overflow flag, set at result overflow (signed).&lt;br /&gt;
|-&lt;br /&gt;
|  G   || Go flag, set when GSU is running.&lt;br /&gt;
|-&lt;br /&gt;
|  R   || Set when reading from ROM.&lt;br /&gt;
|-&lt;br /&gt;
| ALT1 || Opcode modifier 1, set when executing &amp;lt;code&amp;gt;ALT1&amp;lt;/code&amp;gt;.&lt;br /&gt;
|-&lt;br /&gt;
| ALT2 || Opcode modifier 2, set when executing &amp;lt;code&amp;gt;ALT2&amp;lt;/code&amp;gt;.&lt;br /&gt;
|-&lt;br /&gt;
|  IL  || Immediate lower 8-bit flag.&lt;br /&gt;
|-&lt;br /&gt;
|  IH  || Immediate higher 8-bit flag.&lt;br /&gt;
|-&lt;br /&gt;
|  B   || Set when executing &amp;lt;code&amp;gt;WITH&amp;lt;/code&amp;gt;.&lt;br /&gt;
|-&lt;br /&gt;
| IRQ  || Interrupt flag, set when GSU stopped.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Program Bank Register (PBR) ===&lt;br /&gt;
&lt;br /&gt;
The program bank is the bank where GSU code is executed. It&#039;s a readable and writable 8-bit register which is mapped to $3034 on the CPU side.&lt;br /&gt;
Unlike R15, this can only be modified indirectly using &amp;lt;code&amp;gt;LJMP&amp;lt;/code&amp;gt; on GSU side.&lt;br /&gt;
&lt;br /&gt;
=== Game Pak ROM Bank Register (ROMBR) ===&lt;br /&gt;
&lt;br /&gt;
This register controls the bank where ROM is read. It&#039;s set using the &amp;lt;code&amp;gt;ROMB&amp;lt;/code&amp;gt; on the GSU side.&lt;br /&gt;
It&#039;s a readable only 8-bit register which is mapped to $3036 on the CPU side.&lt;br /&gt;
&lt;br /&gt;
=== Game Pak RAM Bank Register (RAMBR) ===&lt;br /&gt;
&lt;br /&gt;
This register is the RAM equivalent to ROMBR. It&#039;s set using the &amp;lt;code&amp;gt;RAMB&amp;lt;/code&amp;gt; on the GSU side.&lt;br /&gt;
It&#039;s a readable only 1-bit register which is mapped to $303C on the CPU side.&lt;br /&gt;
&lt;br /&gt;
=== Cache Base Register (CBR) ===&lt;br /&gt;
&lt;br /&gt;
The Cache Base Register is the address where cache has been enabled through and tells the GSU where to run code in cache.&lt;br /&gt;
It&#039;s readable 16-bit register accessible through $303E and $303F from the CPU and written by the GSU with the &amp;lt;code&amp;gt;CACHE&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;LJMP&amp;lt;/code&amp;gt; opcodes.&lt;br /&gt;
The lowest four bits of this register are open bus since cache is stored in 16-byte blocks.&lt;br /&gt;
&lt;br /&gt;
=== Screen Base Register (SCBR) ===&lt;br /&gt;
&lt;br /&gt;
The Screen Base Register is the high byte of the image buffer i.e. the plotting destination.&lt;br /&gt;
It&#039;s a writeable 8-bit register mapped to $3038 on the CPU side.&lt;br /&gt;
&lt;br /&gt;
=== Screen Mode Register (SCMR) ===&lt;br /&gt;
&lt;br /&gt;
The Screen Mode Register contains the settings for the image buffer (dimensions, bitdepth) but also access to ROM and RAM.&lt;br /&gt;
It&#039;s a writeable 8-bit register mapped to $303A on the CPU side.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+Screen Mode Register bitwise&lt;br /&gt;
! B7 !! B6 !! B5  !! B4  !! B3  !! B2  !! B1  !! B0&lt;br /&gt;
|-&lt;br /&gt;
| -  || -  || HT1 || ROM || RAN || HT0 || MD1 || MD0&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The image buffer dimensions are given by HT0 and HT1. They all are 256 pixels wide but have different heights.&lt;br /&gt;
A special case exists when both bits are 1 which enables OBJ mode which is used to plot single sprites like in Yoshi&#039;s Island.&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+Screen Dimensions&lt;br /&gt;
|-&lt;br /&gt;
! HT1 !! H00 !! Mode&lt;br /&gt;
|-&lt;br /&gt;
|  0  ||  0  || 256 by 128&lt;br /&gt;
|-&lt;br /&gt;
|  0  ||  1  || 256 by 160&lt;br /&gt;
|-&lt;br /&gt;
|  1  ||  0  || 256 by 192&lt;br /&gt;
|-&lt;br /&gt;
|  1  ||  1  || OBJ mode&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The bitdepth of the image buffer is set by the MD0 and MD1 bits:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+Screen Mode&lt;br /&gt;
|-&lt;br /&gt;
! MD1 !! MD0 !! Mode&lt;br /&gt;
|-&lt;br /&gt;
|  0  ||  0  || 4-color mode (2bpp)&lt;br /&gt;
|-&lt;br /&gt;
|  0  ||  1  || 16-color mode (4bpp)&lt;br /&gt;
|-&lt;br /&gt;
|  1  ||  0  || Not used&lt;br /&gt;
|-&lt;br /&gt;
|  1  ||  1  || 256-color mode (8bpp)&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The SCMR register also controls whether Game Pak ROM and RAM can be accessed by the CPU or GSU:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+Screen Mode&lt;br /&gt;
|-&lt;br /&gt;
! Bit !! Description&lt;br /&gt;
|-&lt;br /&gt;
| RON || Gives ROM access to the CPU when 0 and GSU when 1.&lt;br /&gt;
|-&lt;br /&gt;
| RAN || Gives RAM access to the CPU when 0 and GSU when 1.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Color Register (COLR) ===&lt;br /&gt;
&lt;br /&gt;
The Color Register contains the colour for the pixel which is to be plotted.&lt;br /&gt;
It&#039;s an 8-bit register which is set using the &amp;lt;code&amp;gt;COLOR&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;GETC&amp;lt;/code&amp;gt; opcodes on the GSU. There is no access from the CPU.&lt;br /&gt;
&lt;br /&gt;
=== Plot Option Register (POR) ===&lt;br /&gt;
&lt;br /&gt;
The Color Register controls how the colours are loaded into the COLR register as well as .&lt;br /&gt;
It&#039;s an 8-bit register which is set using the &amp;lt;code&amp;gt;CMODE&amp;lt;/code&amp;gt; opcode on the GSU. There is no access from the CPU.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+Screen Mode Register bitwise&lt;br /&gt;
! B7 !! B6 !! B5 !! B4  !! B3 !! B2 !! B1 !! B0&lt;br /&gt;
|-&lt;br /&gt;
| -  || -  || -  || OBJ || FH || HN || DT || TP&lt;br /&gt;
|}&lt;br /&gt;
Note that these abbreviations are inofficial and have been included for simplification.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+Description of Screen Mode Register&lt;br /&gt;
|-&lt;br /&gt;
! Bit !! Description&lt;br /&gt;
|-&lt;br /&gt;
| OBJ || OBJ Flag&lt;br /&gt;
|-&lt;br /&gt;
| FH  || Freeze High Flag&lt;br /&gt;
|-&lt;br /&gt;
| HN  || High Nibble Flag&lt;br /&gt;
|-&lt;br /&gt;
| DT  || Dither Flag&lt;br /&gt;
|-&lt;br /&gt;
| TP  || Transparent Flag&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Backup RAM Register (BRAMR) ===&lt;br /&gt;
&lt;br /&gt;
This controls whether Back-up RAM (not to be confused with Game Pak RAM) becomes “protected”.&amp;lt;sup&amp;gt;1&amp;lt;/sup&amp;gt;&lt;br /&gt;
It&#039;s a 1-bit register mapped to bit 0 of $3033 which can be written by the CPU.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;sup&amp;gt;1&amp;lt;/sup&amp;gt;The definition of “protected” isn&#039;t very clear, though it can be assumed that Back-up RAM can&#039;t be written when it&#039;s set to be protected.&lt;br /&gt;
&lt;br /&gt;
=== Version Code Register (VCR) ===&lt;br /&gt;
&lt;br /&gt;
The Version Code Register contains the version code of the Super FX chip.&lt;br /&gt;
It&#039;s an 8-bit read-only register and accessed $303B on the CPU side.&lt;br /&gt;
&lt;br /&gt;
=== Config Register (CFGR) ===&lt;br /&gt;
&lt;br /&gt;
The Config Register contains two flags:&lt;br /&gt;
The IRQ flag which allows the GSU to fire an interrupt to the CPU should it stop and&lt;br /&gt;
the MS0 which controls the speed of the multiplication.&lt;br /&gt;
It&#039;s mapped to bit 0 of $3039 and is writeable from the CPU.&lt;br /&gt;
&lt;br /&gt;
=== Clock Select Register (CLSR) ===&lt;br /&gt;
&lt;br /&gt;
This register sets the clock speed of Super FX and enables pipelining in the process. When clear, Super FX runs at 10.74 MHz, when set, at 21.48 MHz.&lt;br /&gt;
It&#039;s mapped to bit 0 of $3039 and is writeable from the CPU.&lt;br /&gt;
&lt;br /&gt;
Supposedly, the CLSR and MS0 flags must not be set 1 at the same time but no side effects are known.&lt;br /&gt;
&lt;br /&gt;
== Memory and Bus ==&lt;br /&gt;
&lt;br /&gt;
=== Memory Map ===&lt;br /&gt;
One advantage of Super FX is that it naturally supports ROMs with a size of up to 8 MiB. However, Super FX can only use the first two MiB of a ROM. Similarly, even though a single cartridge may have up to 256 KiB of SRAM, only half of them can be used by Super FX. As a result, there is a difference between the CPU and GSU mapping.&lt;br /&gt;
&lt;br /&gt;
This is how the ROM is mapped from the perspective of the CPU:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
!  Banks  !!   Address   !! Description&lt;br /&gt;
|-&lt;br /&gt;
!rowspan=&amp;quot;6&amp;quot;|$00-$3F&lt;br /&gt;
          || $0000-$1FFF || WRAM mirror&lt;br /&gt;
|-&lt;br /&gt;
|           $2100-$21FF || PPU registers&lt;br /&gt;
|-&lt;br /&gt;
|           $3000-$3FFF || Super FX registers&lt;br /&gt;
|-&lt;br /&gt;
|           $4200-$43FF || CPU registers&lt;br /&gt;
|-&lt;br /&gt;
|           $6000-$7FFF || SRAM mirror&lt;br /&gt;
|-&lt;br /&gt;
|           $8000-$FFFF || ROM (LoROM)&lt;br /&gt;
|-&lt;br /&gt;
| $40-$5F || $0000-$FFFF || Mirror of ROM in banks $00-$3F (HiROM)&lt;br /&gt;
|-&lt;br /&gt;
| $60-$6F || $0000-$FFFF || Unmapped&lt;br /&gt;
|-&lt;br /&gt;
| $70-$71 || $0000-$FFFF || SRAM&lt;br /&gt;
|-&lt;br /&gt;
| $7C-$7D || $0000-$FFFF || Backup RAM&lt;br /&gt;
|-&lt;br /&gt;
| $7E-$7F || $0000-$FFFF || WRAM&lt;br /&gt;
|-&lt;br /&gt;
!rowspan=&amp;quot;6&amp;quot;|$80-$BF&lt;br /&gt;
          || $0000-$1FFF || WRAM mirror&lt;br /&gt;
|-&lt;br /&gt;
|           $2100-$21FF || PPU registers&lt;br /&gt;
|-&lt;br /&gt;
|           $3000-$3FFF || Super FX registers&lt;br /&gt;
|-&lt;br /&gt;
|           $4200-$43FF || CPU registers&lt;br /&gt;
|-&lt;br /&gt;
|           $6000-$7FFF || SRAM mirror&lt;br /&gt;
|-&lt;br /&gt;
|           $8000-$FFFF || ROM (LoROM)&lt;br /&gt;
|-&lt;br /&gt;
| $C0-$FF || $8000-$FFFF || ROM (HiROM)&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The GSU memory map looks similar to the CPU mapping but only with access to ROM and SRAM as well as only access to 2 MiB of ROM and 128 KiB of SRAM. As a result, it looks more like this:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
!  Banks  !!   Address   !! Description&lt;br /&gt;
|-&lt;br /&gt;
!rowspan=&amp;quot;2&amp;quot;|$00-$3F&lt;br /&gt;
          || $0000-$7FFF || Unmapped&lt;br /&gt;
|-&lt;br /&gt;
|            $8000-$FFFF || ROM (LoROM)&lt;br /&gt;
|-&lt;br /&gt;
| $40-$5F || $0000-$FFFF || Mirror of ROM in banks $00-$3F (HiROM)&lt;br /&gt;
|-&lt;br /&gt;
| $60-$6F || $0000-$FFFF || Unmapped&lt;br /&gt;
|-&lt;br /&gt;
| $70-$71 || $0000-$FFFF || SRAM&lt;br /&gt;
|-&lt;br /&gt;
| $72-$7F || $0000-$FFFF || Unmapped&lt;br /&gt;
|-&lt;br /&gt;
| $80-$FF || $0000-$FFFF || Mirror of $00-$7F&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Finally, it should be noted that banks $40-$5F are HiROM mirrors of the LoROM banks $00-$3F interlaced so addresses such as $008000 and $400000 contain the same value.&lt;br /&gt;
&lt;br /&gt;
=== ROM ===&lt;br /&gt;
ROM on Super FX can be up to 8 MiB large. However, even though the size is theoretically doable, the largest published Super FX games had a ROM size of 2 MiBs. As a result, not many emulators (not even BSNES as of 2021) emulate this feature properly and such ROM sizes only exist in homebrewing and modding.&lt;br /&gt;
&lt;br /&gt;
Super FX has also has got limitations with ROM access. This first example is the ROM size. Even though a Super FX ROM can be as large as 8 MiB (in theory), the GSU&#039;s data bus is only connected to 2 MiB of it. Said portion of ROM which the processor can access is called GamePak ROM while the additional 6 MiB, called the Super NES ROM, can only be accessed by the CPU.&lt;br /&gt;
A second limitation is the clock speed. The GSU is clocked very fast at 10,74 Mhz (which can be doubled with pipelining) but ROM is clocked at 3,58 Mhz (unlike on [[SA-1]] where ROM is clocked at the same frequence the coprocessor). As a result, all opcodes, when they are executed in ROM, take at least three cycles to process while reads from ROM are very slow.&lt;br /&gt;
&lt;br /&gt;
To counteract against this limitation, the GSU uses a buffering system. In order to load a value from ROM, the bank must first be set in ROMBR (set by &amp;lt;code&amp;gt;ROMB&amp;lt;/code&amp;gt; in the GSU code) while the address is set in register R14. Any write to R14 initiates the buffering process. The value then can be retrieved with &amp;lt;code&amp;gt;GETB&amp;lt;/code&amp;gt; and similar opcodes (referred to just &amp;lt;code&amp;gt;GETB&amp;lt;/code&amp;gt; from now on).&lt;br /&gt;
&lt;br /&gt;
The GSU doesn&#039;t wait during the process of fetching. As a result, it is possible to call &amp;lt;code&amp;gt;GETB&amp;lt;/code&amp;gt; some time after writing to R14. In fact, this is even recommend because calling &amp;lt;code&amp;gt;GETB&amp;lt;/code&amp;gt; during the process of fetching will cause the GSU to halt up five cycles for executing &amp;lt;code&amp;gt;GETB&amp;lt;/code&amp;gt;. Similarly, writing to &amp;lt;code&amp;gt;ROMB&amp;lt;/code&amp;gt; will halt the code as well until the data has been fetched enabling cache during the process of fetching will mess up the ROM value instead.&lt;br /&gt;
&lt;br /&gt;
=== RAM ===&lt;br /&gt;
&lt;br /&gt;
=== Cache ===&lt;br /&gt;
&lt;br /&gt;
In order to improve the speed of the processor, it includes a 512 byte large memory with the same frequency as the GSU as a cache. This allows Super FX to execute a single opcode with only a single cycle (i.e. three times as fast as in regular use). The cache is separated into 32 16-byte blocks, each with a flag which denotes that a block is used, and is indexed by the cache base register (CBR) which is used to keep track of where cache has been invoked. The cache flags and CBR are reset whenever a zero is written to the GO flag but simply halting or invoking the GSU preserves the content of the cache which in turn can be read by the CPU.&lt;br /&gt;
&lt;br /&gt;
Cache on the SNES is mapped to addresses $xx:3100-$xx:32FF ($xx = $00-$3F, $80-$BF), though the start of the cached code (see below) also is dependent on the CBR (start = $3100 + (CBR &amp;amp; 0x1FF)).&lt;br /&gt;
&lt;br /&gt;
There are two methods to fill the cache:&lt;br /&gt;
* Manual caching&lt;br /&gt;
* Automatic caching&lt;br /&gt;
&lt;br /&gt;
Manual caching involes using the CPU and transfer the code to cache. Keep in mind that Super FX will only execute the cache block which has been set to be used. That means, the code has to be transfered as a full 16 byte block, though strictly speaking, only the last byte of the block (address $XXXF) needs to be written to count the block as used.&lt;br /&gt;
In order to execute GSU code in cache, R15 has to be set to $0000-$01FF.&lt;br /&gt;
&lt;br /&gt;
Automatic caching is instead handled by the GSU itself. This is handled either by the dedicated &amp;lt;code&amp;gt;CACHE&amp;lt;/code&amp;gt; opcode or by a &amp;lt;code&amp;gt;LJMP&amp;lt;/code&amp;gt; opcode, the latter because of the lack of bank information for the cache. Both of them clear the cache flags and store the current PC with the lowest nibble masked out into the CBR (CBR = PC &amp;amp; 0xFFF0). Afterwards, each executed opcode will be written into cache starting from CBR &amp;amp; 0x1FF.&lt;br /&gt;
As a result, this use of cache is recommend for loops and the first loop will always run slower than the remaining loops. Should all the blocks be used, any remaining code will be left uncached and executed in the original memory.&lt;br /&gt;
&lt;br /&gt;
Another side effect is that cache is neither ROM nor GamePak RAM so any Super FX code in cache can run in parallel to the SNES even when access to ROM and RAM is given to the CPU instead of GSU.&lt;br /&gt;
&lt;br /&gt;
=== Pipeline Processing ===&lt;br /&gt;
&lt;br /&gt;
In order to boost the processing speed of the GSU, it uses a technique called &amp;quot;pipeline processing&amp;quot;. Pipelining exists to a lesser extend on the [[65c816]], where opcodes are prepared while the remaining bytes of the opcodes are fetched (this is notable on single byte opcodes such as &amp;lt;code&amp;gt;INC&amp;lt;/code&amp;gt; which take two cycles to process, the same amount of cycles as &amp;lt;code&amp;gt;LDA #$xx&amp;lt;/code&amp;gt;, a two byte opcode) but the GSU takes it further by fetching the next opcode during the current opcode&#039;s execution.&lt;br /&gt;
This runs the code double as fast, virtually increasing the clock speed to 21.48 MHz at the cost of adding more care of the coder whenever R15 — the programm counter — is changed, either through branching or through direct writes to R15. In addition, internal processes such as multiplication and memory access can&#039;t take advantage of the virtual increment in clock speed.&lt;br /&gt;
&lt;br /&gt;
Pipelining is controlled with bit 0 of CLSR, where clear means pipelining disabled and set means pipelining enabled. It&#039;s accessable on the CPU side with the address $3037.&lt;br /&gt;
&lt;br /&gt;
For the most part, having pipelining enabled doesn&#039;t change the code. The only exceptions are when R15 is modified outside of fetching opcodes i.e. the use of branches and writes to R15 (e.g. &amp;lt;code&amp;gt;IWT R15,#$8000&amp;lt;/code&amp;gt;) as well as halting the GSU such as with &amp;lt;code&amp;gt;STOP&amp;lt;/code&amp;gt;. In these cases, the opcode following that instruction will be executed after the branch. A common solution for the unwanted opcode execution is to put a dummy &amp;lt;code&amp;gt;NOP&amp;lt;/code&amp;gt; after the R15 modifying opcode such as in this example:&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;BCC SkipCode&lt;br /&gt;
NOP             ; Dummy NOP&lt;br /&gt;
...&lt;br /&gt;
SkipCode:&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This proves to be inefficient, though. Most Super FX opcodes are one byte larger and take 3 or 1 cycles (depending on whether the code is executed in cache or not) to execute including &amp;lt;code&amp;gt;NOP&amp;lt;/code&amp;gt;. As a result, opcodes such as &amp;lt;code&amp;gt;SUB R0&amp;lt;/code&amp;gt; can be put as a dummy opcode in place of &amp;lt;code&amp;gt;NOP&amp;lt;/code&amp;gt;. The following example demonstrates it:&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;BCC SkipCode&lt;br /&gt;
;NOP            ; Redundant&lt;br /&gt;
SUB R0          ; Set R0 to zero&lt;br /&gt;
STW (R1)&lt;br /&gt;
SkipCode:&lt;br /&gt;
IWT R0,#$1234&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
In the above code, R0 gets overwritten by &amp;lt;code&amp;gt;SUB&amp;lt;/code&amp;gt; no matter whether the branch is taken. However, it later gets overwritten by &amp;lt;code&amp;gt;IWT&amp;lt;/code&amp;gt;. As a result, it doesn&#039;t matter whether the dummy opcode is a &amp;lt;code&amp;gt;NOP&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;SUB&amp;lt;/code&amp;gt; from the branch for the calculation. In fact, using a &amp;lt;code&amp;gt;NOP&amp;lt;/code&amp;gt; increases the code size by one byte which can matter when the code is executed in cache as well as increase the cycle count by 1 or 3 cycles each time the branch is executed, causing in total a minor speed penality.&lt;br /&gt;
&lt;br /&gt;
This doesn&#039;t work for every opcode, though. Opcodes such as &amp;lt;code&amp;gt;ADD #x&amp;lt;/code&amp;gt; (which is internally prefixed with &amp;lt;code&amp;gt;ALT2&amp;lt;/code&amp;gt;), &amp;lt;code&amp;gt;WITH&amp;lt;/code&amp;gt; (register prefixes which change which register is the source or destination), &amp;lt;code&amp;gt;BRA $10&amp;lt;/code&amp;gt; (branches which always use two bytes) and &amp;lt;code&amp;gt;IWT&amp;lt;/code&amp;gt; (immediate value transfers which use two or three bytes) can only be used as a dummy opcode in very specific circumstances. The latter two can even misalign the program counter not unlike executing &amp;lt;code&amp;gt;LDA #$12&amp;lt;/code&amp;gt; when A is in 16-bit mode on the 65816. The following example demonstrates it:&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;BCC SkipCode&lt;br /&gt;
BRA Error       ; Caution!&lt;br /&gt;
...&lt;br /&gt;
SkipCode:&lt;br /&gt;
...&lt;br /&gt;
Error:&lt;br /&gt;
INC R1          ; Will instead be read with the BRA as &amp;quot;BRA $D1&amp;quot;.&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
In addition, the dummy opcode after a &amp;lt;code&amp;gt;STOP&amp;lt;/code&amp;gt; &#039;&#039;&#039;must&#039;&#039;&#039; be a &amp;lt;code&amp;gt;NOP&amp;lt;/code&amp;gt; because putting the GSU in WAIT will not clear the opcode in the pipeline. Extra care should be taken when pipeliend code is executed and a &amp;lt;code&amp;gt;STOP&amp;lt;/code&amp;gt; is located at $XXXF in cache as the pipelined code may be located in unused cache and a value in RAM will be loaded instead.&lt;br /&gt;
&lt;br /&gt;
== Bus Conflicts ==&lt;br /&gt;
&lt;br /&gt;
== Bitmap Processing ==&lt;/div&gt;</summary>
		<author><name>MarioFanGamer</name></author>
	</entry>
	<entry>
		<id>https://sneslab.net/mw/index.php?title=Super_FX&amp;diff=2278</id>
		<title>Super FX</title>
		<link rel="alternate" type="text/html" href="https://sneslab.net/mw/index.php?title=Super_FX&amp;diff=2278"/>
		<updated>2023-02-26T10:00:42Z</updated>

		<summary type="html">&lt;p&gt;MarioFanGamer: Prepared hardware registers, filled some of them, fixed some typos in other sections.&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&#039;&#039;&#039;Super FX&#039;&#039;&#039; is a [[Super NES]] [[enhancement chip]] developed by [https://en.wikipedia.org/wiki/Argonaut_Games Argonaut Games] and [http://en.wikipedia.org/wiki/Nintendo Nintendo]. It&#039;s also known as the &amp;quot;Graphical Support Unit&amp;quot; (short for &amp;quot;GSU&amp;quot;) for its greater graphical capabilities compared to the S-CPU whereas its first revision, used for [[Star Fox]], uses the name &amp;quot;Mathematical, Argonaut, Rotation, &amp;amp; Input/Output&amp;quot; or short MARIO chip. It also is know for the use in [[Super Mario World 2: Yoshi&#039;s Island]].&lt;br /&gt;
&lt;br /&gt;
During this article, GSU refers to Super FX whereas CPU refers to the Super NES CPU.&lt;br /&gt;
&lt;br /&gt;
== Features ==&lt;br /&gt;
The embedded co-processor has got a base clock speed of &#039;&#039;&#039;10.74 MHz&#039;&#039;&#039; which is four times as fast as the S-CPU which uses a base block of 2.68 Mhz. Its features includes but not limited to:&lt;br /&gt;
* A RISC-like processor where most opcodes have an instruction size of one byte and are executed in a single cycle when in cache.&lt;br /&gt;
* 512 bytes of cache RAM for faster processing of instructions.&lt;br /&gt;
* A large memory capactiy, a total capacity of 8 MiB ROM, of which two MiB are shared by CPU and GSU, and 256 KiB RAM, of which 128 KiB are shared by CPU and GSU.&lt;br /&gt;
* A separate bus for ROM and RAM to handle memory in parallel&lt;br /&gt;
* Paralell processing with the CPU&lt;br /&gt;
* Fast Bitmap to Planar conversion&lt;br /&gt;
* Pipeline processing to fetch opcodes twice as fast, effectively increasing the processing speed to 21.48 MHz.&lt;br /&gt;
&lt;br /&gt;
= Technical Information =&lt;br /&gt;
&lt;br /&gt;
== Hardware Registers ==&lt;br /&gt;
&lt;br /&gt;
Super FX comes with various hardware registers of various functions. Most (but not all) of the GSU hardware registers can be accessed from the CPU when the GSU is idling. They are located in the $3000-$3FFF region in banks $00-$3F and $80-$BF.&lt;br /&gt;
&lt;br /&gt;
=== General Registers (R0-R13) ===&lt;br /&gt;
&lt;br /&gt;
These registers are more or less equivalent to the A, X and Y registers on the [[65c816]]. They all are parameters to many opcodes, though not all of them are valid (e.g. R0 can&#039;t be a parameter for the logical operators), and are all 16-bit. Some of them come with a secondary use for certain opcodes. The CPU can directly read from and write to these registers $3000-$301B.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+A list of their addresses and their secondary functions&lt;br /&gt;
|-&lt;br /&gt;
! Name !! Address !! Secondary Function&lt;br /&gt;
|-&lt;br /&gt;
|  R0  ||  $3000  || Default source/destination register.&lt;br /&gt;
|-&lt;br /&gt;
|  R1  ||  $3002  || &amp;lt;code&amp;gt;PLOT&amp;lt;/code&amp;gt; X position&lt;br /&gt;
|-&lt;br /&gt;
|  R2  ||  $3004  || &amp;lt;code&amp;gt;PLOT&amp;lt;/code&amp;gt; Y position&lt;br /&gt;
|-&lt;br /&gt;
|  R3  ||  $3006  ||&lt;br /&gt;
|-&lt;br /&gt;
|  R4  ||  $3008  || Low word for &amp;lt;code&amp;gt;LMULT&amp;lt;/code&amp;gt; result&lt;br /&gt;
|-&lt;br /&gt;
|  R5  ||  $300A  ||&lt;br /&gt;
|-&lt;br /&gt;
|  R6  ||  $300C  || Second input for &amp;lt;code&amp;gt;LMULT&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;FMULT&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|  R7  ||  $300E  || &amp;lt;code&amp;gt;MERGE&amp;lt;/code&amp;gt; source 1&lt;br /&gt;
|-&lt;br /&gt;
|  R8  ||  $3010  || &amp;lt;code&amp;gt;MERGE&amp;lt;/code&amp;gt; source 2&lt;br /&gt;
|-&lt;br /&gt;
|  R9  ||  $3012  ||&lt;br /&gt;
|-&lt;br /&gt;
|  R10 ||  $3014  ||&lt;br /&gt;
|-&lt;br /&gt;
|  R11 ||  $3016  || &amp;lt;code&amp;gt;LINK&amp;lt;/code&amp;gt; destination&lt;br /&gt;
|-&lt;br /&gt;
|  R12 ||  $3018  || &amp;lt;code&amp;gt;LOOP&amp;lt;/code&amp;gt; counter&lt;br /&gt;
|-&lt;br /&gt;
|  R13 ||  $301A  || &amp;lt;code&amp;gt;LOOP&amp;lt;/code&amp;gt; start&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Game Pak ROM Address Pointer (R14) ===&lt;br /&gt;
&lt;br /&gt;
R14 is the ROM Pointer register and is mapped to $301C-$301D on the SNES. It&#039;s the pointer for the &amp;lt;code&amp;gt;GETB&amp;lt;/code&amp;gt; opcodes which allows the GSU to read from ROM.&lt;br /&gt;
It otherwise acts like any normal general register and is sometimes used as such.&lt;br /&gt;
&lt;br /&gt;
=== Program Counter (R15) ===&lt;br /&gt;
&lt;br /&gt;
R15 is the program counter and is mapped to $301E-$301F on the SNES. Unlike on the [[65c816]] processor, the program counter (excluding the bank) can be directly read or modified within code&lt;br /&gt;
as it acts like a general register. This makes it possible to e.g. jump to a certain address without the use of a dedicated opcode.&lt;br /&gt;
For example, &amp;lt;code&amp;gt;IWT R15, #xxxx&amp;lt;/code&amp;gt; on Super FX is equivalent to &amp;lt;code&amp;gt;JMP $xxxx&amp;lt;/code&amp;gt; on the 65c816.&lt;br /&gt;
&lt;br /&gt;
In addition, writing to $301E on the CPU side invokes the GSU.&lt;br /&gt;
&lt;br /&gt;
=== Status/Flag Register (SFR) ===&lt;br /&gt;
&lt;br /&gt;
Super FX comes with a 16-bit register of various flags, mostly from calculations (e.g. a carry flag) but also other flags like whether Super FX is currently running.&lt;br /&gt;
They can be read and written through $3030 and $3031.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+Status/Flag Register bitwise&lt;br /&gt;
!       !! B7  !! B6 !! B5 !! B4 !! B3 !! B2 !!  B1  !!  B0&lt;br /&gt;
|-&lt;br /&gt;
| $3031 || IRQ || -  || -  || B  || IH || IL || ALT1 || ALT2&lt;br /&gt;
|-&lt;br /&gt;
| $3030 ||  -  || R  || G  || OV || S  || CY ||  Z   ||  -&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+Description of Flags&lt;br /&gt;
|-&lt;br /&gt;
! Flag !! Description&lt;br /&gt;
|-&lt;br /&gt;
|  Z   || Zero flag, set when &lt;br /&gt;
|-&lt;br /&gt;
|  CY  || Carry flag, set at result overflow (unsigned)&lt;br /&gt;
|-&lt;br /&gt;
|  S   || Sign flag, set when number is negative.&lt;br /&gt;
|-&lt;br /&gt;
|  OV  || Overflow flag, set at result overflow (signed)&lt;br /&gt;
|-&lt;br /&gt;
|  G   || Go flag, set when GSU is running&lt;br /&gt;
|-&lt;br /&gt;
|  R   || Set when&lt;br /&gt;
|-&lt;br /&gt;
| ALT1 || Opcode modifier 1, set when executing &amp;lt;code&amp;gt;ALT1&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| ALT2 || Opcode modifier 2, set when executing &amp;lt;code&amp;gt;ALT2&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|  IL  || Immediate lower 8-bit flag&lt;br /&gt;
|-&lt;br /&gt;
|  IH  || Immediate higher 8-bit flag&lt;br /&gt;
|-&lt;br /&gt;
|  B   || Set when &amp;lt;code&amp;gt;WITH&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| IRQ  || Interrupt flag, set when GSU stopped&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Program Bank Register (PBR) ===&lt;br /&gt;
&lt;br /&gt;
The program bank is the bank where GSU code is executed. It&#039;s a readable and writable 8-bit register which is mapped to $3034 on the CPU side.&lt;br /&gt;
Unlike R15, this can only be modified indirectly using &amp;lt;code&amp;gt;LJMP&amp;lt;/code&amp;gt; on GSU side.&lt;br /&gt;
&lt;br /&gt;
=== Game Pak ROM Bank Register (ROMBR) ===&lt;br /&gt;
&lt;br /&gt;
This register controls the bank where ROM is read. It&#039;s set using the &amp;lt;code&amp;gt;ROMB&amp;lt;/code&amp;gt; on the GSU side.&lt;br /&gt;
It&#039;s a readable only 8-bit register which is mapped to $3036 on the CPU side.&lt;br /&gt;
&lt;br /&gt;
=== Game Pak RAM Bank Register (RAMBR) ===&lt;br /&gt;
&lt;br /&gt;
This register is the RAM equivalent to ROMBR. It&#039;s set using the &amp;lt;code&amp;gt;RAMB&amp;lt;/code&amp;gt; on the GSU side.&lt;br /&gt;
It&#039;s a readable only 1-bit register which is mapped to $303C on the CPU side.&lt;br /&gt;
&lt;br /&gt;
=== Cache Base Register (CBR) ===&lt;br /&gt;
&lt;br /&gt;
=== Screen Base Register (SCBR) ===&lt;br /&gt;
&lt;br /&gt;
=== Screen Mode Register (SCMR) ===&lt;br /&gt;
&lt;br /&gt;
=== Color Register (COLR) ===&lt;br /&gt;
&lt;br /&gt;
=== Plot Option Register (POR) ===&lt;br /&gt;
&lt;br /&gt;
=== Backup RAM Register (BRAMR) ===&lt;br /&gt;
&lt;br /&gt;
=== Version Code Register (VCR) ===&lt;br /&gt;
&lt;br /&gt;
=== Config Register (CFGR) ===&lt;br /&gt;
&lt;br /&gt;
=== Clock Select Register (CLSR) ===&lt;br /&gt;
&lt;br /&gt;
== Memory and Bus ==&lt;br /&gt;
&lt;br /&gt;
=== Memory Map ===&lt;br /&gt;
One advantage of Super FX is that it naturally supports ROMs with a size of up to 8 MiB. However, Super FX can only use the first two MiB of a ROM. Similarly, even though a single cartridge may have up to 256 KiB of SRAM, only half of them can be used by Super FX. As a result, there is a difference between the CPU and GSU mapping.&lt;br /&gt;
&lt;br /&gt;
This is how the ROM is mapped from the perspective of the CPU:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
!  Banks  !!   Address   !! Description&lt;br /&gt;
|-&lt;br /&gt;
!rowspan=&amp;quot;6&amp;quot;|$00-$3F&lt;br /&gt;
          || $0000-$1FFF || WRAM mirror&lt;br /&gt;
|-&lt;br /&gt;
|           $2100-$21FF || PPU registers&lt;br /&gt;
|-&lt;br /&gt;
|           $3000-$3FFF || Super FX registers&lt;br /&gt;
|-&lt;br /&gt;
|           $4200-$43FF || CPU registers&lt;br /&gt;
|-&lt;br /&gt;
|           $6000-$7FFF || SRAM mirror&lt;br /&gt;
|-&lt;br /&gt;
|           $8000-$FFFF || ROM (LoROM)&lt;br /&gt;
|-&lt;br /&gt;
| $40-$5F || $0000-$FFFF || Mirror of ROM in banks $00-$3F (HiROM)&lt;br /&gt;
|-&lt;br /&gt;
| $60-$6F || $0000-$FFFF || Unmapped&lt;br /&gt;
|-&lt;br /&gt;
| $70-$71 || $0000-$FFFF || SRAM&lt;br /&gt;
|-&lt;br /&gt;
| $7C-$7D || $0000-$FFFF || Backup RAM&lt;br /&gt;
|-&lt;br /&gt;
| $7E-$7F || $0000-$FFFF || WRAM&lt;br /&gt;
|-&lt;br /&gt;
!rowspan=&amp;quot;6&amp;quot;|$80-$BF&lt;br /&gt;
          || $0000-$1FFF || WRAM mirror&lt;br /&gt;
|-&lt;br /&gt;
|           $2100-$21FF || PPU registers&lt;br /&gt;
|-&lt;br /&gt;
|           $3000-$3FFF || Super FX registers&lt;br /&gt;
|-&lt;br /&gt;
|           $4200-$43FF || CPU registers&lt;br /&gt;
|-&lt;br /&gt;
|           $6000-$7FFF || SRAM mirror&lt;br /&gt;
|-&lt;br /&gt;
|           $8000-$FFFF || ROM (LoROM)&lt;br /&gt;
|-&lt;br /&gt;
| $C0-$FF || $8000-$FFFF || ROM (HiROM)&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The GSU memory map looks similar to the CPU mapping but only with access to ROM and SRAM as well as only access to 2 MiB of ROM and 128 KiB of SRAM. As a result, it looks more like this:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
!  Banks  !!   Address   !! Description&lt;br /&gt;
|-&lt;br /&gt;
!rowspan=&amp;quot;2&amp;quot;|$00-$3F&lt;br /&gt;
          || $0000-$7FFF || Unmapped&lt;br /&gt;
|-&lt;br /&gt;
|            $8000-$FFFF || ROM (LoROM)&lt;br /&gt;
|-&lt;br /&gt;
| $40-$5F || $0000-$FFFF || Mirror of ROM in banks $00-$3F (HiROM)&lt;br /&gt;
|-&lt;br /&gt;
| $60-$6F || $0000-$FFFF || Unmapped&lt;br /&gt;
|-&lt;br /&gt;
| $70-$71 || $0000-$FFFF || SRAM&lt;br /&gt;
|-&lt;br /&gt;
| $72-$7F || $0000-$FFFF || Unmapped&lt;br /&gt;
|-&lt;br /&gt;
| $80-$FF || $0000-$FFFF || Mirror of $00-$7F&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Finally, it should be noted that banks $40-$5F are HiROM mirrors of the LoROM banks $00-$3F interlaced so addresses such as $008000 and $400000 contain the same value.&lt;br /&gt;
&lt;br /&gt;
=== ROM ===&lt;br /&gt;
ROM on Super FX can be up to 8 MiB large. However, even though the size is theoretically doable, the largest published Super FX games had a ROM size of 2 MiBs. As a result, not many emulators (not even BSNES as of 2021) emulate this feature properly and such ROM sizes only exist in homebrewing and modding.&lt;br /&gt;
&lt;br /&gt;
Super FX has also has got limitations with ROM access. This first example is the ROM size. Even though a Super FX ROM can be as large as 8 MiB (in theory), the GSU&#039;s data bus is only connected to 2 MiB of it. Said portion of ROM which the processor can access is called GamePak ROM while the additional 6 MiB, called the Super NES ROM, can only be accessed by the CPU.&lt;br /&gt;
A second limitation is the clock speed. The GSU is clocked very fast at 10,74 Mhz (which can be doubled with pipelining) but ROM is clocked at 3,58 Mhz (unlike on [[SA-1]] where ROM is clocked at the same frequence the coprocessor). As a result, all opcodes, when they are executed in ROM, take at least three cycles to process while reads from ROM are very slow.&lt;br /&gt;
&lt;br /&gt;
To counteract against this limitation, the GSU uses a buffering system. In order to load a value from ROM, the bank must first be set in ROMBR (set by &amp;lt;code&amp;gt;ROMB&amp;lt;/code&amp;gt; in the GSU code) while the address is set in register R14. Any write to R14 initiates the buffering process. The value then can be retrieved with &amp;lt;code&amp;gt;GETB&amp;lt;/code&amp;gt; and similar opcodes (referred to just &amp;lt;code&amp;gt;GETB&amp;lt;/code&amp;gt; from now on).&lt;br /&gt;
&lt;br /&gt;
The GSU doesn&#039;t wait during the process of fetching. As a result, it is possible to call &amp;lt;code&amp;gt;GETB&amp;lt;/code&amp;gt; some time after writing to R14. In fact, this is even recommend because calling &amp;lt;code&amp;gt;GETB&amp;lt;/code&amp;gt; during the process of fetching will cause the GSU to halt up five cycles for executing &amp;lt;code&amp;gt;GETB&amp;lt;/code&amp;gt;. Similarly, writing to &amp;lt;code&amp;gt;ROMB&amp;lt;/code&amp;gt; will halt the code as well until the data has been fetched enabling cache during the process of fetching will mess up the ROM value instead.&lt;br /&gt;
&lt;br /&gt;
=== RAM ===&lt;br /&gt;
&lt;br /&gt;
=== Cache ===&lt;br /&gt;
&lt;br /&gt;
In order to improve the speed of the processor, it includes a 512 byte large memory with the same frequency as the GSU as a cache. This allows Super FX to execute a single opcode with only a single cycle (i.e. three times as fast as in regular use). The cache is separated into 32 16-byte blocks, each with a flag which denotes that a block is used, and is indexed by the cache base register (CBR) which is used to keep track of where cache has been invoked. The cache flags and CBR are reset whenever a zero is written to the GO flag but simply halting or invoking the GSU preserves the content of the cache which in turn can be read by the CPU.&lt;br /&gt;
&lt;br /&gt;
Cache on the SNES is mapped to addresses $xx:3100-$xx:32FF ($xx = $00-$3F, $80-$BF), though the start of the cached code (see below) also is dependent on the CBR (start = $3100 + (CBR &amp;amp; 0x1FF)).&lt;br /&gt;
&lt;br /&gt;
There are two methods to fill the cache:&lt;br /&gt;
* Manual caching&lt;br /&gt;
* Automatic caching&lt;br /&gt;
&lt;br /&gt;
Manual caching involes using the CPU and transfer the code to cache. Keep in mind that Super FX will only execute the cache block which has been set to be used. That means, the code has to be transfered as a full 16 byte block, though strictly speaking, only the last byte of the block (address $XXXF) needs to be written to count the block as used.&lt;br /&gt;
In order to execute GSU code in cache, R15 has to be set to $0000-$01FF.&lt;br /&gt;
&lt;br /&gt;
Automatic caching is instead handled by the GSU itself. This is handled either by the dedicated &amp;lt;code&amp;gt;CACHE&amp;lt;/code&amp;gt; opcode or by a &amp;lt;code&amp;gt;LJMP&amp;lt;/code&amp;gt; opcode, the latter because of the lack of bank information for the cache. Both of them clear the cache flags and store the current PC with the lowest nibble masked out into the CBR (CBR = PC &amp;amp; 0xFFF0). Afterwards, each executed opcode will be written into cache starting from CBR &amp;amp; 0x1FF.&lt;br /&gt;
As a result, this use of cache is recommend for loops and the first loop will always run slower than the remaining loops. Should all the blocks be used, any remaining code will be left uncached and executed in the original memory.&lt;br /&gt;
&lt;br /&gt;
Another side effect is that cache is neither ROM nor GamePak RAM so any Super FX code in cache can run in parallel to the SNES even when access to ROM and RAM is given to the CPU instead of GSU.&lt;br /&gt;
&lt;br /&gt;
=== Pipeline Processing ===&lt;br /&gt;
&lt;br /&gt;
In order to boost the processing speed of the GSU, it uses a technique called &amp;quot;pipeline processing&amp;quot;. Pipelining exists to a lesser extend on the [[65c816]], where opcodes are prepared while the remaining bytes of the opcodes are fetched (this is notable on single byte opcodes such as &amp;lt;code&amp;gt;INC&amp;lt;/code&amp;gt; which take two cycles to process, the same amount of cycles as &amp;lt;code&amp;gt;LDA #$xx&amp;lt;/code&amp;gt;, a two byte opcode) but the GSU takes it further by fetching the next opcode during the current opcode&#039;s execution.&lt;br /&gt;
This runs the code double as fast, virtually increasing the clock speed to 21.48 MHz at the cost of adding more care of the coder whenever R15 — the programm counter — is changed, either through branching or through direct writes to R15. In addition, internal processes such as multiplication and memory access can&#039;t take advantage of the virtual increment in clock speed.&lt;br /&gt;
&lt;br /&gt;
Pipelining is controlled with bit 0 of CLSR, where clear means pipelining disabled and set means pipelining enabled. It&#039;s accessable on the CPU side with the address $3037.&lt;br /&gt;
&lt;br /&gt;
For the most part, having pipelining enabled doesn&#039;t change the code. The only exceptions are when R15 is modified outside of fetching opcodes i.e. the use of branches and writes to R15 (e.g. &amp;lt;code&amp;gt;IWT R15,#$8000&amp;lt;/code&amp;gt;) as well as halting the GSU such as with &amp;lt;code&amp;gt;STOP&amp;lt;/code&amp;gt;. In these cases, the opcode following that instruction will be executed after the branch. A common solution for the unwanted opcode execution is to put a dummy &amp;lt;code&amp;gt;NOP&amp;lt;/code&amp;gt; after the R15 modifying opcode such as in this example:&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;BCC SkipCode&lt;br /&gt;
NOP             ; Dummy NOP&lt;br /&gt;
...&lt;br /&gt;
SkipCode:&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This proves to be inefficient, though. Most Super FX opcodes are one byte larger and take 3 or 1 cycles (depending on whether the code is executed in cache or not) to execute including &amp;lt;code&amp;gt;NOP&amp;lt;/code&amp;gt;. As a result, opcodes such as &amp;lt;code&amp;gt;SUB R0&amp;lt;/code&amp;gt; can be put as a dummy opcode in place of &amp;lt;code&amp;gt;NOP&amp;lt;/code&amp;gt;. The following example demonstrates it:&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;BCC SkipCode&lt;br /&gt;
;NOP            ; Redundant&lt;br /&gt;
SUB R0          ; Set R0 to zero&lt;br /&gt;
STW (R1)&lt;br /&gt;
SkipCode:&lt;br /&gt;
IWT R0,#$1234&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
In the above code, R0 gets overwritten by &amp;lt;code&amp;gt;SUB&amp;lt;/code&amp;gt; no matter whether the branch is taken. However, it later gets overwritten by &amp;lt;code&amp;gt;IWT&amp;lt;/code&amp;gt;. As a result, it doesn&#039;t matter whether the dummy opcode is a &amp;lt;code&amp;gt;NOP&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;SUB&amp;lt;/code&amp;gt; from the branch for the calculation. In fact, using a &amp;lt;code&amp;gt;NOP&amp;lt;/code&amp;gt; increases the code size by one byte which can matter when the code is executed in cache as well as increase the cycle count by 1 or 3 cycles each time the branch is executed, causing in total a minor speed penality.&lt;br /&gt;
&lt;br /&gt;
This doesn&#039;t work for every opcode, though. Opcodes such as &amp;lt;code&amp;gt;ADD #x&amp;lt;/code&amp;gt; (which is internally prefixed with &amp;lt;code&amp;gt;ALT2&amp;lt;/code&amp;gt;), &amp;lt;code&amp;gt;WITH&amp;lt;/code&amp;gt; (register prefixes which change which register is the source or destination), &amp;lt;code&amp;gt;BRA $10&amp;lt;/code&amp;gt; (branches which always use two bytes) and &amp;lt;code&amp;gt;IWT&amp;lt;/code&amp;gt; (immediate value transfers which use two or three bytes) can only be used as a dummy opcode in very specific circumstances. The latter two can even misalign the program counter not unlike executing &amp;lt;code&amp;gt;LDA #$12&amp;lt;/code&amp;gt; when A is in 16-bit mode on the 65816. The following example demonstrates it:&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;BCC SkipCode&lt;br /&gt;
BRA Error       ; Caution!&lt;br /&gt;
...&lt;br /&gt;
SkipCode:&lt;br /&gt;
...&lt;br /&gt;
Error:&lt;br /&gt;
INC R1          ; Will instead be read with the BRA as &amp;quot;BRA $D1&amp;quot;.&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
In addition, the dummy opcode after a &amp;lt;code&amp;gt;STOP&amp;lt;/code&amp;gt; &#039;&#039;&#039;must&#039;&#039;&#039; be a &amp;lt;code&amp;gt;NOP&amp;lt;/code&amp;gt; because putting the GSU in WAIT will not clear the opcode in the pipeline. Extra care should be taken when pipeliend code is executed and a &amp;lt;code&amp;gt;STOP&amp;lt;/code&amp;gt; is located at $XXXF in cache as the pipelined code may be located in unused cache and a value in RAM will be loaded instead.&lt;br /&gt;
&lt;br /&gt;
== Bus Conflicts ==&lt;br /&gt;
&lt;br /&gt;
== Bitmap Processing ==&lt;/div&gt;</summary>
		<author><name>MarioFanGamer</name></author>
	</entry>
</feed>