Lameguy64 / PSn00bSDK

The most powerful open source SDK for the PS1 (as far as open source PS1 SDKs go). Not recommended for beginner use.
Other
838 stars 68 forks source link

Struggling With Chapter 1.3 Tutorial, Sprite Is 'Glitched' #66

Closed alex-free closed 1 year ago

alex-free commented 1 year ago

First of all, thank you for all of your work on this project. I have been banging my head against the wall trying to implement your chapter 1.3 tutorial. I have tried and re-read this page many times only to get the same result. I successfully followed every other chapter up to this one in the guide however.

As you most likely know, the tutorials are a bit outdated when used with the latest PSN00bSDK. So I will try to go as in-depth as possible to make this as easily debuggable for you.

I first start by creating a new directory 'test'. I copy the entire contents of the balls example into the test directory, as well as a copy of cmake-presets.json.

I then copy the entire sample code from chapter 1.3 into the 'main.c' file and save it, and then do the following changes:

include // Includes some functions that controls the display

include // GTE header, not really used but libgpu.h depends on it

include // GPU library header

needs to be changed to:

include // Includes some functions that controls the display

include // GTE header, not really used but libgpu.h depends on it

include // GPU library header

for the new toolchain.

I also change this: // Read TIM parameters (PsyQ) OpenTIM(tim); ReadTIM(tparam);

// Read TIM parameters (PSn00bSDK)
//GetTimInfo(tim, tparam);

to

// Read TIM parameters (PsyQ) // OpenTIM(tim); //ReadTIM(tparam);

// Read TIM parameters (PSn00bSDK)
GetTimInfo(tim, tparam);

For PSN00bSDK functionality.

I also change this line CMakeLists.txt: psn00bsdk_target_incbin(balls PRIVATE ball16c ball16c.tim)

to

psn00bsdk_target_incbin(balls PRIVATE tim_my_image ball16c.tim)

It compiles fine now. I did see this: // PSn00bSDK requires having all u_long types replaced with // u_int, as u_long in modern GCC that PSn00bSDK uses defines it as a 64-bit integer.

So I find and replace recursively u_long to u_int32_t in my text editor. I tried to replace it with just u_int but I get some warnings.

So at this point I need to change the original balls16c.tim to the image in the tutorial. I downloaded the png from the tutorial. I also downloaded and opened timtool 0.10a windows (via wine, I'm using Linux and didn't yet compile a native version). Now in Timedit I import the png and using all default options save it as an 8 bit TIM. I double checked that the following is true:

a 8-bit TIM file with image coordinates of 640,0 and CLUT coordinates of 0,480.

attached are some screenshots of me doing this in timedit.

import options

save imported tim

tim-imported

Now I believe that I should finally be able to see the texture in DuckStation. However I see this screen:

duckstation

For the life of me I can't figure it out. Real hardware is the same.

Also, attached is my entire little 'test' folder for help with further debugging. Thank you for your time reading all of this. It may be a small issue on my part, but alas I have exhausted everything I know on this subject (which is very little).

test.zip

I have compiled the SDK and toolchain with a script I wrote that does this: build-psn00bsdk.zip

And I set the env vars with another script I wrote

psn00b-env.zip

spicyjpeg commented 1 year ago

This was a fun one to debug. It turns out my reimplementation of PutDrawEnv() ignores the DRAWENV.tpage attribute, which is used by your code to set the texture page instead of manually instantiating and linking a DR_TPAGE primitive as most PSn00bSDK examples do.

I am going to fix this as part of version 0.22; for the moment you can get around it by using the DR_TPAGE primitive to set the page (which is better anyway as it allows you to use more than one texture page in the same OT/display list). The code would look like this:

uint16_t tim_texpage;

// In your init function, instead of setting draw[N].tpage:
tim_texpage = getTPage(tim_mode & 3, 0, tim_prect.x, tim_prect.y);

// In your main loop, *after* (not before) linking the primitive you want to apply the texture to:
DR_TPAGE *texpage = (DR_TPAGE *) nextpri;
// - the second argument unlocks drawing to the currently displayed framebuffer (no reason to do that usually)
// - the third argument enables dithering
setDrawTPage(texpage, 0, 0, tim_texpage);

addPrim(ot[db], texpage);
nextpri += sizeof(TEXPAGE);

And yes, the tutorials should be updated at some point to reflect the changes in the SDK. You can still refer to the documentation in this repo's doc folder, which is up-to-date with v0.21 (available prebuilt here - note that the CMake scripts, among other things, changed significantly from 0.19 to 0.21).

alex-free commented 1 year ago

Thank you so much! I can finally finish my demo (which I was wondering, would you be interested in a pull request to add another demo example?).

Also I was thinking, maybe it would be nice to include the examples from the tutorial in the examples directory of the SDK as well? I know the first hello world example is there already in the template folder, but I don't believe any other chapter sample code is available anywhere.

Attached is the 'fixed' Chapter 1.3 sample code in all of it's glory for reference with all your fixes and my updates for the new SDK. main.c.zip

spicyjpeg commented 1 year ago

I'm going to close this issue as v0.22 has been released and this bug fixed for good.

Also I was thinking, maybe it would be nice to include the examples from the tutorial in the examples directory of the SDK as well? I know the first hello world example is there already in the template folder, but I don't believe any other chapter sample code is available anywhere.

I am already working on integrating Lameguy's tutorials and code examples into the documentation. There are a few parts that need to be rewritten though, so it's going to take some time.