High color bitmap on the SNES

Discussion of hardware and software development for Super NES and Super Famicom. See the SNESdev wiki for more information.
Forum rules
  • For making cartridges of your Super NES games, see Reproduction.
User avatar
Khaz
Posts: 314
Joined: Thu Dec 25, 2014 10:26 pm
Location: Canada

Re: High color bitmap on the SNES

Post by Khaz »

hcolor looks pretty impressive. I'll have to read back to the start when I have a night with some actual spare time and see how you did it...

Anyways, here's roughly what I was thinking of for the Arbitrary Code, in WLA format:

Code: Select all

	sep #$20	;8 bit A
	rep #$10	;16 bit X / Y

	lda.b #$00
	pha
	plb		;set bank to zero, in case it was in a bank without the hardware registers

	stz.w $4200	;disable all interrupts (and joypad reading)

	lda.b #$80
	sta.w $2100	;turn screen off

	lda.b #$04
	sta.w $212C	;enable BG3, disable all others and sprites

	lda.b #$41
	sta.w $2105	;set BG3 tile size to 16x16 and Mode 1

	stz.w $2109	;set BG3 TileMAP VRAM location to $0000 and map size to 32x32
	lda.b #$02
	sta.w $210C	;set BG3 TileSET VRAM location to $1000 (VRAM addresses are measured in WORDS not bytes)

	stz.w $2111
	stz.w $2112	;set BG3 horiz and vertical scrolls to zero

;===== SET UP DMA TO CLEAR BG3 TILEMAP =====

	lda.b #$80
	sta.w $2115	;set up VRAM port to accept the DMA properly

	ldx.w #$0000
	stx.w $2116	;VRAM write address is $0000 for tilemap

	lda.b #$11	
	sta.w $4300	;Set DMA Control - should set to read from (I HOPE?) a fixed address.

	lda.b #$18
	sta.w $4301	;set destination address to VRAM port - $2118
	
	ldx.w #$????	;address of a place in ROM that has a $0000
	stx.w $4302
	lda.b #$??	;bank of said place in ROM
	sta.w $4304
	
	ldx.w #$0800
	stx.w $4305	;Number of bytes to transfer - $800 should cover a 32x32 tilemap
	
	lda.b #$01
	sta.w $420B	;initiate DMA to clear BG3 Tilemap.

;======= WRITE TILES TO VRAM MANUALLY ======

	;$2115 should still be set up correctly

	ldx.w #$1000
	stx.w $2116	;VRAM write address is $1000 for tileSET

	ldx.w #$????
	stx.w $2118

	ldx.w #$????
	stx.w $2118	;write your tiles like so

	[...]

	ldx.w #$????
	stx.w $2118

;====== WRITE TILEMAP TO VRAM MANUALLY =====
	;same idea as writing the tile set, just reset $2116 to point to the right part of the tilemap

;======= WRITE SOME PALETTES TO CGRAM ======

	lda.b #$01	;Color zero is background colour, so unless it's bad, start at one.
	sta.w #$2121	;remember, for BG3 (2bpp), a palette is four colours.
			;and color zero of each palette is always transparent.
	lda.b #$??
	sta.w $2122
	lda.b #$??
	sta.w $2122	;write color data - format is 0BBBBBGG GGGRRRRR.  Write lo byte then hi to same register

	lda.b #$??
	sta.w $2122
	lda.b #$??
	sta.w $2122	;color 2...

	lda.b #$??
	sta.w $2122
	lda.b #$??
	sta.w $2122	;color 3.  So that gives you one full palette, do more if you want/have room

;============= DISPLAY RESULTS =============

	stz.w $2100	;turn screen on
	STP		;halt processor.  Done!
Can anyone tell me if I have the right idea on how to do the tilemap-clearing DMA? Set the "do not increment" bit in $4300, then find an address in ROM with $0000 and set it as the source? I think that's how it works.

Then, all you need to do is come up with some simple tiles for the logo and a colour palette, and it should work.
93143 wrote:I don't suppose you could load a graphics loader and then upload a bunch of tiles through the controller ports...
... I'm really not sure of how the process works now that I think about it. Can you just execute controller input directly? Does "open bus" have to get involved, like I hear was used in the SMW ACE TAS?
User avatar
feos
Posts: 108
Joined: Tue Apr 19, 2011 11:26 am
Location: RU

Re: High color bitmap on the SNES

Post by feos »

93143 wrote:That sounds like a pretty ambitious plan for someone who's never seen SNES code before.

I don't suppose you could load a graphics loader and then upload a bunch of tiles through the controller ports...
Khaz wrote:... I'm really not sure of how the process works now that I think about it. Can you just execute controller input directly? Does "open bus" have to get involved, like I hear was used in the SMW ACE TAS?
http://www.youtube.com/watch?v=YHyaTCuZRzM#t=245

Notice how little time it took to program that thing in. We have 8 controllers plugged via Multitap, so we can feed data really fast.

http://tasvideos.org/3957S.html

There's already a setup to jump to there, so the only thing left is the very payload.
93143
Posts: 1913
Joined: Fri Jul 04, 2014 9:31 pm

Re: High color bitmap on the SNES

Post by 93143 »

Oh, it's we, is it?

Okay, yeah, I hadn't seen that. All I saw was the Pong clone. If you can load data that quickly, you can pretty much do whatever you want.
tepples
Posts: 22993
Joined: Sun Sep 19, 2004 11:12 pm
Location: NE Indiana, USA (NTSC)

Re: High color bitmap on the SNES

Post by tepples »

feos wrote:Notice how little time it took to program that thing in. We have 8 controllers plugged via Multitap, so we can feed data really fast.
I worry about the stresses on the power supply from using two multitaps long-term. You might remember that some Super FX games display an error message and halt if a high-current-draw peripheral, such as the multitap or Super NES Mouse, is connected. But that'd still be impressive with only two multitaps.
User avatar
Khaz
Posts: 314
Joined: Thu Dec 25, 2014 10:26 pm
Location: Canada

Re: High color bitmap on the SNES

Post by Khaz »

feos wrote:http://tasvideos.org/3957S.html

There's already a setup to jump to there, so the only thing left is the very payload.
Okay, so now that I've refreshed my memory... Does the entire thing happen in that same controller loop? Execute three bytes, WAI-NOP-WAI, branch back and read another three bytes? The link there mentions that being "unstable", and it seems like it would take forever to do anything useful if you only get one instruction off every other frame, so am I misunderstanding how it works?

If that is stable and predictable though, sounds trivial to send it the program I wrote there and I don't see that there'd be any real limit on how long you could do it for...
User avatar
feos
Posts: 108
Joined: Tue Apr 19, 2011 11:26 am
Location: RU

Re: High color bitmap on the SNES

Post by feos »

Here's an lsnes movie that was replayed in the vid I posted.
http://tasvideos.org/userfiles/info/19873869950560708
You can open the movie as an archive and watch inputs as plain text.

Another attempt in game end glitch has a bit different input than the one I posted above, it seems:
http://tasvideos.org/4315S.html
Last edited by feos on Fri Sep 04, 2015 10:03 am, edited 2 times in total.
tepples
Posts: 22993
Joined: Sun Sep 19, 2004 11:12 pm
Location: NE Indiana, USA (NTSC)

Re: High color bitmap on the SNES

Post by tepples »

Just a guess based on the description of 3957S:
  • SMW glitchy gameplay loads a first-stage bootloader optimized heavily for size over speed. This is where WAI/NOP/WAI comes in, to ensure the autoreader has had a chance to read the controller.
  • The first-stage bootloader slowly loads a second-stage bootloader that can make full use of the multitaps.
  • The second-stage bootloader rapidly loads the game into RAM.
93143
Posts: 1913
Joined: Fri Jul 04, 2014 9:31 pm

Re: High color bitmap on the SNES

Post by 93143 »

In the 'BGMODE or parameter changes during scanline' thread, byuu wrote:I've never once seen a CGRAM write fail.
Thanks for the tip. I broke higan again.
You do not have the required permissions to view the files attached to this post.
Near
Founder of higan project
Posts: 1553
Joined: Mon Mar 27, 2006 5:23 pm

Re: High color bitmap on the SNES

Post by Near »

Writing to CGRAM during active display to transfer data would require absolutely perfect CGRAM fetch timings. It's possible that with a few small tweaks we can make it look nicer, but we're a very long way from being able to pull that off flawlessly. Especially if you're using actual tiles there in any way (which I'm guessing you are to avoid having to write $2121 as well?)

Still though, it's pretty close. At least, it's infinitely better than literally everything else ;)

At any rate, you're a monster, congrats :P
You do not have the required permissions to view the files attached to this post.
User avatar
Drew Sebastino
Formerly Espozo
Posts: 3496
Joined: Mon Sep 15, 2014 4:35 pm
Location: Richmond, Virginia

Re: High color bitmap on the SNES

Post by Drew Sebastino »

93143 wrote:
In the 'BGMODE or parameter changes during scanline' thread, byuu wrote:I've never once seen a CGRAM write fail.
Thanks for the tip. I broke higan again.
I wonder how well that would look with a transparent tiled overlay on it. Although it wouldn't be 60fps, you could do something like a jpg image where you have one color in a 4x1 pixel area and 4 shades of that pixel using color math, like just subtracting various amounts. As you already know, there are 4 possible colors with a 2bpp pixel. I bet it would look amazing if you overlayed a 8bpp layer over it, as you could handle more than just shade. (You could change the tint to an extent.) This whole thing is possible, isn't it? I mean, as long as you're changing color 1 instead of color 0.
Near
Founder of higan project
Posts: 1553
Joined: Mon Mar 27, 2006 5:23 pm

Re: High color bitmap on the SNES

Post by Near »

I didn't inspect what was actually going on, just looked at the screen after running in higan.

If I were to guess, he's designed it so that each scanline contains tiledata that represent color palette entries 0,0,0,0,1,1,1,1,....62,62,62,62,63,63,63,63

That way each DMA can just write to $2122 twice per pixel. That takes 16 clocks, which is 4 pixels. Which explains the 4:1 ratio. Having to write to $2121 to reset the CGRAM index every time would result in an 8:1 ratio.

Essentially, he's created a 64x224x15bpp@60fps video mode :P
With MSU1, you could play back such a stream of video, too. But ... I doubt it'd be very pleasing or useful.
tepples
Posts: 22993
Joined: Sun Sep 19, 2004 11:12 pm
Location: NE Indiana, USA (NTSC)

Re: High color bitmap on the SNES

Post by tepples »

A 2bpp layer blended onto this layer to enhance luminance detail would provide the equivalent of 4:1:1 video, with brightness coming mostly from the 2bpp layer and color coming from the 15bpp layer.
Near
Founder of higan project
Posts: 1553
Joined: Mon Mar 27, 2006 5:23 pm

Re: High color bitmap on the SNES

Post by Near »

You're not going to be able to do anything in addition to this.

He's literally bit-blasting the final output color fetches themselves and rewriting the entire palette as he goes along.

EDIT: actually, shit. Not even DMA can overcome DRAM refresh, yet I don't see any penalty.

Alright I give up, I have no idea what the hell he's doing here. I guess we have to sit around and wait for him to decide to tell us.
93143
Posts: 1913
Joined: Fri Jul 04, 2014 9:31 pm

Re: High color bitmap on the SNES

Post by 93143 »

byuu wrote:If I were to guess, he's designed it so that each scanline contains tiledata that represent color palette entries 0,0,0,0,1,1,1,1,....62,62,62,62,63,63,63,63
Actually, I just used 1 through 5 in a repeating pattern, since that's all I needed to buffer through refresh. But that's the general idea, yeah.

Originally, I was planning to do the refresh area with escalating-index tiles and preload it during HBlank, and do everything else on a constant index. But since DMA aligns to a multiple of 8 master cycles since the last reset, and scanlines aren't divisible by that, there would have been an unavoidable offset of at least one dot every scanline. And since every other frame is a dot cycle short, a static pattern would have been impossible. I thought of trying to pull off a scrolling diagonal pattern, which might have resulted in a higher perceived horizontal resolution due to the larger amount of data present when averaging all frames, but it would have required complicated timed code, and besides, I really wanted to do a direct static equivalent to the Mega Drive's FantomBitmap mode.

In testing, I noticed that ordinary CPU writes to CGDATA would randomly target indices from the main screen and subscreen, about 50:50. Which makes sense, because CPU activity is only quantized to half-dot resolution. But DMA does that 8-clock alignment thing before it starts, and at least on my SNES this results in DMA reliably targeting the main screen.

So what I did was I put a preload pattern in BG1 on the main screen (to set the CGRAM address to receive writes) and a display pattern in BG2 on the subscreen (to output the colours written to the preload pattern), turned on colour addition, and had the PPU clip the main screen to black before math. Turns out it still reads the main screen pixel colour when doing that, so the preload pattern works fine even though you can't see it. (I was originally hoping DMA would target the subscreen, because the PPU will read CGRAM for a BG on the subscreen even if colour math isn't turned on, but this trick works just as well.)

I may have misunderstood something here, but the upshot would appear to be the same...

...

This implementation is interrupt-driven, with a separate DMA transfer for each line (and as you can see from the bsnes image below, the timing is just barely tight enough; IIRC kicking the H-IRQ one dot in either direction results in misses). I imagine it's possible to do it with timed code, which would free up enough cycles to allow an extra DMA to a different destination - say, four bytes to the APU each line... I might try that some time.

The first few colours of the line are preloaded during HBlank, so as to buffer enough colours to get through the DRAM refresh. The required order of the colours is a bit garbled, but that's the one part that every emulator gets right (even ZSNES), so I'm guessing I didn't feed pcx2snes carefully enough (garbled colour indices in my patterns, I imagine). If I can fix it, the data format should be a simple raster list of 15-bit values with no wasted entries. I'll post source once I've sussed that out.
Still though, it's pretty close. At least, it's infinitely better than literally everything else ;)
Being lazy, I'm still using bsnes v072 a fair bit (it can open an SFC file on double-click, and it has blargg's NTSC filter); the accuracy core is naturally worse than higan's latest but far better than the rest of the pack. On the other end of the spectrum, ZSNES somehow manages to bodge up even the easy part...
dmacolor_bsnes072.png
dmacolor_zsnes.png
At any rate, you're a monster, congrats :P
Thankyew, thankyew...
Espozo wrote:I wonder how well that would look with a transparent tiled overlay on it.
I don't think that would work, unless there's another way to do this that doesn't completely kill the main screen*. As it stands, colour blending of any kind is impossible (well, you could do averaging instead of addition and get half brightness, but a fat lot of good that does you, especially with the IRQ approach where the whole main screen has to be indexed to receive writes).

However, while I haven't tried it, I imagine the sprite system and the spare 2bpp BG3 layer would display fine if you just sent them to the subscreen. If sprites work, that's at least half a screenful of Quantomatic on top of what I've got here... or heck, you could play Super Mario Bros. with a video of F-Zero GX playing in the background (will the code for SMB fit in VBlank without egregious slowdown?)...

...

* Actually, it occurs to me that my original idea with the diagonal scrolling pattern (or just vertical columns with 30fps edge dither) should work with transparency, since it would be writing directly to the visible layer, and in my experience DMA never accidentally writes to the subscreen. But I don't know how good it'd look...
Essentially, he's created a 64x224x15bpp@60fps video mode :P
With MSU1, you could play back such a stream of video, too. But ... I doubt it'd be very pleasing or useful.
True - unfortunately the aesthetic difference between double-wide pixels and quadruple-wide pixels is fairly substantial. One could add static horizontal dither to the display pattern, but it might look funny (haven't tried it), and the actual amount of information wouldn't change... This technique might be good for impressionist backgrounds, or impressing people with raw colour counts...
6315colours.png
But I think this does finally answer the OP's question. You can, in fact, do DMA colour on the SNES. Shame about the bus width...
You do not have the required permissions to view the files attached to this post.
AWJ
Posts: 433
Joined: Mon Nov 10, 2008 3:09 pm

Re: High color bitmap on the SNES

Post by AWJ »

Well, that answers one of my questions about the S-PPU. During rendering, it evidently always does a CGRAM read for every main and sub pixel, regardless of how any of the math registers are set. That's pretty much what I expected but it's nice to have it confirmed. Also, it's interesting that DMA accesses to CGDATA always line up with the main fetches rather than the sub fetches. I wonder if that's true on all SNES models, including the mini-SNES (should be easy to test; if I understand how the demo works correctly, the picture will be more or less completely garbled if it isn't the case)