32X VDP going crazy with my attempts to draw

Ask anything your want about the 32X Mushroom programming.

Moderator: BigEvilCorporation

saxman
Interested
Posts: 19
Joined: Mon Sep 15, 2008 6:35 am

32X VDP going crazy with my attempts to draw

Post by saxman » Wed Dec 01, 2021 8:20 pm

I am using Chilly Willy's 32X toolchain, and I'm getting acquainted with the hardware. I have worked with the 32X in the past, but it was only with the SH-2s. Now I'm trying to bite off a lot more, and I'm starting with the VDP. However, I'm running into strange issues that I can't make sense of.

Some things you should know:
1) I've loaded 8-bit graphics into SDRAM. These are 8x8 tiles.
2) I call a function called "drawScreen()" one time upon pressing Up.
3) Despite trying to get it to draw only a single 8x8 tile at a specific location on the screen, it gives me tall columns of various tiles. It doesn't seem to match the logic I have put into place *at all*.

Here's the code for the 'drawScreen()' method I'm working with:

Code: Select all

void drawScreen() {
	volatile unsigned short *frameBuffer16 = &MARS_FRAMEBUFFER;
	volatile unsigned short *sdramArt = &SDRAM_ART;
	
	volatile unsigned int screenWidth = 320/2;
	unsigned int tileOffsetX = 0;
	unsigned int tileOffsetY = 0/2;
	
	// Draw frame 1
	//for (int i=64/2; i<bufferSize; i++) {
	//	frameBuffer16[tileOffsetX + (i & 3) + ((tileOffsetY + (i>>2)) * screenWidth)] = 0x6161;
	//}

	// Flip the framebuffer selection bit and wait for it to take effect
	MARS_VDP_FBCTL = currentFrameBuffer ^ 1;
	while ((MARS_VDP_FBCTL & MARS_VDP_FS) == currentFrameBuffer);
	currentFrameBuffer ^= 1;

	// Draw frame 2
	for (int i=64/2; i<bufferSize; i++) {
		frameBuffer16[tileOffsetX + (i & 3) + ((tileOffsetY + (i>>2)) * screenWidth)] = sdramArt[i+(4*0x40)]+0x6060;
	}
}
I've attached a screenshot of the results here:
32x_00.png
32x_00.png (6.47 KiB) Viewed 57955 times
What in the world am I doing wrong?

(Also, please ignore the sloppiness of the code... I'm actively experimenting, so it's not intended to be neat.)

saxman
Interested
Posts: 19
Joined: Mon Sep 15, 2008 6:35 am

Re: 32X VDP going crazy with my attempts to draw

Post by saxman » Wed Dec 01, 2021 11:39 pm

Well it would help if I could setup a for loop properly...

Code: Select all

for (int i=0; i<64/2; i++)
Instead of

Code: Select all

for (int i=64/2; i<bufferSize; i++)
It's amazing how long I worked at this before I finally noticed >_< I thought maybe I was interfacing with the 32X hardware incorrectly or something. But this is an easy fix now that I know what's going on.

saxman
Interested
Posts: 19
Joined: Mon Sep 15, 2008 6:35 am

Re: 32X VDP going crazy with my attempts to draw

Post by saxman » Sun Dec 05, 2021 6:25 am

I'll use the topic I already created for this question since it's related to my attempts at drawing on the 32X...

I know writing 16-bit on an odd address is a no go for the frame buffer. I know what happens in Kega Fusion when I attempt it... it drops the least-significant bit. What happens on real hardware?

And just for my overall knowledge, does this same thing apply when reading/writing SDRAM via words?

Chilly Willy
Very interested
Posts: 2984
Joined: Fri Aug 17, 2007 9:33 pm

Re: 32X VDP going crazy with my attempts to draw

Post by Chilly Willy » Mon Dec 06, 2021 12:58 pm

Sorry, just noticed this thread...

First off, the first 256 words of the framebuffer is the line offset table. You CANNOT draw in this area as it sets the offset (a word) to each line. Look at the example code I've provided - when a video mode is setup, the first offset is set to 256 to set the start of the first line (the offsets are in WORDs, not BYTEs - everything about the 32X VDP concerns words), the second offset is set to 256+160 to set the start of the second line, etc.

So when drawing to the framebuffer, be sure to skip the first 256 words (512 bytes) when setting your pointers. As to how you write the framebuffer, writing bytes of 0 are ALWAYS ignored. When you write bytes, the framebuffer acts like the overwrite buffer, ignoring 0 values. If you want to write a 0 to the framebuffer, you need to write it as a word. Writing 0x0000 to the framebuffer is okay.

As to writing a word to odd addresses, don't. Like the 68000, this will generate an odd address exception (which emulators may or may not emulate).

saxman
Interested
Posts: 19
Joined: Mon Sep 15, 2008 6:35 am

Re: 32X VDP going crazy with my attempts to draw

Post by saxman » Tue Dec 07, 2021 7:53 am

Thanks for the information! Very helpful.

Here's something else for you or whomever wants to chime in... I'm used to the x86 and 68k where I can expect certain instructions to take X number of CPU cycles to complete, thus aiding me in optimization efforts I may engage in. I see no information on cycles for the SH2 in any of the manuals available, neither Hitachi nor Sega. That said, reading about RISC generally, I get the impression that *most* instructions will be expected to take a single cycle. Can you confirm or deny this? This may help me decide certain things such as how long ANDing data can take, or whether there's a difference between bit shifting 2 vs 6. If they're all basically the same, then I guess I would need to be more concerned with how many instructions I use vs. which ones.

Chilly Willy
Very interested
Posts: 2984
Joined: Fri Aug 17, 2007 9:33 pm

Re: 32X VDP going crazy with my attempts to draw

Post by Chilly Willy » Tue Dec 07, 2021 11:58 am

The SH2 has a five stage pipeline - each instruction takes (nearly always with a few exceptions) five cycles to complete. However, the pipe can be loaded on each cycle, so after five cycles for the first instruction, all further instructions complete on the next cycle for an effective cycle count of one. Conditional branching can result in the pipe being flushed, meaning four more cycles. You'll want to read the pipeline section of the Hitachi SH2 Programming Manual for details (section 7). In general, though, you can count most instructions as one cycle long... as long as the code is cached and makes no outside memory fetches/stores. The 32X hardware manual tells you how many cycles for reading/writing various blocks in the SH2 address map. For example, reading sdram takes 12 cycles since it does a burst read, but only 2 cycles on a write since writes are not burst. Burst reading reads 8 words (one cache line) in one go of 12 cycles - or 1.5 cycles per word on average (the fastest non-cache memory can be read). Note that burst read ALWAYS reads 8 words, even if none of the other words are ever used. So watch how often you read non-cached memory to avoid lots of unused burst reading.

Bit shifting can be a pain on the sh2. There's no dynamic shift by N on the SH2. You can shift logically or arithmetically by one either direction, and you can shift logically (but NOT arithmetically) by 2, 8, or 16 bits either direction. So to shift by four logically, you have to do two shifts by 2. To shift by four arithmetically, you have to do FOUR arithmetic shifts. The result: always shift by a constant when possible, and shift unsigned values. Shifting by N or shifting signed vars will invoke a gcc subroutine for generalized shifting, making shifts in an inner loop very slow.

Note that a shift by 6 can be done two ways: three shifts by 2, or one shift by 8 followed by a shift the opposite direction by 2.

saxman
Interested
Posts: 19
Joined: Mon Sep 15, 2008 6:35 am

Re: 32X VDP going crazy with my attempts to draw

Post by saxman » Tue Dec 28, 2021 7:25 pm

Many thanks for the helpful input thus far.

I finally have graphics drawing correctly after a lot of work playing around with formatting the data in a way that speeds up the drawing. Inevitably, I believe I'll have to rewrite some of this in assembly for speed, but it's nice to work out some issues in C first.

EDIT: I had some lengthy text here at this point in the post posing a question, but the more I thought about it, the more I answered my own question. I was trying to define specific addresses in SDRAM to store some data, while letting the compiler decide where to store certain global variables. As you might imagine, that can create quite a nasty conflict. I don't think it makes sense to tell the compiler the specific location in SDRAM to place data, because that's not how C programming really works... ever.
Attachments
32x_01.png
32x_01.png (10.94 KiB) Viewed 57632 times

ob1
Very interested
Posts: 463
Joined: Wed Dec 06, 2006 9:01 am
Location: Aix-en-Provence, France

Re: 32X VDP going crazy with my attempts to draw

Post by ob1 » Wed Dec 29, 2021 9:44 pm

The 32x really has a lot to offer, 2D-wise.
Keep on the hard work ;)

saxman
Interested
Posts: 19
Joined: Mon Sep 15, 2008 6:35 am

Re: 32X VDP going crazy with my attempts to draw

Post by saxman » Sun Jan 02, 2022 5:27 am

Posting a screenshot of the latest. I have an entire level drawing now. Y scrolling has some bugs due to my tile buffer not clearing adequately, but apart from that, it's doing exactly what it's supposed to do.
32x_02.png
32x_02.png (17.18 KiB) Viewed 57496 times
However, it's so slow that it's no practical to use it for anything thus far. Having less than 60 FPS also makes that VDP screen shift flag effect *very* jittery! But otherwise, it works.

I've been delaying that assembly rewrite, but it's getting harder to speed this thing up any more than I already have thus far.
ob1 wrote:
Wed Dec 29, 2021 9:44 pm
The 32x really has a lot to offer, 2D-wise.
Keep on the hard work ;)
I believe you started that Super VDP topic. I read through many pages of that, trying to learn what I could. Very interesting stuff in there! Looks like I'm going through many of the same growing pains as demonstrated in that discussion at the moment. Makes me wish the 32X could draw that screen just a tad bit faster.

djcouchycouch
Very interested
Posts: 710
Joined: Sat Feb 18, 2012 2:44 am

Re: 32X VDP going crazy with my attempts to draw

Post by djcouchycouch » Sun Jan 02, 2022 10:02 am

Take a look at my research posts about drawing sprites. There are routines that draws 32x32 sprites in various ways. It may give you some ideas.

But realistically chances are you’ll have to settle for a low framerate or draw just the important objects. The 32x doesn’t give you enough pixel throughput if it has to draw everything itself at 60fps and barely enough at 30fps.

saxman
Interested
Posts: 19
Joined: Mon Sep 15, 2008 6:35 am

Re: 32X VDP going crazy with my attempts to draw

Post by saxman » Sun Jan 02, 2022 5:51 pm

djcouchycouch wrote:
Sun Jan 02, 2022 10:02 am
Take a look at my research posts about drawing sprites. There are routines that draws 32x32 sprites in various ways. It may give you some ideas.

But realistically chances are you’ll have to settle for a low framerate or draw just the important objects. The 32x doesn’t give you enough pixel throughput if it has to draw everything itself at 60fps and barely enough at 30fps.
I will definitely be keeping that in my back pocket. Thanks!

It's unfortunate. However, I still need to see what I can do to further improve performance. Using both processors, for instance, will probably help. I would have a hard time accepting 30 FPS and might instead try leveraging the Genesis VDP for certain things to try and keep the frame rate. Granted, this isn't necessarily going to be a Sonic clone (I don't know what I'm making yet), so it isn't required to be as smooth. But 30 sure does feel like selling short, to me at least.

I always wondered why games like Chaotix seemed to use the Genesis VDP to do a majority of the drawing with the 32X only doing sprites. This little project is making it clear as to why they went that direction.

TmEE co.(TM)
Very interested
Posts: 2440
Joined: Tue Dec 05, 2006 1:37 pm
Location: Estonia, Rapla City
Contact:

Re: 32X VDP going crazy with my attempts to draw

Post by TmEE co.(TM) » Sun Jan 02, 2022 6:49 pm

There is only enough fill rate to cover all of the screen once while using all of the CPU power, due to all the wait states on VRAM access. If you want 60FPS you need to limit amount of stuff that gets drawn, both in area and definitely in overdraw. It is faster to check what has to be drawn and cull out pixels that will not be seen, not unlike a 3D engine has to do with its polygons.
Mida sa loed ? Nagunii aru ei saa ;)
http://www.tmeeco.eu
Files of all broken links and images of mine are found here : http://www.tmeeco.eu/FileDen

ob1
Very interested
Posts: 463
Joined: Wed Dec 06, 2006 9:01 am
Location: Aix-en-Provence, France

Re: 32X VDP going crazy with my attempts to draw

Post by ob1 » Mon Jan 03, 2022 10:49 am

Once upon a time, Phil Lewin made an amazing Job with the unreleased Pinocchio : https://hiddenpalace.org/Pinocchio_32x_ ... prototype)

ob1
Very interested
Posts: 463
Joined: Wed Dec 06, 2006 9:01 am
Location: Aix-en-Provence, France

Re: 32X VDP going crazy with my attempts to draw

Post by ob1 » Mon Jan 03, 2022 10:50 am

djcouchycouch wrote:
Sun Jan 02, 2022 10:02 am
Take a look at my research posts about drawing sprites. There are routines that draws 32x32 sprites in various ways. It may give you some ideas.

But realistically chances are you’ll have to settle for a low framerate or draw just the important objects. The 32x doesn’t give you enough pixel throughput if it has to draw everything itself at 60fps and barely enough at 30fps.
Man!! Those research of yours blew me away !!

Chilly Willy
Very interested
Posts: 2984
Joined: Fri Aug 17, 2007 9:33 pm

Re: 32X VDP going crazy with my attempts to draw

Post by Chilly Willy » Mon Jan 03, 2022 3:08 pm

If you want a scrolling layer on the 32X, you need to use 256 color mode, then use (nearly) all the vram, the pixel shift register, and the line table in vram to scroll the screen, only changing newly displayed areas of the screen. Beware of a bug with the shift bit: if a line table entry ends in 0xFF, the shift bit is ignored. That makes it really "fun" trying to make a generalized scroll layer as you need to keep any line in the view area from ever becoming xxFF.

Post Reply