PlayStation dev tutorials, need feedback

Discussion in 'Sony Programming and Development' started by Gemini, Jun 11, 2016.

  1. Gemini

    Gemini Retro developer

    Joined:
    Apr 1, 2008
    Messages:
    406
    Likes Received:
    88
    Lately I started writing some PS development tutorials / advise articles that provide some directions to users who would like to get involved in the topic or for those interested in tackling the system in more efficient ways. So far I came up with two articles, but I have a third one already written and scheduled for release; this one talks about setting up light/color matrices for the GTE, with some code samples to avoid tl;dr effects.

    Article 1: The do’s and don’ts of PlayStation programming
    Article 2: Writing a good replacement for LibGS
    Article 3: Light sources: how they work and what you can do with them
    Article 4: Working around 2D primitives
    Article 5: 3D graphics and controller handling

    Are these articles any easy to follow or interesting to read? I'm thinking of writing more, but I need some directions to check if I'm making any sense.
     
    Last edited: Jun 14, 2016
  2. gwald

    gwald Net Yaroze '99

    Joined:
    Jan 6, 2016
    Messages:
    105
    Likes Received:
    36
    Hey that's pretty cool.. I'll have to read it in more dept and get back to you.

    The Overlay section is good intro, but how's it done?
    I assume the Net Yaroze (gcc) do it also?
    found some general info:
    ftp://ftp.gnu.org/old-gnu/Manuals/ld-2.9.1/html_node/ld_22.html
    http://davis.lbl.gov/Manuals/GDB/gdb_11.html

    The GS lib replacement tut is really a good start, but it you should also mention the helper functions, ie rot/trans/scale
    I see you did the light tut :)
    I'm using the NY lib, I know the GS lib stuff is bloated and 6 times slower..
    I'm creating my own dynamic TMD's any tips on how to better use GS libs would be good :p

    The 2D lib tut and code is good to, very clear and clean, thank you!
     
    Last edited: Jun 13, 2016
  3. Gemini

    Gemini Retro developer

    Joined:
    Apr 1, 2008
    Messages:
    406
    Likes Received:
    88
    Not sure about the NY toolchain, but on PSY-Q you can configure linker scripts to dump code to whatever binary you need. I'll make sure to include them in a following article.

    You mean the scaling on sprites? That will be done at some point or added as subcode for another demo.

    Then the newest article might come in handy: 3D graphics and controller handling
    It does rendering in at least 3 different ways and comes with all inlined GTE code. Should be useful to get rid of TMD.

    Glad to know somebody might actually be using it.
     
    gwald likes this.
  4. gwald

    gwald Net Yaroze '99

    Joined:
    Jan 6, 2016
    Messages:
    105
    Likes Received:
    36
    Sprites & 3D objects, I know it's just basic math stuff

    :D I can't just not use TMD, the Yaroze (GS) lib only supports TMD objects.. (and I'm not going to use PSYQ)
    If you know how to speed up GS lib, any tips would be great :)
    ie: is it possible to use GTE inline codes with GS lib?

    Oh that controller demo is really good.. haven't looked much at it yet.
    You should have a readme or a link or txt copy of your tut in side the zip, so people know where it came from.
     
  5. Gemini

    Gemini Retro developer

    Joined:
    Apr 1, 2008
    Messages:
    406
    Likes Received:
    88
    Might do that as a "silent update" for the next article. Something like a cracktro call back could make use of similar effects, tho the 3D objects should be at least covered in the last article.

    Besides pre-emptive packet allocation (I think one of the object link methods has this), there is very little you can do for speed. LibGS is horribly written and pretty much kills any performance unless you find a way to gather primitives of the same type and merge them together to take advantage of the code cache with some custom procedure. My advise is to just analyze a TMD and organize the data better. HMD did something like that, but performance is killed due to all the poorly optimized code using ZERO handshake between CPU and GTE.

    As long as you have the inline macros and dmpsx (to which I made a free alternative), yes. Inline code is as low level as it gets and can be integrated into anything.

    Good idea, I didn't think of adding something like that. I will update the packages, just in case.
     
  6. Trident6

    Trident6 Spirited Member

    Joined:
    Oct 17, 2015
    Messages:
    119
    Likes Received:
    55
    Interesting, my few additions would be to maybe qualify your comments on dynamic allocation some. Weather or not to use dynamic allocation in embedded systems is an argument that has been done to death. Personally I love it and use it all the time. I would first verify (maybe you have) that the underlying allocator is indeed a first-fit algorithm, and not something more complex like a slab/block allocator. We use these quite frequently on systems down to about 32kb of RAM with high uptime and no fragmentation whatsoever.

    Also maybe go into the benefits of grouping your allocations and limiting them to initialization time only, and writing a wrapper utility to keep track of leaks. Most game programmers I have met have a horrible habits and understandings of system-level issues.

    Sort of in-line with that, I would maybe steer people away from stack allocations. They are certainly useful but without a real solid understanding of scope or object lifetime it is asking for trouble. For instance, DMA transferring a stack object without waiting for the operation to finish can result in some seriously difficult to track down memory corruption issues if the stack descends back over your start address before the operation completes.

    On the whole, looks very good though.
     
  7. Gemini

    Gemini Retro developer

    Joined:
    Apr 1, 2008
    Messages:
    406
    Likes Received:
    88
    The problem with dynamic allocation is really that you can have way too many variables going on at once and very little memory to manage, which becomes awful when you start pushing overlays and your main exe is already gigantic. A custom allocator sure helps to avoid stuff accidentally overlapping on code or other resources, especially when one of them is supposed to overlap the other at some point.

    As for stack allocation, I was thinking of making a detailed article on how to use incremental allocation and parallel operations with DMA working in parallel (especially CD requests + VRAM uploads), but that will require some complexity. I'm counting on talking about that in an article about threads (should call them Fibers really) so that I don't need to come up with monkey code to simulate a scheduler.
     
  8. Gemini

    Gemini Retro developer

    Joined:
    Apr 1, 2008
    Messages:
    406
    Likes Received:
    88
    New article is up: Intro coding and CD-rom usage

    I'm open to tutorial requests at this point. Thinking of doing cooperative threading and async CD reads, unless something more demanded/interesting comes up.
     
    Borman likes this.
  9. Trident6

    Trident6 Spirited Member

    Joined:
    Oct 17, 2015
    Messages:
    119
    Likes Received:
    55
    There is lots of stuff to get into I suppose. Admittedly I do embedded work and only have passing experience with the PSX, but some topics to consider:

    Threading - models, cooperative, pre-emptive, how to implement, pitfalls, etc.
    DMA - synchronization and pitfalls.
    Caching - PSX's setup, how to utilize scratchpad, cached vs. non-cached segments, etc.
    GPU model - how to keep the pipeline full, what to offload to the GPU, how to do so effectively.
    Input - handling asyc input in a thread-safe manner.
    Overlays - how this aligns with low-level system calls, resource usage, etc.

    Maybe get into some system-level stuff as well, and talk about how to effectively manage resources. Also I don't see a lot of people cover sound output.
     
  10. Jackhead

    Jackhead Site Soldier

    Joined:
    Apr 2, 2008
    Messages:
    2,433
    Likes Received:
    610
    Really like to read your articles.
    Thanks alot for the work!
     
  11. smf

    smf mamedev

    Joined:
    Apr 14, 2005
    Messages:
    1,255
    Likes Received:
    88
    I haven't compiled it, so it's not tested. But I'd code it more like this. I think it makes it look simpler and I would guess that it's smaller. I don't know if you can skip the second seek.

    Code:
    void Cd_read(u32 lba, u32 size, u32 *dest)
    {
        CdlLOC loc;
        u32 sectors;
        u32 bytes;
    
        // full sectors
        sectors = size / 2048;
    
        // bytes from last sector
        bytes = size % 2048;
    
        if (sectors)
        {
            // convert lba to MSF and seek
            CdIntToPos(lba, &loc);
            CdControlB(CdlSetloc, (u8*)&loc, NULL);
            // read sectors into destination
            CdRead(sectors, dest, CdlModeSpeed);
            CdReadSync(0, NULL);
         }
    
        if (bytes)
        {
            // seek to last sectors
            CdIntToPos(lba + sectors, &loc);
            CdControlB(CdlSetloc, (u8*)&loc, NULL);
            // read reminder in a separate buffer
            CdRead(1, (u32*)buffer, CdlModeSpeed);
            CdReadSync(0, NULL);
            // copy reminder to destination
            memcpy(&((u8*)dest)[size - bytes], buffer, bytes);
        }
    }
    
     
    Last edited: Jun 26, 2016
  12. Gemini

    Gemini Retro developer

    Joined:
    Apr 1, 2008
    Messages:
    406
    Likes Received:
    88
    Yeah, your approach seems better and more well-thought in general. As for the second seek, it's always mandatory. The CD unit, no matter where the disk ends up with a read, still requires a seek command for any new read command issued (which takes effect almost immediately as the laser is already there, but the internal CD status ignores this).

    Threading on PlayStation is just of one kind (cooperative), but that can be used along with a number of those topics, like async handling. Caching is already covered, I guess I could expand it a bit more and provide more examples of usage and why it's important to take advantage of both cache types.
     
  13. Trident6

    Trident6 Spirited Member

    Joined:
    Oct 17, 2015
    Messages:
    119
    Likes Received:
    55
    I have seen a few times where the vsync handler or a root counter interrupt is used as a systick timer to get a scheduler and preemptive threading models working on it, but that may be off a bit into OS design rather than specifics to the Playstation.
     
  14. Gemini

    Gemini Retro developer

    Joined:
    Apr 1, 2008
    Messages:
    406
    Likes Received:
    88
    That is more or less how you would execute code related to vsync interrupts (or anything else a root counter can provide), which usually gives you a robust base for specific tasks that need to be executed independently from program code and on a constant basis, say music trackers. Actual cooperative threading allows you to switch around code with ease and from any point of the code.

    For example, you could have a main loop with just a bunch of system functions (pad, display swap, mdec playback, etc.) while a scheduler (i.e. thread tasks) executes game logic/rendering, async cd operations, and such.

    To give an even better example:
    - you have your game loop as task 0 executing as an infinite loop with a switch command at the end of said loop to pass on to the next task
    - task 1 takes care of cd reads and switches task as soon as it enters a wait state.
    You don't even need to add a million jumps to specific parts of either task because cooperative threading takes care of it and even restores the full state of your environment (i.e. no global variables required for local scope), meaning you can leave and go back with almost no need to change your logic.
     
  15. Trident6

    Trident6 Spirited Member

    Joined:
    Oct 17, 2015
    Messages:
    119
    Likes Received:
    55
    I think we are saying the same thing essentially, what you do is offload your kernel's context switch routine to the interrupt fired by the vsync timer or the root counter and get the next task served up by whatever scheduler you wanted to write. I guess it depends on if you want determinism on both PAL and NTSC systems as to which interrupt source you select.

    I can't remember if the library primitives for task switching could be called from an interrupt context or not, otherwise you would have to write a manual context switching routine as well.
     
  16. theps1master

    theps1master Robust Member

    Joined:
    Jun 25, 2016
    Messages:
    271
    Likes Received:
    26
    Very impressive where did u learn all this
     
    CodeAsm likes this.
  17. Gemini

    Gemini Retro developer

    Joined:
    Apr 1, 2008
    Messages:
    406
    Likes Received:
    88
  18. Orion_

    Orion_ Member

    Joined:
    Feb 13, 2012
    Messages:
    13
    Likes Received:
    14
    this tutorial seems really great ! I always had difficulties understanding the 3D part in PS1 dev and producing TMD file is just a nightmare. I will need to take some times reading this tutorial ! Thank you for your work !
    I made some PS1 dev tutorials too, but it's more about 2D, and the basics on how the PS1 hardware works.
    http://onorisoft.free.fr/psx/psx.htm
    http://onorisoft.free.fr/psx/tutorial/tuto.htm
     
    gwald likes this.
sonicdude10
Draft saved Draft deleted
Insert every image as a...
  1.  0%

Share This Page