$00/E672 89 80 BIT #$80 A:0145 X:0001 Y:000B D:0000 DB:06 S:01FF P:envMXdIzC HC:0788 VC:078 FC:20 I:00
$00/E674 F0 03 BEQ $03 [$E679] A:0145 X:0001 Y:000B D:0000 DB:06 S:01FF P:envMXdIZC HC:0812 VC:078 FC:20 I:00
$00/E679 A6 A5 LDX $A5 [$00:00A5] A:0145 X:0001 Y:000B D:0000 DB:06 S:01FF P:envMXdIZC HC:0842 VC:078 FC:20 I:00
$00/E67B 9D 04 06 STA $0604,x[$06:0604] A:0145 X:0000 Y:000B D:0000 DB:06 S:01FF P:envMXdIZC HC:0874 VC:078 FC:20 I:00
$00/E67E A5 6E LDA $6E [$00:006E] A:0145 X:0000 Y:000B D:0000 DB:06 S:01FF P:envMXdIZC HC:0920 VC:078 FC:20 I:00
$00/E680 9D 05 06 STA $0605,x[$06:0605] A:0108 X:0000 Y:000B D:0000 DB:06 S:01FF P:envMXdIzC HC:0952 VC:078 FC:20 I:00
$00/E683 A9 80 LDA #$80 A:0108 X:0000 Y:000B D:0000 DB:06 S:01FF P:envMXdIzC HC:0998 VC:078 FC:20 I:00 - Text color
$00/E685 9D 00 06 STA $0600,x[$06:0600] A:0180 X:0000 Y:000B D:0000 DB:06 S:01FF P:eNvMXdIzC HC:1022 VC:078 FC:20 I:00
$00/E688 C2 21 REP #$21 A:0180 X:0000 Y:000B D:0000 DB:06 S:01FF P:eNvMXdIzC HC:1068 VC:078 FC:20 I:00
$00/E68A A5 6A LDA $6A [$00:006A] A:0180 X:0000 Y:000B D:0000 DB:06 S:01FF P:eNvmXdIzc HC:1098 VC:078 FC:20 I:00
$00/E68C 65 6C ADC $6C [$00:006C] A:0886 X:0000 Y:000B D:0000 DB:06 S:01FF P:envmXdIzc HC:1172 VC:078 FC:20 I:00
$00/E68E 18 CLC A:0888 X:0000 Y:000B D:0000 DB:06 S:01FF P:envmXdIzc HC:1212 VC:078 FC:20 I:00
$00/E68F 69 20 00 ADC #$0020 A:0888 X:0000 Y:000B D:0000 DB:06 S:01FF P:envmXdIzc HC:1234 VC:078 FC:20 I:00
$00/E692 29 FF 07 AND #$07FF A:08A8 X:0000 Y:000B D:0000 DB:06 S:01FF P:envmXdIzc HC:1266 VC:078 FC:20 I:00
$00/E695 09 00 08 ORA #$0800 A:00A8 X:0000 Y:000B D:0000 DB:06 S:01FF P:envmXdIzc HC:1298 VC:078 FC:20 I:00
$00/E698 9D 01 06 STA $0601,x[$06:0601] A:08A8 X:0000 Y:000B D:0000 DB:06 S:01FF P:envmXdIzc HC:1330 VC:078 FC:20 I:00
$00/E69B E6 6C INC $6C [$00:006C] A:08A8 X:0000 Y:000B D:0000 DB:06 S:01FF P:envmXdIzc HC:0020 VC:079 FC:20 I:00
$00/E69D E2 20 SEP #$20 A:08A8 X:0000 Y:000B D:0000 DB:06 S:01FF P:envmXdIzc HC:0082 VC:079 FC:20 I:00
$00/E69F A9 02 LDA #$02 A:08A8 X:0000 Y:000B D:0000 DB:06 S:01FF P:envMXdIzc HC:0112 VC:079 FC:20 I:00
$00/E6A1 9D 03 06 STA $0603,x[$06:0603] A:0802 X:0000 Y:000B D:0000 DB:06 S:01FF P:envMXdIzc HC:0136 VC:079 FC:20 I:00
$00/E6A4 8A TXA A:0802 X:0000 Y:000B D:0000 DB:06 S:01FF P:envMXdIzc HC:0182 VC:079 FC:20 I:00
$00/E6A5 18 CLC A:0800 X:0000 Y:000B D:0000 DB:06 S:01FF P:envMXdIZc HC:0204 VC:079 FC:20 I:00
$00/E6A6 69 06 ADC #$06 A:0800 X:0000 Y:000B D:0000 DB:06 S:01FF P:envMXdIZc HC:0226 VC:079 FC:20 I:00
$00/E6A8 85 A5 STA $A5 [$00:00A5] A:0806 X:0000 Y:000B D:0000 DB:06 S:01FF P:envMXdIzc HC:0250 VC:079 FC:20 I:00
$00/E6AA AD 49 1F LDA $1F49 [$06:1F49] A:0806 X:0000 Y:000B D:0000 DB:06 S:01FF P:envMXdIzc HC:0282 VC:079 FC:20 I:00
$00/E6AD F0 38 BEQ $38 [$E6E7] A:0800 X:0000 Y:000B D:0000 DB:06 S:01FF P:envMXdIZc HC:0322 VC:079 FC:20 I:00
$00/E6E7 AD 4A 1F LDA $1F4A [$06:1F4A] A:0800 X:0000 Y:000B D:0000 DB:06 S:01FF P:envMXdIZc HC:0352 VC:079 FC:20 I:00
$00/E6EA 30 08 BMI $08 [$E6F4] A:0801 X:0000 Y:000B D:0000 DB:06 S:01FF P:envMXdIzc HC:0392 VC:079 FC:20 I:00
$00/E6EC CE 4A 1F DEC $1F4A [$06:1F4A] A:0801 X:0000 Y:000B D:0000 DB:06 S:01FF P:envMXdIzc HC:0416 VC:079 FC:20 I:00
$00/E6EF F0 03 BEQ $03 [$E6F4] A:0801 X:0000 Y:000B D:0000 DB:06 S:01FF P:envMXdIZc HC:0470 VC:079 FC:20 I:00
$00/E6F4 A6 6F LDX $6F [$00:006F] A:0801 X:0000 Y:000B D:0000 DB:06 S:01FF P:envMXdIZc HC:0500 VC:079 FC:20 I:00 - Text speed
$00/E6F6 F0 2D BEQ $2D [$E725] A:0801 X:0004 Y:000B D:0000 DB:06 S:01FF P:envMXdIzc HC:0532 VC:079 FC:20 I:00
$00/E6F8 E0 01 CPX #$01 A:0801 X:0004 Y:000B D:0000 DB:06 S:01FF P:envMXdIzc HC:0596 VC:079 FC:20 I:00
$00/E6FA F0 1C BEQ $1C [$E718] A:0801 X:0004 Y:000B D:0000 DB:06 S:01FF P:envMXdIzC HC:0620 VC:079 FC:20 I:00
$00/E6FC AD B3 1F LDA $1FB3 [$06:1FB3] A:0801 X:0004 Y:000B D:0000 DB:06 S:01FF P:envMXdIzC HC:0644 VC:079 FC:20 I:00
$00/E6FF D0 17 BNE $17 [$E718] A:0800 X:0004 Y:000B D:0000 DB:06 S:01FF P:envMXdIZC HC:0684 VC:079 FC:20 I:00
$00/E701 5A PHY A:0800 X:0004 Y:000B D:0000 DB:06 S:01FF P:envMXdIZC HC:0708 VC:079 FC:20 I:00
$00/E702 AD 49 1F LDA $1F49 [$06:1F49] A:0800 X:0004 Y:000B D:0000 DB:06 S:01FE P:envMXdIZC HC:0738 VC:079 FC:20 I:00
$00/E705 F0 0B BEQ $0B [$E712] A:0800 X:0004 Y:000B D:0000 DB:06 S:01FE P:envMXdIZC HC:0778 VC:079 FC:20 I:00
$00/E712 A9 1E LDA #$1E A:0800 X:0004 Y:000B D:0000 DB:06 S:01FE P:envMXdIZC HC:0808 VC:079 FC:20 I:00 - SFX to use each time a letter is written
$00/E714 20 79 85 JSR $8579 [$00:8579] A:081E X:0004 Y:000B D:0000 DB:06 S:01FE P:envMXdIzC HC:0832 VC:079 FC:20 I:00
These appear once the letters do
DMA[0]: CPU->PPU Mode:1 0x000604->0x2118 Bytes:34 (inc) V:232 VRAM: 0984 (1,0) word
DMA[0]: CPU->PPU Mode:1 0x00063C->0x2118 Bytes:2 (inc) V:233 VRAM: 0984 (1,0) word
DMA[0]: CPU->PPU Mode:1 0x000642->0x2118 Bytes:34 (inc) V:234 VRAM: 09C4 (1,0) word
DMA[0]: CPU->PPU Mode:1 0x00067A->0x2118 Bytes:2 (inc) V:235 VRAM: 09C4 (1,0) word
DMA[0]: CPU->PPU Mode:1 0x000680->0x2118 Bytes:28 (inc) V:235 VRAM: 0A04 (1,0) word
DMA[0]: CPU->PPU Mode:1 0x0006AC->0x2118 Bytes:28 (inc) V:236 VRAM: 0A44 (1,0) word
$00/E67B 9D 04 06 STA $0604,x[$06:0604] A:012E X:0000 Y:0016 P:envMXdIZC
DMA[0]: CPU->PPU Mode:1 0x000604->0x2118 Bytes:2 (inc) V:235 VRAM: 0BB4 (1,0) word
$7E/22BC 8D 0B 42 STA $420B [$06:420B] A:0001 X:0004 Y:0000 P:envMXdIzc
Oh duh, right. Completely bypassed that. The screen I've been looking at is the Capcom Copyright screen right when the game starts. Ends up being 1308 IS where it's all being stored correctly. I thought maybe this wasn't the right area to check but that area loads the font as well so it's generally okay. So yep, 1308 is the right spot.
Would my next step to trace it backwards? If so, how do you work backwards from VRAM? I've never done it with that but I've done it multitudes of times with regular code.
..ffcf nop A:00 X:00 Y:00 SP:01ef YA:0000 nvpbhizc
008106 beq $8103 [008103] A:0100 X:00ff Y:0001 S:02ff D:0000 DB:06 nvMXdIZc V:241 H: 18
008103 lda $09ce [0609ce] A:0100 X:00ff Y:0001 S:02ff D:0000 DB:06 nvMXdIZc V:241 H: 40
..ffd2 nop A:00 X:00 Y:00 SP:01ef YA:0000 nvpbhizc
001ff3 jml $7e2000 [7e2000] A:0100 X:00ff Y:0001 S:02fb D:0000 DB:06 nvMXdIZc V:225 H: 104
DMA[0]: CPU->PPU Mode:1 0x000604->0x2118 Bytes:34 (inc) V:232 VRAM: 0984 (1,0) word
This is for actual in-game dialogue:
$00/E679 A6 A5 LDX $A5 [$00:00A5] A:0145 X:0001 Y:000B D:0000 DB:06 S:01FF P:envMXdIZC HC:0842 VC:078 FC:20 I:00
$00/E67B 9D 04 06 STA $0604,x[$06:0604] A:0145 X:0000 Y:000B D:0000 DB:06 S:01FF P:envMXdIZC HC:0874 VC:078 FC:20 I:00 - Storage for Letter being written
$00/E67E A5 6E LDA $6E [$00:006E] A:0145 X:0000 Y:000B D:0000 DB:06 S:01FF P:envMXdIZC HC:0920 VC:078 FC:20 I:00
$00/E680 9D 05 06 STA $0605,x[$06:0605] A:0108 X:0000 Y:000B D:0000 DB:06 S:01FF P:envMXdIzC HC:0952 VC:078 FC:20 I:00
$40/0034 B1 68 LDA ($68),y[$12:E827] A:0A3E X:0010 Y:0006 P:envMXdIzC
$40/0036 C8 INY A:0A49 X:0010 Y:0006 P:envMXdIzC
$40/0037 AB PLB A:0A49 X:0010 Y:0007 P:envMXdIzC
ldx #UntitledData ; Address
lda #:UntitledData ; of UntitledData
ldy #(15*16*2) ; length of data
stx $4302 ; write
sta $4304 ; address
sty $4305 ; and length
lda #%00000001 ; set this mode (transferring words)
sta $4300
lda #$18 ; $211[89]: VRAM data write
sta $4301 ; set destination
ldy #$0000 ; Write to VRAM from $0000
sty $2116
lda #%00000001 ; start DMA, channel 0
sta $420B
Sorry to necropost but I've been looking at VWF routines a bit more.
I noticed and just realized when re-looking this: It actually LOADS the font character's graphics itself (From what I saw anyway) and copies that into RAM. Then.. does it store that into VRAM? Then when doing so, it does basically the same thing for the next letter but it loads a value before hand to dictate how much space is between each letter?
I'm so sorry if I'm not getting this after all this time.
The game is farther ahead in the steps than what MMX1-3 were. The font IS loaded directly from rom staring at C00000 (Literally right at the start of the game). It's a 16x16 font that gets pulled from ROM then stored directly into VRAM. I've found the base area for where it stores into VRAM, how it loads the graphics I believe and all that fun stuff. There's even a fun thing that after a certain byte is hit, it jumps 180 for a new line and such.
But now that the basis of this is already there (It's not fixed width per se), where would be the next step to start to make this into a VWF?
(Note: I'm not sure exactly how bitshifting works on SNES, but you'll need to pay attention to the bit depth of the graphics. If it were 1bpp, an 8 pixel row would be one byte, and you could just shift right once per pixel you wanted to shift. But if it were 2bpp, you'd have two bytes, and you'd need to shift twice, making sure to shift the leftover from the first byte into the second byte. I can post more details on the shifting if you have trouble.)I'd generate a 1bpp VWF (including the shifting) and then convert it when the tiles are copied to VRAM, usually that conversion is just simply a matter of writing the 1bpp tile multiples, or with zeros depending on which palette entry the game uses for "drawn" pixels.
1a) Relocate the section of code that copies data to VRAM. Modify the original code so that it calls this routine to copy the data. (Note: for a 16x16 font, this routine should draw a half the character - an 8 px wide strip. So you will need to call the routine once for the first half and once for the second half. You'll see why this is in a bit.)
$80/BB94 C2 20 REP #$20 A:0000 X:0000 Y:0200 P:envmxdIZc
$80/BB96 E2 10 SEP #$10 A:0000 X:0000 Y:0200 P:envmxdIZc
$80/BB98 AD B0 0F LDA $0FB0 [$80:0FB0] A:0000 X:0000 Y:0000 P:envmXdIZc - Loads font pointer
$80/BB9D 8D 02 43 STA $4302 [$80:4302] A:0260 X:0000 Y:0000 P:envmXdIzc
$80/BBA0 A0 01 LDY #$01 A:0260 X:0000 Y:0000 P:envmXdIzc
$80/BBA2 8C 00 43 STY $4300 [$80:4300] A:0260 X:0000 Y:0001 P:envmXdIzc
$80/BBA5 A0 18 LDY #$18 A:0260 X:0000 Y:0001 P:envmXdIzc
$80/BBA7 8C 01 43 STY $4301 [$80:4301] A:0260 X:0000 Y:0018 P:envmXdIzc
$80/BBAA AC B2 0F LDY $0FB2 [$80:0FB2] A:0260 X:0000 Y:0018 P:envmXdIzc
$80/BBAD 8C 04 43 STY $4304 [$80:4304] A:0260 X:0000 Y:00C0 P:eNvmXdIzc
$80/BBB0 AD B8 0F LDA $0FB8 [$80:0FB8] A:0260 X:0000 Y:00C0 P:eNvmXdIzc - Load VRAM storage
$80/BBB3 8D 16 21 STA $2116 [$80:2116] A:6100 X:0000 Y:00C0 P:envmXdIzc
$80/BBB6 A9 20 00 LDA #$0020 A:6100 X:0000 Y:00C0 P:envmXdIzc - Load top right piece of font
$80/BBB9 8D 05 43 STA $4305 [$80:4305] A:0020 X:0000 Y:00C0 P:envmXdIzc
$80/BBBC A0 01 LDY #$01 A:0020 X:0000 Y:00C0 P:envmXdIzc
$80/BBBE 8C 0B 42 STY $420B [$80:420B] A:0020 X:0000 Y:0001 P:envmXdIzc
$80/BBC1 A0 01 LDY #$01 A:0020 X:0000 Y:0001 P:envmXdIzc
$80/BBC3 8C 00 43 STY $4300 [$80:4300] A:0020 X:0000 Y:0001 P:envmXdIzc
$80/BBC6 A0 18 LDY #$18 A:0020 X:0000 Y:0001 P:envmXdIzc
$80/BBC8 8C 01 43 STY $4301 [$80:4301] A:0020 X:0000 Y:0018 P:envmXdIzc
$80/BBCB AC B2 0F LDY $0FB2 [$80:0FB2] A:0020 X:0000 Y:0018 P:envmXdIzc
$80/BBCE 8C 04 43 STY $4304 [$80:4304] A:0020 X:0000 Y:00C0 P:eNvmXdIzc
$80/BBD1 AD B0 0F LDA $0FB0 [$80:0FB0] A:0020 X:0000 Y:00C0 P:eNvmXdIzc
$80/BBD4 18 CLC A:0260 X:0000 Y:00C0 P:envmXdIzc
$80/BBD5 69 00 01 ADC #$0100 A:0260 X:0000 Y:00C0 P:envmXdIzc - Loads bottom half of font
$80/BBD8 8D 02 43 STA $4302 [$80:4302] A:0360 X:0000 Y:00C0 P:envmXdIzc
$80/BBDB AD B8 0F LDA $0FB8 [$80:0FB8] A:0360 X:0000 Y:00C0 P:envmXdIzc
$80/BBDE 18 CLC A:6100 X:0000 Y:00C0 P:envmXdIzc
$80/BBDF 69 10 00 ADC #$0010 A:6100 X:0000 Y:00C0 P:envmXdIzc - Load height of bottom half of font?
$80/BBE2 8D 16 21 STA $2116 [$80:2116] A:6110 X:0000 Y:00C0 P:envmXdIzc
$80/BBE5 A9 20 00 LDA #$0020 A:6110 X:0000 Y:00C0 P:envmXdIzc - Loads bottom right of font
$80/BBE8 8D 05 43 STA $4305 [$80:4305] A:0020 X:0000 Y:00C0 P:envmXdIzc
$80/BBEB A0 01 LDY #$01 A:0020 X:0000 Y:00C0 P:envmXdIzc
$80/BBED 8C 0B 42 STY $420B [$80:420B] A:0020 X:0000 Y:0001 P:envmXdIzc
$80/BBF0 9C B0 0F STZ $0FB0 [$80:0FB0] A:0020 X:0000 Y:0001 P:envmXdIzc
1b) Instead of copying directly from the ROM, copy the data from the ROM to some unused RAM area. Then use the a call to the routine from 1a to copy from RAM to VRAM. After this step, you'll have code that copies the left half of the character from ROM->RAM-> VRAM, then does the same with the right half.
$80/B87A 85 00 STA $00 [$00:0000] A:000B X:0002 Y:0420 P:eNVmxdIzc
$80/B87C 29 F8 00 AND #$00F8 A:000B X:0002 Y:0420 P:eNVmxdIzc
$80/B87F 4A LSR A A:0008 X:0002 Y:0420 P:enVmxdIzc
$80/B880 4A LSR A A:0004 X:0002 Y:0420 P:enVmxdIzc
$80/B881 AA TAX A:0002 X:0002 Y:0420 P:enVmxdIzc
$80/B882 BD BC B8 LDA $B8BC,x[$80:B8BE] A:0002 X:0002 Y:0420 P:enVmxdIzc - Loads font graphic pointers
$80/B885 85 02 STA $02 [$00:0002] A:0200 X:0002 Y:0420 P:enVmxdIzc
$80/B887 A5 00 LDA $00 [$00:0000] A:0200 X:0002 Y:0420 P:enVmxdIzc
$80/B889 29 07 00 AND #$0007 A:000B X:0002 Y:0420 P:enVmxdIzc
$80/B88C 0A ASL A A:0003 X:0002 Y:0420 P:enVmxdIzc
$80/B88D 0A ASL A A:0006 X:0002 Y:0420 P:enVmxdIzc
$80/B88E 0A ASL A A:000C X:0002 Y:0420 P:enVmxdIzc
$80/B88F 0A ASL A A:0018 X:0002 Y:0420 P:enVmxdIzc
$80/B890 0A ASL A A:0030 X:0002 Y:0420 P:enVmxdIzc
$80/B891 18 CLC A:0060 X:0002 Y:0420 P:enVmxdIzc
$80/B892 65 02 ADC $02 [$00:0002] A:0060 X:0002 Y:0420 P:enVmxdIzc
$80/B894 18 CLC A:0260 X:0002 Y:0420 P:envmxdIzc
$80/B895 69 00 00 ADC #$0000 A:0260 X:0002 Y:0420 P:envmxdIzc - Loads pointer of font
$80/B898 8D B0 0F STA $0FB0 [$80:0FB0] A:0260 X:0002 Y:0420 P:envmxdIzc
$80/B89B A9 C0 00 LDA #$00C0 A:0260 X:0002 Y:0420 P:envmxdIzc - Loads bank of font
$80/B89E 8D B2 0F STA $0FB2 [$80:0FB2] A:00C0 X:0002 Y:0420 P:envmxdIzc
$80/B8A1 AD CC 0F LDA $0FCC [$80:0FCC] A:00C0 X:0002 Y:0420 P:envmxdIzc
$80/B8A4 18 CLC A:0000 X:0002 Y:0420 P:envmxdIZc
$80/B8A5 6D CA 0F ADC $0FCA [$80:0FCA] A:0000 X:0002 Y:0420 P:envmxdIZc - ADC VRAM storage
$80/B8A8 8D B8 0F STA $0FB8 [$80:0FB8] A:6100 X:0002 Y:0420 P:envmxdIzc - Store valuea gain
$80/B8AB AD CC 0F LDA $0FCC [$80:0FCC] A:6100 X:0002 Y:0420 P:envmxdIzc
$80/B8AE 18 CLC A:0000 X:0002 Y:0420 P:envmxdIZc
$80/B8AF 69 20 00 ADC #$0020 A:0000 X:0002 Y:0420 P:envmxdIZc - ??? (Goes by intervals of 20)
$80/B8B2 8D CC 0F STA $0FCC [$80:0FCC] A:0020 X:0002 Y:0420 P:envmxdIzc
$80/B8B5 A9 00 00 LDA #$0000 A:0020 X:0002 Y:0420 P:envmxdIzc
$80/B8B8 8D BA 0F STA $0FBA [$80:0FBA] A:0000 X:0002 Y:0420 P:envmxdIZc
$80/B8BB 60 RTS A:0000 X:0002 Y:0420 P:envmxdIZc
2) Modify the code so that it draws each half twice. You'll need to modify the part of the code that increments the tile number that is printed to for this. This is why we relocated the code in 1a - it's easy to add another call. I made a diagram to see why you do this:
3) The first time the character (or half of character) is drawn, shift each row of pixels right by X. (On this step I usually leave X as a hardcoded value, like 3 or 4, so it's obvious if it works.) The second time each half is drawn, shift left by 8-X. Shifting should be done on the data in ROM, so it can be done outside of vblank. Copying must be done in vblank.
(Note: I'm not sure exactly how bitshifting works on SNES, but you'll need to pay attention to the bit depth of the graphics. If it were 1bpp, an 8 pixel row would be one byte, and you could just shift right once per pixel you wanted to shift. But if it were 2bpp, you'd have two bytes, and you'd need to shift twice, making sure to shift the leftover from the first byte into the second byte. I can post more details on the shifting if you have trouble.)
At this point you should have something similar to the diagram, but you'll only see the second half of the character, because we still have it overwriting the previously drawn data.
LSR A
ROR $00
A $00 c
1111111111111111 0000000000000000 ?
0111111111111111 0000000000000000 1 (after LSR)
0111111111111111 1000000000000000 0 (after ROR)
I do plan to cut the font down to 8x16 after I get a VWF in place. 16x16 is just way too ridiculously big for a semi-text heavy game. Rather fit as much dialogue as I can while still making it not and not a thousand boxes.
And yes, I should have explained further. It does exactly that. ROM --> VRAM being a 2bpp 16x16 font.
Modifying the 'A9 20 00' to 'A9 10 00' only loads the top/bottom left pieces of the font. Essentially 'Half' of it.
When it's being copied to RAM instead, would it literally copy the entire piece of the font used into ram using a decent amount of space? Or would it just be byte per byte transfer from RAM to VRAM?
2) Modify the code so that it draws each half twice. You'll need to modify the part of the code that increments the tile number that is printed to for this. This is why we relocated the code in 1a - it's easy to add another call. I made a diagram to see why you do this:
I'm really not sure how to go about this nor do I think I quite understand it fully.
Would bit shifting be using the ASL/LSR commands? I've heard the term used a lot but never actually 'knew' what was being fully said. Better to get it now while this is all in the works. So if we had to shift right twice it'd be 4A 4A in just plain ASM?
I kind of got a gist of the rest of the post but I think it'd be better for the moment if I focused on the top portion so I can actually understand/see what's going on with some of the modified code. It'd make it a lot easier to chunk everything together.
$80/BBB6 A9 20 00 LDA #$0020 A:6100 X:0000 Y:00C0
$80/BBE5 A9 20 00 LDA #$0020 A:6110 X:0000 Y:00C0 Loads top right/bottom right corner of letters (Both changed to A9 10 00 for half)
$80/B882 BD BC B8 LDA $B8BC,x[$80:B8BE] A:0002 X:0002 Y:0420 Pointers to each letter (Changed to accommodate for half letters)
$80/B8AF 69 20 00 ADC #$0020 A:0000 X:0002 Y:0420 VRAM storage/Spacing of letters (Changed to 08 so they're next to each other)
$80/B88C 0A ASL A A:0003 X:0000 Y:0420 Double's letter value (NOP'd)
$80/B895 69 00 00 ADC #$0000 A:0060 X:0000 Y:0420 ADC value for letter value (Changed to 69 10 00 to load correct letter value)
$80/B8AF 69 20 00 ADC #$0020 A:0000 X:0002 Y:0420
- The code here is what's doing the odd storage. Currently it's 08 so the letters are side by side. The normal value is 20. This is the VRAM Storage/Spacing of letters type.. thing.6100 6108 | 6120 6128 | ...
6110 6118 | 6130 6138 | ...
6100 | 6110 | 6120 | 6130 | ...
6108 | 6118 | 6128 | 6138 | ...
6100 | 6108 | 6110 | 6118 | ... | 61B8 (this is the rightmost tile of the first row)
--------------------------------------------
61C0 | 61C8 | 61D0 | 61D8 | ...
$7E/2296 BD 01 06 LDA $0601,x[$06:0601] A:0080 X:0000 Y:0000 P:eNvMXdIzc - Location to write on Layer 3
$7E/2299 8D 16 21 STA $2116 [$06:2116] A:00A1 X:0000 Y:0000 P:eNvMXdIzc
$7E/229C BD 02 06 LDA $0602,x[$06:0602] A:00A1 X:0000 Y:0000 P:eNvMXdIzc
$7E/229F 8D 17 21 STA $2117 [$06:2117] A:000A X:0000 Y:0000 P:envMXdIzc
$7E/22A2 BD 03 06 LDA $0603,x[$06:0603] A:000A X:0000 Y:0000 P:envMXdIzc
$7E/22A5 8D 05 43 STA $4305 [$06:4305] A:0002 X:0000 Y:0000 P:envMXdIzc
$7E/22A8 9C 06 43 STZ $4306 [$06:4306] A:0002 X:0000 Y:0000 P:envMXdIzc
$7E/22AB E8 INX A:0002 X:0000 Y:0000 P:envMXdIzc
$7E/22AC E8 INX A:0002 X:0001 Y:0000 P:envMXdIzc
$7E/22AD E8 INX A:0002 X:0002 Y:0000 P:envMXdIzc
$7E/22AE E8 INX A:0002 X:0003 Y:0000 P:envMXdIzc
$7E/22AF 8E 02 43 STX $4302 [$06:4302] A:0002 X:0004 Y:0000 P:envMXdIzc
$7E/22B2 A9 06 LDA #$06 A:0002 X:0004 Y:0000 P:envMXdIzc
$7E/22B4 8D 03 43 STA $4303 [$06:4303] A:0006 X:0004 Y:0000 P:envMXdIzc
$7E/22B7 9C 04 43 STZ $4304 [$06:4304] A:0006 X:0004 Y:0000 P:envMXdIzc
$7E/22BA A9 01 LDA #$01 A:0006 X:0004 Y:0000 P:envMXdIzc
$7E/22BC 8D 0B 42 STA $420B [$06:420B] A:0001 X:0004 Y:0000 P:envMXdIzc
$7E/22BF 8A TXA A:0001 X:0004 Y:0000 P:envMXdIzc
$7E/22C0 7D FF 05 ADC $05FF,x[$06:0603] A:0004 X:0004 Y:0000 P:envMXdIzc
$7E/22C3 B0 FE BCS $FE [$22C3] A:0006 X:0004 Y:0000 P:envMXdIzc
$7E/22C5 AA TAX A:0006 X:0004 Y:0000 P:envMXdIzc
$7E/22C6 E4 A5 CPX $A5 [$00:00A5] A:0006 X:0006 Y:0000 P:envMXdIzc
$7E/22C8 D0 C6 BNE $C6 [$2290] A:0006 X:0006 Y:0000 P:envMXdIZC
$7E/22CA 64 A5 STZ $A5 [$00:00A5] A:0006 X:0006 Y:0000 P:envMXdIZC
$7E/22A2 BD 03 06 LDA $0603,x[$06:0603] A:000A X:0000 Y:0000 P:envMXdIzc
$7E/22A5 8D 05 43 STA $4305 [$06:4305] A:0002 X:0000 Y:0000 P:envMXdIzc ;set transfer size (low byte)
$7E/22A8 9C 06 43 STZ $4306 [$06:4306] A:0002 X:0000 Y:0000 P:envMXdIzc ;set transfer size high byte to 0
$7E/22AB E8 INX A:0002 X:0000 Y:0000 P:envMXdIzc
$7E/22AC E8 INX A:0002 X:0001 Y:0000 P:envMXdIzc
$7E/22AD E8 INX A:0002 X:0002 Y:0000 P:envMXdIzc
$7E/22AE E8 INX A:0002 X:0003 Y:0000 P:envMXdIzc
$7E/22AF 8E 02 43 STX $4302 [$06:4302] A:0002 X:0004 Y:0000 P:envMXdIzc ;X+4 = low byte of source address
$7E/22B2 A9 06 LDA #$06 A:0002 X:0004 Y:0000 P:envMXdIzc ;high byte of source address = 6
$7E/22B4 8D 03 43 STA $4303 [$06:4303] A:0006 X:0004 Y:0000 P:envMXdIzc
$7E/22B7 9C 04 43 STZ $4304 [$06:4304] A:0006 X:0004 Y:0000 P:envMXdIzc ;bank byte of source = 0 (so read from RAM 00:06XX
$7E/22BA A9 01 LDA #$01 A:0006 X:0004 Y:0000 P:envMXdIzc
$7E/22BC 8D 0B 42 STA $420B [$06:420B] A:0001 X:0004 Y:0000 P:envMXdIzc ;do transfer
$7E/22BF 8A TXA A:0001 X:0004 Y:0000 P:envMXdIzc ;this is effectively increasing X by the amount of transferred data
$7E/22C0 7D FF 05 ADC $05FF,x[$06:0603] A:0004 X:0004 Y:0000 P:envMXdIzc
$7E/22C3 B0 FE BCS $FE [$22C3] A:0006 X:0004 Y:0000 P:envMXdIzc
$7E/22C5 AA TAX A:0006 X:0004 Y:0000 P:envMXdIzc
$7E/22C6 E4 A5 CPX $A5 [$00:00A5] A:0006 X:0006 Y:0000 P:envMXdIzc ;I'm assuming $A5 is the total amount of data to transfer
$7E/22C8 D0 C6 BNE $C6 [$2290] A:0006 X:0006 Y:0000 P:envMXdIZC
$7E/22CA 64 A5 STZ $A5 [$00:00A5] A:0006 X:0006 Y:0000 P:envMXdIZC
;bank byte of source = 0 (so read from RAM 00:06XX
$7E/22A2 BD 03 06 LDA $0603,x[$06:0603] A:000A X:0000 Y:0000 P:envMXdIzc
$7E/22A5 8D 05 43 STA $4305 [$06:4305] A:0002 X:0000 Y:0000 P:envMXdIzc ;set transfer size (low byte)
$7E/22A8 9C 06 43 STZ $4306 [$06:4306] A:0002 X:0000 Y:0000 P:envMXdIzc ;set transfer size high byte to 0
$7E/22AB E8 INX A:0002 X:0000 Y:0000 P:envMXdIzc
$7E/22AC E8 INX A:0002 X:0001 Y:0000 P:envMXdIzc
$7E/22AD E8 INX A:0002 X:0002 Y:0000 P:envMXdIzc
$7E/22AE E8 INX A:0002 X:0003 Y:0000 P:envMXdIzc
$7E/22AF 8E 02 43 STX $4302 [$06:4302] A:0002 X:0004 Y:0000 P:envMXdIzc ;X+4 = low byte of source address
$7E/22B2 A9 06 LDA #$06 A:0002 X:0004 Y:0000 P:envMXdIzc ;high byte of source address = 6
$7E/22B4 8D 03 43 STA $4303 [$06:4303] A:0006 X:0004 Y:0000 P:envMXdIzc
$7E/22B7 9C 04 43 STZ $4304 [$06:4304] A:0006 X:0004 Y:0000 P:envMXdIzc ;bank byte of source = 0 (so read from RAM 00:06XX) [ Makes it read from 7E0604)
$7E/22BA A9 01 LDA #$01 A:0006 X:0004 Y:0000 P:envMXdIzc
$7E/22BC 8D 0B 42 STA $420B [$06:420B] A:0001 X:0004 Y:0000 P:envMXdIzc ;do transfer
$7E/22BF 8A TXA A:0001 X:0004 Y:0000 P:envMXdIzc ;this is effectively increasing X by the amount of transferred data
$7E/22C0 7D FF 05 ADC $05FF,x[$06:0603] A:0004 X:0004 Y:0000 P:envMXdIzc
$7E/22C3 B0 FE BCS $FE [$22C3] A:0006 X:0004 Y:0000 P:envMXdIzc
$7E/22C5 AA TAX A:0006 X:0004 Y:0000 P:envMXdIzc
$7E/22C6 E4 A5 CPX $A5 [$00:00A5] A:0006 X:0006 Y:0000 P:envMXdIzc ;I'm assuming $A5 is the total amount of data to transfer
Do you know what a tilemap is, it's format, and how it works on the SNES? I'm not sure you understand exactly what you're looking for sometimes. A tilemap entry is always 2 bytes per tile. So, your single byte text letter is going to turn into a 2-byte tilemap entry. It's a simple conversion here as the game uses $49 $08 as the entry for the tilemap. I highly suggest using VSNES (http://www.romhacking.net/utilities/274/) to play around. It will tell you precisely where in VRAM the tilemap is for a given layer in any savestate with text on it. You can then edit the VRAM bytes of said tilemap to see what happens. If you understand how a screen is put together, this stuff is much simpler.
Your text is on layer 3. The tilemap is stored at effective VRAM location 0x1000. This DMA transfer handles transfer of a single 2-byte tilemap entry of 'I' from 7E:0604 to the specific address this tile entry goes at in the tilemap in VRAM. In this game, each tilemap entry gets transferred individually it seems.
I assume your actual text string has 0x49 only, right? If so, there's a small routine that turns that into 0x49 0x08 that gets stored at 7E:0604 for the tilemap entry. For VWF purposes, you're going to hijack that routine. You're no longer going to do that simple conversion anymore, and you won't be using the static font anymore that is stored in VRAM. You'll be building new dynamic tiles and make the tilemap entries point to those new tiles.
I'm not sure HOW it takes that value from VRAM and uses it to get the actual tile from VRAM.
$7E/212D A5 CE LDA $CE [$00:00CE] A:009F X:0000 Y:0200 P:eNvMxdIzc - Load tilemap data (Sets as $1000)
$7E/212F 8D 09 21 STA $2109 [$06:2109] A:000A X:0000 Y:0200 P:envMxdIzc - Stores
$7E/2132 A5 C7 LDA $C7 [$00:00C7] A:000A X:0000 Y:0200 P:envMxdIzc - Load tile base data
$7E/2134 8D 0C 21 STA $210C [$06:210C] A:0000 X:0000 Y:0200 P:envMxdIZc - Stores tile base data
All that's setting the Tile Base to $0000 in VRAM and then the tilemap to $1000. I think that's what I've seen anyway.
So it picks the letter '49' (I) from 7E0604. It's 49 08 now and that gets used as the index for tilemap entry and placement on screen basically?
Edit: Semi off topic in a way, but isn't Tilemap editing for a sprite basically it's Sprite Assembly? So isn't this essentially just a background layer assembly/construction to put into other terms?
The tile character data is stored at the address pointed to by registers
$210b-c, starting at byte address:
(Base<<13) + (TileNumber * 8*NumBitplanes)
Starting at the tilemap address, the first $800 bytes are for tilemap A. Then
come the $800 bytes for B, then C then D. Of course, if only A is required
something else could be stuck in the empty space.
210B/210C gets stored twice it seems. Each resulting in '11' as the byte.
So would it be like Tile Number = 49 * 8 * 2 = 490 (Which is actually where 'I' is stored in VRAM)That part is correct.
Does this apply to all background layers?
There is an $11 in $210b and $210C is $00. If you look at the details on those registers, you'll see there is a nibble for each of the 4 background layers tile bases. That's why BG3 and 4 have a base of $0000 and BG 1 and 2 have $2000.
Yes. That whole paragraph is a fancy way of saying the tilemap will vary in the size it takes in VRAM depending on the tilemap size you use for the background. Toggle the last two bits of $2109 to see the tilemap effects on that layer. The background size will change from 1 to 4 maps to make up the entire layer.
$7E/22A2 BD 03 06 LDA $0603,x[$06:0603] A:000A X:0000 Y:0000 P:envMXdIzc
$7E/22A5 8D 05 43 STA $4305 [$06:4305] A:0002 X:0000 Y:0000 P:envMXdIzc ;set transfer size (low byte)
$7E/22A8 9C 06 43 STZ $4306 [$06:4306] A:0002 X:0000 Y:0000 P:envMXdIzc ;set transfer size high byte to 0
$7E/22AB E8 INX A:0002 X:0000 Y:0000 P:envMXdIzc
$7E/22AC E8 INX A:0002 X:0001 Y:0000 P:envMXdIzc
$7E/22AD E8 INX A:0002 X:0002 Y:0000 P:envMXdIzc
$7E/22AE E8 INX A:0002 X:0003 Y:0000 P:envMXdIzc
$7E/22AF 8E 02 43 STX $4302 [$06:4302] A:0002 X:0004 Y:0000 P:envMXdIzc ;X+4 = low byte of source address
$7E/22B2 A9 06 LDA #$06 A:0002 X:0004 Y:0000 P:envMXdIzc ;high byte of source address = 6
$7E/22B4 8D 03 43 STA $4303 [$06:4303] A:0006 X:0004 Y:0000 P:envMXdIzc
$7E/22B7 9C 04 43 STZ $4304 [$06:4304] A:0006 X:0004 Y:0000 P:envMXdIzc ;bank byte of source = 0 (so read from RAM 00:06XX) [ Makes it read from 7E0604)
$7E/22BA A9 01 LDA #$01 A:0006 X:0004 Y:0000 P:envMXdIzc
$7E/22BC 8D 0B 42 STA $420B [$06:420B] A:0001 X:0004 Y:0000 P:envMXdIzc ;do transfer
$7E/22BF 8A TXA A:0001 X:0004 Y:0000 P:envMXdIzc ;this is effectively increasing X by the amount of transferred data
$7E/22C0 7D FF 05 ADC $05FF,x[$06:0603] A:0004 X:0004 Y:0000 P:envMXdIzc
$7E/22C3 B0 FE BCS $FE [$22C3] A:0006 X:0004 Y:0000 P:envMXdIzc
$7E/22C5 AA TAX A:0006 X:0004 Y:0000 P:envMXdIzc
$7E/22C6 E4 A5 CPX $A5 [$00:00A5] A:0006 X:0006 Y:0000 P:envMXdIzc ;I'm assuming $A5 is the total amount of data to transfer
So what I need to do is hijack the routine that basically loads 7E0604 and gets the Tilemap data, correct? So would I have to drop how it gets the value from VRAM and make it read from ROM instead. Then transfer that from ROM to RAM to VRAM?
$7E/2283 A9 01 LDA #$01 A:0006 X:0031 Y:0000 P:envMXdIzc
$7E/2285 8D 00 43 STA $4300 [$06:4300] A:0001 X:0031 Y:0000 P:envMXdIzc
$7E/2288 A9 18 LDA #$18 A:0001 X:0031 Y:0000 P:envMXdIzc
$7E/228A 8D 01 43 STA $4301 [$06:4301] A:0018 X:0031 Y:0000 P:envMXdIzc
$7E/228D 18 CLC A:0018 X:0031 Y:0000 P:envMXdIzc
$7E/228E A2 00 LDX #$00 A:0018 X:0031 Y:0000 P:envMXdIzc
$7E/2290 BD 00 06 LDA $0600,x[$06:0600] A:0018 X:0000 Y:0000 P:envMXdIZc
$7E/2293 8D 15 21 STA $2115 [$06:2115] A:0080 X:0000 Y:0000 P:eNvMXdIzc
$7E/2296 BD 01 06 LDA $0601,x[$06:0601] A:0080 X:0000 Y:0000 P:eNvMXdIzc
$7E/2299 8D 16 21 STA $2116 [$06:2116] A:00EA X:0000 Y:0000 P:eNvMXdIzc
$7E/229C BD 02 06 LDA $0602,x[$06:0602] A:00EA X:0000 Y:0000 P:eNvMXdIzc
$7E/229F 8D 17 21 STA $2117 [$06:2117] A:0008 X:0000 Y:0000 P:envMXdIzc
$7E/22A2 BD 03 06 LDA $0603,x[$06:0603] A:0008 X:0000 Y:0000 P:envMXdIzc
$7E/22A5 8D 05 43 STA $4305 [$06:4305] A:0002 X:0000 Y:0000 P:envMXdIzc ;set transfer size (low byte)
$7E/22A8 9C 06 43 STZ $4306 [$06:4306] A:0002 X:0000 Y:0000 P:envMXdIzc ;set transfer size high byte to 0
$7E/22AB E8 INX A:0002 X:0000 Y:0000 P:envMXdIzc
$7E/22AC E8 INX A:0002 X:0001 Y:0000 P:envMXdIzc
$7E/22AD E8 INX A:0002 X:0002 Y:0000 P:envMXdIzc
$7E/22AE E8 INX A:0002 X:0003 Y:0000 P:envMXdIzc
$7E/22AF 8E 02 43 STX $4302 [$06:4302] A:0002 X:0004 Y:0000 P:envMXdIzc ;X+4 = low byte of source address
$7E/22B2 A9 06 LDA #$06 A:0002 X:0004 Y:0000 P:envMXdIzc ;high byte of source address = 6
$7E/22B4 8D 03 43 STA $4303 [$06:4303] A:0006 X:0004 Y:0000 P:envMXdIzc
$7E/22B7 9C 04 43 STZ $4304 [$06:4304] A:0006 X:0004 Y:0000 P:envMXdIzc ;bank byte of source = 0 (so read from RAM 00:06XX) [ Makes it read from 7E0604 ]
$7E/22BA A9 01 LDA #$01 A:0006 X:0004 Y:0000 P:envMXdIzc
$7E/22BC 8D 0B 42 STA $420B [$06:420B] A:0001 X:0004 Y:0000 P:envMXdIzc ;do transfer
$7E/22BF 8A TXA A:0001 X:0004 Y:0000 P:envMXdIzc ;this is effectively increasing X by the amount of transferred data
$7E/22C0 7D FF 05 ADC $05FF,x[$06:0603] A:0004 X:0004 Y:0000 P:envMXdIzc
$7E/22C3 B0 FE BCS $FE [$22C3] A:0006 X:0004 Y:0000 P:envMXdIzc
$7E/22C5 AA TAX A:0006 X:0004 Y:0000 P:envMXdIzc
$7E/22C6 E4 A5 CPX $A5 [$00:00A5] A:0006 X:0006 Y:0000 P:envMXdIzc - Check for background scroll
$7E/22C8 D0 C6 BNE $C6 [$2290] A:0006 X:0006 Y:0000 P:envMXdIZC
$7E/22CA 64 A5 STZ $A5 [$00:00A5] A:0006 X:0006 Y:0000 P:envMXdIZC
$40/A010 A9 18 LDA #$18 A:0000 X:0000 Y:000B P:envMXdIZc
$40/A012 8D 01 43 STA $4301 [$06:4301] A:0018 X:0000 Y:000B P:envMXdIzc
$40/A015 A9 01 LDA #$01 A:0018 X:0000 Y:000B P:envMXdIzc
$40/A017 8D 00 43 STA $4300 [$06:4300] A:0001 X:0000 Y:000B P:envMXdIzc
$40/A01A A9 80 LDA #$80 A:0001 X:0000 Y:000B P:envMXdIzc
$40/A01C 8D 15 21 STA $2115 [$06:2115] A:0080 X:0000 Y:000B P:eNvMXdIzc
$40/A01F C2 21 REP #$21 A:0080 X:0000 Y:000B P:eNvMXdIzc
$40/A021 A9 00 01 LDA #$0100 A:0080 X:0000 Y:000B P:eNvmXdIzc ;VRAM store location
$40/A024 8D 16 21 STA $2116 [$06:2116] A:0100 X:0000 Y:000B P:envmXdIzc
$40/A027 A9 10 00 LDA #$0010 A:0100 X:0000 Y:000B P:envmXdIzc ;How many bytes to transfer
$40/A02A 8D 05 43 STA $4305 [$06:4305] A:0010 X:0000 Y:000B P:envmXdIzc
$40/A02D A9 10 02 LDA #$0210 A:0010 X:0000 Y:000B P:envmXdIzc ;2-byte Base Pointer to read from
$40/A030 8D 02 43 STA $4302 [$06:4302] A:0210 X:0000 Y:000B P:envmXdIzc
$40/A033 E2 20 SEP #$20 A:0210 X:0000 Y:000B P:envmXdIzc
$40/A035 A9 7E LDA #$7E A:0210 X:0000 Y:000B P:envMXdIzc ;Bank to read from (Results in 7E:0210)
$40/A037 8D 04 43 STA $4304 [$06:4304] A:027E X:0000 Y:000B P:envMXdIzc
$40/A03A A9 01 LDA #$01 A:027E X:0000 Y:000B P:envMXdIzc
$40/A03C 8D 0B 42 STA $420B [$06:420B] A:0201 X:0000 Y:000B P:envMXdIzc
$40/A03F 6B RTL A:0201 X:0000 Y:000B P:envMXdIzc
02 7E 1C 7C 7A 06 7C 1C 70 10 02 7E 7E 7E 00 00
- This is what's currently at 7E:0210 as an example. But VRAM just consistently keeps storing 00 00 00 00 00 00
waitforvblank:
lda $4212
bpl waitforvblank
The biggest limitation is speed. Rendering an entire screen full of item names at 2bpp on a 2.68MHz CPU is indeed painful. Combined with limited Vblank time to transfer the tile data, you can find yourself needing up to 2000ms to render a full screen. And during this time, you will see the new items slowly replacing old items as you flip through screens, with significant lag.
When you are requested to write an item into the tile map, simply ensure that you are in Vblank, index into your block of all pre-rendered item names, and then DMA it over. This takes about one scanline per item.
What the article means is rendering all of the menus and items once ahead of time, and storing the results in ROM. Then you simply DMA them like pre-rendered graphics when you need them. That's how you could do a VWF 8x8 menu in 2 frames.
That almost sounds like 'faking' a VWF by using the graphics tiles in ROM as different 8x8 blocks.
I didn't think you could store the data straight INTO ROM though and use it from there.
I'd prefer to go the straight up route of having it pull the letters from one font set instead of multiples.That would be only useful for screens with intensive lag due to shifting. Otherwise you probably don't need it.
So then if I understand any of this correctly: It grabs the font graphics, shifts it to the left and repeats the process until it hits the end of the 'width'. Once it does, if there's another letter or anything after, it ORs it so it can merge the two bits together after that space?It reads, left shifts, ORs and writes when you push a tile to merge, then it simply reads, right shifts and writes if you have graphics left from a previous tile. In other words: x%8 != 0 -> read+left shift+or+write, otherwise read and write; data left from tile? Read+right shift+write.
data left from tile? Read+right shift+write.
It's slighter easier if you use 16 bits words. But maybe SNES has not 16 bits data registers ?
I do not agree with Gemini about 1bpp.Technically speaking 1 BPP is not that much useful, even for code simplicity reasons. Sure, you do less shifting as you only deal with one plane, but you still need to upscale to 2 BPP at some point, which is trivial and only required when your font is really huge with little room left for storage. In the end it doesn't provide any usefulness, it's only extra steps, more code, and slower performance when you need a huge bulk of stuff to be rendered at once.
I always use 1bpp because I can make my VWF code simpler and more to-the-point without trying to combine (and debug!) two tasks together.
I don't even know if the "shadow" part applies to Justin's game, but even if it does, I'd ignore for the time being until the core problem is understood, and then we work out the other details later (such as the one at the end of my "Lesson 1" example).
$83/99ED 22 40 ED 83 JSL $83ED40[$83:ED40] A:001A X:9B73 Y:006D P:envMxdIzC
$83/ED40 85 02 STA $02 [$00:0002] A:001A X:9B73 Y:006D P:envMxdIzC ;Store current letter to 7E:0002
$83/ED42 A9 7F LDA #$7F A:001A X:9B73 Y:006D P:envMxdIzC ;Set bank to be $7F
$83/ED44 48 PHA A:007F X:9B73 Y:006D P:envMxdIzC
$83/ED45 AB PLB A:007F X:9B73 Y:006D P:envMxdIzC
$83/ED46 C2 30 REP #$30 A:007F X:9B73 Y:006D P:envMxdIzC
$83/ED48 A5 02 LDA $02 [$00:0002] A:007F X:9B73 Y:006D P:envmxdIzC ;Load current letter
$83/ED4A 29 FF 00 AND #$00FF A:001A X:9B73 Y:006D P:envmxdIzC ;AND value
$83/ED4D 85 02 STA $02 [$00:0002] A:001A X:9B73 Y:006D P:envmxdIzC ;Store back to 7E:0002
$83/ED4F A0 00 00 LDY #$0000 A:001A X:9B73 Y:006D P:envmxdIzC ;Set Y to 0000
$83/ED52 20 70 ED JSR $ED70 [$83:ED70] A:001A X:9B73 Y:0000 P:envmxdIZC ;Load 'Letter Writing' routine
$83/ED70 A5 02 LDA $02 [$00:0002] A:001A X:9B73 Y:0000 P:envmxdIZC ;Load current letter
$83/ED72 38 SEC A:001A X:9B73 Y:0000 P:envmxdIzC ;Set carry flag
$83/ED73 E9 10 00 SBC #$0010 A:001A X:9B73 Y:0000 P:envmxdIzC ;Subtract 10 from accumulator
$83/ED76 85 02 STA $02 [$00:0002] A:000A X:9B73 Y:0000 P:envmxdIzC ;Store value back to 7E:0002
$83/ED78 0A ASL A A:000A X:9B73 Y:0000 P:envmxdIzC ;Double accumulator
$83/ED79 0A ASL A A:0014 X:9B73 Y:0000 P:envmxdIzc ;Double accumulator
$83/ED7A 0A ASL A A:0028 X:9B73 Y:0000 P:envmxdIzc ;Double accumulator
$83/ED7B 0A ASL A A:0050 X:9B73 Y:0000 P:envmxdIzc ;Double accumulator
$83/ED7C 18 CLC A:00A0 X:9B73 Y:0000 P:envmxdIzc ;Clear carry flag
$83/ED7D 69 00 F2 ADC #$F200 A:00A0 X:9B73 Y:0000 P:envmxdIzc ;Add #$F200 current accumulator value
$83/ED80 AA TAX A:F2A0 X:9B73 Y:0000 P:eNvmxdIzc ;Transfer A to X
$83/ED81 BF 00 00 81 LDA $810000,x[$81:F2A0] A:F2A0 X:F2A0 Y:0000 P:eNvmxdIzc ;Load letter graphics
$83/ED85 99 00 FF STA $FF00,y[$7F:FF00] A:0606 X:F2A0 Y:0000 P:envmxdIzc ;Store to 7F:FF00 (Loops until Y is 8)
$83/ED88 E8 INX A:0606 X:F2A0 Y:0000 P:envmxdIzc ;Increase X
$83/ED89 E8 INX A:0606 X:F2A1 Y:0000 P:eNvmxdIzc ;Increase X
$83/ED8A C8 INY A:0606 X:F2A2 Y:0000 P:eNvmxdIzc ;Increase Y
$83/ED8B C8 INY A:0606 X:F2A2 Y:0001 P:envmxdIzc ;Increase Y
$83/ED8C C0 08 00 CPY #$0008 A:0606 X:F2A2 Y:0002 P:envmxdIzc ;Check if Y is 08
$83/ED8F D0 F0 BNE $F0 [$ED81] A:0606 X:F2A2 Y:0002 P:eNvmxdIzc ;If not, send back to loading letter graphics.
$83/ED91 60 RTS A:2626 X:F2A8 Y:0008 P:envmxdIZC
$83/ED55 20 A0 ED JSR $EDA0 [$83:EDA0] A:2626 X:F2A8 Y:0008 P:envmxdIZC ;Load routine to grab the width of letter
$83/EDA0 A5 02 LDA $02 [$00:0002] A:2626 X:F2A8 Y:0008 P:envmxdIZC ;Load current letter
$83/EDA2 AA TAX A:000A X:F2A8 Y:0008 P:envmxdIzC ;Transfer A to X
$83/EDA3 BF 40 EE 83 LDA $83EE40,x[$83:EE4A] A:000A X:000A Y:0008 P:envmxdIzC ;Load width of letter from table
$83/EDA7 29 FF 00 AND #$00FF A:FF07 X:000A Y:0008 P:eNvmxdIzC ;AND
$83/EDAA 85 02 STA $02 [$00:0002] A:0007 X:000A Y:0008 P:envmxdIzC ;Store back to 7E:0002
$83/EDAC A2 00 00 LDX #$0000 A:0007 X:000A Y:0008 P:envmxdIzC ;Set X to 0000
$83/EDAF 60 RTS A:0007 X:0000 Y:0008 P:envmxdIZC
$83/ED58 20 B0 ED JSR $EDB0 [$83:EDB0] A:0007 X:0000 Y:0008 P:envmxdIZC ;Load routine to shift/merge letters.
$83/EDB0 A0 00 00 LDY #$0000 A:0007 X:0000 Y:0008 P:envmxdIZC ;Set Y to 0000
$83/EDB3 E2 20 SEP #$20 A:0007 X:0000 Y:0000 P:envmxdIZC
$83/EDB5 AD F0 FE LDA $FEF0 [$7F:FEF0] A:0007 X:0000 Y:0000 P:envMxdIZC ;Load PixelOffset
$83/EDB8 F0 36 BEQ $36 [$EDF0] A:0000 X:0000 Y:0000 P:envMxdIZC ;Go to 83:EDF0 if value is 00
$83/EDF0 BD 00 FF LDA $FF00,x[$7F:FF00] A:0000 X:0000 Y:0000 P:envMxdIZC ;Load Font workspace
$83/EDF3 1D 10 FF ORA $FF10,x[$7F:FF10] A:0006 X:0000 Y:0000 P:envMxdIzC ;OR VWF workspace
$83/EDF6 9D 10 FF STA $FF10,x[$7F:FF10] A:0006 X:0000 Y:0000 P:envMxdIzC ;Store to VWF workspace
$83/EDF9 E8 INX A:0006 X:0000 Y:0000 P:envMxdIzC ;Increase X
$83/EDFA E0 10 00 CPX #$0010 A:0006 X:0001 Y:0000 P:envMxdIzC ;Check if X is 10, if not, send back to 'Load Font workspace'
$83/EDFD D0 F1 BNE $F1 [$EDF0] A:0006 X:0001 Y:0000 P:eNvMxdIzc
$83/EDFF A5 02 LDA $02 [$00:0002] A:0000 X:0010 Y:0000 P:envMxdIZC ;Load width of letter
$83/EE01 18 CLC A:0007 X:0010 Y:0000 P:envMxdIzC ;Clear carry flag
$83/EE02 6D F0 FE ADC $FEF0 [$7F:FEF0] A:0007 X:0010 Y:0000 P:envMxdIzc ;Add PixelOffset to current value
$83/EE05 8D F0 FE STA $FEF0 [$7F:FEF0] A:0007 X:0010 Y:0000 P:envMxdIzc ;Store back to PixelOffset
$83/EE08 60 RTS A:0007 X:0010 Y:0000 P:envMxdIzc
$83/ED5B A9 83 LDA #$83 A:0007 X:0010 Y:0000 P:envMxdIzc ;Set bank back to #$83 after the entire routine is done
$83/ED5D 48 PHA A:0083 X:0010 Y:0000 P:eNvMxdIzc
$83/ED5E AB PLB A:0083 X:0010 Y:0000 P:eNvMxdIzc
$83/ED5F 6B RTL A:0083 X:0010 Y:0000 P:eNvMxdIzc
$83/EDBA 85 04 STA $04 [$00:0004] A:0007 X:0000 Y:0000 P:envMxdIzC (This is when 7F:FEF0 =/= 00) ;Stores Pixeloffset to 7E:0004
$83/EDBC 64 05 STZ $05 [$00:0005] A:0007 X:0000 Y:0000 P:envMxdIzC ;Set 7E:0005 to 00
$83/EDBE 5E 00 FF LSR $FF00,x[$7F:FF00] A:0007 X:0000 Y:0000 P:envMxdIzC ;LSR 7F:FF00
$83/EDC1 7E 08 FF ROR $FF08,x[$7F:FF08] A:0007 X:0000 Y:0000 P:envMxdIzc ;Shift right to 7F:FF08
$83/EDC4 E8 INX A:0007 X:0000 Y:0000 P:envMxdIZc ;Increase X
$83/EDC5 C8 INY A:0007 X:0001 Y:0000 P:envMxdIzc ;Increase Y
$83/EDC6 C4 04 CPY $04 [$00:0004] A:0007 X:0001 Y:0001 P:envMxdIzc ;Check if Y is == to Pixeloffset
$83/EDC8 D0 F4 BNE $F4 [$EDBE] A:0007 X:0001 Y:0001 P:eNvMxdIzc ;If not, send back to LSR 7F:FF00
$83/EDCA A2 00 00 LDX #$0000 A:0007 X:0007 Y:0007 P:envMxdIZC ;Set X to 0000
$83/EDCD BD 00 FF LDA $FF00,x[$7F:FF00] A:0007 X:0000 Y:0007 P:envMxdIZC ;Load Font workspace
$83/EDD0 1D 10 FF ORA $FF10,x[$7F:FF10] A:0010 X:0000 Y:0007 P:envMxdIzC ;OR with VWF workspace
$83/EDD3 9D 1F FF STA $FF1F,x[$7F:FF1F] A:0016 X:0000 Y:0007 P:envMxdIzC ;Store to area to be transfered
$83/EDD6 E8 INX A:0016 X:0000 Y:0007 P:envMxdIzC ;Increase X
$83/EDD7 E0 10 00 CPX #$0010 A:0016 X:0001 Y:0007 P:envMxdIzC ;Check if X == 10
$83/EDDA D0 F1 BNE $F1 [$EDCD] A:0016 X:0001 Y:0007 P:eNvMxdIzc ;If not, send back to 'Load Font workspace'
$83/EDDC 80 21 BRA $21 [$EDFF] A:0016 X:0010 Y:0007 P:envMxdIZC ;Always Branch to 83:EDFF to set PixelOffset to what it should be
I'll worry about making the font 2bpp after I get a grasp of understanding on this at the moment. It's not too big of a deal right now, more-so understanding is the key.Barely a change. You simply loop twice the height of a tile in 2 BPP. SNES formats make it simple for you, so I guess you can even easily upgrade.
A similar case appears when the game caches text glyphs on demand and renders as individual sprites
ABCDEFGHIJKLMNO
abcdefghijklmno
Except this massive spacing between the letters.you need to change the incremental spacing to be proportional and possibly hack in a static font rather than cache on demand.It's the part of finding the code responsible for the spacing that is making this difficult for me.
EDIT: Can anyone tell me if this font is the PSX's internal BIOS font? It sure does look like it to me...It looks like it to me.
It's the part of finding the code responsible for the spacing that is making this difficult for me.Usually you monitor primitives via pSX's debugger and GPU capture, find a text sprite primitive, and add a write breakpoint to its xy coordinates. Unless the game uses an abstraction layer such as libgs, that should give you the whereabouts of text sprite fillers and somewhere close by the spacing line.
I don't know where to start to find it. It could be either hardcoded or have data in a file controlling each characters spacing. (which I doubt for this case, since they all use the same spacing.)
Is there a place I should put a breakpoint that (in most cases) should take me to the code responsible for it? If so, where?
As of right now, I can't see why having the full font loaded into VRAM would be beneficial to this. Maybe I will find out as I investigate more. Could you explain the benefit of having it always in VRAM as oppose to having just what is currently needed?Using a precached font is the way to go with any English translation for three reasons:
if((CurrentPrintedLetter == 'A') & (NextLetterToBePrinted == 'B'))
{
// Customize the 'B' coordinates to make it squeeze in close next to 'A'
}