Super Mario Land

Use this forum to share and discuss Uzebox games and demos.
User avatar
nicksen782
Posts: 714
Joined: Wed Feb 01, 2012 8:23 pm
Location: Detroit, United States
Contact:

Re: Super Mario Land

Post by nicksen782 »

uimgview_dragons loaded just fine. This is an SPIRAM video mode? That means this confirms that reading from SPIRAM works. Also, I'm guessing that a new image is loaded from SD for each slide. Ejecting the SD card and then changing the slide gives a black screen until I reset the program.

Where in the code are you copying an SD binary into SPIRAM? It appears you are doing it image by image. I've been reading an entire file in sector by sector. I'm suspecting strongly that my binary reading function is faulty. I have a code snip-it below that shows how I am reading the data. Again, this all works on the emulator but not the hardware. I'm using the portable and my original unit. Both encounter the error at the same position.

I tried the portable and my original Uzebox unit with the RPG I was working on. It worked just fine on the emulator and both hardware units.

I'm really starting to suspect that this has something to do with the screen resolution. In the past I have been able to use SPIRAM and the SD card with the bootlib library but the screen dimensions were different.

Code: Select all

	// (void)(SPSR); // http://uzebox.org/forums/viewtopic.php?f=3&t=7788&p=27613&hilit=SPSR#p27609
	u32 pos;
	do{
		debugDisplay(0,numSectorsToRead);
		debugDisplay(1,sectorCount);
		debugDisplay(2,readFlag1);

		readFlag1 = FS_Read_Sector(&sdFile1Ptr);

		pos               = sectorCount*512UL;
		
		// Read 512 bytes at a time.
		// bank              = getBankFromPos(pos);
		// addr              = getAddrFromPos(pos);
		// SpiRamWriteFrom(bank, addr, ram_tiles, 512UL);

		// Write one byte at a time.
		for(u32 i=0; i<512UL; i+=1){
			// WaitVsync(1);
			SpiRamWriteU8(
				getBankFromPos( pos + i ),
				getAddrFromPos( pos + i ),
				ram_tiles[i]
			);
		}

		// Check the read. Make sure the SPIRAM values for the sector match the sector read.
		for(u32 i=0; i<512UL; i+=1){
			u8 check1=ram_tiles[i];
			u8 check2=SpiRamReadU8 ( getBankFromPos(pos+i), getAddrFromPos(pos+i) );
			if(check1 != check2 ) {
				debugDisplay(2,i);
				debugDisplay(3,check1);
				debugDisplay(4,check2);
				errorCrash(ERROR_WHERE_BYTEREADERROR, i);
			}
		}

		nextFlag = FS_Next_Sector(&sdFile1Ptr);
		if(nextFlag){ errorCrash(ERROR_WHERE_FS_NEXT_SECTOR, nextFlag); }

		sectorCount++;

	}
	// Repeat until done.
	while(sectorsRemaining--);
User avatar
Jubatian
Posts: 1564
Joined: Thu Oct 01, 2015 9:44 pm
Location: Hungary
Contact:

Re: Super Mario Land

Post by Jubatian »

nicksen782 wrote: Sat Jun 22, 2019 9:39 pmuimgview_dragons loaded just fine. This is an SPIRAM video mode? That means this confirms that reading from SPIRAM works. Also, I'm guessing that a new image is loaded from SD for each slide.
Yes, it is SPIRAM, I posted it since the copy from SD to SPI RAM uses the same mechanism (function calls and their order) like yours (although coded in assembler). Display is entirely disabled during the copy, all CPU time is utilized for transferring data (with that kernel you can not even do it otherwise as the enabled display uses the SPI bus).

What were the symptoms of that error? (Did you have code to display the return value?)

Otherwise if it is nothing conclusive, my next bet would be trying a fresh checkout from the master for the kernel. That on your last posted binary the sync singnal is somewhat broken is really suspicious, especially as you mention that it is supposedly an unmodified kernel and mode 3, I don't remember it having any such bug remaining. I suspect there might be some experimental code left in that which you are currently using which you may not be aware of. Of course if the broken sync reproduces with a clean kernel, then that's a kernel bug (please post kernel flags used, I will try to reproduce and fix it).
User avatar
nicksen782
Posts: 714
Joined: Wed Feb 01, 2012 8:23 pm
Location: Detroit, United States
Contact:

Re: Super Mario Land

Post by nicksen782 »

I have the latest master. My previous experiments are in a different folder. The kernel I'm using for SML has no modifications. Stock kernel.

I've tried reading in chunks, byte by byte. Nothing works unless it is on the emulator. The emulator does in fact show red vertical bars instead of blue. This turned out to be important although I'm not sure how to fix it.

I think I've found the problem. It is definitely related to timing somehow.

I had these lines in my Makefile:

Code: Select all

LDFLAGS += -Wl,--relax                # Enables linker relaxations.
LDFLAGS += --param inline-call-cost=2 # Can reduce flash usage
Once they were commented out I got blue bars. I was on a quest some time ago to find extra flash wherever I could find it and these flags helped. I wasn't using SPIRAM or the SD card at the time though.

Can you explain what they do and why they may have caused my problem?

Further, is there a definitive guide for how the horizontal bars work and what to do when they are not blue?

... The portable and the original unit work fine now. I would really like to understand how to handle these types of problems in the future and I really think that better understanding the vertical bars in CUzeBox will help!
User avatar
Jubatian
Posts: 1564
Joined: Thu Oct 01, 2015 9:44 pm
Location: Hungary
Contact:

Re: Super Mario Land

Post by Jubatian »

nicksen782 wrote: Mon Jun 24, 2019 1:32 amI had these lines in my Makefile:

Code: Select all

LDFLAGS += -Wl,--relax                # Enables linker relaxations.
LDFLAGS += --param inline-call-cost=2 # Can reduce flash usage
Once they were commented out I got blue bars. I was on a quest some time ago to find extra flash wherever I could find it and these flags helped. I wasn't using SPIRAM or the SD card at the time though.
Wow, that actually explains a lot!

The problem there is that the part generating the video is all assembly. Apparently when linker relaxation is on, that also affects assembly sources (actually it necessarily has to as at the point of linking there is no further information on whether the object file came from an assembler or a C compiler). This means that the linker starts replacing some jump instructions, messing up timing. This does not only affect the video mode, but also SPI access if those were designed with adding sufficient cycles between data accesses instead of polling for transmission completion. The SPI RAM library is cycle timing based, ensuring that normally there are at least the required number of cycles between data accesses (this is more efficient than polling for getting the best bandwidth).

So it is likely that the linker messed it up, subtly reducing some cycle counts here and there, below what is needed on the real HW. There is a tricky behaviour of the SPI peripheral which is not emulated, apparently you have to use 17 cycles between writes (so one write in each 18 clocks) on the real thing. When reading, you can not do anything else as the IN and OUT is back to back, but when writing, you could write code which puts 16 clocks between each write access to the SPI data register. In theory this should work, in practice, it doesn't seem to on the real HW (actual behaviour is more complex, that's why I didn't emulate it). My best guess is that the linker triggered exactly this, so in emulator, your code worked, on real HW, it didn't.

The blue / red bars:

They indicate sync correctness for the line. The right side indicates whether the falling edge of the sync signal comes the right amount of clocks after the last rising edge (end of scanline), the left side whether the rising edge comes the right amount of clocks after the last falling edge (beginning of scanline). The VSync timing is on the bottom, there are 272 sync pulses in a frame (262 scanlines, the VSync has a number of half-wide pulses).

Typically when tampering with video modes, the right side would fail (as the scanline code may have the incorrect amount of cycles), only in the lines where there is actual display. When tampering with the inline mixer, typically the left side fails, and the failure notably extends all the way, on the bottom showing an alternating pattern (as during the half-wide pulses, the kernel only calls audio every second pulse to maintain proper sample rate).

When the red extends to the left, it indicates that the pulse is short by one or two clocks (for two, it is larger). A yellow dot on the left shows if it is shorter by 3 or more cycles. When the pulse is too long, same to the right. Using this, you can even just get some video code right by trial and error until it shows okay.
User avatar
nicksen782
Posts: 714
Joined: Wed Feb 01, 2012 8:23 pm
Location: Detroit, United States
Contact:

Re: Super Mario Land

Post by nicksen782 »

Maybe we need some kind of list of compiler/linker options that are labeled such as "DON'T USE THIS! BAD IDEA!". Also, I should have understood better what they did before I started using them.

So, now I have all the graphics and things move well. I think I'll have some sort of game world struct that indicates where enemies are supposed to spawn.

I need to figure out scrolling. The demo was mode 3 with no scrolling and I was just moving the tiles in vram on the grid. It looks fine when you are moving fast or even scrolling through a level. However, once I put sprites up which do not need to be on a grid I will need some way to smooth scroll everything. That can be handled by mode 3 with scrolling. The concept makes sense. I would just need to keep the current scroll value in mind when I do collision detection.

But, I am at a fork in the road now. Do I do this with mode 3 scrolling? If so, I understand that the screen width must be a multiple of 8 or does it need to be 32? The game's screen width is 20. I could draw more on the screen if I wanted but I do like the ram savings.

Mode 52: So, smaller bg tiles and ram tiles. You can do palette changes. Each row can have it's own tileset and that means that you can also do a sort of split screen. Like, in Super Mario Land the top two rows use the font characters but the rest of the screen rarely does. I have the bg tile resources for that game down to 206. Some tiles are reused within each world such as the question block and pipes. So, the ram tiles would use up the remaining indexes. That leaves 50 then. I was already going to split up the sprite banks by enemies, bosses, mario. Can you still specify a sprite bank like you can with mode 3? In mode 3 the sprite banks just read into ramtiles anyway for sprites which is probably why you can have many tilesets on screen at a time. Can a similar thing happen with mode 52?

I think I'm going to run out of space and if mode 52 gives me more ram tiles and a smaller flash footprint overall then I need to consider using it instead.

Since I'm already considering SPIRAM for the world maps I would also like to consider SPIRAM for the sprite tiles. On any screen with sprites (other than Mario) there are only one or two enemies usually. This means that I could probably just read that data in and use ram-sprites for them. That would save me the 206 tiles that I have for the non-boss sprites. Maybe even those as well. Leaves me lots of room for a game, and music too.

Edit: "Up to 256 tiles, the count of ROM/RAM tiles within this is arbitrary." Does that mean that the number of ram tiles does not need to be an unchanging number?? If so then that really makes me consider mode 52 even more.
User avatar
Jubatian
Posts: 1564
Joined: Thu Oct 01, 2015 9:44 pm
Location: Hungary
Contact:

Re: Super Mario Land

Post by Jubatian »

nicksen782 wrote: Sat Jun 29, 2019 6:43 pmMaybe we need some kind of list of compiler/linker options that are labeled such as "DON'T USE THIS! BAD IDEA!". Also, I should have understood better what they did before I started using them.
I would say, probably a pinned thread, as the list might grow while discovering stuff. There is one certain thing which I have in all my Makefiles which also belongs to this category (you may lose some RAM without any real advantage with the wrong setting).
nicksen782 wrote: Sat Jun 29, 2019 6:43 pmBut, I am at a fork in the road now. Do I do this with mode 3 scrolling? If so, I understand that the screen width must be a multiple of 8 or does it need to be 32? The game's screen width is 20. I could draw more on the screen if I wanted but I do like the ram savings.
With scrolling Mode 3, unfortunately you need 32 tiles wide VRAM (the actual display can be narrower, but due to the special VRAM layout of this mode variant, the VRAM width is fixed). Also it is either 8, 16, 24 or 32 tiles tall, and there are no other options.
nicksen782 wrote: Sat Jun 29, 2019 6:43 pmCan you still specify a sprite bank like you can with mode 3? In mode 3 the sprite banks just read into ramtiles anyway for sprites which is probably why you can have many tilesets on screen at a time. Can a similar thing happen with mode 52?
Mode 52, like all my other modes, misses the highest level of sprite abstraction. You have a blitter (see M52_BlitSpriteRom and M52_BlitSpriteRam) which works that way that it takes a 8x8 tile from wherever you specifiy it, and puts it on the screen (managing RAM tile allocation proper). So you don't have sprite objects, it is up to you to desing that layer in the manner it fits best to the game, but that also means you don't have those limitations either.

SPI RAM sourced sprites with Mode 52 currently can work that way that you copy the sprite tile data (16 or 24 bytes) from SPI RAM to RAM, then blit it with M52_BlitSpriteRam(). A Mode 74 like SPI sprite approach would be faster if I ever designed it, but for your game this deficiency likely wouldn't matter a whole lot as you have ample VBlank.
nicksen782 wrote: Sat Jun 29, 2019 6:43 pmEdit: "Up to 256 tiles, the count of ROM/RAM tiles within this is arbitrary." Does that mean that the number of ram tiles does not need to be an unchanging number?? If so then that really makes me consider mode 52 even more.
Yes, see m52_ramt_base.
User avatar
nicksen782
Posts: 714
Joined: Wed Feb 01, 2012 8:23 pm
Location: Detroit, United States
Contact:

Re: Super Mario Land

Post by nicksen782 »

Okay. So, I'll need to change all my tile data and maps to work with mode 52. I would want to modify my own toolset to do that. How do you create the actual tiles?

Tile maps are handled similar, right? I don't think I need to change tilesets anywhere other than for the first two rows which I had as a screen section.

I need a good start. I'm thinking of my mode 3 knowledge here but with changes to support mode 52. Mode 52 is still just in your repo, right? Maybe if I could get somewhere with it you could make it an official mode in the kernel?

I just need to figure out how to start. Somehow I think this may be easier than mode 3 in some ways from a resource limitation perspective. Would i be correct?

I'm ready to learn mode 52 and do this! Maybe other games can be created with it too. Bubble Bobble for instance would have enough ram for all the bubbles! Could mode 52 really replace mode 3 as king?
User avatar
Jubatian
Posts: 1564
Joined: Thu Oct 01, 2015 9:44 pm
Location: Hungary
Contact:

Re: Super Mario Land

Post by Jubatian »

nicksen782 wrote: Sun Jun 30, 2019 2:53 pmOkay. So, I'll need to change all my tile data and maps to work with mode 52. I would want to modify my own toolset to do that. How do you create the actual tiles?
Look into the generators folder, there is a very crude tool there. It demands Gimp, within Gimp there is an option to export an image as a C header, which produces the appropriate header for this tool to use if that image has palette (make sure to convert to it if necessary). It may be useful to give you an idea on how to add support quickly into your utilities.
nicksen782 wrote: Sun Jun 30, 2019 2:53 pmTile maps are handled similar, right? I don't think I need to change tilesets anywhere other than for the first two rows which I had as a screen section.
There is the VRAM, and no other abstraction above that. To scroll, see the "Tile row modes overview" section in the manual, that's what you have to work with. Devise an appropriate scrolling algorithm, simplest is to shift 7 pixels, then for the 8th, copy the VRAM.
nicksen782 wrote: Sun Jun 30, 2019 2:53 pmMode 52 is still just in your repo, right? Maybe if I could get somewhere with it you could make it an official mode in the kernel?
Yes, it is only in my repo, I actually wonder why I didn't merge it in. If you make use of it, that sure would be a good excuse for finally merging it! (the repo is up to date, 1 commit behind only, the Mac OS X bootloader fix I think, so nothing relevant).
nicksen782 wrote: Sun Jun 30, 2019 2:53 pmSomehow I think this may be easier than mode 3 in some ways from a resource limitation perspective. Would i be correct?
A lot more ROM (considering your plans), a lot more RAM. I guess that could qualify as easier, not? :)
nicksen782 wrote: Sun Jun 30, 2019 2:53 pmCould mode 52 really replace mode 3 as king?
No. This is a 2bpp mode, so fit for games with limited colours, giving you a lot more resources to work with as a trade-off, so serves a significantly different use-case efficiently than Mode 3 does.
User avatar
nicksen782
Posts: 714
Joined: Wed Feb 01, 2012 8:23 pm
Location: Detroit, United States
Contact:

Re: Super Mario Land

Post by nicksen782 »

I see the export as c header option in GIMP. How does this handle tile de-duplication though?

So, there is VRAM and that's it? Tiles are indexed like in mode 3? What about flash tile ids vs ram tile ids? In mode 3 the ram tile ids come first. To draw a flash tile map each tile in the tile map must have RAM_TILES_COUNT added to it to get the correct id. How will that work here since the number of ram tiles can vary? When using a ram tile where do you copy the data to?

Okay. I'll just use your mode 52 repo branch then.

More ROM tiles and more RAM tiles available. Great!

Mode 52 has far fewer colors available and that's the trade-off then, right? More ROM/RAM but less colors? That might be fine. Many games only use a few colors on screen anyway. There are 16 and 24 byte tiles, right? What's the difference?

I need to build something to work as an example. Something simple like a ball bouncing or Mario running. If I can get things on the screen then I'll feel more confident. It seems that each row can be configured differently at any time. I don't expect to do much of that though.
User avatar
Jubatian
Posts: 1564
Joined: Thu Oct 01, 2015 9:44 pm
Location: Hungary
Contact:

Re: Super Mario Land

Post by Jubatian »

nicksen782 wrote: Mon Jul 01, 2019 6:38 pmI see the export as c header option in GIMP. How does this handle tile de-duplication though?
No de-duplication, that's just a simple tool to get you a tileset into 2bpp format. You neet to add the converter code to a map creator (tile de-duplication doesn't make much sense without one).
nicksen782 wrote: Mon Jul 01, 2019 6:38 pmSo, there is VRAM and that's it? Tiles are indexed like in mode 3? What about flash tile ids vs ram tile ids? In mode 3 the ram tile ids come first. To draw a flash tile map each tile in the tile map must have RAM_TILES_COUNT added to it to get the correct id. How will that work here since the number of ram tiles can vary? When using a ram tile where do you copy the data to?
See m52_ramt_base's description. The ROM tiles are at the bottom, the RAM tiles begin at the split point. Then for sprites, see the descriptions of m52_sprite_ramt_base and m52_sprite_ramt_max in videoMode52_sprite.s.
nicksen782 wrote: Mon Jul 01, 2019 6:38 pmMode 52 has far fewer colors available and that's the trade-off then, right? More ROM/RAM but less colors? That might be fine. Many games only use a few colors on screen anyway. There are 16 and 24 byte tiles, right? What's the difference?
Yes, the trade-off is that. The 24 byte tiles are for sprites, an aggregation of a normal 2bpp tile and a 1bpp mask. The format allows you to have a sprite which can use all the 4 colours (which is useful at this low colour count, although the GameBoy didn't have such capability, so you may not need it for your game).
nicksen782 wrote: Mon Jul 01, 2019 6:38 pmI need to build something to work as an example. Something simple like a ball bouncing or Mario running. If I can get things on the screen then I'll feel more confident. It seems that each row can be configured differently at any time. I don't expect to do much of that though.
Check the Li-2 demo (examples/plane), it is quite elaborate, showing the function of several things in the mode to create something actually interesting.
Post Reply