SNES Splatoon (How do I shot HiROM?)
Moderator: Moderators
Forum rules
- For making cartridges of your Super NES games, see Reproduction.
- Drew Sebastino
- Formerly Espozo
- Posts: 3496
- Joined: Mon Sep 15, 2014 4:35 pm
- Location: Richmond, Virginia
Re: SNES Splatoon (Not Even A Demo Yet Though...)
Oh yeah, how do you multiply on the SNES? I looked at the SNES hardware register page on superfamicom.org and it lists the multiplicand and multiplier registers for the CPU, but it doesn't seem to for the 8x16 multiplication in the PPU for mode 7. However, it does list the registers that hold the product. Obviously, we're not dealing with Mode 7 here so it should be safe.
Re: SNES Splatoon (Not Even A Demo Yet Though...)
The part that talks about the result registers tells you what the inputs are. They're just part of the Mode 7 matrix.
This is a neat idea, though. Good thing it's not me conceptualizing it - I'd have insisted on doing a full 3D version with the Super FX2 and software texture re-rendering or some nonsense... with explicit XBAND support, of course... I haven't yet learned that there's a difference between what a SNES could do and what a SNES should do...
This is a neat idea, though. Good thing it's not me conceptualizing it - I'd have insisted on doing a full 3D version with the Super FX2 and software texture re-rendering or some nonsense... with explicit XBAND support, of course... I haven't yet learned that there's a difference between what a SNES could do and what a SNES should do...
- Drew Sebastino
- Formerly Espozo
- Posts: 3496
- Joined: Mon Sep 15, 2014 4:35 pm
- Location: Richmond, Virginia
Re: SNES Splatoon (Not Even A Demo Yet Though...)
Wow, I'm an idiot...93143 wrote:The part that talks about the result registers tells you what the inputs are. They're just part of the Mode 7 matrix.
What does it mean by "write twice" though? Is it just that it's two 8 bit writes, or one 16 bit write?Registers 211b through 2120 are 16 bits wide.
0x211B is also used as the 16-bit multiplicand for registers 0x2134-6 (write twice)
0x211C is also used as the 8-bit multiplier for registers 0x2134-6
Anyway, I think I figured out how to calculate the vertical offset: You take the YPosition, divide it by 8 by bit shifting, multiply this number by the amount of pixels in the buffer horizontally times the amount of data per tile (pre calculated obviously) store this, load YPosition again, "and" this to where only the first 3 bits are left, multiply this number times the amount of data per 8 pixels (2 for 2 bytes) and then add the result of the previous thing to this for the final result. I'll probably code this tomorrow and try and do some other stuff to it also.
Just thinking, another thing that made me thing about it is how the maps are mostly 2D but with elevation differences. I wonder how well you could port the maps in this game to Doom...93143 wrote:This is a neat idea, though.
Are you regretting working with the Super FX? Although something like XBAND is obviously out of the question, making a local cable for hooking multiple SNES's together would be awesome. I was actually thinking about this in the old discussion about how a 2 player F-Zero wouldn't be (easily) possible because of only having one tilemap.93143 wrote: Good thing it's not me conceptualizing it - I'd have insisted on doing a full 3D version with the Super FX2 and software texture re-rendering or some nonsense... with explicit XBAND support, of course... I haven't yet learned that there's a difference between what a SNES could do and what a SNES should do...
Wait... SNES Doom could be 2 player!? https://www.youtube.com/watch?v=-P3JGxBNUyM I didn't think any game actually worked around the XBAND. It's not like there's a game built around the Game Genie anyway.
Re: SNES Splatoon (Not Even A Demo Yet Though...)
Talking purely about mode 7 crap:Espozo wrote:What does it mean by "write twice" though? Is it just that it's two 8 bit writes, or one 16 bit write?Registers 211b through 2120 are 16 bits wide.
0x211B is also used as the 16-bit multiplicand for registers 0x2134-6 (write twice)
0x211C is also used as the 8-bit multiplier for registers 0x2134-6
It means two 8-bit writes, in the order of low byte followed by high byte of whatever 16-bit multiplicand value you have. The 16-bit value is signed, so the MSB of the 16-bit value defines signage.
A native 16-bit write to $211B would write to both registers $211B and $211C, which isn't what you want.
Proper order of operation:
1. Write 8-bit value (lower byte of multiplicand) to $211b
2. Write 8-bit value (upper byte of multiplicand) to $211b
3. Write 8-bit value (multiplier) to $211c
4. Read $2134, $2135, $2136 for results
I've never done mode 7 stuff, and these registers are actually described more thoroughly in the official documentation, including mentioning something about decimal placement.
If what you're looking for is literal/absolute unsigned multiplication or division, then those can be done through different registers. For 8-bit multiplication (with a 16-bit result):
1. Write $4202 (multiplicand) (8-bit)
2. Write $4203 (multiplier) (8-bit)
3. Wait 8 CPU cycles
4. Read $4216 (result or "product") (16-bit)
For division:
1. Write $4204 (dividend) (16-bit)
2. Write $4206 (divisor) (8-bit)
3. Wait 16 CPU cycles
4. Read $4214 (quotient) (16-bit)
5. Read $4216 (remainder) (16-bit)
The order in which you write to these registers matters.
"Wait N CPU cycles" means you won't have a valid result (in $4216/4217) until N number of CPU cycles has passed. You can do other things in the meantime (i.e. you don't need to do 8 or 16 cycles worth of NOPs unless you really want to).
Re: SNES Splatoon (Not Even A Demo Yet Though...)
No, no. It's just that in this case, judging by how Doom turned out, I imagine it'd probably be better to go with a demake rather than trying for a direct port. In the case of the shmup I'm porting, based on my calculations I think I can pretty much preserve the gameplay and (to an extent) the graphical look and feel without having to redesign it to fit on the platform. Splatoon is a different matter.Espozo wrote:Are you regretting working with the Super FX?
Why add a coprocessor (thus "cheating") and all the programming headaches of a 3D Super FX game in order to produce an end product that looks and plays worse than a 2D version that would only have needed the base hardware? Not to mention that while a 2D version would be its own thing, a 3D version would just be a bad version of the Wii U game.
As I said, I'm speaking against my instincts here...
If I recall correctly, the ALU multiplier does give a valid result early if the numbers being multiplied are small. Taz-Mania relies on this behaviour, and I believe higan emulates it correctly. As far as I know, no other emulator even bothers with the delay.koitsu wrote:"Wait N CPU cycles" means you won't have a valid result (in $4216/4217) until N number of CPU cycles has passed.
- Drew Sebastino
- Formerly Espozo
- Posts: 3496
- Joined: Mon Sep 15, 2014 4:35 pm
- Location: Richmond, Virginia
Re: SNES Splatoon (Not Even A Demo Yet Though...)
Wait, I'm an idiot, instead of leaving empty space at the graphic for the splat at the bottom and the top, I could just still draw the splat tile by tile, but I'd have special code for each tile height. It would go through the first tile height loop for one whole row, then it would go to the second for more than likely multiply rows and this would undoubtedly be 8 pixels tall, and then it would go to the last loop. Although there'd be slightly more preparation at the beginning for this, it would probably still save time overall and a little memory too. I'm working on it now.
Re: SNES Splatoon (Not Even A Demo Yet Though...)
You know, even F-Zero X and GX don't have multiplayer GPs like Mario Kart. It's always head-to-head with maybe a couple of CPU opponents. And X provides a precedent for streamlining the graphics in multiplayer modes. In that context, it seems less unreasonable to use double-buffered quarter-maps (possibly with reduced texture resolution to help ensure that the edges of a quarter-map are always out of sight) and devote 4 KB of DMA per frame to tilemap updates; there should be enough room for software-scaled sprites at a reasonable frame rate if there can only ever be 6 of them.Espozo wrote:I was actually thinking about this in the old discussion about how a 2 player F-Zero wouldn't be (easily) possible because of only having one tilemap.
And I'm sure the SA-1 in an F-Zero SX cart could spare the ~6% of a frame it would take to build a half-dual-quarter-map for both players with repeated ROM-to-BWRAM DMA transfers, so it's ready for an easy one-shot DMA to VRAM during VBlank. You wouldn't need to waste VBlank time on Mode 7 HDMA tables for non-flat courses either, since unlike the Super FX (which either hogs its memory or can't use it at all) the SA-1 can share memory with the S-CPU, so if you build the tables in BWRAM there's no need to move them.
...see, that's how I normally think about SNES development (and I've barely scratched the surface of what I'd want to do with that game). I'm apparently a big fan of enhancement chips. I know lots of people consider it cheating, but I just don't feel it...
- Attachments
-
- 2pmap_fzero_halfupdate.png (520 Bytes) Viewed 3012 times
Re: SNES Splatoon (Not Even A Demo Yet Though...)
There's a big difference between the kind of chips that were released at a time and a coprocessor based on modern hardware.
- Drew Sebastino
- Formerly Espozo
- Posts: 3496
- Joined: Mon Sep 15, 2014 4:35 pm
- Location: Richmond, Virginia
Re: SNES Splatoon (Not Even A Demo Yet Though...)
I know. We went over this, it's just at the time I didn't know. Anyway, I'm not interested in doing that, at the moment anyway.93143 wrote:You know, even F-Zero X and GX don't have multiplayer GPs like Mario Kart. It's always head-to-head with maybe a couple of CPU opponents. And X provides a precedent for streamlining the graphics in multiplayer modes. In that context, it seems less unreasonable to use double-buffered quarter-maps (possibly with reduced texture resolution to help ensure that the edges of a quarter-map are always out of sight) and devote 4 KB of DMA per frame to tilemap updates; there should be enough room for software-scaled sprites at a reasonable frame rate if there can only ever be 6 of them.
Well, I mean, I wouldn't compare a game using software rendering vs. the Super FX... It's its own category.93143 wrote:I know lots of people consider it cheating, but I just don't feel it...
Well, this is an entirely different category.Sik wrote:There's a big difference between the kind of chips that were released at a time and a coprocessor based on modern hardware.
Anyway, about having the code for each tile height, I think I'll have the code for an 5 pixel height and then an 8 pixel height and then a 3 pixel height grouped together because it's faster, but I'm also lazy...
Re: SNES Splatoon (Not Even A Demo Yet Though...)
I'm sorry; I'm not intending to drag your thread off topic. I had just realized that with an SA-1, the map preparation actually seems quite tractable. And since you had mentioned it, and I had been generating (largely useless) noise over my tendency to want to use special chips with everything...
I might be interested in doing it. But probably not until after my current project, which is going to take a while...
I've posted my realization to the F-Zero 2-player thread, where it belongs.
I might be interested in doing it. But probably not until after my current project, which is going to take a while...
I've posted my realization to the F-Zero 2-player thread, where it belongs.
- Drew Sebastino
- Formerly Espozo
- Posts: 3496
- Joined: Mon Sep 15, 2014 4:35 pm
- Location: Richmond, Virginia
Re: SNES Splatoon (Not Even A Demo Yet Though...)
It's fine. Most of the time, I derail my own topics anyway... 
Anyway, what I said earlier about having the unrolled loop thing, (That's what an unrolled loop is, isn't it?) that's definitely the best option. I forgot how drawing four pixels at the top of a tile and drawing four at the bottom aren't exactly the same thing...
Also, I have the graphics format down for how I want the splats. it's going to alternate between a word that's a mask and a word that's the actual pattern, like I always thought I would. However, the main thing is I'll have it to where when the tile's completed, instead of going to the one on the right until the end of the row, it'll go all the way down and then over one. The reason for this is that regardless of vertical position of the splat, every line down is incremented by the same amount of data, which isn't the case for if it were the normal way because of tile boundaries. Luckily, I have no homework or tests so I can work on this again. I did not expect this to be even remotely as difficult as it is...
Also, are you squidding (sorry...
) me Nintendo?

There are people in territories outside of Japan that play this game... Why aren't we allowed to have cheap gummies and crappy plastic watches andpicture books mangas and admittedly cool plushies and t-shirts? 
Anyway, what I said earlier about having the unrolled loop thing, (That's what an unrolled loop is, isn't it?) that's definitely the best option. I forgot how drawing four pixels at the top of a tile and drawing four at the bottom aren't exactly the same thing...
Also, I have the graphics format down for how I want the splats. it's going to alternate between a word that's a mask and a word that's the actual pattern, like I always thought I would. However, the main thing is I'll have it to where when the tile's completed, instead of going to the one on the right until the end of the row, it'll go all the way down and then over one. The reason for this is that regardless of vertical position of the splat, every line down is incremented by the same amount of data, which isn't the case for if it were the normal way because of tile boundaries. Luckily, I have no homework or tests so I can work on this again. I did not expect this to be even remotely as difficult as it is...
Also, are you squidding (sorry...

There are people in territories outside of Japan that play this game... Why aren't we allowed to have cheap gummies and crappy plastic watches and
- Drew Sebastino
- Formerly Espozo
- Posts: 3496
- Joined: Mon Sep 15, 2014 4:35 pm
- Location: Richmond, Virginia
Re: SNES Splatoon (Not Even A Demo Yet Though...)
Here's the rendering code for a splat that's been shifted down 3 pixels. (If the splat is partially off the screen vertically, it may skip the first tile row code and jump to the second or third set. This would be coded elsewhere.) Holy crap... I didn't expect it to be even a fraction as difficult to make as this, and the worst part is that I have to make this six more times... (The one for if the tile is directly in the right spot won't be nearly as difficult) I know this is a giant waste of memory, but frankly, I'm going to be more worried about my sanity in copying this several times... In the jump table for selecting what code to jump to because of the different vertical heights, I'll have all of them point to this, and if it works, I'll copy it. I need to fix the preparation code for this now. Anyway...
I hope it works... 
Code: Select all
start_draw_offset_3_splat:
ldx SplatBufferPosition
cpx EndOfBuffer
bcs draw_offset_3_splat_done
ldy SplatGraphicOffset
lda SplatGraphicOffset
clc
adc #$0014
sta SplatGraphicOffset
draw_offset_3_splat_first_rows:
lda Buffer+6,x
and #$0000,y
ora #$0002,y
sta Buffer+6,x
lda Buffer+8,x
and #$0004,y
ora #$0006,y
sta Buffer+8,x
lda Buffer+10,x
and #$0008,y
ora #$000A,y
sta Buffer+10,x
lda Buffer+12,x
and #$000C,y
ora #$000E,y
sta Buffer+12,x
lda Buffer+14,x
and #$0010,y
ora #$0012,y
sta Buffer+14,x
inc TilesDrawnHorizontally
cmp SplatTileWidth
bcs start_offset_3_splat_middle_rows
txa
clc
adc #$0010
tax
tya
clc
adc SplatDataHeight
tay
bra draw_offset_3_splat_first_rows
;======================================================================
start_draw_offset_3_splat_middle_rows:
ldx SplatBufferPosition
stz TilesDrawnHorizontally
txa
clc
adc DataPerRowInBuffer
tax
ldy SplatGraphicOffset
draw_offset_3_splat_middle_rows:
lda Buffer,x
and #$0000,y
ora #$0002,y
sta Buffer,x
lda Buffer+2,x
and #$0004,y
ora #$0006,y
sta Buffer+2,x
lda Buffer+4,x
and #$0008,y
ora #$000A,y
sta Buffer+4,x
lda Buffer+6,x
and #$000C,y
ora #$000E,y
sta Buffer+6,x
lda Buffer+8,x
and #$0010,y
ora #$0012,y
sta Buffer+8,x
lda Buffer+10,x
and #$0014,y
ora #$0016,y
sta Buffer+10,x
lda Buffer+12,x
and #$0018,y
ora #$001A,y
sta Buffer+12,x
lda Buffer+14,x
and #$001C,y
ora #$001E,y
sta Buffer+14,x
lda FullTilesDrawnVertically
cmp FullTileSplatHeight
bcs start_draw_offset_3_splat_last_rows
inc TilesDrawnHorizontally
cmp SplatTileWidth
bcs offset_3_splat_next_row
txa
clc
adc #$0010
tax
tya
clc
adc SplatDataHeight
tay
bra draw_offset_3_splat_middle_rows
offset_3_splat_next_row:
cpx EndOfBuffer
bcs draw_offset_3_splat_done
inc FullTilesDrawnVertically
inc TilesDrawnHorizontally
txa
clc
adc DataPerRowInBuffer
tax
lda SplatGraphicOffset
clc
adc #$0020
sta SplatGraphicOffset
tay
bra draw_offset_3_splat_middle_rows
;======================================================================
start_draw_offset_3_splat_last_rows:
ldx SplatBufferPosition
cpx EndOfBuffer
bcs draw_offset_3_splat_done
stz TilesDrawnHorizontally
txa
clc
adc DataPerRowInBuffer
tax
ldy SplatGraphicOffset
draw_offset_3_splat_last_rows:
lda Buffer,x
and #$0000,y
ora #$0002,y
sta Buffer,x
lda Buffer+2,x
and #$0004,y
ora #$0006,y
sta Buffer+2,x
lda Buffer+4,x
and #$0008,y
ora #$000A,y
sta Buffer+4,x
inc TilesDrawnHorizontally
cmp SplatTileWidth
bcs draw_offset_3_splat_done
txa
clc
adc #$0010
tax
tya
clc
adc SplatDataHeight
tay
bra draw_offset_3_splat_last_rows-
psycopathicteen
- Posts: 3001
- Joined: Wed May 19, 2010 6:12 pm
Re: SNES Splatoon (Not Even A Demo Yet Though...)
Address don't have a #.
- Drew Sebastino
- Formerly Espozo
- Posts: 3496
- Joined: Mon Sep 15, 2014 4:35 pm
- Location: Richmond, Virginia
Re: SNES Splatoon (Not Even A Demo Yet Though...)
I know. Where did I get that wrong?
Also, you actually read it?
Also, you actually read it?
- Drew Sebastino
- Formerly Espozo
- Posts: 3496
- Joined: Mon Sep 15, 2014 4:35 pm
- Location: Richmond, Virginia
Re: SNES Splatoon (Not Even A Demo Yet Though...)
I think this should be the top, "preparation" part. It's got initialization stuff I still need to do, but it's mostly done if there aren't any problems I find with it. I still need to code where it says what tiles need to be uploaded, but I'll try and upload the tiles from a fixed position and if it works correctly, I'll implement it then. I also need to implement the splat being only partially on the buffer, but I have no clue how I want to do that. Oh yeah, and collision detection. Some tiles would be don't draw at all, and then some would be draw with an extra mask for diagonal walls and stuff like that. If I ever get this far, I kind of wonder how I'll handle collision detection with the player and the ink. I'll probably just check one pixel in the middle of them and see what color it is. Anyway...
...I just noticed how the Splatoon candy says "ikasu", just like on the Batman squid snacks... Well, at least it makes sense here. 
Code: Select all
lda SplatRequestTable+YPosition,x
and #$0000000000000111
asl
bne continue_calculating_vertical_offset
sta SplatSubTileYPosition
continue_calculating_vertical_offset:
lda SplatRequestTable+YPosition,x
ror
ror
ror
sep #$20 ;A=8
sta $4202
lda DataPerRowInBuffer
sta $4203 ;Apparently, there's some sort of waiting time for this?
lda SplatRequestTable+Height,x
sta FullTileSplatHeight
asl
asl
asl
asl
asl
sta DataSplatHeight
lda SplatRequestTable+Width,x
sta TileSplatWidth
rep #$30 ;A=16, X/Y=16
lda $4216
sta SplatBufferPosition
;======================================================================
lda SplatRequestTable+XPosition,x
ror
ror
and #%0011111111111111
clc
adc SplatBufferPosition
sta SplatBufferPosition
lda SplatRequestTable+XPosition,x
and #%0000000000000111
bne continue_calculating_x_offset
inc TileSplatWidth
lda SplatRequestTable+XPosition,x
and #%0000000000000111
continue_calculating_x_offset:
clc
adc SplatRequestTable+GraphicOffset,x
sta SplatGraphicOffset
lda SplatSubTileYPosition
asl
tax
jsr (VariableYOffsetCodeJumpTable,x)