Порядок в каталогах
This commit is contained in:
410
2_EP/EP_main_grouped.asm
Normal file
410
2_EP/EP_main_grouped.asm
Normal file
@@ -0,0 +1,410 @@
|
||||
;
|
||||
; Persona 2 Eternal Punishment (PSX) JAP / Custom Characters/Data Patch
|
||||
; Author: Sergey Shemet 06/10/2022
|
||||
|
||||
.psx
|
||||
|
||||
// Определения функций
|
||||
.definelabel SetDrawTPage, 0x800578fc
|
||||
.definelabel storeColor, 0x8001c0b4
|
||||
.definelabel initCopyCharChain, 0x8001b110
|
||||
.definelabel MakeShadowSmallChar, 0x8001b2a8
|
||||
.definelabel PrintBigDMAText, 0x8001a3a8
|
||||
|
||||
.definelabel MyAddr, 0x8009
|
||||
|
||||
.open "SLPS_028.25", 0x8000F800
|
||||
|
||||
.org 0x80090000
|
||||
|
||||
ExternalPrint:
|
||||
// Текстовая тестовая процедура
|
||||
lhu v0, 0x0(a0) // Читаем 2 байта текста
|
||||
nop
|
||||
srl v1, v0, 0xD // Проверяем 13-й бит (система 1 байт)
|
||||
bne v1, zero, MyPrintLineRoutine // Если установлен, переходим к нашей процедуре
|
||||
clear v1
|
||||
j PrintBigDMAText // Иначе используем стандартную процедуру
|
||||
nop
|
||||
|
||||
MyPrintLineRoutine:
|
||||
addiu sp, sp, -0x50 // Выделяем место в стеке
|
||||
sw s4, 0x38(sp) // Сохраняем регистры
|
||||
move s4, a0 // Адрес чтения текста -> s4
|
||||
sw s0, 0x28(sp)
|
||||
move s0, a1
|
||||
sw s1, 0x2c(sp)
|
||||
move s1, a2
|
||||
sw s3, 0x34(sp)
|
||||
|
||||
// Обработка новой команды
|
||||
andi v0, v0, 0xff // Берем младший байт
|
||||
addiu s4, s4, 0x2 // Сдвигаем указатель текста на +2 байта
|
||||
|
||||
lui s3, MyAddr
|
||||
sw v0, -0x10(s3) // Сохраняем счетчик байтов @ 8008fff0
|
||||
|
||||
// Инициализация scratchpad
|
||||
lui s3, 0x1f80
|
||||
ori s3, s3, 0x3d0 // s3 = 1f8003d0 - команда копирования спрайта
|
||||
lui t0, 0xff
|
||||
ori t0, t0, 0xffff // t0 = 00FFFFFF
|
||||
|
||||
andi a0, a3, 0xff // Режим текста (цвет и тень)
|
||||
lui a3, 0x8008 // a3 = 80080000
|
||||
lui a2, 0xff00 // a2 = FF000000
|
||||
|
||||
addiu t1, a3, -0x31a8 // t1 = 8007b6d0 - новая свободная цепочка
|
||||
lw v1, -0x31a8(a3) // v1 = загружаем свободную цепочку
|
||||
lbu a1, 0x60(sp) // Флаг тени из стека -> a1
|
||||
lui v0, 0x8000 // v0 = 80000000
|
||||
sw ra, 0x48(sp) // Сохраняем регистры
|
||||
sw s7, 0x44(sp)
|
||||
sw s6, 0x40(sp)
|
||||
sw s5, 0x3c(sp)
|
||||
sw s2, 0x30(sp)
|
||||
|
||||
// Инициализация цепочек
|
||||
and a2, v1, a2 // a2 = v1 & ff000000
|
||||
andi a1, a1, 0xff // Очищаем режим текста
|
||||
and v1, v1, t0 // v1 & 00ffffff
|
||||
or s5, v1, v0 // s5 - основной адрес свободной цепочки
|
||||
lw v0, 0x4(t1) // Загружаем счетчик DMA
|
||||
lw v1, 0x0(s5) // v1 = следующая свободная цепочка
|
||||
addiu v0, v0, -0x1 // Уменьшаем счетчик DMA
|
||||
and v1, v1, t0 // v1 & 00ffffff
|
||||
or a2, a2, v1 // a2 | v1 = следующая свободная цепочка
|
||||
sw v0, 0x4(t1) // Сохраняем счетчик DMA
|
||||
sw a2, -0x31a8(a3) // Сохраняем следующую свободную цепочку
|
||||
jal storeColor
|
||||
move a0, s5 // Текущий адрес цепочки
|
||||
sll a1, s0, 0x10 // a1 = X << 16
|
||||
sra a1, a1, 0x10 // a1 = X координата
|
||||
sll a2, s1, 0x10 // a2 = Y << 16
|
||||
jal initCopyCharChain // Инициализация цепочек символов
|
||||
sra a2, a2, 0x10 // a2 = Y координата
|
||||
|
||||
// Инициализация ScratchPad (CPU to VRAM)
|
||||
lui a2, 0x1f80
|
||||
ori a2, a2, 0x348 // a2 = первый символ начала
|
||||
|
||||
// 4-битная таблица паттернов
|
||||
.include "EP_4bitPattern.asm"
|
||||
|
||||
li v0, 0x2
|
||||
sh v0, 0x1c(sp)
|
||||
li v0, 0xc
|
||||
li a0, 0x10 // Команды в цепочке формирования символа?
|
||||
lui v1, 0xa000 // a0 = a0000000
|
||||
sh v0, 0x1e(sp) // Сохраняем 000C0002 в стек+1c
|
||||
|
||||
// Инициализация символа
|
||||
lui v0, 0x100 // Сброс кэша 01000000
|
||||
sb a0, 0x3(a2) // Сохраняем количество команд
|
||||
sw v1, 0x4(a2) // Сохраняем a0000000
|
||||
|
||||
lui at, 0x1f80 // Начало scratchpad
|
||||
sw v0, 0x388(at) // Сохраняем в конец первой цепочки символов
|
||||
|
||||
// Формирование команды DMA копирования спрайта
|
||||
li v0, 0x4
|
||||
sb v0, 0x3(s3) // Длина цепочки = 4
|
||||
li v0, 0x64
|
||||
sb v0, 0x7(s3) // Команда копирования спрайта
|
||||
|
||||
lhu a0, 0x98(gp) // Загружаем X координату
|
||||
lhu v1, 0x9a(gp) // Загружаем Y координату
|
||||
|
||||
li v0, 0x80
|
||||
sb v0, 0x4(s3)
|
||||
sb v0, 0x5(s3)
|
||||
sb v0, 0x6(s3) // Формируем 80808064
|
||||
|
||||
setY1:
|
||||
lw v0, 0x1c(sp) // v0 = 000c0002 из стека
|
||||
lh a3, 0x98(gp) // Для дальнейших расчетов X спрайта
|
||||
sh a0, 0x18(sp)
|
||||
sh v1, 0x1a(sp) // Сохраняем координаты в стек
|
||||
lw a0, 0x18(sp) // Загружаем координаты из стека
|
||||
move t0, a3
|
||||
sw a0, 0x8(a2) // Загружаем координаты в DMA
|
||||
sw v0, 0xc(a2) // Сохраняем в первый символ
|
||||
|
||||
bgez a3, LAB_800194fc
|
||||
|
||||
SetX1:
|
||||
sh s1, 0x20(sp) // Сохраняем X половину в sp+20
|
||||
addiu t0, a3, 0x3f
|
||||
|
||||
LAB_800194fc:
|
||||
// Декодирование координат для исходного спрайта
|
||||
sra v0, t0, 0x6 // v0 = t0 >> 6
|
||||
sll v0, v0, 0x6 // v0 << 6
|
||||
subu v0, a3, v0 // v0 = a3 - v0
|
||||
lh v1, 0x9a(gp) // Загружаем Y половину из памяти
|
||||
sll v0, v0, 0x2 // v0 << 2
|
||||
sb v0, 0xc(s3) // Сохраняем X байт спрайта символа
|
||||
bgez v1, LAB_80019520 // Если Y >= 0 - ветвление
|
||||
move v0, v1
|
||||
addiu v0, v1, 0xff // Иначе v0 = ff - v1
|
||||
|
||||
LAB_80019520:
|
||||
sra v0, v0, 0x8
|
||||
sll v0, v0, 0x8
|
||||
subu v0, v1, v0
|
||||
sb v0, 0xd(s3) // Сохраняем Y байт спрайта символа
|
||||
lhu v1, 0xa0(gp)
|
||||
|
||||
li v0, 0x8 // Ширина спрайта = 8
|
||||
sh v0, 0x10(s3) // Сохраняем ширину
|
||||
sh v1, 0xe(s3) // Сохраняем значение
|
||||
|
||||
sh s0, 0x8(s3) // Сохраняем X
|
||||
sh s1, 0xa(s3) // Сохраняем Y
|
||||
|
||||
li v0, 0xc // Высота спрайта = 12
|
||||
sh v0, 0x12(s3) // Сохраняем высоту
|
||||
|
||||
// Начало чтения текста
|
||||
lbu a0, 0x0(s4) // Основное чтение байта команды
|
||||
nop
|
||||
addiu s4, s4, 0x1 // Сдвиг адреса чтения на +1 байт
|
||||
|
||||
SpaceCheckBranch:
|
||||
jal makeCharPixelsCustom // Создание маленького символа в scratch
|
||||
clear s2
|
||||
|
||||
lui t2, 0xff00 // t2 = ff000000
|
||||
move t6, s5 // Параметры
|
||||
addiu t5, sp, 0x10 // t5 = sp + 10
|
||||
lui t3, 0x8008
|
||||
addiu t4, t3, -0x31a8
|
||||
move t1, s5 // Параметры снова
|
||||
|
||||
SetY:
|
||||
SetX:
|
||||
PageLoop:
|
||||
// Создание цепочки копирования спрайта
|
||||
lw v0, -0x3198(s6) // v0 = *адрес свободной цепочки
|
||||
nop
|
||||
and a0, v0, t2 // a0 = v0 & ff00..
|
||||
and v0, v0, s0 // v0 & 00FFFFFF
|
||||
or a1, v0, s1 // a1 = v0 | 80000000
|
||||
lw v0, 0x4(s7) // Счетчик команд
|
||||
lw v1, 0x0(a1) // Новый адрес свободной цепочки
|
||||
addiu v0, v0, -0x1 // Уменьшаем счетчик
|
||||
and v1, v1, s0 // v1 & 00FFFFFF
|
||||
or a0, a0, v1 // a0 & v1
|
||||
sw v0, 0x4(s7) // Сохраняем счетчик DMA
|
||||
sw a0, -0x3198(s6) // Сохраняем новую свободную цепочку
|
||||
|
||||
CopyCmdFromScratch:
|
||||
// Копирование команды из scratch
|
||||
lw t9, 0x0(s3) // Количество команд DMA
|
||||
lw t7, 0x4(s3) // Команда копирования спрайта
|
||||
lw t8, 0x8(s3) // Координаты экрана XY
|
||||
lw t5, 0xc(s3) // CLUT и координаты текстуры
|
||||
sw t9, 0x0(a1)
|
||||
sw t7, 0x4(a1)
|
||||
sw t8, 0x8(a1)
|
||||
sw t5, 0xc(a1)
|
||||
lw t9, 0x10(s3) // Размер спрайта после копирования
|
||||
nop
|
||||
sw t9, 0x10(a1) // Сохраняем последнюю команду
|
||||
|
||||
lw v1, 0x18(t1) // Следующий параметр
|
||||
lw v0, 0x0(a1) // Текущий новый адрес цепочки
|
||||
lw v1, 0x0(v1) // Загружаем значение
|
||||
and v0, v0, t2 // v0 & ff000000
|
||||
and v1, v1, s0 // v1 & 00FFFFFF
|
||||
or v0, v0, v1 // Команды с FFFFFF
|
||||
sw v0, 0x0(a1) // Обновляем текущий адрес цепочки
|
||||
lw a0, 0x18(t1) // Первый адрес цепочки
|
||||
nop
|
||||
lw v0, 0x0(a0) // Первая ссылка цепочки на следующую
|
||||
and v1, a1, s0 // v1 = a1 & 00FFFFFF
|
||||
and v0, v0, t2 // v0 & FF000000
|
||||
or v0, v0, v1 // Последний адрес цепочки
|
||||
sw v0, 0x0(a0) // Первая цепочка следующего адреса
|
||||
sw a1, 0x18(t1) // Текущий адрес цепочки
|
||||
lhu v0, 0x4(t6) // Счетчик символов
|
||||
nop
|
||||
bne v0, zero, NotFirstChar // Если счетчик символов ≠ 0, переходим
|
||||
nop
|
||||
|
||||
sw a1, 0x28(t1) // Устанавливаем первую цепочку символов
|
||||
sw t8, 0xc(t6) // Сохраняем координаты в параметры
|
||||
// sh s2, 0xe(t4) // Сохраняем половину Y
|
||||
|
||||
NotFirstChar:
|
||||
lui a1, 0x1f80 // Адрес символа здесь
|
||||
lw v0, -0x31a8(t3) // Следующая свободная цепочка
|
||||
ori a1, a1, 0x348 // a1 | 1f800348 = Scratch данные символа
|
||||
and a0, v0, t2 // a0 = v0 & FF000000
|
||||
and v0, v0, s0 // v0 & 00FFFFFF
|
||||
or a3, v0, s1 // a3 = следующая цепочка & 80...
|
||||
move a2, a3 // a2 = a3 (следующая цепочка)
|
||||
lw v0, 0x4(t4) // Счетчик команд
|
||||
lw v1, 0x0(a3) // Новый адрес свободной цепочки
|
||||
addiu v0, v0, -0x1 // Уменьшаем счетчик
|
||||
and v1, v1, s0 // v1 & 80... количество команд
|
||||
or a0, a0, v1 // a0 & v1
|
||||
sw v0, 0x4(t4) // Сохраняем счетчик DMA
|
||||
andi v0, a3, 0x3 // Проверяем адрес назначения MOD 4
|
||||
sw a0, -0x31a8(t3) // Сохраняем новую свободную цепочку
|
||||
|
||||
beq v0, zero, Copy16Bytes // Если MOD 4 = 0, ветвление
|
||||
addiu v0, a1, 0x40
|
||||
|
||||
CopyBy2Bytes:
|
||||
// Копируем по 2 байта если MOD 4 ≠ 0
|
||||
lwl t9, 0x3(a1)
|
||||
lwr t9, 0x0(a1)
|
||||
lwl t7, 0x7(a1)
|
||||
lwr t7, 0x4(a1)
|
||||
lwl t8, 0xb(a1)
|
||||
lwr t8, 0x8(a1)
|
||||
lwl t5, 0xf(a1)
|
||||
lwr t5, 0xc(a1)
|
||||
swl t9, 0x3(a2)
|
||||
swr t9, 0x0(a2)
|
||||
swl t7, 0x7(a2)
|
||||
swr t7, 0x4(a2)
|
||||
swl t8, 0xb(a2)
|
||||
swr t8, 0x8(a2)
|
||||
swl t5, 0xf(a2)
|
||||
swr t5, 0xc(a2)
|
||||
addiu a1, a1, 0x10
|
||||
bne a1, v0, CopyBy2Bytes
|
||||
addiu a2, a2, 0x10
|
||||
j last4BytesCopy
|
||||
nop
|
||||
|
||||
Copy16Bytes:
|
||||
// Копируем по 16 байт
|
||||
lw t9, 0x0(a1)
|
||||
lw t7, 0x4(a1)
|
||||
lw t8, 0x8(a1)
|
||||
lw t5, 0xc(a1)
|
||||
sw t9, 0x0(a2)
|
||||
sw t7, 0x4(a2)
|
||||
sw t8, 0x8(a2)
|
||||
sw t5, 0xc(a2)
|
||||
addiu a1, a1, 0x10
|
||||
bne a1, v0, Copy16Bytes
|
||||
addiu a2, a2, 0x10
|
||||
|
||||
last4BytesCopy:
|
||||
// Копируем последние 4 байта
|
||||
lwl t9, 0x3(a1)
|
||||
lwr t9, 0x0(a1)
|
||||
nop
|
||||
swl t9, 0x3(a2)
|
||||
swr t9, 0x0(a2)
|
||||
|
||||
// Связывание DMA символа + копирование спрайта
|
||||
lw v1, 0x18(t1) // Текущая цепочка DMA копирования спрайта
|
||||
lw v0, 0x0(a3) // Текущие команды цепочки символов
|
||||
lw v1, 0x0(v1) // Количество команд + следующая ссылка
|
||||
and v0, v0, t2 // v0 & FF.....
|
||||
and v1, v1, s0 // v1 & 00FFFFFF
|
||||
or v0, v0, v1 // Количество команд & FF..
|
||||
sw v0, 0x0(a3) // Сохраняем текущую команду цепочки
|
||||
lw a0, 0x18(t1) // Адрес заголовка текущей команды копирования спрайта
|
||||
nop
|
||||
lw v0, 0x0(a0) // 04FFFFFF
|
||||
and v1, a3, s0 // v1 = копирование текущей цепочки символов
|
||||
and v0, v0, t2 // v0 & FF000000 (количество команд)
|
||||
or v0, v0, v1 // Полная команда со ссылкой
|
||||
sw v0, 0x0(a0) // Сохраняем с ссылкой на цепочку символов
|
||||
sw a3, 0x18(t1) // Последняя цепочка символов
|
||||
|
||||
addiu t1, t1, 0x4 // Сдвигаем параметры для следующей страницы
|
||||
addiu v0, t6, 0x8 // Сдвигаем первый параметр цепочки для страницы
|
||||
sltu v0, t1, v0 // Проверяем прохождение первой страницы
|
||||
bne v0, zero, PageLoop // Если не прошли, продолжаем цикл страниц
|
||||
nop
|
||||
|
||||
// Сдвиг X координаты (+6)
|
||||
lhu v0, 0xa8(gp) // Загружаем начальный X
|
||||
lhu v1, 0x8(s3) // Загружаем последний X в scratch
|
||||
addiu v0, v0, 0x6 // v0 = начальный X + 6
|
||||
addu v1, v1, v0 // Последний X = последний X + (начальный X + 6)
|
||||
sh v1, 0x8(s3) // Обновляем последний X в DMA scratch
|
||||
|
||||
SpaceJump:
|
||||
// Увеличиваем счетчик символов + проверка
|
||||
lhu v0, 0x4(s5) // Текущее количество символов DMA
|
||||
lui t9, MyAddr
|
||||
addiu v0, v0, 0x1 // Увеличиваем на 1
|
||||
sh v0, 0x4(s5) // Сохраняем счетчик в цепочку
|
||||
|
||||
// Проверка переполнения DMA
|
||||
lw v0, 0x4(s7) // Счетчик команд DMA
|
||||
move v1, 5 // Минимальный счетчик команд
|
||||
sltu v0, v0, v1 // v0 < v1?
|
||||
bne v0, zero, TextEnd // Если переполнение DMA, завершаем текст
|
||||
nop
|
||||
|
||||
lui t3, MyAddr
|
||||
lhu v0, -0xE(t3) // Количество символов в строке
|
||||
lhu v1, -0x10(t3) // Общее количество символов в строке
|
||||
addiu v0, v0, 0x1 // Увеличиваем на 1
|
||||
lbu a0, 0x0(s4) // Загружаем следующий символ
|
||||
sh v0, -0xE(t3) // Сохраняем счетчик символов
|
||||
addiu s4, s4, 0x1 // Сдвигаем адрес символа
|
||||
|
||||
bne v0, v1, NextChar // Если текущий символ ≠ общему количеству, продолжаем
|
||||
nop
|
||||
|
||||
TextEnd:
|
||||
clear s2
|
||||
lui s3, 0x8008
|
||||
addiu s4, s3, -0x3198 // s4 = 7b6d0
|
||||
lui s1, 0xff
|
||||
ori s1, s1, 0xffff // s1 = 00ffffff
|
||||
move s0, s5 // s0 = текущие параметры строки
|
||||
clear a1
|
||||
|
||||
PageTLoop:
|
||||
// Завершающая обработка страниц
|
||||
li a2, 0x1 // a2 = 1
|
||||
addu s2, s2, a2 // Увеличиваем счетчик
|
||||
lui v0, 0x8000 // v0 = 80000000
|
||||
lui a0, 0xff00 // a0 = ff000000
|
||||
lw v1, -0x3198(s3) // Следующая свободная цепочка
|
||||
lw a3, 0x9c(gp) // Некоторые параметры (почти DMA)
|
||||
and v1, v1, s1 // v1 & 00FFFFFF
|
||||
or v1, v1, v0 // v1 | v0 = 80.....
|
||||
sw v1, 0x30(s0) // Сохраняем последний свободный адрес в параметрах DMA
|
||||
lw v0, -0x3198(s3) // Следующая свободная цепочка
|
||||
lw v1, 0x0(v1) // Создаем еще одну цепочку
|
||||
and v0, v0, a0 // v0 & ff000000
|
||||
and v1, v1, s1 // v1 & 00FFFFFF
|
||||
lw a0, 0x4(s4) // Счетчик DMA
|
||||
or v0, v0, v1 // v0 | v1
|
||||
sw v0, -0x3198(s3) // Новый адрес свободной цепочки
|
||||
addiu a0, a0, -0x1 // Уменьшаем счетчик DMA
|
||||
sw a0, 0x4(s4) // Сохраняем счетчик DMA
|
||||
lw a0, 0x30(s0) // Начало цепочки DMA
|
||||
jal SetDrawTPage // Устанавливаем страницу отрисовки
|
||||
addiu s0, s0, 0x4 // Сдвигаем параметры DMA для следующей страницы
|
||||
sltiu v0, s2, 0x2 // Проверяем счетчик < 2
|
||||
bne v0, zero, PageTLoop // Если да, продолжаем цикл
|
||||
clear a1 // a1 = 0
|
||||
|
||||
move v0, s5 // Возвращаем основные параметры DMA
|
||||
|
||||
// Восстанавливаем регистры из стека
|
||||
lw ra, 0x48(sp)
|
||||
lw s7, 0x44(sp)
|
||||
lw s6, 0x40(sp)
|
||||
lw s5, 0x3c(sp)
|
||||
lw s4, 0x38(sp)
|
||||
lw s3, 0x34(sp)
|
||||
lw s2, 0x30(sp)
|
||||
lw s1, 0x2c(sp)
|
||||
lw s0, 0x28(sp)
|
||||
|
||||
jr ra // Возврат
|
||||
addiu sp, sp, 0x50 // Восстанавливаем стек
|
||||
Reference in New Issue
Block a user