6.2 KiB
6.2 KiB
Вот модифицированная программа для 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. Ключевые изменения
-
Загрузка из сектора:
- Вместо поиска файла (
CdSearchFile) используется прямой доступ к сектору:CdRead(start_sector, (uint32_t*)tex_buffer, TEX_SECTORS); start_sector— начальный сектор текстуры на диске (например,1000).
- Вместо поиска файла (
-
Размер текстуры:
- Рассчитывается автоматически:
#define TEX_SECTORS (TEX_SIZE / 2048) // 2048 байт = 1 сектор Mode 1
- Рассчитывается автоматически:
-
Выравнивание в RAM:
- Буфер
tex_bufferвыровнен по 64 байта для эффективного DMA:uint16_t tex_buffer[...] __attribute__((aligned(64)));
- Буфер
-
Загрузка в VRAM:
LoadImageкопирует данные изtex_buffer(RAM) в VRAM:LoadImage(&vram_rect, (uint32_t*)tex_buffer);
3. Как подготовить диск
-
Конвертируйте текстуру в RAW 16-бит (например, через Photoshop или
ffmpeg):ffmpeg -i texture.png -f rawvideo -pix_fmt rgb565 texture.raw -
Запишите RAW-данные на CD в нужный сектор (например, с помощью
mkpsxiso):mkpsxiso -y -o texture.cue -c "CDROM_DATA" texture.raw- Узнайте начальный сектор через
cdrdaoили hex-редактор.
- Узнайте начальный сектор через
4. Важные нюансы
- Режим CD-ROM: Данные должны быть записаны в Mode 1 (2048 байт/сектор).
- Размер текстуры: Должен быть кратен размеру сектора (иначе чтение "сломает" данные).
- Проверка сектора: Убедитесь, что сектор не занят другими файлами.
5. Пример для сборки
- Скомпилируйте:
ccpsx MAIN.C -o CD_SECTOR_DEMO.EXE - Запишите на диск, указав в
SYSTEM.CNF:BOOT = cdrom:\CD_SECTOR_DEMO.EXE;1
6. Дополнительная оптимизация
Для работы с Mode 2 XA (формат видео) измените:
CdReadMode(CdMode_CD_XA); // Перед CdRead
и корректируйте размер сектора (2336 байт).
Этот код идеален для демо-сцен, где нужно напрямую читать графику с CD без файловой системы! 📀