vault backup: 2025-04-19 22:12:43
This commit is contained in:
6
.obsidian/workspace.json
vendored
6
.obsidian/workspace.json
vendored
@@ -41,12 +41,12 @@
|
||||
"state": {
|
||||
"type": "markdown",
|
||||
"state": {
|
||||
"file": "PERSONAL PROJECTS/PS1 DOCS/fade calculation.md",
|
||||
"file": "PERSONAL PROJECTS/PS1 DOCS/PS1 IRQ.md",
|
||||
"mode": "source",
|
||||
"source": false
|
||||
},
|
||||
"icon": "lucide-file",
|
||||
"title": "fade calculation"
|
||||
"title": "PS1 IRQ"
|
||||
}
|
||||
}
|
||||
],
|
||||
@@ -207,8 +207,8 @@
|
||||
},
|
||||
"active": "dd912cc876184c4f",
|
||||
"lastOpenFiles": [
|
||||
"PERSONAL PROJECTS/PS1 DOCS/PS1 Gamepad.md",
|
||||
"PERSONAL PROJECTS/PS1 DOCS/fade calculation.md",
|
||||
"PERSONAL PROJECTS/PS1 DOCS/PS1 Gamepad.md",
|
||||
"PERSONAL PROJECTS/PS1 DOCS/PS1 Gpu-DMA.md",
|
||||
"PERSONAL PROJECTS/PS1 DOCS/PS1 Ordering table.md",
|
||||
"PERSONAL PROJECTS/PS1 DOCS/PS1 DMA.md",
|
||||
|
||||
@@ -295,4 +295,203 @@ SetIntrMask(old_mask);
|
||||
|
||||
4. **Сочетание с обработчиками**: Даже если прерывание разрешено маской, для него должен быть установлен обработчик через соответствующие функции PsyQ.
|
||||
|
||||
Эта функция предоставляет низкоуровневый контроль над прерываниями и обычно используется в сочетании с более высокоуровневыми API PsyQ для управления конкретными типами прерываний.
|
||||
Эта функция предоставляет низкоуровневый контроль над прерываниями и обычно используется в сочетании с более высокоуровневыми API PsyQ для управления конкретными типами прерываний.
|
||||
|
||||
|
||||
|
||||
---
|
||||
|
||||
Вот подробное объяснение работы прерываний в PlayStation 1 с примерами на ассемблере MIPS R3000, который используется в PS1:
|
||||
|
||||
## 1. Регистры прерываний
|
||||
|
||||
Основные регистры (все адреса в шестнадцатеричном формате):
|
||||
|
||||
```mips
|
||||
li $t0, 0x1F801070 # I_STAT - статус прерываний
|
||||
li $t1, 0x1F801074 # I_MASK - маска прерываний
|
||||
```
|
||||
|
||||
## 2. Установка обработчика прерываний
|
||||
|
||||
Вектор прерываний находится по адресу 0x80000080. Пример установки обработчика:
|
||||
|
||||
```mips
|
||||
.org 0x80000080 # Вектор прерываний
|
||||
j my_irq_handler # Переход к обработчику
|
||||
nop
|
||||
|
||||
my_irq_handler:
|
||||
# Сохраняем регистры
|
||||
addiu $sp, $sp, -32
|
||||
sw $ra, 0($sp)
|
||||
sw $a0, 4($sp)
|
||||
sw $v0, 8($sp)
|
||||
|
||||
# Проверяем тип прерывания
|
||||
lw $t0, 0x1F801070 # Читаем I_STAT
|
||||
lw $t1, 0x1F801074 # Читаем I_MASK
|
||||
|
||||
and $t2, $t0, $t1 # Активные и разрешенные прерывания
|
||||
|
||||
# Обработка VBLANK
|
||||
andi $t3, $t2, 0x1
|
||||
beqz $t3, not_vblank
|
||||
nop
|
||||
|
||||
# Код обработки VBLANK
|
||||
jal handle_vblank
|
||||
nop
|
||||
|
||||
not_vblank:
|
||||
# Обработка других прерываний...
|
||||
|
||||
# Сброс флагов прерываний
|
||||
sw $t0, 0x1F801070 # Записываем обратно в I_STAT
|
||||
|
||||
# Восстанавливаем регистры
|
||||
lw $ra, 0($sp)
|
||||
lw $a0, 4($sp)
|
||||
lw $v0, 8($sp)
|
||||
addiu $sp, $sp, 32
|
||||
|
||||
# Возврат из прерывания
|
||||
eret
|
||||
```
|
||||
|
||||
## 3. Включение прерываний
|
||||
|
||||
Пример настройки VBLANK прерывания:
|
||||
|
||||
```mips
|
||||
# Разрешаем VBLANK в маске
|
||||
li $t0, 0x1
|
||||
sw $t0, 0x1F801074 # I_MASK
|
||||
|
||||
# Включаем прерывания глобально
|
||||
mfc0 $t0, $12 # Читаем Status register
|
||||
ori $t0, $t0, 0x1 # Разрешаем прерывания
|
||||
mtc0 $t0, $12 # Записываем обратно
|
||||
```
|
||||
|
||||
## 4. Обработка VBLANK
|
||||
|
||||
Пример обработчика вертикального гашения:
|
||||
|
||||
```mips
|
||||
handle_vblank:
|
||||
addiu $sp, $sp, -16
|
||||
sw $ra, 0($sp)
|
||||
|
||||
# Инкрементируем счетчик кадров
|
||||
la $t0, frame_counter
|
||||
lw $t1, 0($t0)
|
||||
addiu $t1, $t1, 1
|
||||
sw $t1, 0($t0)
|
||||
|
||||
# Вызов C-функции
|
||||
jal update_graphics
|
||||
nop
|
||||
|
||||
lw $ra, 0($sp)
|
||||
addiu $sp, $sp, 16
|
||||
jr $ra
|
||||
nop
|
||||
```
|
||||
|
||||
## 5. Обработка контроллера
|
||||
|
||||
Пример обработки ввода с геймпада:
|
||||
|
||||
```mips
|
||||
handle_controller:
|
||||
addiu $sp, $sp, -16
|
||||
sw $ra, 0($sp)
|
||||
|
||||
# Чтение состояния контроллера
|
||||
li $t0, 0x1F801040 # JOY_DATA
|
||||
lw $t1, 0($t0)
|
||||
|
||||
# Проверка кнопки START
|
||||
andi $t2, $t1, 0x1000
|
||||
beqz $t2, no_start
|
||||
nop
|
||||
|
||||
# Обработка нажатия START
|
||||
jal pause_game
|
||||
nop
|
||||
|
||||
no_start:
|
||||
lw $ra, 0($sp)
|
||||
addiu $sp, $sp, 16
|
||||
jr $ra
|
||||
nop
|
||||
```
|
||||
|
||||
## 6. Критические секции
|
||||
|
||||
Отключение/включение прерываний:
|
||||
|
||||
```mips
|
||||
disable_interrupts:
|
||||
mfc0 $t0, $12
|
||||
li $t1, 0xFFFFFFFE
|
||||
and $t0, $t0, $t1
|
||||
mtc0 $t0, $12
|
||||
jr $ra
|
||||
nop
|
||||
|
||||
enable_interrupts:
|
||||
mfc0 $t0, $12
|
||||
ori $t0, $t0, 0x1
|
||||
mtc0 $t0, $12
|
||||
jr $ra
|
||||
nop
|
||||
```
|
||||
|
||||
## 7. Таймеры
|
||||
|
||||
Настройка таймера 0:
|
||||
|
||||
```mips
|
||||
setup_timer0:
|
||||
# Устанавливаем период (1/60 секунды для NTSC)
|
||||
li $t0, 0x1F801100
|
||||
li $t1, 0x0000
|
||||
sw $t1, 0($t0) # TIMER0_COUNTER
|
||||
li $t1, 0x03FF
|
||||
sw $t1, 4($t0) # TIMER0_MODE
|
||||
li $t1, 0x0100
|
||||
sw $t1, 8($t0) # TIMER0_TARGET
|
||||
|
||||
# Разрешаем прерывание таймера
|
||||
li $t0, 0x1F801074
|
||||
lw $t1, 0($t0)
|
||||
ori $t1, $t1, 0x10 # BIT 4 - TIMER0
|
||||
sw $t1, 0($t0)
|
||||
|
||||
jr $ra
|
||||
nop
|
||||
```
|
||||
|
||||
## Важные замечания:
|
||||
|
||||
1. Все обработчики должны:
|
||||
- Сохранять/восстанавливать регистры
|
||||
- Быть максимально быстрыми
|
||||
- Сбрасывать флаги прерываний
|
||||
|
||||
2. Для работы с прерываниями в C через PsyQ SDK используются:
|
||||
```c
|
||||
SetIntrMask(0x400); // Разрешить прерывания
|
||||
EnterCriticalSection(); // Запретить прерывания
|
||||
ExitCriticalSection(); // Разрешить прерывания
|
||||
```
|
||||
|
||||
3. Стандартная инициализация в PsyQ:
|
||||
```c
|
||||
ResetCallback();
|
||||
SetIntrHandler(MyHandler);
|
||||
```
|
||||
|
||||
Эти примеры демонстрируют низкоуровневую работу с прерываниями на ассемблере MIPS R3000, который используется в PlayStation 1. В реальных проектах часто используют комбинацию ассемблера и C для удобства.
|
||||
Reference in New Issue
Block a user