diff --git a/.obsidian/workspace.json b/.obsidian/workspace.json index 71a7779..77d30c1 100644 --- a/.obsidian/workspace.json +++ b/.obsidian/workspace.json @@ -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", diff --git a/PERSONAL PROJECTS/PS1 DOCS/PS1 IRQ.md b/PERSONAL PROJECTS/PS1 DOCS/PS1 IRQ.md index b34ef5f..f6c353b 100644 --- a/PERSONAL PROJECTS/PS1 DOCS/PS1 IRQ.md +++ b/PERSONAL PROJECTS/PS1 DOCS/PS1 IRQ.md @@ -295,4 +295,203 @@ SetIntrMask(old_mask); 4. **Сочетание с обработчиками**: Даже если прерывание разрешено маской, для него должен быть установлен обработчик через соответствующие функции PsyQ. -Эта функция предоставляет низкоуровневый контроль над прерываниями и обычно используется в сочетании с более высокоуровневыми API PsyQ для управления конкретными типами прерываний. \ No newline at end of file +Эта функция предоставляет низкоуровневый контроль над прерываниями и обычно используется в сочетании с более высокоуровневыми 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 для удобства. \ No newline at end of file