Skip to content

Instantly share code, notes, and snippets.

@JixunMoe JixunMoe/04,AB68.s
Last active Aug 8, 2016

Embed
What would you like to do?
Contra Chinese Translation Assembly Code.
; ROM 位置: 012B78 (04:AB68)
; 原始函数: LoadNextChar
; LoadNextChar (01180D / 04:97FD): JMP AB68
.org $AB68
; LoadNextChar
; 04,AB68
; byte[0043] 等待帧数, 如果不是 0 则跳出
DEC $0043
BNE _END
LDA #$08
STA $0043
; byte [0046] = 当前对话文字指针偏移
LDA $0046
ASL ; Shift left
TAY
; WORD [9848] = 对话文字指针
LDA $9848,Y ; WORD: 0x4E 0x98 (984E)
STA $0002 ;
LDA $9849,Y ;
STA $0003 ;
; byte [0047] = 当前对话文字偏移
LDY $0047 ; Y = [0047] (01)
INC $0047 ; [0047]++
LDA ($02),Y ; A = _THE_CHR
; 控制符检测
CMP #$FF
BEQ _END_WITH_CARRY
CMP #$FE
BNE _SKIP_LINE_BREAK
; 换行符号
INC $0048 ; Y Position?
JSR _UpdatePosition
_READ_NEXT_CHAR:
LDY $0047
INC $0047
LDA ($02),Y
jmp _END_CONTROL_CHAR
_SKIP_LINE_BREAK:
CMP #$FD
BNE _SKIP_ENABLE_CHINESE
LDA #$01
STA $07EE
jmp _READ_NEXT_CHAR
_SKIP_ENABLE_CHINESE:
_END_CONTROL_CHAR:
STA $0008
CMP #$00
BEQ _SKIP_NO_SOUND
AND #$C0
CMP #$C0
BEQ _SKIP_NO_SOUND
LDA #$0E
JSR $F9BC
_SKIP_NO_SOUND:
JSR PutNextDialogChar
; 因为是中文, 到时候看情况是否需要加延迟。
;LDA $0008
;BPL _END
LDA #$0C
STA $0043
_END:
CLC
RTS
_END_WITH_CARRY:
; 清空中文标记
LDA #$00
STA $07EE
SEC
RTS
PutNextDialogChar:
LDX $0021 ; X = [0021]; Offset, usually 0x00.
; 写出信息标记?
LDA #$01 ; A = 0x01
STA $0700,X ; [0700] = 0x01
; 写出位置
LDA $004A ; A = [004A]
STA $0701,X ; [0701] = A
LDA $0049 ; A = [0049]
STA $0702,X ; [0702] = A
; LDY $0047 ; 还原当前对话的偏移
; Loop - 检查中文字符
_Loop_SearchForChinese:
LDA ($02),Y ; A = 当前字符
AND #$C0 ; 检查第一位是不是 1
CMP #$C0 ; 中文控制符
BNE _END_CHINESE; 跳过中文字符处理
; 是中文控制符
; 加入两个字符,并,自循环
; 写出 2 个控制符
TXA ;
PHA ; push X
LDA ($02),Y ; A = ChineseCtrlChar
AND #$7 ;
TAX ; X = A
INY ; Y++
; 此时的 stack: X
; 此时的值: X = PPU 序号
; Y = 正常的序号
LDA ($02),Y ; A = NextChar
STA $07F0,X ; [07FX] = A (CHR_BANK_X)
INY ; Y++
PLA
TAX ; pop X
STY $0047 ; 储存对话偏移
INC $0047
JSR $FACE
JMP _Loop_SearchForChinese
_END_CHINESE:
LDA ($02),Y
STA $0703,X ; [0704] = A
LDA #$FF ; A = __END_MARK__
STA $0704,X ; [0705] = A
TXA ; A = X
CLC ; Clear Carry
ADC #$05 ; Add 06 to A
STA $0021 ; [0021] = A
INC $0049 ; [0049]++
RTS
_UpdatePosition:
; 读取下一行的位置的偏移地址
LDA $0046
ASL
TAY
LDA $97DB,Y
STA $0000
LDA $97DC,Y
STA $0001
; 写出 PPU 定位地址
LDA $0048
ASL
TAY
LDA ($00),Y
STA $0049
INY
LDA ($00),Y
STA $004A
RTS
; 012C70:FF UNDEFINED
; 04:AC60:FF UNDEFINED
PlaceNextDialogPassChar:
.org $AC60
DEC $0047
BEQ _DO_PROC
_EXIT_WITH_CARRY:
CLC
RTS
_DO_PROC:
LDA #$06 ; A = 06
; byte [0047] = 当前对话文字偏移
STA $0047 ; [0047] = 06
LDA $0030 ; A = [0030]
ASL ; A <<= 1
TAY ; Y = A
LDA $A1D6,Y ;
STA $0000 ;
LDA $A1D7,Y ;
STA $0001 ;
LDY $0046 ; Y = [0046]
LDA ($00),Y ; 读取下一个要打印的字符
CMP #$FF ; 如果是结束符, 跳走
BNE _CONTINUE_EXECUTE
LDA #$00
STA $07EE
SEC
RTS
_CONTINUE_EXECUTE:
STA $0008 ; [0008] = A
CMP #$FE
BNE _SKIP_LINE_BREAK
INY
JSR _NEXT_LINE
JMP _END_OF_CONTROL_CHAR
_SKIP_LINE_BREAK:
CMP #$FD
BNE _SKIP_ENABLE_CHINESE
LDA #$02
STA $07EE
_LOAD_NEXT_CHAR:
INY
INC $0046
JMP _END_OF_CONTROL_CHAR
_SKIP_ENABLE_CHINESE:
CMP #$FC
BNE _SKIP_CLEAR_SCREEN
JSR _CLEAR_DIALOG
LDA #$20 ; TODO: 清屏后的等待时间
_SET_TIMER_AND_EXIT_WITH_CARRY:
STA $0047
INC $0046
JMP _EXIT_WITH_CARRY
_SKIP_CLEAR_SCREEN:
CMP #$FB
BNE _SKIP_WAIT_TIMER
LDA #$80 ; TODO: 清屏后的等待时间
JMP _SET_TIMER_AND_EXIT_WITH_CARRY
_SKIP_WAIT_TIMER:
_END_OF_CONTROL_CHAR:
LDX $0021 ; X = [0021]
LDA #$01 ; 需要写出文字标记
STA $0700,X
LDA $004B ; 写出位置
STA $0701,X
LDA $004A
STA $0702,X
; Loop - 检查中文字符
_Loop_SearchForChinese:
LDA ($00),Y ; A = 当前字符
AND #$C0 ; 检查第一位是不是 1
CMP #$C0 ; 中文控制符
BNE _END_CHINESE; 跳过中文字符处理
; 是中文控制符
; 加入两个字符,并,自循环
; 写出 2 个控制符
TXA ;
PHA ; push X
LDA ($00),Y ; A = ChineseCtrlChar
AND #$7 ;
TAX ; X = A
INY ; Y++
; 此时的 stack: X
; 此时的值: X = PPU 序号
; Y = 正常的序号
LDA ($00),Y ; A = NextChar
STA $07F0,X ; [07FX] = A (CHR_BANK_X)
INY ; Y++
PLA
TAX ; pop X
STY $0046 ; 储存对话偏移
INC $0046
JSR $FACE
JMP _Loop_SearchForChinese
_END_CHINESE:
LDA ($00),Y ; 写出需要处理的字符
STA $0703,X
BEQ _SKIP_NO_SOUND ; if char == 0 jump
AND #$C0
CMP #$C0
BEQ _SKIP_NO_SOUND
LDA #$10 ; Play sound
JSR $F9BC
_SKIP_NO_SOUND:
LDA #$FF
STA $0704,X ; 结束符号
TXA ; A = X
CLC
ADC #$05
STA $0021
INY
STY $0046 ; 储存下一个偏移
INC $004A
LDA $0008
_EXIT:
CLC
RTS
; 清空屏幕字符
_CLEAR_DIALOG:
JSR _RESET_POSITION
; 清除八行
LDA #$10
; 循环八次
_LOOP_CLEAR:
PHA
JSR _ERASE_LINE
PLA
CLC
SBC #$01
BNE _LOOP_CLEAR
; 循环结束, 清理现场
JSR _RESET_POSITION
RTS
_ERASE_LINE:
LDA #$10
_ERASE_NEXT_CHAR:
LDY #$00
STY $2007
CLC
STY $2007
CLC
STY $2007
CLC
STY $2007
CLC
STY $2007
CLC
STY $2007
CLC
STY $2007
CLC
CLC
SBC #$01
BNE _ERASE_NEXT_CHAR
JSR _NEXT_LINE_8px
RTS
_NEXT_LINE:
; 低位
CLC
LDA $0048
ADC #$40
STA $0048
STA $004A
; 高位
LDA $0049
ADC #$00
STA $0049
STA $004B
; 设定等待, 不需要
; LDA #$30
; STA $0047
RTS
; This will destory ACC register.
_RESET_POSITION:
; HI LO
; 21 11
; ** [0048, 004A]
; ** [0049, 004B]
LDA #$21
STA $0049
STA $004B
STA $2006
LDA #$11
STA $0048
STA $004A
STA $2006
RTS
_NEXT_LINE_8px:
; 低位
CLC
LDA $0048 ; Add new line
ADC #$20
STA $0048
STA $004A
; 高位
LDA $0049
ADC #$00
STA $0049
STA $004B
STA $2006
; 写低位地址
LDA $0048
STA $2006
RTS
; 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
; 04:AF60:FF UNDEFINED
; 012F70:FF UNDEFINED
.org $AF60
LoadNextEndingChar:
LDA #$00
STA $0023
; 拷贝字符串地址
LDA $855B,Y
STA $0000
LDA $855C,Y
STA $0001
; Y = 读取的字符偏移
_GET_NEXT_CHAR:
LDY $0042
INC $0042
LDA ($00),Y
BEQ _SED_EXIT
CMP #$FB
BNE _SKIP_SET_WAIT
LDA #$01
STA $001A
RTS
_SKIP_SET_WAIT:
CMP #$FF
BEQ _EXIT_FINISH_DIALOG
CMP #$FE
BEQ _NEW_LINE
CMP #$FD
BNE _SKIP_ENABLE_CHINESE
; LDA #$03
; STA $07EE
; Read next char
JMP _GET_NEXT_CHAR
_SKIP_ENABLE_CHINESE:
; Loop - 检查中文字符
_Loop_SearchForChinese:
LDA ($00),Y ; A = 当前字符
AND #$C0 ; 检查第一位是不是 1
CMP #$C0 ; 中文控制符
BNE _END_CHINESE; 跳过中文字符处理
; 是中文控制符
; 加入两个字符,并,自循环
; 写出 2 个控制符
LDA ($00),Y ; A = ChineseCtrlChar
AND #$7 ;
TAX ; X = A
INY ; Y++
; 此时的 stack: X
; 此时的值: X = PPU 序号
; Y = 正常的序号
LDA ($00),Y ; A = NextChar
STA $07F0,X ; [07FX] = A (CHR_BANK_X)
INY ; Y++
STY $0042 ; 储存对话偏移
INC $0042
JSR $FACE
JMP _Loop_SearchForChinese
_END_CHINESE:
LDX $0021
LDA #$01
STA $0700,X
; 检查是否为中文字符.
AND #$C0
CMP #$80
BEQ _ADD_CHINESE
JMP _END_ADD_CHAR
_ADD_CHINESE:
; 定位
; LO ADDR
LDA $0043
STA $0702,X
CLC
ADC #$20
STA $0708,X
; HI ADDR
LDA $0044
STA $0701,X
ADC #$00
STA $0707
; 写出第一个贴图块
LDA ($00),Y
STA $0703,X
; 写出后续贴图块
CLC
ADC #$01
STA $0704,X
CLC
ADC #$01
STA $0709,X
CLC
ADC #$01
STA $070A,X
; 写出终止符
LDA #$FF
STA $0705,X
STA $070B,X
INC $0043
TXA
CLC
ADC #$0C ; 下次写出的偏移
STA $0021
LDA #$10
JSR $F9BC ; Play sound
_SED_EXIT:
INC $0043
_EXIT:
RTS
_EXIT_FINISH_DIALOG:
LDA #$00
STA $07EE
LDA #$FF
RTS
_NEW_LINE:
; 0043:
LDA $0043
AND #$E0
STA $0043
; [0043] = [0043] + #$45
LDA #$43 ; Position next line; Original Value #$45
LDX #$43
JSR _C72D
LDA #$01
RTS
_C72D:
CLC
ADC $00,X
STA $00,X
BCC _C736
INC $01,X
_C736:
RTS
; 07,FB40: 01FB50
; STA $2007
.org $FB40
; A = THE VALUE
; 检查是否为中文字符
PHA ; push A
AND #$C0
CMP #$80
BNE _NOT_CHINESE
; 检查中文 flag
LDA $07EE
CMP #$00
BEQ _NOT_CHINESE
; 中文字符!
PLA ; pop A
; 获取字符信息
ASL
ASL
; A = Tile ID
; 写出左上角
STA $2007
ADC #$1
; 写出右上角
STA $2007
ADC #$1
PHA
LDA $07EE
CMP #$01
BEQ _TYPE_01
CMP #$02
BEQ _TYPE_02
CMP #$03
BEQ _TYPE_03
JMP _NOT_CHINESE
_NOT_CHINESE:
PLA ; pop A
_DISPLAY:
STA $2007
_EXIT:
; JMP $CB9E
RTS
_TYPE_01_JMP:
; JMP _TYPE_01
_TYPE_02_JMP:
; JMP _TYPE_02
_TYPE_01:
; 寻找左下角的坐标
LDA $0049 ; A = LOW_ADDR
CLC
ADC #$1F
LDA $004A
ADC #$00
STA $2006 ; Write Hi Part.
CLC
LDA $0049
ADC #$1F
STA $2006 ; Write Lo Part.
CLC
INC $0049 ; 跳过写出了的位置
PLA ; pop A
STA $2007
ADC #$1
JMP _DISPLAY
_TYPE_02:
; 寻找左下角的坐标
LDA $004A ; A = LOW_ADDR
CLC
ADC #$1F
LDA $004B
ADC #$00
STA $2006 ; Write Hi Part.
CLC
LDA $004A
ADC #$1F
STA $2006 ; Write Lo Part.
CLC
INC $004A ; 跳过写出了的位置
PLA ; pop A
STA $2007
ADC #$1
JMP _DISPLAY
_TYPE_03:
; 寻找左下角的坐标
LDA $0043 ; A = LOW_ADDR
CLC
ADC #$1F
LDA $0044 ; HI ADDR
ADC #$00
STA $2006 ; Write Hi Part.
CLC
LDA $0043
ADC #$1F
STA $2006 ; Write Lo Part.
CLC
INC $0043 ; 跳过写出了的位置
PLA ; pop A
STA $2007
ADC #$1
JMP _DISPLAY
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.