Banner
Views: 854,166,736
Time:
23 users online: AmperSam, autisticsceptile1993, AyGaAlPa, bandicoot, bersi, Dan Drigues, DasFueller, Fermín Acosta Jr., Gamersmw, GbreezeSunset, Green Jerry, KaidenThelens, katun24,  KevinM, King Mayro, Linatic,  Linkdeadx2, lordkronos100, MirrorReflect, Rustifuzzy, SimFan96,  Tob, UwU - Guests: 59 - Bots: 65 Users: 47,134 (2,480 active)
Latest: Bruno_Peixoto
Tip: Press F2 on the level editor to see sub-screen boundaries. This will help you avoid glitching Dragon Coins by putting them on the sub-screen boundaries.Not logged in.
Mode 7 Findings/Info Tutorial
Forum Index - SMW Hacking - SMW Hacking Help - Tutorials - Old Tutorials - Mode 7 Findings/Info Tutorial
Pages: « 1 »
I've been recently interested in Mode 7, but even asking Roy and going through regs.txt, etc, I've yet to find some real information on the addresses that scale and such. So I've decided to make a thread with my findings.
Registers I looked at:
$211B - $211E
$211C - $211D
$211F - $2120
$211A
$36
$3A
(and a few other SMW-specific mode 7 helpers.)
First of all:
All of these addresses are "write twice," meaning you store the low byte to the address first, then the high byte. I.E.
LDA #$00 ;\ low byte
STA $00 ;/
LDA #$00 ;\ high byte
STA $00 ;/

They are all 16-bit, to quote Roy, "All in the sense that you write to them twice."

Format


This is fairly important. These address are write twice- but the format is this:
Hibyte.lowbyte
The high byte is the ones/tens digit, and the low byte is the first two decimals. This is why the default for most addresses is 0100: becuase it's 01.00 or 1. For scaling, this means 1 times it's size, etc. It's very important you keep this in mind throughout these findings. However, the high/low byte is still in hex, so if you want to scale down something to .5 it's size you do 0080 because 80 is half of 1 in hex. Remember, 0100 is 1 in hex, not decimal!

Some of the addresses I will basically state the same things you find in the ASM Workshop Summary, which you can find in the Advanced SMW Hacking forum as a sticky.
$211A
Format:
rc----yx

R: Repeat bit. If clear, this will repeat the playing field over and over again. When set, the outside of the playing field will be nothing or tile 0, depending on:
C: This bit determines what is outside the playing field, depending on wether it is set or clear. Clear = No tiles Set = Tile 0.
Here you can see the unset R bit in action:

Thanks to Roy for supplying the RAM mirror in SMK.


Y: Y will flip the playing field upside-down.
See:

My driving was backwards (look at the player on the big map, and the one of the top screen) and the thwomps would come closer as you drove away. It also flipped the course, but you can't tell.
X: X will flip the playing field.
See:

The thwomps are displaced since the way they turned was opposite of what the track did. My driving was also flipped- left = right and vice versa.
$211B - $211E
These are the stretching registers. $211B stretches X-wise, and $211E Y-wise. The default for these values are #$0100 (remember, this is write twice, so you'd load 00 to this value, then 01, to get that effect.)
$211B:
The default is #$0100. Going lower than that will stretch him, going higher than that will shrink him. (#$0200 will shrink him by half, but #$0300 will shrink him by one-fourth, and #$0400 by one-sixteeth. Every 0100 will square the denominator).

That is in hex. You might want to convert to decimal, as windows calculator doesn't support decimals in everything else.


Here's Roy being half his size. The code I got to get this effect:
LDA #$00
STA $211B
LDA #$02
STA $211B

But for stretching (below 0100:)
Code
   
Y =  The reciprocal of (X / 100)

X = number you input
Y = How many times bigger he will be

(That is also hex.)


This is Morton being twice his size, with the code
LDA #$80
STA $211B
LDA #$00
STA $211B

As 0080 is half of 0100. (Plug that into the formula and you'll understand if you don't already.)

The same applies for $211E.
But then you have to ask, "what are the rest of the values?" and, well, as far as I can tell, they're just extremes of these values. O.O;
$211C-$211D
Shear X is $211C, and Shear Y $211D.
These are used for rotation, but in actually $211C will "tilt" the sprite to the right, and $211D to the left. ( I have heard something about parallelograms and squares, but I have yet to find any real evidence of this.)
Unlike the stretching, the default for these values is 0000- and to stretch him exactly to the 45 degree angle is 0100.

$211C in action:



Morton stretched to the right doubly, with the code:
LDA #$00
STA $211C
LDA #$02
STA $211C
Or 0200.


To make a sprite rotate, you have to put the opposite of X in Y. I.E.,
if you make X = 0100, Y = FFFF - 100, which = FEFF...this is not entirely correct, however. The code is really:
Code
LDA !x
EOR #$FFFF
INC A
STA !x

Or flipping X with EOR.

However, this code:



So obvioiusly, that idea is not entirely correct. However!
Gekko was going through the SNES Development Manual and found this:
For rotation in mode 7:
Matrix Parameter A = cos (x) * scale
B = sin (x) * scale
C = -sin (x) * scale
D = cos (x) scale
Parameter A-D being 211B-211E respectively.
X = degrees of rotation
Scale = times bigger
This makes heavy use of the fact that this is write twice- BUT! As you can see above:
High byte is actually the ones place
Low byte is the first two decimals!


As for
$211F-$2120
Not much can be said. These are the center positions. They are the coordinates of where Mode 7 will make mode 7 effects from. These are write twice as well, in the typical low-high format. Default is 0000.


SMW-specific registers
I couldn't put this in the SMW Dta repository unless I had some information on SMW-specific stuff too!
Code
$7E:0036	2 bytes	Misc.	Mode 7 Rotation. It will rotate layer 1/BG1 clockwise as you increase it.

SMW has an algorithm for this, and it works perfectly. This will rotate the object perfectly. If you plan to rotate things, use this address. Default seems to be 0000 (these ARE 16-bit addresses!) and the more you increase it, the more you rotate.


Quote

CODE_008AE0: A5 30 LDA $30 ; \ Shear X
CODE_008AE2: 49 FF FF EOR.W #$FFFF ; | is opposite
CODE_008AE5: 1A INC A ; | of shear Y (+1)
CODE_008AE6: 85 32 STA $32 ; /
CODE_008AE8: A5 36 LDA $36
CODE_008AEA: 0A ASL
CODE_008AEB: 48 PHA
CODE_008AEC: EB XBA
CODE_008AED: 29 03 00 AND.W #$0003
CODE_008AF0: 0A ASL
CODE_008AF1: A8 TAY
CODE_008AF2: 68 PLA
CODE_008AF3: 29 FE 00 AND.W #$00FE
CODE_008AF6: 59 B4 8A EOR.W DATA_008AB4,Y
CODE_008AF9: 18 CLC
CODE_008AFA: 79 BC 8A ADC.W DATA_008ABC,Y
CODE_008AFD: AA TAX
CODE_008AFE: 20 2B 8B JSR.W CODE_008B2B
CODE_008B01: C0 04 00 CPY.W #$0004
CODE_008B04: 90 04 BCC CODE_008B0A
CODE_008B06: 49 FF FF EOR.W #$FFFF
CODE_008B09: 1A INC A
CODE_008B0A: 85 30 STA $30

Code found by Roy, and coincidentally, Gekko.

Code
$7E:0038	2 bytes	Misc.	Mode 7 scaling. Byte 1 scales it horizontally, while byte 2 scales it vertically.
$7E:003A	2 bytes	Misc.	Mode 7 Layer 1 X Position
$7E:003C	2 bytes	Misc.	Mode 7 Layer 1 Y Position

These are convienent and more easy to use registers, and among a few others in this area, make up all the mode 7 mirrors SMW uses. I would advise using these in SMW. Any mode 7 things you find are these addresses, used in things like the Card Crusher rom Roy made.
The absolute mirrors:
Code
|          |
V 16-bit   V Write-Twice
$2E/$2F = $211B
$30/$31 = $211C
$32/$33 = $211D
$34/$35 = $211E


These are my current findings, and I will correct and add to this thread as I find more. If you have corrections,(I KNOW I've got mistakes to correct based on some of my more strange findings,) your own findings to post, questions, anything, just post- whatever it takes to get more information on this somewhat confusing mode.

Thanks to Roy and Gekko for helping out.
Yes, there is an algorithm for this.
Note that:
$2E/$2F = Mirror of $211B
$30/$31 = Mirror of $211C
$32/$33 = Mirror of $211D
$34/$35 = Mirror of $211E

Quote

CODE_008AE0: A5 30 LDA $30 ; \ Shear X
CODE_008AE2: 49 FF FF EOR.W #$FFFF ; | is opposite
CODE_008AE5: 1A INC A ; | of shear Y (+1)
CODE_008AE6: 85 32 STA $32 ; /
CODE_008AE8: A5 36 LDA $36
CODE_008AEA: 0A ASL
CODE_008AEB: 48 PHA
CODE_008AEC: EB XBA
CODE_008AED: 29 03 00 AND.W #$0003
CODE_008AF0: 0A ASL
CODE_008AF1: A8 TAY
CODE_008AF2: 68 PLA
CODE_008AF3: 29 FE 00 AND.W #$00FE
CODE_008AF6: 59 B4 8A EOR.W DATA_008AB4,Y
CODE_008AF9: 18 CLC
CODE_008AFA: 79 BC 8A ADC.W DATA_008ABC,Y
CODE_008AFD: AA TAX
CODE_008AFE: 20 2B 8B JSR.W CODE_008B2B
CODE_008B01: C0 04 00 CPY.W #$0004
CODE_008B04: 90 04 BCC CODE_008B0A
CODE_008B06: 49 FF FF EOR.W #$FFFF
CODE_008B09: 1A INC A
CODE_008B0A: 85 30 STA $30


Also, when I made that Card Crusher effect, I believed I disabled $38-$39's functions and used $2E-$2F and $34-$35 for the scaling instead, to get a more accurate result.
There's also an algorithm for the $38-$39 conversion into $2E-$2F and $34-$35. It's in the same routine as the one I quoted.

Also, $211F-$2120 are pretty important since they define the Center X and Y position. This is the point from which the entire playing field rotates and scales.
This might also affect the shape of the parallellogram in some way, if shear X or shear Y were to be affected.

Anoter note: Their default is #$0000.

As for the scaling registers, they seem to flip the playing field horizontally AND vertically, or at least in SMW, if bit 15 is set.
#$7FFF and #$8000 are the smallest possible values, but #$8000 is flipped horizontally and vertically compared to #$7FFF.
You could've noticed this in card.ips.

--------------------
--------> Don't follow "Find Roy's Dignity", my hack. Because it's pretty outdated. <--------
HyperHacker
That sounds suspiciously like a signed value. #$7FFF = 32767, #$8000 = -32768. (Or more likely some fixed-point numbers, but same idea.)
My projects - ROM hacks, Gameshark codes, homebrew, useful apps, online 65816 disassembler
SCAM: HomebreWare and Wiiunlocker
Generation over 9000: The first time you see this, put a meme in your signature.
Yes, it is. (That's why #$8000 isn't equal to #$0000, but to #$7FFF instead)
The same applies for shear, IIRC.

--------------------
--------> Don't follow "Find Roy's Dignity", my hack. Because it's pretty outdated. <--------
Edited with some of Gekko's findings from the Developement manual, about the format as well as how to rotate things.

I also added some minor corrections and new facts. Not really quite as noticeable, however.
Yeah, the SMW engine has addresses specifically there to handle to mode 7, addresses 2A - 3C I do believe, which as Roy stated are mirrors of the mode 7 hardware registers. Something I was wondering, since these addresses receive two bytes of information, why wouldn't you switch to 16-bit addressing? For example, when messing with $211B:

LDA #$00
XBA
LDA #$4F
REP #$20
STA $211B
SEP #$20

    ; load A with High Byte
    ; Swap upper 16-bit value of A with lower 16-bit value of A
    ; load A with Low Byte
    ; Switch to 16-bit addressing
    ; Store 16-bit value in A to $211B
    ; Switch back to 8-bit addressing


Thought I would point that out. I had no idea that one can get away with writing the low byte to one of the mode 7 registers, and then immediately writing the high byte to the same register afterwards. All in all, these are some excellent discoveries - especially the "Write Twice" method!


You don't want to do this, since this will not store a 16-bit value to $211B, but an 8-bit (low byte) value to $211B and an 8-bit (high byte) value to $211C. This is one of the reasons why there are mirrors placed in the NMI - so we don't have to deal with that crap.


--------------------
--------> Don't follow "Find Roy's Dignity", my hack. Because it's pretty outdated. <--------
Holy crap, thanks for explaining that Roy! No wonder my mode 7 sprite didn't do what I wanted it to do. This thread is pure gold for explaining how to properly handle writing values to the mode 7 registers, as well as explaining the importance of the SMW mirrored registers (I originally thought they were useless). Thanks for posting your findings guys! It's a GREAT help!
Cool topic. All the stuff to operate mode7 is actually in regs.txt although if you don't understand the matrix arithmetic and trigonometry behind it it's all gibberish to you. When I first told roy I just used the terms 'shear x/y' and such because alot of those things are really easy to operate based on what they appear to do on screen. regs.txt appears to be geared towards emulator authors so it won't do much hand holding.
hard to keep up with this lol. wow maxx, that must have tooken you a long time to type XD

--------------------
Oh...that was meant to be a joke?
Moved this to the Tutorials forum since I think it better fits there (and this is hardly related to SMW data repository anyway).

--------------------
My blog. I could post stuff now and then
No idea about Mode 7 but the images are dead, someone'll have to look at that sometime.

--------------------
Your layout has been removed.
Pages: « 1 »
Forum Index - SMW Hacking - SMW Hacking Help - Tutorials - Old Tutorials - Mode 7 Findings/Info Tutorial

The purpose of this site is not to distribute copyrighted material, but to honor one of our favourite games.

Copyright © 2005 - 2020 - SMW Central
Legal Information - Privacy Policy - Link To Us


Menu

Follow Us On

  • YouTube
  • Twitch
  • Twitter

Affiliates

  • Super Mario Bros. X Community
  • ROMhacking.net
  • Mario Fan Games Galaxy