Files
SergObsidian/PERSONAL PROJECTS/PS1 DOCS/PSX code - Load texture from SECTOR!.md
2025-04-18 23:10:56 +05:00

6.2 KiB
Raw Permalink Blame History

Вот модифицированная программа для PlayStation 1, которая загружает текстуру напрямую из указанного сектора CD-ROM в RAM, а затем выводит её на экран с эффектом плавного появления. Код адаптирован для работы с "сырыми" секторами диска.


1. Изменённый код (MAIN.C)

#include <sys/types.h>
#include <libetc.h>
#include <libgte.h>
#include <libgpu.h>
#include <libcd.h>

#define SCREEN_WIDTH  320
#define SCREEN_HEIGHT 240

// Параметры текстуры (256x256, 16-бит)
#define TEX_WIDTH   256
#define TEX_HEIGHT  256
#define TEX_SIZE    (TEX_WIDTH * TEX_HEIGHT * 2)  // 131072 байт (16-бит)
#define TEX_SECTORS (TEX_SIZE / 2048)             // Размер в секторах CD (1 сектор = 2048 байт)

// Буфер для текстуры в RAM (выровнен для DMA)
uint16_t tex_buffer[TEX_WIDTH * TEX_HEIGHT] __attribute__((aligned(64)));

// Структура спрайта
typedef struct {
    RECT img_rect;      // Размеры текстуры
    TIM_IMAGE tim;      // Данные TIM-формата (не используется, но нужен для LoadImage)
    int brightness;     // Текущая яркость (0-128)
    int fade_speed;     // Скорость изменения яркости
} Sprite;

void init() {
    ResetGraph(0);
    InitPad(NULL, 0, NULL, 0);
    CdInit();
    SetVideoMode(MODE_NTSC);
    FntLoad(960, 256);
    FntOpen(16, 16, 256, 224, 0, 512);
}

void load_texture_from_sector(int start_sector) {
    // Чтение текстуры из указанного сектора CD-ROM в RAM через DMA
    CdRead(start_sector, (uint32_t*)tex_buffer, TEX_SECTORS);
    CdReadSync(0);  // Ожидание завершения DMA
}

void draw_sprite(Sprite* sprite) {
    // Настройка полупрозрачности для эффекта яркости
    float alpha = (float)sprite->brightness / 128.0f;
    DR_MODE dr_mode;
    SetDrawMode(&dr_mode, 0, 0, GetTPage(0, 0, 0, 0), 0);
    SetSprt16(&sprite->img_rect);
    SetSemiTrans(&sprite->img_rect, 1);
    setRGB0(&sprite->img_rect, alpha * 255, alpha * 255, alpha * 255);
    DrawPrim(&sprite->img_rect);
}

int main() {
    init();

    // Параметры загрузки (пример: текстура начинается с сектора 1000)
    int texture_start_sector = 1000;  // Замените на реальный сектор!
    load_texture_from_sector(texture_start_sector);

    // Настройка спрайта
    Sprite sprite = {
        .img_rect = {0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, 0, 0, 0},
        .brightness = 0,
        .fade_speed = 1
    };

    // Загрузка текстуры в VRAM (адрес в RAM -> VRAM)
    RECT vram_rect = {0, 0, TEX_WIDTH, TEX_HEIGHT};  // Куда загружать в VRAM
    LoadImage(&vram_rect, (uint32_t*)tex_buffer);

    // Главный цикл
    while (1) {
        FntPrint("Sector Load Demo\nBrightness: %d\nSector: %d", 
                sprite.brightness, texture_start_sector);

        // Плавное изменение яркости
        sprite.brightness += sprite.fade_speed;
        if (sprite.brightness >= 128 || sprite.brightness <= 0) 
            sprite.fade_speed *= -1;

        // Отрисовка
        draw_sprite(&sprite);
        FntFlush(-1);
        VSync(0);
    }

    return 0;
}

2. Ключевые изменения

  1. Загрузка из сектора:

    • Вместо поиска файла (CdSearchFile) используется прямой доступ к сектору:
      CdRead(start_sector, (uint32_t*)tex_buffer, TEX_SECTORS);
      
    • start_sector — начальный сектор текстуры на диске (например, 1000).
  2. Размер текстуры:

    • Рассчитывается автоматически:
      #define TEX_SECTORS (TEX_SIZE / 2048)  // 2048 байт = 1 сектор Mode 1
      
  3. Выравнивание в RAM:

    • Буфер tex_buffer выровнен по 64 байта для эффективного DMA:
      uint16_t tex_buffer[...] __attribute__((aligned(64)));
      
  4. Загрузка в VRAM:

    • LoadImage копирует данные из tex_buffer (RAM) в VRAM:
      LoadImage(&vram_rect, (uint32_t*)tex_buffer);
      

3. Как подготовить диск

  1. Конвертируйте текстуру в RAW 16-бит (например, через Photoshop или ffmpeg):

    ffmpeg -i texture.png -f rawvideo -pix_fmt rgb565 texture.raw
    
  2. Запишите RAW-данные на CD в нужный сектор (например, с помощью mkpsxiso):

    mkpsxiso -y -o texture.cue -c "CDROM_DATA" texture.raw
    
    • Узнайте начальный сектор через cdrdao или hex-редактор.

4. Важные нюансы

  • Режим CD-ROM: Данные должны быть записаны в Mode 1 (2048 байт/сектор).
  • Размер текстуры: Должен быть кратен размеру сектора (иначе чтение "сломает" данные).
  • Проверка сектора: Убедитесь, что сектор не занят другими файлами.

5. Пример для сборки

  1. Скомпилируйте:
    ccpsx MAIN.C -o CD_SECTOR_DEMO.EXE
    
  2. Запишите на диск, указав в SYSTEM.CNF:
    BOOT = cdrom:\CD_SECTOR_DEMO.EXE;1
    

6. Дополнительная оптимизация

Для работы с Mode 2 XA (формат видео) измените:

CdReadMode(CdMode_CD_XA);  // Перед CdRead

и корректируйте размер сектора (2336 байт).


Этот код идеален для демо-сцен, где нужно напрямую читать графику с CD без файловой системы! 📀