FC 魂斗罗汉化日记 (第四集)
第四集 - 标题界面的游戏介绍
(目录)
当你在标题界面什么都不干的时候,会使用打字特效介绍「魂斗罗」这个词的含义:
若显示完毕之后还是没有操作,则会跳转到游戏试玩界面。
用 YY-CHR 以及 FCEUX 的 PPU 查看器查看:
当年的 ROM 卡槽相对来讲还是比较贵的,估计这也是为什么开发者选择了压缩图像。压缩的实现原理很简单:FC 对区块可以设定调色板,每个调色板可以选择四种颜色。一个背景色,一个共用色,以及两个独立的颜色。通过利用调色板的特性,可以储存双倍的单色图片/文字。
因为我不会操纵屏幕上的调色板,于是我选择把中文字模全部使用共用色导入到游戏内:
打开游戏观察:
从 Name Table 可以看出,“乃”这个文字的贴图编码为 02 03 12 13
。
在 Rom 内也能够正常搜索到结果:
但是,从这里开始到结束位置的字符数目对不上,于是回到 FCEUX 的调试器,针对写出屏幕下断 (第一个“乃”字的左上角地址为 $2114
):
断下后发现:这不还是从 $0700
读缓冲区后写出嘛,
PrintNextChar:
>07:CB9B:8D 07 20 STA $2007 = #$00
07:CB9E:B9 00 07 LDA $0700,Y @ $0704 = #$03
07:CBA1:C8 INY
07:CBA2:C9 FF CMP #$FF
07:CBA4:D0 F5 BNE PrintNextChar
地址 内存内容
0700 01 21 14 02 03 FF 01 21 34 12 13 FF
继续,对 0703
下写入断点,看看数据怎么来的:
04:906F:B9 57 91 LDA $9157,Y @ $915F = #$02
>04:9072:9D 03 07 STA $0703,X @ $0703 = #$02
04:9075:B9 58 91 LDA $9158,Y @ $9160 = #$03
04:9078:9D 04 07 STA $0704,X @ $0704 = #$03
缕一缕… 简单来说,程序从 $915F
读数据然后写到 $0703
,而这里存放着之前搜到的内容;
点 Step Out
跳出函数,看上面一行的内容定位函数地址为 $9034
,因此在这里下断。
重启游戏,运行,发现经过此函数的时候,寄存器的内容依次为:00 12 13 12 11
。
到文件搜索,发现这行内容刚好在刚才搜到的数据前面,数据如下:
00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
00011140 00 12 13 12 11 42 42 C3 04 05 06 07 22 08 09
00011150 09 0A 0A AB 0C 0C 05 04 0B 23 0D 0D 0B 0E 0E AB
00011160 0F 0F 08 10 10 81 FF
把数据与游戏的文字并列查看,效果如下:
00 | 12 | 13 | 12 | 11 | 42 | 42 | C3 | ||||
「 | 魂 | 斗 | 羅 | 」 | と | は | 、 | ||||
04 | 05 | 06 | 07 | 22 | 08 | 09 | 09 | 0A | 0A | AB | |
熱 | い | 斗 | 魂 | と | ゲ | リ | ラ | 戦 | 術 | の | |
0C | 0C | 05 | 04 | 0B | 23 | 0D | 0D | 0B | 0E | 0E | AB |
素 | 質 | を | 持 | つ | 、 | 最 | 強 | の | 闘 | 士 | の |
0F | 0F | 08 | 10 | 10 | 81 | FF | |||||
呼 | 称 | で | あ | る | 。 |
而出现重复字符代码的地方,则刚好在相应的帖图块里包含这两个字符。
至于换行,通过观察换行处的字符,可以看见其二进制码的第一位都是 1
。
使用字库工具生成图库想办法导入到 rom,然后调整文字颜色为公用色。
最后,就是喜闻乐见的代码修改了:
; JSR $9034
; 012DD0:FF UNDEFINED
; 04:ADC0:FF UNDEFINED
.org $ADC0
LDA $0008
AND #$40
BNE _LARGE_LETTER ; 如果是大字就跳 (24x24)
LDA $0008
ASL ; A <<= 2 (字符 * 4)
ASL
AND #$7F
TAY ; Y = A
; A = (a * 4 overflow) ? 20 : 0
; Offset = A
LDA $0008 ; A = [0008]
AND #$20 ; 20 表示写出位置 + 20
CLC
; 坐标~
ADC $0042
STA $0000
LDA #$00
ADC $0043
STA $0001
; Load x offset.
LDX $0021
LDA #$01
STA $0700,X
STA $0706,X
; 写出坐标
LDA $0000
STA $0702,X
CLC
ADC #$20
STA $0708,X
LDA $0001
STA $0701,X
ADC #$00
STA $0707,X
LDA _TITLE_CHAR_TABLE + 0, Y
STA $0703,X
LDA _TITLE_CHAR_TABLE + 1, Y
STA $0704,X
LDA _TITLE_CHAR_TABLE + 2, Y
STA $0709,X
LDA _TITLE_CHAR_TABLE + 3, Y
STA $070A,X
LDA #$FF
STA $0705,X
STA $070B,X
TXA ; A = X
CLC
ADC #$0C ; A += 0x0C
STA $0021 ; Write x-offset
; 向右移动两个字节
LDA $0042
CLC
ADC #$02
STA $0042
RTS
_LARGE_LETTER:
LDA $0008
CLC
SBC #$40
STA $0000
ASL
ASL
ASL
CLC
ADC $0000
TAY ; Y = A
LDA $0042
CLC
ADC #$20
STA $0000
LDA $0043
ADC #$00
STA $0001
LDX $0021
LDA #$01
STA $0700,X
STA $0707,X
STA $070E,X
LDA $0042
STA $0702,X
LDA $0043
STA $0701,X
LDA $0000
STA $0709,X
CLC
ADC #$20
STA $0710,X
LDA $0001
STA $0708,X
ADC #$00
STA $070F,X
LDA $919B,Y
STA $0703,X
LDA $919C,Y
STA $0704,X
LDA $919D,Y
STA $0705,X
LDA $919E,Y
STA $070A,X
LDA $919F,Y
STA $070B,X
LDA $91A0,Y
STA $070C,X
LDA $91A1,Y
STA $0711,X
LDA $91A2,Y
STA $0712,X
LDA $91A3,Y
STA $0713,X
LDA #$FF
STA $0706,X
STA $070D,X
STA $0714,X
TXA
CLC
ADC #$15
STA $0021
LDA $0042
CLC
ADC #$03
STA $0042
RTS
_TITLE_CHAR_TABLE:
.byte $0,$1,$10,$11
.byte $2,$3,$12,$13
.byte $4,$5,$14,$15
.byte $6,$7,$16,$17
.byte $8,$9,$18,$19
.byte $a,$b,$1a,$1b
.byte $c,$d,$1c,$1d
.byte $e,$f,$1e,$1f
.byte $20,$21,$30,$31
.byte $22,$23,$32,$33
.byte $24,$25,$34,$35
.byte $26,$27,$36,$37
.byte $28,$29,$38,$39
.byte $2a,$2b,$3a,$3b
; 前引号
; .byte $2c,$2d,$3c,$3d
.byte $0B,$00,$00,$00
; 逗号
; .byte $2e,$2f,$3e,$3f
.byte $00,$00,$1B,$00
; 句号 (10)
; .byte $40,$41,$50,$51
.byte $00,$00,$0A,$00
; 之 (11)
.byte $F7,$F8,$F9,$FA
; 名
.byte $FB,$FC,$FD,$FE
.byte $46,$47,$56,$57
.byte $48,$49,$58,$59
.byte $4a,$4b,$5a,$5b
.byte $4c,$4d,$5c,$5d
.byte $4e,$4f,$5e,$5f
.byte $60,$61,$70,$71
.byte $62,$63,$72,$73
.byte $64,$65,$74,$75
.byte $66,$67,$76,$77
.byte $68,$69,$78,$79
.byte $6a,$6b,$7a,$7b
.byte $6c,$6d,$7c,$7d
.byte $6e,$6f,$7e,$7f
编译后,把翻译后的数据也一并回写到游戏里看看:
完成啦~