Files
SergObsidian/PERSONAL PROJECTS/PS1 DOCS/PSX code logo show.md
2025-04-20 13:20:44 +05:00

5.0 KiB

Here's the rewritten code with detailed English comments, following PlayStation 1 (PS1) hardware constraints and PsyQ SDK best practices:


1. RDLogo_DrawFramePadCheck() - Renders Frame and Handles Pad Input

#include <sys/types.h>
#include <psxgpu.h>
#include <psxpad.h>

/**
 * Renders logo frame and checks controller input
 * 
 * @param isCheckPadBtn If 1, checks for button press to skip animation
 * @return 1 if button pressed (and isCheckPadBtn=1), otherwise 0
 */
int RDLogo_DrawFramePadCheck(int isCheckPadBtn) {
    static int currentBuffer = 0;  // Double buffer index (0/1)
    PADTYPE padStatus;            // PS1 controller status struct
    int padPressed = 0;           // Button press flag
    
    // (1) Get current buffer and set OT
    currentBuffer = GsGetActiveBuff();
    GsSetWorkBase((u_long*)&gpu_ot[currentBuffer]);  // Set OT for current buffer
    
    // (2) Clear ordering table for new frame
    GsClearOt(0, 0, &gpu_ot[currentBuffer]);
    
    // (3) Add logo sprites to OT
    // PS1 hardware limitation: Max sprite width = 256px, so logo is split
    GsSortFastSprite(&leftLogoPart, &gpu_ot[currentBuffer], 0);  // Left 256px
    GsSortFastSprite(&rightLogoPart, &gpu_ot[currentBuffer], 0); // Right 64px
    
    // (4) Wait for GPU and VBlank sync
    DrawSync(0);                        // Wait for drawing completion
    VSync(0);                           // Sync to vertical refresh
    
    // (5) Read controller input
    PadRead(&padStatus);                // Poll controller
    padPressed = (padStatus.btns != 0); // Any button pressed
    
    // (6) Skip input check or no button pressed
    if ((isCheckPadBtn == 0) || (padPressed == 0)) {
        GsSwapDispBuff();               // Flip buffers
        GsSortClear(0, 0, 0, &gpu_ot[currentBuffer]);  // Clear screen
        GsDrawOt(&gpu_ot[currentBuffer]); // Render OT
        return 0;                       // No button pressed
    }
    
    return 1;  // Button pressed (only if isCheckPadBtn=1)
}

2. RDLogo_show() - Main Logo Display Function

#include <psxgpu.h>
#include <psxcd.h>

// Global sprite definitions (split due to PS1's 256px width limit)
GsSPRITE leftLogoPart;  // Left 256px of logo (texture + attributes)
GsSPRITE rightLogoPart; // Right 64px of logo (320px total width)
u_long gpu_ot[2][OTSIZE]; // Double buffered ordering tables

/**
 * Displays logo with fade-in/out animation
 * Splits rendering due to PS1 hardware limitations:
 * - Maximum single sprite width: 256px
 * - 15-bit color (RGB555)
 * - Requires manual VRAM management
 */
void RDLogo_show(void) {
    int alpha;  // Transparency value (0=transparent, 128=opaque)
    int i;
    
    // (1) Initialize graphics
    SetDispMask(0);                     // Disable display
    ResetGraph(1);                      // Reset GPU
    GsInitGraph(320, 240, 4, 1, 0);    // 320x240, 16-bit color
    GsDefDispBuff(0, 0, 0, 240);       // Setup double buffering
    
    // (2) Load logo from CD-ROM
    CdInit();                           // Initialize CD drive
    // Read raw sector containing logo (bypass filesystem for speed)
    CdRead(104798, (u_long*)&leftLogoPart, 2048);  // Sector 104798
    
    // (3) Configure split sprites
    // Left part: 256px wide, positioned left of center (-160px)
    GsSetSprite(&leftLogoPart, -160, -120, 256, 240, 5);  // Palette slot 5
    // Right part: 64px wide, positioned right of center (+160px)
    GsSetSprite(&rightLogoPart, 160, -120, 64, 240, 7);  // Palette slot 7
    
    // (4) Fade-in animation
    for (alpha = 0; alpha < 128; alpha += 4) {
        leftLogoPart.r = alpha;   // Set transparency (PS1 uses .r for blending)
        rightLogoPart.r = alpha;
        RDLogo_DrawFramePadCheck(0);  // Render without input check
    }
    
    // (5) Display pause (120 frames) with skip option
    for (i = 0; i < 120; i++) {
        if (RDLogo_DrawFramePadCheck(1)) break;  // Check for button press
    }
    
    // (6) Fade-out animation
    for (alpha = 128; alpha >= 0; alpha -= 4) {
        leftLogoPart.r = alpha;
        rightLogoPart.r = alpha;
        RDLogo_DrawFramePadCheck(0);
    }
    
    SetDispMask(0);  // Disable display before exiting
}

Key Hardware Considerations:

  1. Sprite Width Limit:

    // PS1 GPU cannot render >256px wide sprites in one operation
    GsSetSprite(&leftLogoPart, ..., 256, ...);  // Max allowed width
    
  2. VRAM Management:

    CdRead(104798, ...); // Bypass filesystem for direct sector access
    
  3. 15-bit Color:

    GsInitGraph(..., 4, ...); // 4 = 16-bit color mode (RGB555)
    
  4. Ordering Table (OT):

    GsClearOt(0, 0, &gpu_ot[currentBuffer]); // Critical for proper z-sorting
    

Compilation Notes:

  1. Requires PsyQ SDK (libpsxgpu.a, libpsxcd.a)
  2. Link with -lpsxetc -lpsxgpu -lpsxcd
  3. MIPS R3000 compiler needed (e.g., mipsel-unknown-elf-gcc)

This implementation respects all PS1 hardware limitations while maintaining readability. The logo splitting is mandatory due to the GPU's 256px render width constraint.