Here I am, back with some FFIV hacking of the PlayStation build (and consequently also of the original). Today's topic is:
battle backgrounds.
According to my brief research, $00:1802 holds the value used to determine the background image and it uses the lower 7 bits to define said image range (0x80 is the magnetic field flag, apparently).
Here's a lookup table I've been using to turn those 7 bits into usable values (pictures are ordered according to the values used in the GBA/PSP port):
.db 0x00, 0 ; surface field
.db 0x01, 4 ; forest
.db 0x02, 5 ; mountain
.db 0x03, 16 ; castle
.db 0x04, 1 ; cave
.db 0x05, 12 ; moon
.db 0x06, 15 ; airship
.db 0x07, 3 ; cave, water field
.db 0x08, 6 ; magnetic cave
.db 0x09, 2 ; desert
.db 0x0A, 20 ; beach
.db 0x0B, 9 ; lava cave
.db 0x0C, 18 ; blue tower
.db 0x0D, 11 ; lunar cave
.db 0x0E, 13 ; moon core
.db 0x0F, 7 ; underground field
.db 0x10, 14 ; zeromus
.db 0x20, 17 ; surface field, night
.db 0x24, 21 ; blue cave
.db 0x27, 3 ; blue cave, water field
.db 0x28, 8 ; brown cave
.db 0x2B, 10 ; sylph cave
.db 0x2C, 19 ; giant of babilResult:

For those interested enough to check this out themselves, here's a snippet of code used by the game to load battle backgrounds:
$02/91D2 AD 02 18 LDA $1802 [$00:1802] A:00F0 X:0044 Y:0000 P:eNvMxdizc
$02/91D5 29 1F AND #$1F A:00F0 X:0044 Y:0000 P:eNvMxdizc
$02/91D7 0A ASL A A:00F0 X:0044 Y:0000 P:eNvMxdizc
$02/91D8 AA TAX A:00F0 X:0044 Y:0000 P:eNvMxdizc
$02/91D9 C2 20 REP #$20 A:00F0 X:0044 Y:0000 P:eNvMxdizc
$02/91DB A9 28 00 LDA #$0028 A:00F0 X:0044 Y:0000 P:eNvmxdizc
$02/91DE 85 00 STA $00 [$00:0600] A:00F0 X:0044 Y:0000 P:eNvmxdizc
$02/91E0 BF B4 FD 16 LDA $16FDB4,x[$16:FDF8] A:00F0 X:0044 Y:0000 P:eNvmxdizc
$02/91E4 AA TAX A:00F0 X:0044 Y:0000 P:eNvmxdizc
$02/91E5 7B TDC A:00F0 X:0044 Y:0000 P:eNvmxdizc
$02/91E6 E2 20 SEP #$20 A:00F0 X:0044 Y:0000 P:eNvmxdizc
$02/91E8 A9 1C LDA #$1C A:00F0 X:0044 Y:0000 P:eNvMxdizc
$02/91EA A0 10 40 LDY #$4010 A:00F0 X:0044 Y:0000 P:eNvMxdizc
$02/91ED 20 0F 86 JSR $860F [$00:860F] A:00F0 X:0044 Y:0000 P:eNvMxdizc
$02/91F0 22 BD E8 01 JSL $01E8BD[$01:E8BD] A:00F0 X:0044 Y:0000 P:eNvMxdizc
$02/91F4 A2 80 04 LDX #$0480 A:00F0 X:0044 Y:0000 P:eNvMxdizc
$02/91F7 86 00 STX $00 [$00:0600] A:00F0 X:0044 Y:0000 P:eNvMxdizc
$02/91F9 A9 7E LDA #$7E A:00F0 X:0044 Y:0000 P:eNvMxdizc
$02/91FB A2 FD 6C LDX #$6CFD A:00F0 X:0044 Y:0000 P:eNvMxdizc
$02/91FE A0 00 58 LDY #$5800 A:00F0 X:0044 Y:0000 P:eNvMxdizc
$02/9201 20 75 86 JSR $8675 [$00:8675] A:00F0 X:0044 Y:0000 P:eNvMxdizc
$02/9204 AD C0 6C LDA $6CC0 [$00:6CC0] A:00F0 X:0044 Y:0000 P:eNvMxdizc
$02/9207 48 PHA A:00F0 X:0044 Y:0000 P:eNvMxdizc
$02/9208 A9 FF LDA #$FF A:00F0 X:0044 Y:0000 P:eNvMxdizc
$02/920A 8D C0 6C STA $6CC0 [$00:6CC0] A:00F0 X:0044 Y:0000 P:eNvMxdizc
$02/920D 22 D4 E9 01 JSL $01E9D4[$01:E9D4] A:00F0 X:0044 Y:0000 P:eNvMxdizc
$02/9211 68 PLA A:00F0 X:0044 Y:0000 P:eNvMxdizc
$02/9212 8D C0 6C STA $6CC0 [$00:6CC0] A:00F0 X:0044 Y:0000 P:eNvMxdizc
$02/9215 A2 80 04 LDX #$0480 A:00F0 X:0044 Y:0000 P:eNvMxdizc
$02/9218 86 00 STX $00 [$00:0600] A:00F0 X:0044 Y:0000 P:eNvMxdizc
$02/921A A9 7E LDA #$7E A:00F0 X:0044 Y:0000 P:eNvMxdizc
$02/921C A2 FD 6C LDX #$6CFD A:00F0 X:0044 Y:0000 P:eNvMxdizc
$02/921F A0 00 5C LDY #$5C00 A:00F0 X:0044 Y:0000 P:eNvMxdizc
$02/9222 4C 75 86 JMP $8675 [$00:8675] A:00F0 X:0044 Y:0000 P:eNvMxdizcCorresponding PSX code for the PAL build:
.org 0x800762D8
TransferBG:
addiu $sp, -0x18
sw $ra, 0x10($sp)
jal LDA_ptr16 # LDA $1802
li $a0, 0x1802
jal AND_imm8 # AND #$1F
li $a0, 0x1F
jal ASL # ASL A
nop
lw $v0, unk_8019E80C # TAX
lw $a1, unk_8019E81C
lhu $v1, 0($v0)
li $a0, 0x20
jal REP # REP #$20
sh $v1, 0($a1)
jal unk_800F6548 # LDA #$0028
li $a0, 0x28
jal unk_800F8264 # STA $00
move $a0, $0
lui $a0, 0x16
jal unk_800F6CE4 # LDA $16FDB4,x
li $a0, 0x16FDB4
lw $v1, unk_8019E80C # TAX
lw $a0, unk_8019E81C
lhu $v0, 0($v1)
jal TDC
sh $v0, 0($a0)
jal SEP # SEP #$20
li $a0, 0x20
jal LDA_imm8 # LDA #$1C
li $a0, 0x1C
jal LDY_imm16 # LDY #$4010
li $a0, 0x4010
jal UpscaleTile3BPP # JSR $860F
nop
jal unk_8013E9B4 # JSL $01E8BD
nop
jal LDX_imm16 # LDX #$0480
li $a0, 0x480 # transfer size
jal STX_ptr8 # STX $00
move $a0, $0
jal LDA_imm8 # LDA #$7E
li $a0, 0x7E
jal LDX_imm16 # LDX #$6CFD
li $a0, 0x6CFD
jal LDY_imm16 # LDY #$5800
li $a0, 0x5800
jal BtlSetDMATrans # JSR $8675
nop
jal LDA_ptr16 # LDA $6CC0
li $a0, 0x6CC0
jal PHA # PHA
nop
jal LDA_imm8 # LDA #$FF
li $a0, 0xFF
jal STA_rel16 # STA $6CC0
li $a0, 0x6CC0
jal unk_8013EFC8 # JSL $01E9D4
nop
jal PLA # PLA
nop
jal STA_rel16 # STA $6CC0
li $a0, 0x6CC0
jal LDX_imm16 # LDX #$0480
li $a0, 0x480
jal STX_ptr8 # STX $00
move $a0, $0
jal LDA_imm8 # LDA #$7E
li $a0, 0x7E
jal LDX_imm16 # LDX #$6CFD
li $a0, 0x6CFD
jal LDY_imm16 # LDY #$5C00
li $a0, 0x5C00
jal BtlSetDMATrans # JMP $8675
nop
lw $ra, 0x10($sp)
nop
jr $ra
addiu $sp, 0x18And it was replaced with this temp function to test it all:
LoadBattleBgTest:
addiu sp, -0x18
sw ra, 0(sp)
sw s0, 4(sp)
; search bg match
lbu a2, 0x800D1802
la t0, bg_lookup
andi a2, 0x3F
li v0, 23 ; search range
@@search_bg:
lbu t1, 0(t0) ; get lookup value
lbu t2, 1(t0) ; corresponding tim
addiu t0, 2 ; next value
beq t1, a2, @@search_complete
addiu v0, -1 ; i++
bnez v0, @@search_bg
nop
; ---
j @@match_not_found
li s0, 0 ; if no result was found, default to forest
@@search_complete:
move s0, t2 ; copy found match
@@match_not_found:
; format string
la a0, file_bg
li t0, 10
divu s0, t0
mflo t0 ; division result
mfhi t1 ; modulo
addiu t0, '0'
addiu t1, '0'
sb t1, 10(a0)
sb t0, 9(a0)
; load file
lui a1, BtlBgImg>>16
jal CdLoadFile
ori a1, BtlBgImg&0xFFFF
; palette
li t0, 256
li t1, 144
li t2, 256
li t3, 1
sh t0, 0x10(sp)
sh t1, 0x12(sp)
sh t2, 0x14(sp)
sh t3, 0x16(sp)
la a1, BtlBgImg
jal LoadImage
addiu a0, sp, 0x10
jal DrawSync
li a0, 0
; picture
li t0, 256
li t2, 128
li t3, 144
sh t0, 0x10(sp) ; x
sh r0, 0x12(sp) ; y
sh t2, 0x14(sp) ; w
sh t3, 0x16(sp) ; h
la a1, BtlBgImg+512
jal LoadImage
addiu a0, sp, 0x10
jal DrawSync
li a0, 0
; ---
li v0, 14 ; check for zeromus' battle
bne s0, v0, @@skip_mirror
addiu a0, sp, 0x10 ; *RECT
li a1, 384 ; dest x
jal MoveImage
li a2, 0 ; dest y
jal DrawSync
li a0, 0
; ---
@@skip_mirror:
lw ra, 0(sp)
lw s0, 4(sp)
jr ra
addiu sp, 0x18
file_bg:
.db "ENGBIN\BG__.BIN",0I have no precise idea how the original code works exactly and I've gotta fix a few details, like the HDMA movement used in Zeromus' battle. All I've done in my hack was replacing the whole tile loading code with a much simpler sequence loading a palette+picture from CD and then sending it straight to VRAM (bypassing all the SFC upscaling, DMA copies, etc...). All I know is that it defines the index in $1802, then it does some funky calculations with it and decides where to load and upscale 3BPP tiles from. The rest is just magic for me, so it's up to you to find out what it does. :p
Unfortunately highly detailed pictures cannot be used on the SFC builds as the game only allow 2 palettes for BG2 in battle (index 2-7 are already taken for enemy use-only).

The only solution I can think about is finding a way to create mini maps with 15*2 colors just for battles, which is more or less what FFVI did but with a much greater palette range.
Anyways, mission accomplished. Hopefully the next step will be finally having 4BPP pictures for monsters and less constrains for character sprites.
PS: Just in case, you can download from
this link a rip of the FFIV Complete Collection battle backgrounds used in my lookup list, so that you don't have to use those lo-res GBA pictures anymoar.
