5.9 KiB
5.9 KiB
Вот готовая программа для PlayStation 1, которая загружает текстуру с CD-ROM, передаёт её в VRAM и плавно выводит на экран с анимацией яркости (от 0 до 128). Код использует PsyQ SDK и разбит на логические блоки.
1. Структура проекта
texture_demo/
├── MAIN.C # Основной код
├── TEXTURE.BIN # RAW-текстура 256x256 (16-бит RGB)
└── SYSTEM.CNF # Конфигурационный файл
2. Код программы (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_SIZE (256 * 256 * 2) // 131072 байт
uint16_t tex_buffer[256 * 256] __attribute__((aligned(64))); // Выравнивание для DMA
// Параметры спрайта
typedef struct {
RECT img_rect; // Размеры текстуры
TIM_IMAGE tim; // Данные TIM-файла
int brightness; // Текущая яркость (0-128)
int fade_speed; // Скорость изменения яркости
} Sprite;
void init() {
// Инициализация системных библиотек
ResetGraph(0);
InitPad(NULL, 0, NULL, 0);
CdInit();
// Настройка видеорежима (NTSC)
SetVideoMode(MODE_NTSC);
FntLoad(960, 256);
FntOpen(16, 16, 256, 224, 0, 512);
}
void load_texture(const char* filename) {
CdlFILE file;
uint8_t sector_buffer[2048]; // Буфер для сектора CD
// Поиск файла на диске
if (CdSearchFile(&file, filename) == 0) {
FntPrint("Error: File not found!\n");
return;
}
// Чтение текстуры в буфер через DMA
CdRead(file.pos, (uint32_t*)tex_buffer, TEX_SIZE / 2048);
CdReadSync(0); // Ожидание завершения
}
void draw_sprite(Sprite* sprite) {
// Установка яркости (0-128 → 0.0-1.0)
float alpha = (float)sprite->brightness / 128.0f;
// Рисуем полноэкранный спрайт с альфа-смешением
DR_MODE dr_mode;
SetDrawMode(&dr_mode, 0, 0, GetTPage(0, 0, sprite->tim.prect->x, sprite->tim.prect->y), 0);
SetSprt16(&sprite->img_rect); // 16-битный спрайт
// Применяем яркость через полупрозрачность
SetSemiTrans(&sprite->img_rect, 1);
setRGB0(&sprite->img_rect, alpha * 255, alpha * 255, alpha * 255);
// Вывод спрайта
DrawPrim(&sprite->img_rect);
}
int main() {
init(); // Инициализация
// Загрузка текстуры
load_texture("\\TEXTURE.BIN"); // Путь на CD
// Настройка спрайта
Sprite sprite = {
.img_rect = {0, 0, SCREEN_WIDTH, SCREEN_HEIGHT},
.brightness = 0,
.fade_speed = 1
};
// Загрузка текстуры в VRAM
sprite.tim.mode = 0;
sprite.tim.prect = (RECT*)tex_buffer;
LoadImage(&sprite.tim.prect[0], &sprite.tim.pdata[0]);
// Главный цикл
while (1) {
FntPrint("Fade Demo: Brightness = %d\n", sprite.brightness);
// Плавное увеличение яркости
sprite.brightness += sprite.fade_speed;
if (sprite.brightness >= 128 || sprite.brightness <= 0)
sprite.fade_speed *= -1; // Меняем направление
// Отрисовка
draw_sprite(&sprite);
FntFlush(-1);
// Синхронизация с VBlank
VSync(0);
}
return 0;
}
3. Как это работает?
-
Инициализация:
- Настраивается видеорежим (NTSC 320x240).
- Инициализируются CD-ROM и геймпад.
-
Загрузка текстуры:
- Файл
TEXTURE.BIN(RAW 256x256, 16-бит) читается с диска через DMA. - Данные копируются в буфер
tex_buffer.
- Файл
-
Передача в VRAM:
LoadImage()загружает текстуру в VRAM (адрес автоматически выбирается GPU).
-
Плавное затемнение:
- В главном цикле меняется параметр
brightness(0 → 128 → 0). - Яркость применяется через полупрозрачность (
SetSemiTrans).
- В главном цикле меняется параметр
-
Вывод:
- Спрайт рисуется на весь экран с текущей яркостью.
4. Требования к текстуре
- Формат: RAW 16-бит RGB (без заголовков).
- Размер: 256x256 (можно изменить в коде).
- Размещение: корень CD (
TEXTURE.BIN).
5. Сборка
- Скомпилируйте через PsyQ SDK:
ccpsx MAIN.C -o TEXTURE_DEMO.EXE - Запишите на диск вместе с
TEXTURE.BINиSYSTEM.CNF.
6. Демонстрация эффекта
- Текстура плавно "проявляется" (от чёрного к нормальной яркости) и затем исчезает.
- Скорость регулируется
fade_speed.
7. Оптимизации
- Для плавности используется VSync(0).
- DMA ускоряет загрузку текстуры.
- Полупрозрачность GPU имитирует изменение яркости.
Этот код можно расширить для загрузки анимаций или сложных эффектов! 🎮