Snes Transparencies, A Temporary Solution?


you forget that we have hardware layers, it may be posibil to just draw the transperencys to another layer and set ti to teh wished transperence.
I hav eno idear how many layers the snes itself managed, but maybe theres could be mapped 1:1 on the gp2x's layers and than used for cheap transperence? (complete layer at once)


Possibly but that would require alot of hacking around on the second core and 2D chip etc. It would maybe be possible someday as they get more familiar with the hardware. My idea was for a quick solution that could be burped out in the next update as a stop-gap. It would be much better than having NO transparencies at all.
 
Last edited by a moderator:
If we all shut up and let the pros handle it, noone would get anywhere fast. o.o

Anyway. It's a valid point that DaveC makes. It would be very fast, but there are better ways of doing it. The one already mentioned here probably would work, but I have no idea how. =(.

The mine?

It's really simple - what is really an ALU? In 32bit cpu like the ARM It's 32 dimensional vector unit with scalars what have accuracy of 1 bit. Bitwise AND is the same as arithmetical ADD just with carry for higher bit.

Carry is usefull (obviously) but trick is to prevent it from some bits so we could isolate some regions of ALU's bits.

So we can have 4 8bit values in 32bit register, right? But arithmetic ADD will mess up individual values as results of summing two 8bit can be 9bit. But when we reduce these values to 7 bits (by zeroing least significant bit of every scalar) and logically shift by one bit to left (to make place for eventual carry) we are effectively not adding one 32bit value but 4 7bit ones.

Imagine 16 bit register (to make the example shorter):
|00000000|000000000| - two bytes = 16 bits

Get two values - let it be 59 and 20:
00111011 - 59
00010100 - 20

Put them in the 16 bit register this way: |59|20| so:
|00111011|00010100|

Get another pair of 7bit numbers, lets them be 100 and 77:
01100100 - 100
01001101 - 77

Put them to another register similar way: |100|77|:
|01100100|01001101|

So we have two registers:
|00111011|00010100|
|01100100|01001101|

Arithmetically they are 15124 and 25677.
15124 + 25677 = 40801
Bitwise 40801 is equal to:
|10011111|01100001| (so |159|97|)

and

59 + 100 = 159
77 + 20 = 97

See? :rolleyes:
 
Last edited by a moderator:
If we all shut up and let the pros handle it, noone would get anywhere fast. o.o

Anyway. It's a valid point that DaveC makes. It would be very fast, but there are better ways of doing it. The one already mentioned here probably would work, but I have no idea how. =(.

The mine?

It's really simple - what is really an ALU? In 32bit cpu like the ARM It's 32 dimensional vector unit with scalars what have accuracy of 1 bit. Bitwise AND is the same as arithmetical ADD just with carry for higher bit.

Carry is usefull (obviously) but trick is to prevent it from some bits so we could isolate some regions of ALU's bits.

So we can have 4 8bit values in 32bit register, right? But arithmetic ADD will mess up individual values as results of summing two 8bit can be 9bit. But when we reduce these values to 7 bits (by zeroing least significant bit of every scalar) and logically shift by one bit to left (to make place for eventual carry) we are effectively not adding one 32bit value but 4 7bit ones.

Imagine 16 bit register (to make the example shorter):
|00000000|000000000| - two bytes = 16 bits

Get two values - let it be 59 and 20:
00111011 - 59
00010100 - 20

Put them in the 16 bit register this way: |59|20| so:
|00111011|00010100|

Get another pair of 7bit numbers, lets them be 100 and 77:
01100100 - 100
01001101 - 77

Put them to another register similar way: |100|77|:
|01100100|01001101|

So we have two registers:
|00111011|00010100|
|01100100|01001101|

Arithmetically they are 15124 and 25677.
15124 + 25677 = 40801
Bitwise 40801 is equal to:
|10011111|01100001| (so |159|97|)

and

59 + 100 = 159
77 + 20 = 97

See? :rolleyes:

Wouldn't you have to do that for every pixel? sounds like it would cause some slowdown.
 
Last edited by a moderator:
Yes DaveC, it could be done like that, but I don't think it would actually improve the speed by much. Transparency on the snes is done by color addition or subtraction - you have multiple backgrounds (main screens layers and subscreen layers) and you can subtract one from the other to give the illusion of transparency. Subtracting the color values doesn't take that much time, so I don't know whether replacing it with your method would actually speed it up by anything noticable.

However, disable transparencies completely and you remove a shedload of code and processing time as you don't even have to bother to look for it.

vimacs: The hardware layers on the mmsp2 are useless in snes emulation - most snes games usually use mode 1 which is 3 layers I think, but don't forget on the snes you can assign an individual priority to every tile (Z-drawing order, so your sprite for example can appear behind a truck but in front of a tree), and with hdma emulation you can change this every scan line. Break that down into layers that are suitable for the mmsp2 and it wouldn't give you any advantage. The same goes for the blitter - you can't use it to draw the tiles as they could change every scanline, so you have to draw just 8 pixels of each 64 pixel tile each scanline, and it's kinda useless to use the blitter for just 8 pixels - it would take more than that to just set it up for the operation.
 
If we all shut up and let the pros handle it, noone would get anywhere fast. o.o

Anyway. It's a valid point that DaveC makes. It would be very fast, but there are better ways of doing it. The one already mentioned here probably would work, but I have no idea how. =(.

The mine?

It's really simple - what is really an ALU? In 32bit cpu like the ARM It's 32 dimensional vector unit with scalars what have accuracy of 1 bit. Bitwise AND is the same as arithmetical ADD just with carry for higher bit.

Carry is usefull (obviously) but trick is to prevent it from some bits so we could isolate some regions of ALU's bits.

So we can have 4 8bit values in 32bit register, right? But arithmetic ADD will mess up individual values as results of summing two 8bit can be 9bit. But when we reduce these values to 7 bits (by zeroing least significant bit of every scalar) and logically shift by one bit to left (to make place for eventual carry) we are effectively not adding one 32bit value but 4 7bit ones.

Imagine 16 bit register (to make the example shorter):
|00000000|000000000| - two bytes = 16 bits

Get two values - let it be 59 and 20:
00111011 - 59
00010100 - 20

Put them in the 16 bit register this way: |59|20| so:
|00111011|00010100|

Get another pair of 7bit numbers, lets them be 100 and 77:
01100100 - 100
01001101 - 77

Put them to another register similar way: |100|77|:
|01100100|01001101|

So we have two registers:
|00111011|00010100|
|01100100|01001101|

Arithmetically they are 15124 and 25677.
15124 + 25677 = 40801
Bitwise 40801 is equal to:
|10011111|01100001| (so |159|97|)

and

59 + 100 = 159
77 + 20 = 97

See? :rolleyes:

Wouldn't you have to do that for every pixel? sounds like it would cause some slowdown.

Yes of course but assuming 16bpp mode we can put two RGB 5-6-5 pixels into 32 bit register. These are 6 scalar values and this way they can be added and divided by 2 at once. In ARM assembler it's only four instruction and they will execute in 4 machine cycles. So one transparent pixel per two cycles. Assuming we have 320x240 at 60Hz we have at worst 320*240*60 = 4608000 pixels to process. It's only 8.8 mips. It's not counting load/store from memory so it will be slower in practice but still way faster than processing every R, G, B channel individually.
 
Last edited by a moderator:
davec's suggestion is good and one that i have though of myself, i'm surprised at people shooting it down so quickly. but in the end it's probably just better to spend time trying to do real transparency than trying to do it 'bootleg' and then have to debug that if something goes wrong etc.

my idea was to just flicker every other frame, but with emulation you're typically running at less than normal framerate anyway, and with frameskip you'd destroy the whole effect. so i sort of get the idea that its one of those problems were you'd do more work avoiding it than if you actually tackle it.

squidge - does it really just subtract the colors? i would have thought that it subtracted and then multiplied by 2, no? which would potentially take more time than turning pixels on/off.

this is all out of curiosity though as i have to admit, i'm not crazy about dithering transparency...as much as i loved my genesis i always thought those water effects looked cheap.
 
Could someone point me in the direction of some technical docs on the snes? I am interested in how a real snes does transparency.

http://www.zophar.net/tech/snes.html

edit: those are by no means official and probably not all that helpful unless you like memorizing memory locations. but interestingly, the snes has special hardware for doing division and multiplication. perhaps that's how the math for transparency was done? i dunno.
 
Last edited by a moderator:
Hmm... I remember on OS9xGP on the GP32, Yoyo added in some hacks that would make the transparencies show up one at a time, without a noticeable performance hit. Perhaps something resulting in the effect described in this thread could be done with those hacks?
 
Too be honest, I think squidge has probably thought about alot of this stuff before.

Yes of course but what we are discusing here goes beyond the snes emulation. No one is forcing anyone to use any of suggested methods too. The ideas what are offered might be usefull for someone - I already learned two new tricks in similar topics.

Back to the SNES... it can be approached in many ways - the main choice is the pixel format for the final output. The 8bit palletized mode will be probably fastest and snes has 256 positional clut too. At other hand such mode is excluding true RGB mixing for transparencies. The 16bit direct mapped mode will make them possible but then there is twice the bandwidth needed. Perhaps the SNES's pixel data could be precomputed to the linear format to make blits much faster but it might make compatibility troublesome. And so on, and so on...
 
Last edited by a moderator:
You do have to admit that it is a bit ironic that someone who rants about "accuracy" (i.e. no stretching, blurring, smudging of colors etc etc) thinks it is a "good idea" to have transparencies rendered at every other line (ugh, that is ugly) etc.

Again, not that I care either way ... just ironic.
 
You do have to admit that it is a bit ironic that someone who rants about "accuracy" (i.e. no stretching, blurring, smudging of colors etc etc) thinks it is a "good idea" to have transparencies rendered at every other line (ugh, that is ugly) etc.

Again, not that I care either way ... just ironic.
Really, what's all this bitterness around here?

I know he might be hard to withstand at times, but if you don't like his posts, why do you bother reading them in the first place?
 
Last edited by a moderator:
You do have to admit that it is a bit ironic that someone who rants about "accuracy" (i.e. no stretching, blurring, smudging of colors etc etc) thinks it is a "good idea" to have transparencies rendered at every other line (ugh, that is ugly) etc.

Again, not that I care either way ... just ironic.
Really, what's all this bitterness around here?

I know he might be hard to withstand at times, but if you don't like his posts, why do you bother reading them in the first place?
seriously.. it's getting out of hand in here
 
Last edited by a moderator:
Yes DaveC, it could be done like that, but I don't think it would actually improve the speed by much. Transparency on the snes is done by color addition or subtraction - you have multiple backgrounds (main screens layers and subscreen layers) and you can subtract one from the other to give the illusion of transparency. Subtracting the color values doesn't take that much time, so I don't know whether replacing it with your method would actually speed it up by anything noticable.

However, disable transparencies completely and you remove a shedload of code and processing time as you don't even have to bother to look for it.


Yes but disable transparencies and you also disable the playability of many games. Plus when they are missing you lose alot of the effect of some games.

The way transparencies seem to be rendered now is that they are just opaque (I looked at CastleVania IV and the mist in the beginning is solid rather than transparent, but still there). So obviously those layers are still being rendered, they are just not doing the addition or subtraction per pixel, those operations are left out to conserve speed. So what I am saying is if it was set up so that the layer that is designated as transparent is really a line pattern it would not produce a hit in performance at all. It would render just as it does now, only every other line or pixel is just not rendered. So to the emu it thinks it is just rendering the layer as it does now, but to the user it appears transparent. You basically get pseudo transparencies for "free".

How this is done in the code is beyond my scope as I am no coder. I think it would just be some area of memory etc that is normally set up for that layer which would normally render all opaque but when the time comes for the emu to paint where the missing line or pixel is designated it would just be redirected to nothing or cancel out or something. It is hard to explain for me being such a lamer when it comes to code ;) But I would bet you could come up with a clever efficient way of doing it.
 
Last edited by a moderator:
How this is done in the code is beyond my scope as I am no coder. I think it would just be some area of memory etc that is normally set up for that layer which would normally render all opaque but when the time comes for the emu to paint where the missing line or pixel is designated it would just be redirected to nothing or cancel out or something. It is hard to explain for me being such a lamer when it comes to

It should work the same way as with transparencies set to opaque just skip every odd (or even) line when blitting transparent playfields to the final surface. Not hard to do - only two more ARM opcodes per scanline would be needed. And skipped scanlines wouldn't need to be touched at all so it could be faster than just opague rendering.

Edit: Another idea... Just compute true transparency but only for odd scanlines then blit it twice to odd and next even scanline of final surface. This way you could get get faster transperencies at reduced resolution. Not ideal but should be acceptable and hardly distracting.

It would look like this:
snestrans0eh.png
 
Last edited by a moderator:
Hmm, what I need to do is some playing :)

What would be excellent is a rom where it is very easy to get it to show some transparency effects. A demo or something perhaps.

Hmmm, actually, now that I've placed save states in the emulator, maybe someone could create a savestate of a certain rom (the original picture DaveC posted would be excellent, but I'm not sure of what that game is) and email it to me. I can then try lots of different ways very easily.
 
I've just found what appears like water in Megaman9 near the start and move a little to the right and it goes up and down the screen as you hop on a small craft made of what looks like woodish. Perfect :)

Actually, scratch that. Megaman9 causes the DMA routines to fall over :/ Time to find another game.
 
Squidge,
As DaveC mentioned you could try Super Castlevania IV;

opening sequence
1106602127006hc.png


stage 2
1106602502006sd.png


Or there's the first level of indiana jones' greatest adventures
1089577197009si.png
 
Super metroid has all sorts of transparencies iirc. It may even use them on the intro section
 
Back
Top