PVSnesLib for Snes 20th birthday :D !

This is an archive of a topic from NESdev BBS, taken in mid-October 2019 before a server upgrade.
View original topic
PVSnesLib for Snes 20th birthday :D !
by on (#95096)
Hello,
I posted it on some others forums but I forgot to do a complete post here ...
I want to share with you this new try to have a generic C lib for Snes (We need homebrew for this really nice console, it's its birthday :D).
It's based on snes-sdk, with help of tools from mic_, shiru , mukunda and others (just see thanks webpage on pvsneslib documentation).
I know c source code from 816-tcc is nto really optimized and result are often slow with it, but it's a try, so why not :D !
There is now everything to do a project, even sound support, thanks of snesmod library (and Kung Fu Furby for help ;-) ).
Here is the wiki entry I made about it, of course **it far to be complete** and it really need more work to have something that be ok with all Snes functionnalities.

http://www.portabledev.com/wiki/doku.php

You can download the last version from wiki here : http://www.portabledev.com/wiki/doku.ph ... version_en

Google code entry : http://code.google.com/p/pvsneslib/

Here is a screen shot from something I ported from Shiru's source code :

(image too huge, just the link) http://www.portabledev.com/media/SNES/PVSnesLib/uwol_supaboy.jpg

I still have problem with speed and optimore (thanks mic_ ;-) ) seems to have problem with the lib (no keypad support when I'm using it, don't know currently why).

by on (#95209)
hey Alekmaul!

Nice work!!!

pm me whenever you have a chance! **URGENT**

by on (#95295)
This does look very nice! I love how clean and structured the wiki looks. Definitely gonna try this next week!

by on (#95457)
Hey, alekmaul,

thanks a lot for this! I had been waiting/hoping for a toolchain like this for a very long time. Thanks to you, I might finally venture deep into the mysterious realm of SNES programming. :lol:

After fiddling around a bit with pvsneslib, I think I've found a bug or two:


KEY_X and KEY_Y refer to the Y button and the X button, respectively. This can be corrected by simply swapping around their BIT numbers in include/snes/pads.h like so:

Code:
  KEY_X      = BIT(6), //!< pad X button.
  KEY_Y      = BIT(14), //!< pad Y button.



Additionally, I couldn't get the following condition to behave correctly:

Code:
if (joypad1 & (KEY_B | KEY_UP)) {
      // blah, blah
     }


Here, "blah, blah" happens when either B or up is pressed, not both at the same time as stated in the wiki.


Haven't tried much more yet, but will definitely do so. :)

Thanks again!

by on (#95458)
For both it should be if((joypad1&KEY_B)&&(joypad1&KEY_UP)) { }, or less obvious if(!(~joypad1&(KEY_B|KEY_UP))) { }

by on (#95496)
Thanks a lot for the bug about X & Y buttons, fixed in next release (will be available at the end of this month with , of course, some new features).

by on (#95507)
Shiru wrote:
if((joypad1&KEY_B)&&(joypad1&KEY_UP)) { }


That works, thanks! :D

alekmaul, I've spotted another minor issue: The internal ROM name doesn't match whatever you put in the NAME section in hdr.asm, instead the project name (e.g. "hello_world") is used.

Thanks again, and I'm looking forward to the next release! :D

by on (#95510)
About internal name, it is certainly because you have the following lines in your makefile (they are in each examples) :

GTITLE := -ht"$(TARGET)"

#---------------------------------------------------------------------------------
all : bitmaps $(OUTPUT).sfc
$(SNTOOLS) -hi! $(GTITLE) $(TARGET).sfc

So, the internal name is changed with the current directory name $(TARGET) , as you can see for variable GTITLE.
Use -ht option to change the name with snestool.

by on (#95640)
Can someone help me? I want this demo to display all the colors in palette 0 (it shows most, but some are black instead(?)), and demonstrate layer 1 over layer 0 (or the reverse? I'm not sure). I can't quite figure out how to make it does these things.

The demo

Thank you.

by on (#95642)
EagleEye, I'm not quite there yet, but when I am I'll make sure to give it a try.

alekmaul, thanks again for this project! I find it is much easier this way than learning about the SNES and assembly at the same time. I'm guessing assembly won't be avoidable in the end though, whether it's for speed or more advanced features. I'd love having a variable width font in my project, but looking at the PVSnesLib source gives me a headache for now, so I guess I'll stick to a constant width font until I'm more comfortable with the SNES as a whole :)

by on (#95685)
Sorry juef, do not have time to take a complete look at the code but I see some things :

Code:
   setMode(BG_MODE1,0); bgSetDisable(2); bgSetDisable(1);


So you will only have BG0 enable, your BG1 will never be display.


Code:
   bgInitMapSet(0, &map[0], 64, SC_32x32, 0x0000);
   bgInitMapSet(1, &map[6],  6, SC_32x32, 0x0000);
   bgInitMapSet(0, &map[0], 64, SC_32x32, 0x0020);
   bgInitMapSet(0, &map[0], 64, SC_32x32, 0x0040);
   bgInitMapSet(0, &map[0], 64, SC_32x32, 0x0060);
...


Why so much InitMapSet and an Init to BG1 (the second one), what do you really want to do ?

You've got a tool named gfx2snes that can easily creates for you some map, tiles and palette, why do you not use it ?

Take a look at snes-examples\graphics\Effects\Transparency project, there is a nice effect about a BG with another one just before it scrolling around the screen.

by on (#95701)
I don't use gfx2snes because I'll need to dynamically load in maps into memory and I'm testing that out. Additionally, I need to generate my own palettes and graphics anyway. The idea is that each frame I'll upload the tilemap to VRAM after I've modified it to reflect the current map correctly. I had BG1 disabled because I couldn't get it to work right and I wanted it to look correct enough when run without modification.

I'll look into Transparency's project. Thank you. :)

Combined Edit: I got layer 2 working using Transparency as an example, and then figured out how to use layer 1 instead. Unfortunately, it seems you can't call bgInitMapSet after you've called setMode. I have no clue how to switch out the tilemaps otherwise, so I guess I'll have to figure out how to turn off something, write to the tilemap, and turn that same something back on. In the meantime, I'm going to work on design, etc. I'll probably figure out what to do after a little break. (Here's my thing's mostly-fixed source, for anyone interested.)

P.S. scrY. pad0, and move are defined in the Transparency example, but never used.

by on (#95724)
You need to be near VBL to change tile map.
As you can see in google code of the lib, here is the code of initMapSet:

Code:
void bgInitMapSet(u8 bgNumber, u8 *mapSource, u16 mapSize, u16 sizeMode, u16 address) {
   setBrightness(0);  // Force VBlank Interrupt
      
   dmaCopyVram(mapSource, address,mapSize);
   if (bgNumber != 0xff)
      bgSetMapPtr(bgNumber, address, sizeMode);
}

So, if you only want to change tilemap,just use dmaCopyVram with correct parameters, just after VBL (wait for it with WaitForVBlank() for example)

Quote:
P.S. scrY. pad0, and move are defined in the Transparency example, but never used.

Yep, will fix that for next release. You're right ;-)

Also, I need help for doing something like pseudo3Dmode but i do not understand how matrix are working for snes, someone has a source code example like the squaresoft mode7 demo ? (http://www.unseen64.net/2010/10/28/squa ... tech-demo/)

by on (#95731)
Thanks. Now I'm pretty much set as far as SNES development. You've made this amazingly easy. :)

by on (#96851)
I'm having fun with this! :D

So far, I've only completed the tutorials up to the animated sprites one. I managed to "merge" the previous input tutorial with the animated sprite, improved the display of input buttons, added a position display, and introduced acceleration and screen wrapping (is that the right word?) to the sprite.

If anyone wants to see, download it here!

The only thing I'm having trouble with so far is with the top and left side of the screen. There seems to be a "black bar" at the top, and the sprite disappears all at once on the left side of the screen, whereas it gradually hidden by the bottom and right side. I've tried toying with negative integer positions, alas with no success. Can anyone help?

See video of the "game" in action!

by on (#96865)
It seems sprites disappearing on the left side is a bug in the library, at least judging from the documentation.

oamSet takes x coordinates in range 0..255, but their actual range is -255..255. The most significant (sign) bit lies in the upper 32 bytes of OAM.
(Note that -256 doesn't work correctly in hardware and therefore shouldn't be used).

Code would be something similar to this (note: not "optimized", also: C99/C++)

Code:
void oamSetXY_fixed(unsigned int id, unsigned int x, unsigned char y) {
    const OAM_HI_TABLE_START = 128*4;

    // Set low byte of x position and y position:
    unsigned char x_lo = (unsigned char)x;
    oamSetXY(id,x,y);

    // Note that id isn't the OAM id, but a direct index into OAM shadow memory;
    // the result is that id/4 is the actual oam index, which is required for determining
    // the OAM high table position.
    unsigned char oam_id = (unsigned char)(id >> 2);

    // Set highest bit of x position: Either at bit 0,2,4,6 depending on oam id,
    // as 4 oam entries are merged into one byte of the OAM high table.
    int bit_shift = 2*(oam_id % 4);
    int in_byte_position = 1 << bit_shift;
    int oam_high_table_pos = OAM_HI_TABLE_START + oam_id / 4;
    oamMemory[oam_high_table_pos] &= ~in_byte_position; // Clear current high bit of x
    oamMemory[oam_high_table_pos] |= (x>>8)<<bit_shift; // Fill in new high bit of x
}


Objects disappearing in the top 8 pixels may be a sign of you putting all unused objects with invisible gfx there; unused sprites should be moved to some huge negative x value (EXCEPT -256).

In fact, after looking at the oamInit code, it is another bug in the library: It sets the x position of every entry to (you probably guessed it) -256.
Since I'm already writing so much, I'll explain the curious behavior, too: If I recall correctly, sprites with x=-256 aren't displayed (as their x position is far too small), but due to a bug in the PPU they are considered on screen! They each take up a sprite slot, which has a hardware-based hard limit of 32, i.e. no more than 32 8x8 sprite tiles can be displayed per line. Since all sprites you didn't set to x=-255 are considered on the first 8 lines for sprite display, your sprite gets dropped. Manually setting all sprite positions to x=-255 should fix this.

Please excuse any errors, my last clash with the SNES was several years ago ;)

by on (#96869)
I was skimming through the documentation and noticed a small error in the "Day 2 - Output / Input" page (http://www.portabledev.com/wiki/doku.ph ... toutput_en)

At the bottom of the page it says:
Quote:
... or if (pad0 & (KEY_A | KEY_X)) to know if button A and button X are pressed.

But that condition will actually check if either one of the buttons is pressed (or both).

by on (#97035)
thefox wrote:
At the bottom of the page it says:
Quote:
... or if (pad0 & (KEY_A | KEY_X)) to know if button A and button X are pressed.

But that condition will actually check if either one of the buttons is pressed (or both).

You're right, fixed this day.

by on (#97037)
Jsolo wrote:
(Note that -256 doesn't work correctly in hardware and therefore shouldn't be used).

OK, didn't know about that.

Jsolo wrote:
Objects disappearing in the top 8 pixels may be a sign of you putting all unused objects with invisible gfx there; unused sprites should be moved to some huge negative x value (EXCEPT -256).

In fact, after looking at the oamInit code, it is another bug in the library: It sets the x position of every entry to (you probably guessed it) -256.
Since I'm already writing so much, I'll explain the curious behavior, too: If I recall correctly, sprites with x=-256 aren't displayed (as their x position is far too small), but due to a bug in the PPU they are considered on screen! They each take up a sprite slot, which has a hardware-based hard limit of 32, i.e. no more than 32 8x8 sprite tiles can be displayed per line. Since all sprites you didn't set to x=-255 are considered on the first 8 lines for sprite display, your sprite gets dropped. Manually setting all sprite positions to x=-255 should fix this.
ago ;)

OK, will fix that in next release.
I think I will add another function like oamSetXYEx instead of rewriting the actual one to avoid speed problem.

by on (#97047)
Thank you, Jsolo, thefox and alekmaul! :)
Re:
by on (#98877)
juef wrote:
I'm having fun with this! :D


Couldn't agree more. I used it in Ludum Dare (http://www.ludumdare.com/) #24 last weekend. Ludum Dare is a 48 hour game dev competition.
I have developed software for the SNES (started back in '93 if I remember right), but had never used PVSnesLib before. It was a nice departure for having to write everything myself, and I didn't write one line of 65816 asm code.

Here's my Bacon, Lettuce, and Tomato vertical shooter, from the competition:


Now for a question, is the source for gfx2snes available?
Re: Re:
by on (#98905)
cdoty wrote:

Now for a question, is the source for gfx2snes available?


Everything is available here : http://code.google.com/p/pvsneslib/
You've got gfx2snes, smconv and snestools source codes.
If you made some changes on them, please tell me, I will add your changes to the next version of the lib :)
Re: Re:
by on (#99032)
alekmaul wrote:
Everything is available here : http://code.google.com/p/pvsneslib/
You've got gfx2snes, smconv and snestools source codes.
If you made some changes on them, please tell me, I will add your changes to the next version of the lib :)


Thanks, I'm "looking to steal trade secrets". :)

I am looking to port this to other game systems (like the Genesis,) as the multi palette tile and map creation would be very useful on those systems.

The Gfx2Snes tool is missing the lzss.c file (unless it's somewhere else in the project, I couldn't find it). It's not a bit deal, as I just #ifdef'd out the lzsspacked related code.
Re: PVSnesLib for Snes 20th birthday :D !
by on (#113894)
Hi,
I updated PVSneslib with lot's of things.
Also, I added the missing lzss.c file, even if it is useless currently, I don't decompress BG in the lib...

At least, new game on the way with the lib : http://youtu.be/oVZBEesZZgw
Re: PVSnesLib for Snes 20th birthday :D !
by on (#114025)
Great, thanks! :D Are the binaries available?