; ; 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 makeCharPixels, 0x8001a08f ;need custom routine with custom font ;.definelabel GenerateSmallChar, 0x8001a284 ;need custom routine .definelabel MakeShadowSmallChar, 0x8001b2a8 .definelabel PrintBigDMAText, 0x8001a3a8 .definelabel MyAddr, 0x8009 .open "SLPS_028.25", 0x8000F800 ;.include "complex_strings_copy.asm" ;Make complex strings in battles ;;neeeeed to init 8008fff6 = min dma commands .org 0x80090000 ExternalPrint: ;;;;;;;text routing test routine ; move r3,s3 ; move s3,r4 lhu v0,0x0(a0) ;read half 2 bytes of text (r4, not s1+0c!!!!!) nop ; move s3,r3 srl v1,v0,0xD ;;;;Check 13th bit (1byte system !!!) bne v1,zero,MyPrintLineRoutine clear v1 j PrintBigDMAText nop ;;;;;;;;;;;;;;;;;MyPrintLineRoutine MyPrintLineRoutine: addiu sp,sp,-0x50 sw s4,0x38(sp) move s4,r4 ;textReadAddr - S4 (NOT S6!) sw s0,0x28(sp) move s0,r5 sw s1,0x2c(sp) move s1,r6 sw s3,0x34(sp) ; NEW COMMAND OBRAB ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;lw v1,0x0(s5) ;nop ;v1/r3 - MyChars charcount andi v0,v0,0xff addiu s4,s4,0x2 ;Moving text read pointer +2bytes lui s3,MyAddr sw v0,-0x10(s3) ;store bytecounter @ 8008fff0 and clean charCounter (8008fff2) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; lui s3,0x1f80 ori s3,s3,0x3d0 ;s3 = 1f8003d0 - copysprite cmd in scratch lui t0,0xff ori t0,t0,0xffff ;t0 = 00FFFFFF ;sw s0, 0x28(sp) ;save s0 in stack andi r4,r7,0xff ;s0 - cut textMode (color & shadow) lui r7, 0x8008 ;r7 = 8008 0000 lui r6, 0xff00 ;r6 = FF000000 addiu t1,r7,-0x31a8 ;t1 = 8007b6d0 - new free CHAIN Here lw v1, -0x31a8(r7) ;r3/v1 = load freeChain lbu r5,0x60(sp) ;shadow flag from stack to r5 lui v0,0x8000 ;r2 = 8000 0000 sw ra,0x48(sp) sw s7,0x44(sp) sw s6,0x40(sp) sw s5,0x3c(sp) ; push ra,r30,r23,31,r20 sw s2,0x30(sp) ;;init chains and r6,v1,r6 ;r6 = r3 & ff000000 = FF000000 andi r5,r5,0xff ;clean text mode (color/shadow) and v1,v1,t0 ;r3 & 00ffffff or s5,v1,v0 ;r20 - 80...+r3 = freeChain Main Addr lw v0,0x4(t1) ;Load DMA Counter lw v1,0x0(s5) ;r3 = next free Chain addiu v0,v0,-0x1 ;DMA Counter-1 and v1,v1,t0 ; r3 & r8 (00ffffff) cut f.byte or r6,r6,v1 ; r6 | r3 = ff+r3 = next free Chain (FF...) + sw v0,0x4(t1) ;save DMACounter jal storeColor sw r6,-0x31a8(r7) ;SAVE next free Chain (FF...) to 7b6d0 move r4,s5 ;currentChainAddr sll r5,s0,0x10 ;r5 = X<<10h (003A0000) sra r5,r5,0x10 ; r5=r5>>10h 0000003A sll r6,s1,0x10 ; r6 = Y << 10h jal initCopyCharChain ;init line chains sra r6,r6,0x10 ;r6>>10h - 100% clean coords ;move r7,s0 ;store textMode _THIS IS FOR INIT ;;;;init ScratchPad ;;;;;;;;;;;;;;;;;; CPU TO VRAM lui r6,0x1f80 ori r6,r6,0x348 ;r7 = FIRST CHAR START ;lui r6,0x1f80 ;LOWER HALF OF CHAR - DONT NEED!!! ;ori r6,r6,0x38c ;4bit table pattern .include "EP_4bitPattern.asm" li v0,0x2 sh v0,0x1c(sp) li v0,0xc li r4,0x10 ;COMMANDS IN CHAR FORMING CHAIN? lui r3,0xa000 ;r4 = a000 0000 sh v0,0x1e(sp) ; SAVE 000C0002 TO STACK+1c ; INIT CHAR lui v0,0x100 ;FLUSH CACHE 01 00 00 00 =>DAT_1f80034b sb r4,0x3(r6) ;SAVE 0d 00 00 00 =>DAT_1f80034c cmdcount\ sw r3,0x4(r6); SAVE a000000 TO DAT_1f80034c lui at,0x1f80 ;scrathcpadStart sw v0,0x388(at) ;save 0x01 00 00 00 to end of 1st CHAR chain ; Copy Sprite DMA Command Forming li v0,0x4 sb v0,0x3(s3) ; 04 00 00 00 to 3d0 (sb 04 to 3d3) CHAIN LENGTH li v0,0x64 sb v0,0x7(s3) ;sb 64 to 3d7 (copySpriteCommand) lhu r4,0x98(gp) ;0310 ;Load x(0310) to r8 lhu r3,0x9a(gp) ;01f0 ;Load y(01F0)to r2 ;lui v1,0x100 ;0100 0000 flushcache li v0,0x80 sb v0,0x4(s3) sb v0,0x5(s3) sb v0,0x6(s3) ;make 80 80 80 64 (3d4,5,6) setY1: lw v0,0x1c(sp) ; r2 = 000c0002 from stack lh r7,0x98(gp) ;for futher sprite X calc sh r4,0x18(sp) sh r3,0x1a(sp) ;SAVE CONCAT 013001f0 to stack lw r4,0x18(sp) ;LOAD 013001f0 from stack ;lw v1,0x18(sp) move t0,r7 sw r4,0x8(r6) ;DAT_1f800350 load r4 (upper coord 01f6) to r7+8 (DMA) sw v0,0xc(r6) ;=>DAT_1f800354 r2 - 000c0002 to 1st char (to r7+0c) bgez r7,LAB_800194fc SetX1: sh s1,0x20(sp) ;store X half to sp+10 !!!!!!!!!!!!!!!!! addiu t0,r7,0x3f LAB_800194fc: ;decoding coords for source sprite sra v0,t0,0x6 ;r2 = r6 >> 6 = 4 sll v0,v0,0x6 ;r2 << 6 = 100 subu v0,r7,v0 ;r2 = r6 - r2 = 30 lh v1,0x9a(gp) ;r3 = load Y half from mem sll v0,v0,0x2 ;r2 << 2 sb v0,0xc(s3) ; >DAT_1f8003dc ;STORE CHAR SPRITE X BYTE bgez v1,LAB_80019520 ;if Y r3>=0 - branch & r2=r3 move v0,v1 addiu v0,v1,0xff ;else r2 = ff - r3 LAB_80019520: sra v0,v0,0x8 sll v0,v0,0x8 subu v0,v1,v0 sb v0,0xd(s3) ; >DAT_1f8003dd ;STORE CHAR SPRITE Y BYTE lhu v1,0xa0(gp) ;DIFF BETWEEN VERSs:::::::::::::::::::::: li v0,0x8 ; r2 = 8 Sprite WIDTH sh v0,0x10(s3) ; 3e0 - 0008 save sh v1,0xe(s3);=>DAT_1f8003de ; *3de = r3 = 7df3 sh s0,0x8(s3) sh s1,0xa(s3) li v0,0xc ; r2 = c Sprite HEIGTH sh v0,0x12(s3) ; 3e2 - 000c save ;TEXT READ START lbu r4,0x0(s4) ;MAIN READ CHAR COMMAND - Load Byte Unsigned nop addiu s4,s4,0x1 ;Shift read address +1 byte ;;;;;;;;;;;;;;;;;;;;;;;;;CHAR CHECK CUTTED! lui s6,0x8008 ;load 80080000 to r17 addiu s7,s6,-0x3198 ;r21 = r17-4930= 7b6d0 (tempDMA) lui s0,0xff ori s0,s0,0xffff ;s0 = 00 ff ff ff lui s1,0x8000 ;r3 = 8000 0000 NextChar: addiu r4,r4,-0x20 ;Shift unprintable symbols ;ОБРАБОТКА ПРОБЕЛОВ bne r4,zero,SpaceCheckBranch ;Если не пробел - перепрыгиваем сразу nop lui t2,MyAddr lh v0,-0xE(t2) ;Load my temp CHAR COUNTER for check nop lh t3,-0x10(t2) addiu v0,v0,1 ;overall chars+1 beq v0,t3,SpaceCheckBranch ;is last char - пробел не проверяем! nop ;ITS A SPACE!!!! sh v0,-0xE(t2) ;Save charcount += 1 nop lbu r4,0x0(s4) ;LOAD NEXT CHAR ;j SpaceJump ;X COORD SHIFT (+6) lhu v0,0xa8(gp) ;LOAD INIT X lhu v1,0x8(s3) ;LOAD LAST X IN SCRATCH addiu v0,v0,0x6 ;v0 = INIT X+6 addu v1,v1,v0 ;LAST X = LAST X + (INIT X + 6) sh v1,0x8(s3) ;UPDATE LAST X IN SCRATCH DMA j NextChar addiu s4,s4,0x1 ;Shift read address +1 byte SpaceCheckBranch: ;LAB_8001a608 NextChar: jal makeCharPixelsCustom ;MAKE SMALL CHAR IN SCRATCH ___ CUSTOM ROUTINE clear s2 ; Coords XY init ;lw v0,0xb0(gp); =>DAT_8007b240_parms load r2 from r28+0b0 (7b240)(Xoffs) ;lui t2,MyAddr ;lh v1,-0xE(t2) ;Load my temp CHAR COUNTER for check ; lhu v1,0x4(r20) ; current char = r3 = half *DMAAddr + 4 ;addiu v0,v0,0x6 ; 0x06 * 6px btw letters! ;mult v1,v0 ; r3*r2 = xOffs*charNum lui t2,0xff00 ; r10 = ld upper ff00 = ff000000 move t6,s5 ; r14 = r21 (params) =r9 FROM SMALL SRC addiu t5,sp,0x10 ; r11 = sp + 10 = 807ffe50 lui t3,0x8008 addiu t4,t3,-0x31a8 move t1,s5 ; r9 = r21 (params again) =t9 ;=r8 FROM SMALL SetY: ; sh s8,0xa(s3) ; DAT_1f8003da *r19(1st scr DMA)+0a = r30 (Y??) !!!!!!!!!!!!!!!! SetX: ; lhu t5,0x20(sp) ; r13 = ld half (sp+20) = 003A ---X from sp+20 !! ; mflo t6 ; r14 = lo ;addu v0,t5,t6 ; r2 = r13 + r14 = X + Offset ; sh v0,0x8(s3) ;DAT_1f8003d8 save r2 half to 1f8003d8 = X (3A) !!!!!!!!!!!!!!!! PageLoop: ;MAKING COPYSPRITE CHAIN lw v0,-0x3198(s6); r2 = *freeChainAddr nop and r4,v0,t2 ; r4 = r2 & ff00.. and v0,v0,s0 ; r2 & 00FFFFFF or r5,v0,s1 ; r5 = r2 or r23 (80000000) = 801ADF10 lw v0,0x4(s7) ; CmdCounter r2 = *7b6d0+4 = 705 lw v1,0x0(r5) ; r3 = New Free ChainAddr addiu v0,v0,-0x1 ; r2 -= 1 Counter Down and v1,v1,s0 ; r3 & 00FFFFFF cut begin byte or r4,r4,v1 ; r4 & r3 = ff...... sw v0,0x4(s7) ; CmdCounter save DMA Counter sw r4,-0x3198(s6); freeChain save new freeChain CopyCmdFromScratch: ; CopyScriptChain copy from scratch lw t9,0x0(s3) ;>DAT_1f8003d0 r14 = 04000000 - DMA Commands Count lw t7,0x4(s3) ;>DAT_1f8003d4 r15 = 64808080 - CopySpriteCmd lw t8,0x8(s3) ;>DAT_1f8003d8 r24 = 001500d1 - xy screen coords lw t5,0xc(s3); >DAT_1f8003dc r13 = 7fd3f0c0 (CLUT & tex coord page) sw t9,0x0(r5) ; *r5 = r14 sw t7,0x4(r5) ; *r5+4 = r15 sw t8,0x8(r5) ; *r5+8 = r24 sw t5,0xc(r5) ; *r5+c = r13 lw t9,0x10(s3);>DAT_1f8003e0 r14 = 000c0008 - spritesize after copy nop sw t9,0x10(r5) ; *r5+10 = r14 - LAST COMMAND SAVE ; t1 = t0 (small) !!!! ; t4 = t1 (small) !!!! lw v1,0x18(t1) ;r3 = *r9+18 (next param???) lw v0,0x0(r5) ; r2 = *cur New Chainaddr lw v1,0x0(v1) ; r3 = *r3 and v0,v0,t2 ; r2 & ff000000 and v1,v1,s0 ;r3 & 00FFFFFF or v0,v0,v1 ; r2 | r3 = 04FFFFFF - commands with FFFFFF sw v0,0x0(r5) ; *curChainAddr r5 = r2 (upd ..04 with ..FF04) lw r4,0x18(t1) ; r4 = *r8+18 (first chain addr?) nop lw v0,0x0(r4) ; r2 = *r4 FIRST CHAIN LINK TO NEXT?? and v1,r5,s0 ; r3 = r5 (cur chain) & 00FFFFFF and v0,v0,t2 ; r2 & FF000000 or v0,v0,v1 ; r2 | r3 = last chain adr w 10&.... sw v0,0x0(r4) ; *r4 = r2 FIRST CHAIN NEXT ADDR??? sw r5,0x18(t1) ;t0->t1 ; r5 = *r8+18 curChainAddr lhu v0,0x4(t6) ;t1->t6 r2 = half (DMA params)+4 (charCounter) nop bne v0,zero,NotFirstChar ; if CharCount<>0 then Goto... nop ;clear t0 sw r5,0x28(t1) ;t0->t1 ;*curChain+28 = Set first Char Chain sw t8,0xc(t6) ;t1->t6 ; Params+0c = save STORE COORDS to params ;sh s2,0xe(t4) ;t1->t6 ;Params+0e = save half Y NotFirstChar: ; lui t3,0x1f80 ; ori t3,t3,0x388 ; Scratch DMAChain CharEndAddr lui r5,0x1f80 ;;;;;;;;;;;;;;;;;;;;;;;ADDRESS OF CHAR HERe ---> SLL CHARNUM, 6 lw v0,-0x31a8(t3);>8007b6d0_freeChain r2 = *nextFreeChain ori r5,r5,0x348 ; r5 | 1f800348 = Scratch CharData and r4,v0,t2 ; r4 = r2 & FF000000 FFNEXTCHAIN and v0,v0,s0 ; r2 & 00FFFFFF = 00XTCHAN or r7,v0,s1 ;or (800...) ; r7 = r2 | r12 = nextChain & 80... move r6,r7 ; r6 = r7 (nextChain) lw v0,0x4(t4) ; CmdCounter r2 = DMA Counter lw v1,0x0(r7) ; r3 = New Free ChainAddr / currHeader Addr addiu v0,v0,-0x1 ; r2 -= 1 Counter Down and v1,v1,s0 ; r3 & 80.... commandCount / currHeader or r4,r4,v1 ; r4 & r3 = ff...... sw v0,0x4(t4);>DAT_8007b6d4_CmdCounter save DMA Counter andi v0,r7,0x3 ; r2 = r7 & 3 (check destAddr MOD 4) sw r4,-0x31a8(t3);>8007b6d0_freeChain save new freeChain beq v0,zero,Copy16Bytes ; if r7 MOD 4 = 0 then Branch addiu v0,r5,0x40 ;T3 = 388! ;;;;;;;;;;;;;;;Copy from ScratchPad To Chain CopyBy2Bytes: lwl t9,0x3(r5) ; if r7 mod4 <> 0 - копируем по 2 байта lwr t9,0x0(r5);>DAT_1f800348 lwl t7,0x7(r5) lwr t7,0x4(r5);>DAT_1f80034c lwl t8,0xb(r5) lwr t8,0x8(r5);>DAT_1f800350 lwl t5,0xf(r5) lwr t5,0xc(r5);>DAT_1f800354 swl t9,0x3(r6) swr t9,0x0(r6) swl t7,0x7(r6) swr t7,0x4(r6) swl t8,0xb(r6) swr t8,0x8(r6) swl t5,0xf(r6) swr t5,0xc(r6) addiu r5,r5,0x10 bne r5,v0,CopyBy2Bytes addiu r6,r6,0x10 j last4BytesCopy nop Copy16Bytes: lw t9,0x0(r5);>DAT_1f800348 r5 - curScratchAddr,r6 -cur DMAAddr lw t7,0x4(r5) lw t8,0x8(r5) lw t5,0xc(r5) sw t9,0x0(r6) sw t7,0x4(r6) sw t8,0x8(r6) sw t5,0xc(r6) addiu r5,r5,0x10 bne r5,v0,Copy16Bytes addiu r6,r6,0x10 last4BytesCopy: lwl t9,0x3(r5) ; r14 left = 2 bytes from *r5+3 lwr t9,0x0(r5);>DAT_1f800358 r14 right = 2 bytes from *r5 nop swl t9,0x3(r6) ; *r6 = r14 left swr t9,0x0(r6) ; *r6+3 = r14 right ; linking DMA char+copysprite ; t0 (smallSRC) = t1 (HERE) !!!! ;r8 = r9 !!!!!!!!!!!!! ; t1 (smallSRC) = t6 (HERE) !!!! ;r9 = r14 !!!!!!!!!!!! lw v1,0x18(t1) ; r3 = current DMACopySprite Chain lw v0,0x0(r7) ; r2 = current CharChainCommands lw v1,0x0(v1) ; r3 = *r3 (comNum+FFFFFF(nextLink)) and v0,v0,t2 ; r2 & FF..... and v1,v1,s0 ; r3 & 00FFFFFF or v0,v0,v1 ; r2 | r3 = 10FFFFFF(cmdNum&FF..) sw v0,0x0(r7) ; *r7 = r2 saveCurChainCmd (10FFFFFF) lw r4,0x18(t1) ; r4 = r8+18h - cur CopySpriteCmd hdrAddr nop lw v0,0x0(r4) ; r2 = *r4 (04FFFFFF) and v1,r7,s0 ; r3 = r7 & 00FFFFFF (Copying Cur Char Chain) and v0,v0,t2 ; r2 & FF000000 (04000000) CmdCount or v0,v0,v1 ; R2 | R3 = 04(cmd)..+CharChainAddr sw v0,0x0(r4) ; *r4 = r2 = FullCommand With Link!!! ; (04..CharAddr) + SpriteCopyCommand sw r7,0x18(t1) ; *r8+18 = Last Char Chain! addiu t1,t1,0x4 ; r8 (params) += 4 (shift params for NextPage) addiu v0,t6,0x8 ; r2 = r9+8 (shift first chain param for Page) sltu v0,t1,v0 ; r2 = r8 < r2(r9+8) (first page pass) bne v0,zero,PageLoop ; if r2<>0 (r80 then Goto End Text (DMA OVERFLOW!!!!) nop lui t3,MyAddr lhu v0,-0xE(t3) ; r2 = charCount In string lhu v1,-0x10(t3) ; r3 = My charOverAll In string addiu v0,v0,0x1 ; a += 1 lbu r4,0x0(s4) ; load next Char to r4 (byte) sh v0,-0xE(t3) ; store myCharCounter to MyAddr-E addiu s4,s4,0x1 ;Shift CharAddr bne v0,v1,NextChar ; if currentChar<>OverallChar - branch nop TextEnd: clear r18 lui s3,0x8008 addiu s4,s3,-0x3198 ; r19 = 80080000, r21 = 7b6d0 lui s1,0xff ; r17 = 00ff0000 ori s1,s1,0xffff ; r17 & ffff = 00ff ffff move s0,s5 ; r16 = r20 (currentTLineParam) clear r5 PageTLoop: ;ALMOST FINISH!!!! li r6,0x1 ; r6=1 addu r18,r18,r6 ; r18(Counter) += r6 lui v0,0x8000 ; r2 = 80000000 lui r4,0xff00 ; r4 = ff00 0000 lw v1,-0x3198(s3);>8007b6d0_freeChain r3 = next free Chain (*7b6d0) lw r7,0x9c(gp);>DAT_8007b234 r7 = someParam(почти DMA)gp+a4 = 34 and v1,v1,s1 ; r3 & 00FFFFFF or v1,v1,v0 ; r3 | r2 = 80..... sw v1,0x30(s0) ; store last free ChAddr to DMAParams lw v0,-0x3198(s3);>8007b6d0_freeChain r2 = next free chain lw v1,0x0(v1) ; r3 = *r3 = last chain - made one more chain and v0,v0,r4 ; a2 & ff000000 and v1,v1,s1 ; r3 & 00FFFFFF lw r4,0x4(s4);>DAT_8007b6d4_CmdCounter r4 = DMA Counter or v0,v0,v1 ; r2 | r3 sw v0,-0x3198(s3);>8007b6d0_freeChain new free chain addr add to *7b6b0 addiu r4,r4,-0x1 ; DMA Cunter =- 1 sw r4,0x4(s4);>DAT_8007b6d4_CmdCounter Store DMA Count lw r4,0x30(s0) ; r4 = *DMA params + 30 = Start Of DMA Chain jal SetDrawTPage ; Set DRAW PAGE addiu s0,s0,0x4 ; r16 += 4 - Shgift DMAParams for next Page sltiu v0,r18,0x2 ; r2 = r18<2 bne v0,zero,PageTLoop ; if not r2 then goto Loop clear r5 ; r5 = 0 move v0,s5 ; r2 = DMAParamsMain lw ra,0x48(sp) lw s7,0x44(sp) lw s6,0x40(sp) lw s5,0x3c(sp) ;restoring regs from Stack 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 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; Chars / 2 Return Func .include "EP_charload.asm" .include "charCalcs.asm" ;patching PrintCommandText .org 0x8001d138 ;jal 0x8001a3a8 ORIG CALL jal ExternalPrint .org 0x8001d0c4 ;jal 0x8001a3a8 ORIG CALL jal ExternalPrint .org 0x8001bee0 j ReturnCharsInString ;custom routine ; j 0x8001beec .org 0x8001bf08 ; addiu sp,sp,-0x18 ;Original Code ; sw ra,0x10(sp) j calcnextXCustom ;PATCHED nop .close ;;;;;;;;;;;;;;;;;;;;;;;;; BOSSNAMECOPY ;;.include "battle_patch.asm" ;;.include "txtpatches.asm" ;misc text patches ; COMPILE COMMAND: ./armips -temp 123_EP EP_main.asm