diff --git a/.obsidian/workspace.json b/.obsidian/workspace.json index 683388f..4728a2e 100644 --- a/.obsidian/workspace.json +++ b/.obsidian/workspace.json @@ -41,12 +41,12 @@ "state": { "type": "markdown", "state": { - "file": "PERSONAL PROJECTS/PSX code - modules load and exec.md", + "file": "PERSONAL PROJECTS/PS1 DOCS/PS1 Geometry Transformation Engine.md", "mode": "source", "source": false }, "icon": "lucide-file", - "title": "PSX code - modules load and exec" + "title": "PS1 Geometry Transformation Engine" } } ], @@ -207,17 +207,21 @@ }, "active": "dd912cc876184c4f", "lastOpenFiles": [ - "PERSONAL PROJECTS/PSX code texture load unpack show and fade.md", - "PERSONAL PROJECTS/PSX code - modules load and exec.md", - "PERSONAL PROJECTS/PS1 Gamepad.md", - "PERSONAL PROJECTS/PSX code - Load texture from SECTOR!.md", - "PERSONAL PROJECTS/PSX code - Texture show from file.md", - "PERSONAL PROJECTS/PS1 Vblank.md", - "PERSONAL PROJECTS/PS1 MDEC.md", - "PERSONAL PROJECTS/PS1 DMA.md", - "PERSONAL PROJECTS/PS1 Gpu-DMA.md", - "PERSONAL PROJECTS/PS1 DMA CD-ROM.md", - "PERSONAL PROJECTS/LZSS C++ Lib.md", + "PERSONAL PROJECTS/PS1 DOCS/LZSS C++ Lib.md", + "PERSONAL PROJECTS/PS1 DOCS/PS1 Geometry Transformation Engine.md", + "PERSONAL PROJECTS/PS1 DOCS/PS1 Ordering table.md", + "PERSONAL PROJECTS/PS1 DOCS", + "PERSONAL PROJECTS/PS1 DOCS/PSX code texture load unpack show and fade.md", + "PERSONAL PROJECTS/PS1 DOCS/PSX code inline asm.md", + "PERSONAL PROJECTS/PS1 DOCS/PSX code - Texture show from file.md", + "PERSONAL PROJECTS/PS1 DOCS/PSX code - modules load and exec.md", + "PERSONAL PROJECTS/PS1 DOCS/PS1 Gamepad.md", + "PERSONAL PROJECTS/PS1 DOCS/PSX code - Load texture from SECTOR!.md", + "PERSONAL PROJECTS/PS1 DOCS/PS1 Vblank.md", + "PERSONAL PROJECTS/PS1 DOCS/PS1 MDEC.md", + "PERSONAL PROJECTS/PS1 DOCS/PS1 DMA.md", + "PERSONAL PROJECTS/PS1 DOCS/PS1 Gpu-DMA.md", + "PERSONAL PROJECTS/PS1 DOCS/PS1 DMA CD-ROM.md", "WORK & PROJECTS/Mol/Ideas/Все идеи для Моли.md", "WORK & PROJECTS/Mol/Серверы/mail.mol-soft.ru.md", "WORK & PROJECTS/Mol/Документы для ТЗ ЛИМС/СМК/КУ_Чек_лист_10_ошибок_УД_скачивание.pdf", @@ -239,18 +243,14 @@ "WORK & PROJECTS/Mol/Планы и диаграммы/Alfa Cloud", "WORK & PROJECTS/Mol/Серверы/git.moldev.ru.md", "WORK & PROJECTS/Ulab/передача сформированных заявки и протокола как ссылку или файл.md", - "WORK & PROJECTS/Ulab/Доступы к точкам.md", "Структура объектов испытаний.png", "Схема связей юрлиц и адресов.png", "Структура объектов испытаний.png.0.pdnSave", "WORK & PROJECTS/Mol/Документы для ТЗ ЛИМС/АФ-01 Альбом форм.pdf", "WORK & PROJECTS/Mol/Серверы/Схема инфраструктуры.canvas", - "WORK & PROJECTS/Ulab/Московский проект/ACCESS TABLE.md", "WORK & PROJECTS/Ulab/Автобан/щебень 5-20.xlsx", "WORK & PROJECTS/Ulab/Автобан/щебень 20-40.xlsx", "WORK & PROJECTS/Ulab/Автобан/песок природный.xls", - "WORK & PROJECTS/Ulab/Автобан/грунт песчаный.xlsx", - "WORK & PROJECTS/Mol/Серверы/Alfa cloud prod_canvas2doc-data/newdoc-node_f3d0e9a6d4d8e6a7_fromCanvas.md", "WORK & PROJECTS/Mol/Серверы/Alfa cloud prod.canvas", "PERSONAL PROJECTS/P2EP/cdRead.canvas", "P2EP/cdRead.canvas", diff --git a/PERSONAL PROJECTS/LZSS C++ Lib.md b/PERSONAL PROJECTS/PS1 DOCS/LZSS C++ Lib.md similarity index 100% rename from PERSONAL PROJECTS/LZSS C++ Lib.md rename to PERSONAL PROJECTS/PS1 DOCS/LZSS C++ Lib.md diff --git a/PERSONAL PROJECTS/PS1 DMA CD-ROM.md b/PERSONAL PROJECTS/PS1 DOCS/PS1 DMA CD-ROM.md similarity index 100% rename from PERSONAL PROJECTS/PS1 DMA CD-ROM.md rename to PERSONAL PROJECTS/PS1 DOCS/PS1 DMA CD-ROM.md diff --git a/PERSONAL PROJECTS/PS1 DMA.md b/PERSONAL PROJECTS/PS1 DOCS/PS1 DMA.md similarity index 100% rename from PERSONAL PROJECTS/PS1 DMA.md rename to PERSONAL PROJECTS/PS1 DOCS/PS1 DMA.md diff --git a/PERSONAL PROJECTS/PS1 Gamepad.md b/PERSONAL PROJECTS/PS1 DOCS/PS1 Gamepad.md similarity index 100% rename from PERSONAL PROJECTS/PS1 Gamepad.md rename to PERSONAL PROJECTS/PS1 DOCS/PS1 Gamepad.md diff --git a/PERSONAL PROJECTS/PS1 DOCS/PS1 Geometry Transformation Engine.md b/PERSONAL PROJECTS/PS1 DOCS/PS1 Geometry Transformation Engine.md new file mode 100644 index 0000000..3aef30c --- /dev/null +++ b/PERSONAL PROJECTS/PS1 DOCS/PS1 Geometry Transformation Engine.md @@ -0,0 +1,144 @@ +### **Математический процессор (GTE) в PlayStation 1** + +**Geometry Transformation Engine (GTE)** — это сопроцессор в PS1, отвечающий за ускорение математических операций, критичных для 3D-графики. Он работает параллельно с основным CPU (R3000A) и оптимизирован для: + +1. **Перемножения матриц** +2. **Вращения и трансформации вершин** +3. **Расчёта перспективы и освещения** + +--- + +## **1. Основные функции GTE** +### **1.1. Быстрые матричные операции** +GTE умеет: +- Умножать **матрицу 3×3** на вектор (для поворота объектов). +- Вычислять **матрицу модели-вида** (Model-View). +- Обновлять **нормали объектов** для освещения. + +**Пример**: Поворот вершины: +```mips +# Вход: матрица вращения в $a0, вершина (x,y,z) в $a1 +lw $t0, 0($a0) # Загружаем элемент матрицы +lw $t1, 0($a1) # Загружаем X вершины +mult $t0, $t1 # Умножаем (GTE делает это за 1 такт) +mflo $t2 # Результат +``` + +--- + +### **1.2. Перспективное преобразование** +GTE вычисляет **экранные координаты (X,Y)** из 3D-пространства: +1. Учитывает **камеру** (матрица вида). +2. Применяет **перспективу** (деление на Z). +3. Оптимизирует расчёт **FOV** (поля зрения). + +**Формула**: +\[ +X_{screen} = \frac{X_{3D} \cdot scale}{Z_{3D}} + center\_x +\] + +--- + +### **1.3. Освещение и цвет** +- GTE рассчитывает **интенсивность света** для вершин. +- Поддерживает **до 3 источников света** (накладывает цвета). +- Работает с **нормалями** (через скалярное произведение). + +**Пример**: +```mips +# Нормаль в $a0, свет в $a1 +dp $t0, $a0, $a1 # Скалярное произведение (GTE) +sll $t0, 8 # Яркость = 0..255 +``` + +--- + +## **2. Зачем нужно перемножение матриц?** +Матрицы используются для: +1. **Поворота объектов** + ```math + \begin{bmatrix} + \cosθ & -\sinθ & 0 \\ + \sinθ & \cosθ & 0 \\ + 0 & 0 & 1 \\ + \end{bmatrix} \cdot + \begin{bmatrix} X \\ Y \\ Z \end{bmatrix} + ``` +2. **Масштабирования** + ```math + \begin{bmatrix} + S_x & 0 & 0 \\ + 0 & S_y & 0 \\ + 0 & 0 & S_z \\ + \end{bmatrix} + ``` +3. **Смещения (трансляции)** + ```math + \begin{bmatrix} 1 & 0 & T_x \\ 0 & 1 & T_y \\ 0 & 0 & 1 \end{bmatrix} + ``` + +**GTE делает это за 1-2 такта** (вместо 10+ тактов на R3000A). + +--- + +## **3. Пример: поворот куба на PS1** +### **Код на C с ассемблерными вставками** +```c +#include + +typedef struct { short x, y, z; } Vertex; + +void rotate_vertex(Vertex *v, int angle) { + MATRIX rot_matrix; + int sin, cos; + + // Получаем синус/косинус угла (через GTE) + gte_ldsin(angle, &sin); + gte_ldcos(angle, &cos); + + // Заполняем матрицу поворота вокруг Z + rot_matrix.m[0][0] = cos; rot_matrix.m[0][1] = -sin; + rot_matrix.m[1][0] = sin; rot_matrix.m[1][1] = cos; + + // Умножаем матрицу на вершину (через GTE) + gte_rtps(v->x, v->y, v->z, &rot_matrix, &v->x, &v->y, &v->z); +} +``` + +--- + +## **4. Оптимизации через GTE** +### **4.1. Пакетная обработка** +- GTE может обрабатывать **до 3 вершин за инструкцию** (`rtpt`). +- Пример для треугольника: + ```mips + rtpt # Поворот 3 вершин сразу + nop + ``` + +### **4.2. Отложенные вычисления** +- Команды `nclip` и `avsz3` считают **площадь полигона** и **Z-буфер** без CPU. + +### **4.3. Интеграция с GPU** +- Результаты GTE (экранные X,Y,Z) передаются в **GPU** через DMA. +- Это ускоряет рендеринг в 5-10 раз. + +--- + +## **5. Сравнение с современными GPU** +| Функция | PS1 (GTE) | Современный GPU | +|-----------------------|----------------|----------------| +| Матричные операции | 1-2 такта | 1 такт | +| Макс. источников света| 3 | 100+ | +| Поддержка шейдеров | Нет | Да | + +--- + +## **6. Итог** +- **GTE** — это «сердце» 3D-графики PS1, отвечающее за: + - Поворот, масштабирование, перспективу. + - Освещение и цвет. +- **Без GTE** игры вроде *Tekken 3* или *Metal Gear Solid* работали бы на **1-2 FPS**. +- Оптимизация под GTE — ключ к плавному рендерингу на PS1. + +Для глубокого изучения смотрите [GTE Technical Reference](http://problemkaputt.de/psx-spx.htm#gtegeometrytransformationengine). \ No newline at end of file diff --git a/PERSONAL PROJECTS/PS1 Gpu-DMA.md b/PERSONAL PROJECTS/PS1 DOCS/PS1 Gpu-DMA.md similarity index 100% rename from PERSONAL PROJECTS/PS1 Gpu-DMA.md rename to PERSONAL PROJECTS/PS1 DOCS/PS1 Gpu-DMA.md diff --git a/PERSONAL PROJECTS/PS1 MDEC.md b/PERSONAL PROJECTS/PS1 DOCS/PS1 MDEC.md similarity index 100% rename from PERSONAL PROJECTS/PS1 MDEC.md rename to PERSONAL PROJECTS/PS1 DOCS/PS1 MDEC.md diff --git a/PERSONAL PROJECTS/PS1 DOCS/PS1 Ordering table.md b/PERSONAL PROJECTS/PS1 DOCS/PS1 Ordering table.md new file mode 100644 index 0000000..f5a8fcb --- /dev/null +++ b/PERSONAL PROJECTS/PS1 DOCS/PS1 Ordering table.md @@ -0,0 +1,137 @@ + +### **Сортировка полигонов на PlayStation 1 (PS1)** + +PS1 не имеет аппаратной поддержки **Z-буфера** (depth buffer), поэтому правильный порядок отрисовки полигонов (сортировка) критически важен для корректного отображения 3D-сцен. Вот как это реализовано: + +--- + +## **1. Основные методы сортировки** +### **1.1. Ordering Table (OT)** +**Ordering Table** — это главный механизм сортировки на PS1. +Работает по принципу **связного списка** в VRAM, где полигоны группируются по расстоянию. + +#### **Как это работает?** +1. **Инициализация OT**: + - Создаётся массив указателей (например, на 256 или 1024 элемента). + - Каждый элемент соответствует диапазону глубин (Z-значений). + +2. **Добавление примитивов**: + - Для каждого полигона вычисляется **Z-координата** (например, средняя точка). + - По Z-значению выбирается **ячейка OT** (чем дальше объект, тем меньше индекс). + - Полигон добавляется в список для этой ячейки. + +3. **Рендеринг**: + - OT обрабатывается **от дальних к ближним** ячейкам (от 0 до N). + - Все примитивы в одной ячейке рисуются в порядке добавления. + +#### **Пример кода (PsyQ SDK)** +```c +#include + +#define OT_LEN 256 // Размер Ordering Table +uint32_t ot[OT_LEN]; // Сама таблица + +void init_ot() { + ClearOTagR(ot, OT_LEN); // Очистка OT +} + +void add_polygon(POLY_F4 *poly, int z) { + // Вычисляем индекс в OT (0 = дальний, OT_LEN-1 = ближний) + int ot_entry = (z >> 8) & (OT_LEN - 1); // Простейшее масштабирование Z + + // Добавляем полигон в OT + addPrim(ot + ot_entry, poly); +} + +void render_frame() { + DrawOTag(ot + (OT_LEN - 1)); // Рендеринг OT (от ближних к дальним) +} +``` + +--- + +### **1.2. Сортировка по Bounding Box** +Для сложных объектов (например, моделей) используется **сортировка по ограничивающему объёму**: +1. Вычисляется **сфера или AABB** (коробка), охватывающая объект. +2. Сортируются **центры сфер** по Z-координате. + +#### **Псевдокод** +```c +struct Object { + int center_z; + POLY_F4 *polys; +}; + +void sort_objects(Object *objs, int count) { + qsort(objs, count, sizeof(Object), compare_by_z); +} + +int compare_by_z(const void *a, const void *b) { + return ((Object*)a)->center_z - ((Object*)b)->center_z; +} +``` + +--- + +### **1.3. Priority Groups** +Некоторые игры (например, *Crash Bandicoot*) используют **приоритетные группы**: +- Полигоны делятся на **статические** (уровень) и **динамические** (персонажи). +- Статические рисуются через OT, динамические — поверх них. + +--- + +## **2. Оптимизации** +### **2.1. Z-Сортировка только для прозрачных объектов** +- Непрозрачные полигоны рисуются **без сортировки** (через алгоритм художника). +- Прозрачные (с полупрозрачностью) сортируются **строго от дальних к ближним**. + +### **2.2. Двойная OT** +- **Одна OT для непрозрачных**, вторая — **для прозрачных** полигонов. +- Позволяет уменьшить накладные расходы. + +### **2.3. Субпиксельная корректировка** +- Для борьбы с **Z-файтингом** (мерцание полигонов) используется: + - Случайное смещение Z (`z += rand() % 4`). + - Принудительный порядок для мелких объектов. + +--- + +## **3. Пример для игры** +Допустим, у нас есть: +- **10 коробок** на разных расстояниях. +- **1 полупрозрачный полигон** (вода). + +#### **Код рендеринга** +```c +// 1. Инициализация +init_ot(); + +// 2. Добавление непрозрачных полигонов (коробки) +for (int i = 0; i < 10; i++) { + add_polygon(&boxes[i], boxes[i].z); +} + +// 3. Добавление прозрачного полигона (вода) +add_polygon(&water_poly, water_z); + +// 4. Рендеринг +render_frame(); +``` + +--- + +## **4. Проблемы и решения** +| Проблема | Решение | +|------------------------|----------------------------------| +| **Мерцание полигонов** | Субпиксельная корректировка Z. | +| **Низкая производительность** | Уменьшение размера OT. | +| **Неправильный порядок** | Ручная настройка приоритетов. | + +--- + +## **5. Итог** +- **Ordering Table** — основа сортировки на PS1. +- **Для сложных сцен** комбинируют OT, Bounding Box и приоритетные группы. +- **Оптимизации** нужны для борьбы с артефактами. + +Этот подход использовался в играх типа *Tekken 3* и *Resident Evil*. Для глубокого понимания изучите [документацию PsyQ](http://psx.arthus.net/sdk/PsyQ/DOCS/). \ No newline at end of file diff --git a/PERSONAL PROJECTS/PS1 Vblank.md b/PERSONAL PROJECTS/PS1 DOCS/PS1 Vblank.md similarity index 100% rename from PERSONAL PROJECTS/PS1 Vblank.md rename to PERSONAL PROJECTS/PS1 DOCS/PS1 Vblank.md diff --git a/PERSONAL PROJECTS/PSX code - Load texture from SECTOR!.md b/PERSONAL PROJECTS/PS1 DOCS/PSX code - Load texture from SECTOR!.md similarity index 100% rename from PERSONAL PROJECTS/PSX code - Load texture from SECTOR!.md rename to PERSONAL PROJECTS/PS1 DOCS/PSX code - Load texture from SECTOR!.md diff --git a/PERSONAL PROJECTS/PSX code - Texture show from file.md b/PERSONAL PROJECTS/PS1 DOCS/PSX code - Texture show from file.md similarity index 100% rename from PERSONAL PROJECTS/PSX code - Texture show from file.md rename to PERSONAL PROJECTS/PS1 DOCS/PSX code - Texture show from file.md diff --git a/PERSONAL PROJECTS/PSX code - modules load and exec.md b/PERSONAL PROJECTS/PS1 DOCS/PSX code - modules load and exec.md similarity index 100% rename from PERSONAL PROJECTS/PSX code - modules load and exec.md rename to PERSONAL PROJECTS/PS1 DOCS/PSX code - modules load and exec.md diff --git a/PERSONAL PROJECTS/PS1 DOCS/PSX code inline asm.md b/PERSONAL PROJECTS/PS1 DOCS/PSX code inline asm.md new file mode 100644 index 0000000..77ebc18 --- /dev/null +++ b/PERSONAL PROJECTS/PS1 DOCS/PSX code inline asm.md @@ -0,0 +1,123 @@ +Вот готовая программа для **PlayStation 1**, которая использует **MIPS-ассемблерные вставки** для сложения двух чисел через указатели. Результат возвращается в переменную основной программы. + +--- + +### **1. Полный код (MAIN.C)** +```c +#include +#include + +// Объявляем ассемблерную функцию +int add_numbers_asm(int *a, int *b, int *result); + +int main() { + int num1 = 5; + int num2 = 7; + int result = 0; + + // Вызываем ассемблерную функцию с указателями + add_numbers_asm(&num1, &num2, &result); + + // Выводим результат + FntPrint("Result: %d + %d = %d\n", num1, num2, result); + FntFlush(-1); + + while (1) { + VSync(0); + } + + return 0; +} + +// Реализация на MIPS-ассемблере +int add_numbers_asm(int *a, int *b, int *result) { + int ret; + asm volatile ( + "lw $t0, 0(%1) \n" // Загружаем *a в $t0 + "lw $t1, 0(%2) \n" // Загружаем *b в $t1 + "add $t2, $t0, $t1 \n" // Складываем: $t2 = $t0 + $t1 + "sw $t2, 0(%3) \n" // Сохраняем результат по адресу *result + "move %0, $t2 \n" // Возвращаем результат через регистр + : "=r" (ret) // Выходные операнды + : "r" (a), "r" (b), "r" (result) // Входные операнды + : "$t0", "$t1", "$t2" // Разрушаемые регистры + ); + return ret; +} +``` + +--- + +### **2. Как это работает?** +1. **Передача указателей в ассемблер** + Функция `add_numbers_asm` принимает три указателя: + - `a` — адрес первого числа, + - `b` — адрес второго числа, + - `result` — адрес для сохранения результата. + +2. **Ассемблерная вставка** (`asm volatile`): + - `lw` — загружает значения из памяти по указателям. + - `add` — складывает числа. + - `sw` — сохраняет результат по адресу `result`. + - `move` — возвращает значение через регистр. + +3. **Доступ к результату** + Результат будет: + - В переменной `result` (через указатель). + - В возвращаемом значении функции (если нужно). + +--- + +### **3. Компиляция и запуск** +1. Скомпилируйте через **PsyQ SDK**: + ```bash + ccpsx MAIN.C -o ADD_DEMO.EXE + ``` + +2. Запишите на диск и запустите на эмуляторе или консоли. + На экране появится: + ``` + Result: 5 + 7 = 12 + ``` + +--- + +### **4. Важные нюансы** +- **Регистры MIPS**: + - `$t0`–`$t9` — временные регистры (можно использовать без сохранения). + - `$s0`–`$s7` — должны сохраняться (если используются). + +- **Разрушаемые регистры**: + Указаны в конце `asm volatile` (чтобы компилятор не использовал их для оптимизации). + +- **Опасность**: + Если передать **неверные указатели**, PS1 уйдёт в **краш** (нет защиты памяти). + +--- + +### **5. Пример с глобальными переменными** +Если нужно работать с глобальными переменными напрямую: +```c +int global_num1 = 10; +int global_num2 = 20; + +void add_globals_asm() { + asm volatile ( + "la $t0, global_num1 \n" // Загружаем адрес global_num1 + "lw $t1, 0($t0) \n" // Читаем значение + "la $t0, global_num2 \n" + "lw $t2, 0($t0) \n" + "add $t1, $t1, $t2 \n" + "sw $t1, 0($t0) \n" // Сохраняем сумму в global_num2 + ); +} +``` + +--- + +### **6. Итог** +- **Ассемблерные вставки** дают полный контроль над железом PS1. +- **Указатели** передаются через регистры (`$a0`–`$a3` в MIPS). +- **Результат** можно получить через память или возвращаемое значение. + +Этот подход используется в оптимизированных частях игр (например, в рендеринге или физике). \ No newline at end of file diff --git a/PERSONAL PROJECTS/PSX code texture load unpack show and fade.md b/PERSONAL PROJECTS/PS1 DOCS/PSX code texture load unpack show and fade.md similarity index 100% rename from PERSONAL PROJECTS/PSX code texture load unpack show and fade.md rename to PERSONAL PROJECTS/PS1 DOCS/PSX code texture load unpack show and fade.md