After fiddling around with Mode 7 a bit and asking people, I finally figured out how to upload Mode 7 GFX and use it. So here is a tutorial of my findings.
Starting Mode 7
The first thing you should do is apply this patch. This will allow you to use Mode 7 outside of boss rooms. Thanks HungFluDu!! After that download LevelASM and put this in the main level code:
What this does is set the BG mode, in this case 07, which is Mode 7. You could also set it to other values to activate other level modes. The format is like this:
Uploading GFX
Good now to actually upload the GFX. For now, you can just use these. All you need from there is pwvram.bin and pwcg.bin.
Now then to the actual code. The first thing you want to do is store #$80 to $2115, like this:
this will increase on writing to $2119 or reading from $213A. Now we need to switch to 16-bit mode for the X register. So now we should have this:
after that we need to tell the VRAM where to write. Since Mode 7 is layer one we can store #$0000 to $2116, like so:
Next we store #$01 to $43x0 telling us to store to two registers, but only write once.
now we store #$18 to $43x1, which is our destination to write to.
now we store our data to $43x2-4.
and your table can be this:
now we need to get the size of our data, to do this:
1) Right click on your file and go to Properties (the last option)
2) Search for "size", not "size in disc"
3) Take this value and convert it to hex on the calculator
now store this to $43x5.
and finally we start the DMA transfer.
our code should now look like this:
Uploading Palette
Now don't test this code just yet, we still need to upload the palette. It's pretty much the same thing for the GFX, except for a few small differences. Study this code:
Now try it out. If it worked you successfully started Mode 7, and uploaded GFX with a palette. If not, did you stick those codes in LevelINIT? If its still not working try using the GFX in a boss room and see if it works. If its working there but not outside of a boss romm, mostly likely you'll have to fiddle around with Layer 1 X and Y position, scaling, Center X and Y position, and maybe even rotation.
Doing Things With It
Now what if you want to do things like... rotate it? Well try this:
Put that in LevelASM and now it should rotate. If your wondering what I did all I did was INC $36 every other frame. Here is a list of Mode 7 mirrors that might come in handy, note that they are all 16-bit addresses:
Making Your Own GFX
Now what if you want to make your own mode 7 GFX? Well what I do is use Pcx2snes.
Once you change your .pcx file to mode 7 gfx format you should get a .mp7, .clr, and .pc7 file. After that its just a matter of uploading each of these files separately. The .clr file is your palette file, so you can use that code above to upload that, the .pc7 is your GFX file, and the .mp7 file is your tilemap file. You can either combined these (which I'm not sure how to do), or just upload each one separately.
Interaction
Now how do you get layer 1 to interact with mario in mode 7? Well truthfully I never tried, but I suspect it would be as easy as, First checking if the mode 7 scaling is so-so high and wide, then checking if Mario and layer 1 have the same x and y position.
EXTBG
Apparently its also possible to have more than one layer when Mode 7 is on. Normally your limited to Layer 1 and the sprite layer, but apparently setting $2133 to #$40, you can use layer 2 as well. I'm not sure if anyone has ever tried it yet, but it seems pretty cool. This is what I know about it, taken from regs.txt:
-------------------------------------------
Phew!
Thanks to these people!
Roy
undefined3
HuFlungDu
Maxx
People on #serioushax
Starting Mode 7
The first thing you should do is apply this patch. This will allow you to use Mode 7 outside of boss rooms. Thanks HungFluDu!! After that download LevelASM and put this in the main level code:
Code
LDA #$07 STA $3E
What this does is set the BG mode, in this case 07, which is Mode 7. You could also set it to other values to activate other level modes. The format is like this:
Originally posted by RAM Map
Background mode select applied with IRQ below status bar (so the area above IRQ is not affected by this). Format: 4321pmmm.
4321 = Layer 1/2/3/4 uses 8x8 tiles when clear, 16x16 tiles when set; p = Layer 3 absolute priority (only in background mode 1); mmm = background mode # (0-7).
Mirror of SNES register $2105.
4321 = Layer 1/2/3/4 uses 8x8 tiles when clear, 16x16 tiles when set; p = Layer 3 absolute priority (only in background mode 1); mmm = background mode # (0-7).
Mirror of SNES register $2105.
Uploading GFX
Good now to actually upload the GFX. For now, you can just use these. All you need from there is pwvram.bin and pwcg.bin.
Now then to the actual code. The first thing you want to do is store #$80 to $2115, like this:
Code
LDA #$80 ; \ Increase on $2119 write. STA $2115 ; /
this will increase on writing to $2119 or reading from $213A. Now we need to switch to 16-bit mode for the X register. So now we should have this:
Code
LDA #$80 ; \ Increase on $2119 write. STA $2115 ; / REP #$10
after that we need to tell the VRAM where to write. Since Mode 7 is layer one we can store #$0000 to $2116, like so:
Code
LDX #$0000 STX $2116
Next we store #$01 to $43x0 telling us to store to two registers, but only write once.
Code
LDA #$01 ;\ Set mode to... STA $4300 ;/ 2 regs write once
now we store #$18 to $43x1, which is our destination to write to.
Code
LDA #$18 ;\ STA $4301 ;/ writing to $2118 AND $2119
now we store our data to $43x2-4.
Code
LDX.w #pwvram ;\ STX $4302 ; | LDA.b #pwvram>>16 ; | bank where our data is STA $4304 ;/
and your table can be this:
Code
pwvram: incbin pwvram.bin
now we need to get the size of our data, to do this:
1) Right click on your file and go to Properties (the last option)
2) Search for "size", not "size in disc"
3) Take this value and convert it to hex on the calculator
now store this to $43x5.
Code
LDX #$8000 ;\ size of our data STX $4305 ;/ REP #$10
and finally we start the DMA transfer.
Code
LDA.b #$01 ;\ start DMA STA.w $420B ;/ transfer
our code should now look like this:
Code
LDA #$07 STA $3E LDA #$80 ; \ Increase on $2119 write. STA $2115 ; / REP #$10 LDX #$0000 STX $2116 LDA #$01 ;\ Set mode to... STA $4300 ;/ 2 regs write once LDA #$18 ;\ STA $4301 ;/ writing to $2118 AND $2119 LDX.w #pwvram ;\ STX $4302 ; | LDA.b #pwvram>>16 ; | bank where our data is STA $4304 ;/ LDX #$8000 ;\ size of our data STX $4305 ;/ SEP #$10 LDA.b #$01 ;\ start DMA STA.w $420B ;/ transfer RTS pwvram: incbin pwvram.bin
Uploading Palette
Now don't test this code just yet, we still need to upload the palette. It's pretty much the same thing for the GFX, except for a few small differences. Study this code:
Code
STZ $2121 ; This sets the word address (i.e. color) which will be affected by $2122 and $213b. STZ $4300 ; set mode to 1 register write once LDA #$22 ;\ writing to... STA $4301 ;/ 2122 REP #$10 LDX.w #pwcg ;\ STX $4302 ; | LDA.b #pwcg>>16 ; | bank where our data is STA $4304 ;/ LDX #$0200 ;\ size of our data STX $4305 ;/ LDA #$01 ;\ start DMA transfer STA $420B ;/ pwcg: incbin pwcg.bin
Now try it out. If it worked you successfully started Mode 7, and uploaded GFX with a palette. If not, did you stick those codes in LevelINIT? If its still not working try using the GFX in a boss room and see if it works. If its working there but not outside of a boss romm, mostly likely you'll have to fiddle around with Layer 1 X and Y position, scaling, Center X and Y position, and maybe even rotation.
Doing Things With It
Now what if you want to do things like... rotate it? Well try this:
Code
LDA $13 AND #$03 BNE + INC $36 + RTS
Put that in LevelASM and now it should rotate. If your wondering what I did all I did was INC $36 every other frame. Here is a list of Mode 7 mirrors that might come in handy, note that they are all 16-bit addresses:
Originally posted by RAM Map
$2A - Mode 7 Center X position. Mirror of SNES register $211F, + #$0080.
$2C - Mode 7 Center Y position. Mirror of SNES register $2120, + #$0080.
$2E - Mode 7 matrix parameter A. Mirror of SNES register $211B.
$30 - Mode 7 matrix parameter B. Mirror of SNES register $211C.
$32 - Mode 7 matrix parameter C. Mirror of SNES register $211D.
$34 - Mode 7 matrix parameter D. Mirror of SNES register $211E.
$36 - Mode 7 rotation. Its values are calculated and stored into the respective Mode 7 parameter mirrors at $7E:002E through $7E:0035.
Values #$0000 through #$01FF are all different values, after that it's the same pattern - that is, if you increase this 16-bit address by #$0200, there is a 360 degree rotation.
$38 - Mode 7 scaling; that is, making Layer 1 shrink or grow. Its values are calculated and stored into the respective Mode 7 parameter mirrors at $7E:002E through $7E:0035. The first byte - $7E:0038 - is used for horizontal scaling, whereas the second byte - $7E:0039 - is used for vertical scaling. Default value is #$20. The closer to #$00, the more the layer grows, the further from #$00, the more the layer shrinks. Value #$10 makes the layer twice as large as value #$20, value #$40 makes the layer twice as small as value #$20, etc.
$3A - Mode 7 Layer 1 X position. Mirror of SNES register $210D.
$3C - Mode 7 Layer 1 Y position. Mirror of SNES register $210E.
$2A - Mode 7 Center X position. Mirror of SNES register $211F, + #$0080.
$2C - Mode 7 Center Y position. Mirror of SNES register $2120, + #$0080.
$2E - Mode 7 matrix parameter A. Mirror of SNES register $211B.
$30 - Mode 7 matrix parameter B. Mirror of SNES register $211C.
$32 - Mode 7 matrix parameter C. Mirror of SNES register $211D.
$34 - Mode 7 matrix parameter D. Mirror of SNES register $211E.
$36 - Mode 7 rotation. Its values are calculated and stored into the respective Mode 7 parameter mirrors at $7E:002E through $7E:0035.
Values #$0000 through #$01FF are all different values, after that it's the same pattern - that is, if you increase this 16-bit address by #$0200, there is a 360 degree rotation.
$38 - Mode 7 scaling; that is, making Layer 1 shrink or grow. Its values are calculated and stored into the respective Mode 7 parameter mirrors at $7E:002E through $7E:0035. The first byte - $7E:0038 - is used for horizontal scaling, whereas the second byte - $7E:0039 - is used for vertical scaling. Default value is #$20. The closer to #$00, the more the layer grows, the further from #$00, the more the layer shrinks. Value #$10 makes the layer twice as large as value #$20, value #$40 makes the layer twice as small as value #$20, etc.
$3A - Mode 7 Layer 1 X position. Mirror of SNES register $210D.
$3C - Mode 7 Layer 1 Y position. Mirror of SNES register $210E.
Making Your Own GFX
Now what if you want to make your own mode 7 GFX? Well what I do is use Pcx2snes.
Once you change your .pcx file to mode 7 gfx format you should get a .mp7, .clr, and .pc7 file. After that its just a matter of uploading each of these files separately. The .clr file is your palette file, so you can use that code above to upload that, the .pc7 is your GFX file, and the .mp7 file is your tilemap file. You can either combined these (which I'm not sure how to do), or just upload each one separately.
Interaction
Now how do you get layer 1 to interact with mario in mode 7? Well truthfully I never tried, but I suspect it would be as easy as, First checking if the mode 7 scaling is so-so high and wide, then checking if Mario and layer 1 have the same x and y position.
EXTBG
Apparently its also possible to have more than one layer when Mode 7 is on. Normally your limited to Layer 1 and the sprite layer, but apparently setting $2133 to #$40, you can use layer 2 as well. I'm not sure if anyone has ever tried it yet, but it seems pretty cool. This is what I know about it, taken from regs.txt:
Originally posted by regs.txt
2133 wb+++- SETINI - Screen Mode/Video Select
se--poIi
e = Mode 7 EXTBG ("Extra BG"). When this bit is set, you may enable
BG2 on Mode 7. BG2 uses the same tile and character data as BG1,
but interprets the high bit of the color data as a priority for the
pixel.
-----------------------------------------------
Mode 7's EXTBG mode allows you to enable BG2, which uses the same
tilemap and character data as BG1 but interprets bit 7 of the pixel
data as a priority bit. BG2 also has some oddness to do with some
of the per-BG registers below.
-----------------------------------------------
Mode 7 EXTBG. In this mode, you get a BG2 with 128 colors, which uses the same tilemap and
character data as BG1 but interprets the high bit of the pixel as a priority
bit. The priority map is:
Sprites with priority 3
Sprites with priority 2
BG2 pixels with priority 1
Sprites with priority 1
BG1
Sprites with priority 0
BG2 pixels with priority 0
Note that the BG1 pixels (if BG1 is enabled) will usually completely obscure
the low-priority BG2 pixels.
BG2 uses the Mode 7 scrolling registers ($210d-e) rather than the 'normal' BG2
ones ($210f-10). Subscreen, pseudo-hires, math, and clip windows work as
normal; keep in mind OBJ and that you can do things like enable BG1 on main and
BG2 on sub if you so desire. Mosaic is somewhat weird, see the section on
Mosaic below.
Note that BG1, being a 256-color BG, can do Direct Color mode (in this case, of
course, there is no palette value so you're limited to 256 colors instead of
2048). BG2 does not do direct color mode, since it is only 7-bit.
2133 wb+++- SETINI - Screen Mode/Video Select
se--poIi
e = Mode 7 EXTBG ("Extra BG"). When this bit is set, you may enable
BG2 on Mode 7. BG2 uses the same tile and character data as BG1,
but interprets the high bit of the color data as a priority for the
pixel.
-----------------------------------------------
Mode 7's EXTBG mode allows you to enable BG2, which uses the same
tilemap and character data as BG1 but interprets bit 7 of the pixel
data as a priority bit. BG2 also has some oddness to do with some
of the per-BG registers below.
-----------------------------------------------
Mode 7 EXTBG. In this mode, you get a BG2 with 128 colors, which uses the same tilemap and
character data as BG1 but interprets the high bit of the pixel as a priority
bit. The priority map is:
Sprites with priority 3
Sprites with priority 2
BG2 pixels with priority 1
Sprites with priority 1
BG1
Sprites with priority 0
BG2 pixels with priority 0
Note that the BG1 pixels (if BG1 is enabled) will usually completely obscure
the low-priority BG2 pixels.
BG2 uses the Mode 7 scrolling registers ($210d-e) rather than the 'normal' BG2
ones ($210f-10). Subscreen, pseudo-hires, math, and clip windows work as
normal; keep in mind OBJ and that you can do things like enable BG1 on main and
BG2 on sub if you so desire. Mosaic is somewhat weird, see the section on
Mosaic below.
Note that BG1, being a 256-color BG, can do Direct Color mode (in this case, of
course, there is no palette value so you're limited to 256 colors instead of
2048). BG2 does not do direct color mode, since it is only 7-bit.
-------------------------------------------
Phew!
Thanks to these people!
Roy
undefined3
HuFlungDu
Maxx
People on #serioushax