vault backup: 2025-04-18 23:50:59

This commit is contained in:
sShemet
2025-04-18 23:50:59 +05:00
parent 491d7fc92a
commit f72bc1285d
3 changed files with 226 additions and 5 deletions

View File

@@ -41,12 +41,12 @@
"state": {
"type": "markdown",
"state": {
"file": "PERSONAL PROJECTS/PS1 DOCS/PS1 Geometry Transformation Engine.md",
"file": "PERSONAL PROJECTS/PS1 DOCS/Untitled.md",
"mode": "source",
"source": false
},
"icon": "lucide-file",
"title": "PS1 Geometry Transformation Engine"
"title": "Untitled"
}
}
],
@@ -207,8 +207,10 @@
},
"active": "dd912cc876184c4f",
"lastOpenFiles": [
"PERSONAL PROJECTS/PS1 DOCS/LZSS C++ Lib.md",
"PERSONAL PROJECTS/PS1 DOCS/PS1 IRQ.md",
"PERSONAL PROJECTS/PS1 DOCS/Untitled.md",
"PERSONAL PROJECTS/PS1 DOCS/PS1 Geometry Transformation Engine.md",
"PERSONAL PROJECTS/PS1 DOCS/LZSS C++ Lib.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",
@@ -241,8 +243,6 @@
"WORK & PROJECTS/Mol/Планы и диаграммы/СМК.md",
"WORK & PROJECTS/Mol/Планы и диаграммы/Alfa Cloud/Alfa cloud readme.md",
"WORK & PROJECTS/Mol/Планы и диаграммы/Alfa Cloud",
"WORK & PROJECTS/Mol/Серверы/git.moldev.ru.md",
"WORK & PROJECTS/Ulab/передача сформированных заявки и протокола как ссылку или файл.md",
"Структура объектов испытаний.png",
"Схема связей юрлиц и адресов.png",
"Структура объектов испытаний.png.0.pdnSave",

View File

@@ -0,0 +1,221 @@
### **Прерывания (Interrupts) на PlayStation 1: Зачем они нужны и как работают?**
Прерывания в PS1 — это механизм, позволяющий процессору **мгновенно реагировать** на критичные события (например, завершение рендеринга кадра или чтение с диска), не требуя постоянного опроса (polling). Они играют ключевую роль в синхронизации и эффективности системы.
---
## **1. Основные типы прерываний**
В PS1 есть несколько аппаратных прерываний, каждое обслуживает свою задачу:
| Прерывание | Источник | Задача |
|------------|---------------------------|-----------------------------------------------------------------------|
| **IRQ0** | VBlank (вертикальная синхронизация) | Оповещает о завершении рендеринга кадра. Используется для обновления графики. |
| **IRQ1** | GPU | Генерируется при ошибках GPU (например, переполнение буфера команд). |
| **IRQ2** | CD-ROM | Сигнализирует о завершении чтения данных с диска. |
| **IRQ3** | DMA | Уведомляет о завершении передачи данных (например, в VRAM). |
| **IRQ4** | Timer (таймер) | Используется для точного измерения времени. |
| **IRQ5** | Контроллеры (геймпады) | Обработка ввода игрока. |
| **IRQ6** | SPU (звук) | Прерывание от звукового процессора (например, окончание воспроизведения сэмпла). |
---
## **2. Зачем они нужны?**
### **(1) Синхронизация графики (VBlank)**
Без прерывания **IRQ0** (VBlank) игра не могла бы:
- Плавно обновлять кадры (без разрывов изображения).
- Безопасно изменять VRAM (иначе артефакты).
**Пример кода:**
```mips
wait_vblank:
li $t0, 0x1F801070 # I_STAT (регистр статуса прерываний)
lw $t1, 0($t0)
andi $t1, 0x1 # Проверяем бит IRQ0 (VBlank)
beqz $t1, wait_vblank
nop
jr $ra
```
---
### **(2) Асинхронная работа с CD-ROM**
Прерывание **IRQ2** позволяет:
- Читать данные с диска **без блокировки основного цикла игры**.
- Загружать уровни/аудио **в фоне**.
**Пример:**
```mips
cd_read_done:
# IRQ2 вызвано — данные готовы
la $t0, cd_buffer
sw $t0, 0x1F8010A0 # DMA CD-ROM
jr $ra
```
---
### **(3) Обработка ввода (геймпады)**
Прерывание **IRQ5** сообщает:
- Когда игрок нажал кнопку (без задержек).
- Поддерживает **вибрацию** (если есть DualShock).
**Пример:**
```mips
read_pad:
li $t0, 0x1F801040 # SIO_DATA
lw $t1, 0($t0) # Чтение кнопок
andi $t1, 0xFF // Фильтруем биты
jr $ra
```
---
## **3. Как работают прерывания?**
1. **Аппаратное событие** (например, завершение VBlank) устанавливает флаг в **I_STAT (0x1F801070)**.
2. Процессор **приостанавливает текущий код** и переходит к **обработчику прерывания** (адрес задаётся в **$k0**).
3. Обработчик:
- Сохраняет регистры в стек.
- Выполняет нужные действия (например, обновляет графику).
- Очищает флаг прерывания.
- Восстанавливает регистры и возвращает управление.
**Пример обработчика на ассемблере:**
```mips
irq_handler:
addiu $sp, -32 # Резервируем стек
sw $ra, 0($sp) # Сохраняем $ra
sw $a0, 4($sp) # Сохраняем аргументы
# Проверяем источник прерывания
li $t0, 0x1F801070
lw $t1, 0($t0)
andi $t2, $t1, 0x1 # IRQ0 (VBlank)?
bnez $t2, handle_vblank
nop
# Выход
lw $a0, 4($sp)
lw $ra, 0($sp)
addiu $sp, 32
eret # Возврат из прерывания
handle_vblank:
# Обновляем кадр
jal update_graphics
nop
j irq_handler # Возврат
```
---
## **4. Почему без прерываний — плохо?**
- **Графика**: Без VBlank появится **tearing** (разрывы кадров).
- **Звук**: SPU будет работать с задержками.
- **Ввод**: Кнопки станут «лагающими».
- **CD-ROM**: Игра зависнет на время загрузки.
---
## **5. Итог**
Прерывания в PS1 — это **«нервная система» консоли**, которая:
1. **Синхронизирует** графику, звук, ввод и загрузку данных.
2. **Избегает busy-waiting** (постоянного опроса), экономя ресурсы CPU.
3. **Гарантирует точность** (например, 60 FPS через VBlank).
Если ты **пишешь на ассемблере**, прерывания придётся обрабатывать вручную. В **C** этим частично занимается PsyQ SDK.
P.S. В твоём переводе Persona 2 прерывания **уже работают** — иначе игра бы просто не запустилась! 😉 Но если хочешь **добавить свои обработчики** (например, для кастомной загрузки), дай знать — помогу с кодом.
------------------
### **Как работают прерывания на PlayStation 1: детальный разбор**
Прерывания (IRQ) в PS1 — это механизм, позволяющий процессору R3000A мгновенно реагировать на аппаратные события. Вот их полный цикл работы:
#### **1. Инициализация прерываний**
Перед использованием нужно:
- Задать адрес обработчика в **$k0** (регистр ядра)
- Разрешить нужные IRQ в регистре **I_MASK (0x1F801074)**
```mips
setup_irq:
la $k0, irq_handler # Устанавливаем обработчик
li $t0, 0x1F801074
li $t1, 0x0001 # Разрешаем только IRQ0 (VBlank)
sw $t1, 0($t0)
jr $ra
```
#### **2. Аппаратный триггер**
Когда происходит событие (например, VBlank):
1. CD-ROM контроллер/GPU устанавливает бит в **I_STAT (0x1F801070)**
2. Процессор проверяет:
- Разрешено ли это прерывание в **I_MASK**
- Не находится ли он уже в обработчике (бит **IEc** в регистре **SR**)
#### **3. Переход в обработчик**
Если условия выполнены:
1. Процессор:
- Сохраняет **PC** и **SR** в специальных регистрах (**EPC**, **ErrorEPC**)
- Переходит в режим ядра (бит **KUc** = 0)
- Прыгает по адресу в **$k0**
#### **4. Обработка прерывания**
Типичный обработчик:
```mips
irq_handler:
# 1. Сохраняем контекст
addiu $sp, -120 # Резервируем место для 30 регистров
sw $at, 0($sp)
sw $v0, 4($sp)
# ... сохраняем все используемые регистры
# 2. Определяем источник
li $t0, 0x1F801070
lw $t1, 0($t0) # Читаем I_STAT
# 3. Обработка VBlank
andi $t2, $t1, 0x1
beqz $t2, not_vblank
nop
jal handle_vblank
nop
not_vblank:
# 4. Сбрасываем флаг прерывания
li $t3, 0xFFFF00FF # Маска для очистки
and $t1, $t1, $t3
sw $t1, 0($t0) # Пишем обратно в I_STAT
# 5. Восстанавливаем контекст
lw $at, 0($sp)
lw $v0, 4($sp)
# ...
addiu $sp, 120
# 6. Возврат
eret # Возврат с восстановлением SR и PC
```
#### **5. Возврат из прерывания**
Инструкция **eret**:
- Восстанавливает **PC** из **EPC**
- Восстанавливает **SR** (включая бит **IEc**)
- Возвращает процессор в пользовательский режим
#### **6. Особенности PS1**
1. **Приоритеты**: Нет аппаратного приоритета - порядок обработки определяется программно
2. **Вложенность**: Новые прерывания блокируются, пока **IEc = 0**
3. **Задержки**: Минимальная задержка между прерываниями - 5 тактов
#### **7. Реальный пример из PsyQ**
Обработчик VBlank в библиотеке **libgs**:
1. Сохраняет матрицу преобразования
2. Обновляет буферы GPU
3. Вызывает пользовательский callback
#### **8. Оптимизации**
- **Короткие обработчики**: Не более 100 тактов
- **Минимальное сохранение**: Только используемые регистры
- **Аппаратное ускорение**: Для DMA используйте **D_ICR (0x1F8010F4)**
Для отладки в no$psx используйте точки останова на записи в **I_STAT**!

View File