跳至内容

Jixun's Blog 填坑还是开坑,这是个好问题。

FC 魂斗罗汉化日记 (第六集) (完)

第六集 - 执行效率优化 #

(目录)

因为效率问题 (修改的地方是原本游戏用来显示缓冲区的内容),决定重写。

主要的更改,就是取消在 $CB30 这个函数里对最终打印到屏幕的代码片段,修改为对话时生成对应的文字。

同时为了方便维护,很多代码片段将拆分为独立的函数方便调用;然后因为寄存器的限制,统一了各函数调用通用函数时所使用的内存地址 (因为之前生成的翻译数据,都是 FD 打头,可以利用这一个特性进行数据的初始化&修复)。

使用的编辑器为 Atom,因为有一个 6502 汇编的语法高亮可以直接安装。

; 魂斗罗部分地址偏移 / 常量

; Function Import --------------------------
.alias _fn_PrologueDialog     $AB70
.alias _fn_ContraIntro        $AB73
.alias _fn_LevelClearDialog   $AB76
.alias _fn_ScrectEnding       $AB79

; 原本就在魂斗罗 Rom 内的函数地址
.alias _fn_PlaySound          $F9BC
; END Function Import ----------------------



; 定位地址
.alias POSITION_LO        $0049
.alias POSITION_HI        $004A



; 写出基地址
.alias PPU_BUFF_OFFSET    $0021

.alias PPU_BUFF_TYPE      $0700
.alias PPU_BUFF_HI_ADDR   $0701
.alias PPU_BUFF_LO_ADDR   $0702
.alias PPU_BUFF_TILE      $0703
.alias PPU_BUFF_END       $0704

; Used by ScrectEnding
; Set to 00 to render until FF.
.alias G_PPU_RENDER_TYPE  $0023
.alias PPU_RENDER_TILE    $00


; 中文字符缓冲区开始 -------------------------
.alias CHS_BUFF_TYPE1     $0700
.alias CHS_BUFF_HI_TOP    $0701
.alias CHS_BUFF_LO_TOP    $0702
.alias CHS_BUFF_TILE1     $0703
.alias CHS_BUFF_TILE2     $0704
.alias CHS_BUFF_END1      $0705

.alias CHS_BUFF_TYPE2     $0706
.alias CHS_BUFF_HI_BOT    $0707
.alias CHS_BUFF_LO_BOT    $0708
.alias CHS_BUFF_TILE3     $0709
.alias CHS_BUFF_TILE4     $070A
.alias CHS_BUFF_END2      $070B
; 中文字符缓冲区结束 -------------------------



; 中文控制符开始 -----------------------------
.alias CTRL_END           $FF
.alias CTRL_NEWLINE       $FE
.alias CTRL_UPDATE_PPU    $FD
.alias CTRL_CLEAR         $FC
.alias CTRL_WAIT          $FB
.alias CTRL_PAUSE         $FB
.alias CTRL_CLEARLINE     $FA


.alias CHS_CHAR_FLAG      $80
.alias CHS_CHAR_MASK      $C0

.alias CHS_CTRL_FLAG      $C0
.alias CHS_CTRL_MASK      $C0
; 中文控制符结束 -----------------------------



; BEGIN PPU Bank ---------------------------
.alias CHR_BANK_BASE      $07F0

.alias CHR_BANK_0         $07F0
.alias CHR_BANK_1         $07F1
.alias CHR_BANK_2         $07F2
.alias CHR_BANK_3         $07F3
.alias CHR_BANK_4         $07F4
.alias CHR_BANK_5         $07F5
.alias CHR_BANK_6         $07F6
.alias CHR_BANK_7         $07F7
; END PPU Bank -----------------------------



; BEGIN Dialog Generic ---------------------
.alias ALL_DIALOG_HI      $0001
.alias ALL_DIALOG_LO      $0000

.alias DIALOG_ADDR        $0000
; END Dialog Generic -----------------------



; BEGIN Contra Intro -----------------------
.alias CI_CURRENT_CHAR    $0008
; END Contra Intro -------------------------



; BEGIN Level Clear Dialog -----------------
.alias LCD_RESET_HI       $21
.alias LCD_RESET_LO       $11

.alias LCD_TEXT_OFFSET    $0046
.alias LCD_WAIT_COUNTER   $0047

; 行首位置
.alias LCD_BACKUP_LO      $0048
.alias LCD_BACKUP_HI      $004B

; 对话文字偏移
.alias LCD_DIALOG_HI      $A1D7
.alias LCD_DIALOG_LO      $A1D6
; END Level Clear Dialog -------------------




; BEGIN Prologue Dialog --------------------
.alias PLD_WAIT_COUNTER   $0043
.alias PLD_CUR_DIALOG     $0046
.alias PLD_TEXT_OFFSET    $0047
.alias PLD_LINE_COUNT     $0048

.alias PLD_DIALOGS_HI     $9849
.alias PLD_DIALOGS_LO     $9848

.alias PLD_DIALOG_POS_HI  $97DC
.alias PLD_DIALOG_POS_LO  $97DB

.alias PLD_TMP_POS_ADDR   $0002
.alias PLD_TMP_POS_HI     $0003
.alias PLD_TMP_POS_LO     $0002
; END Prologue Dialog ----------------------


; BEGIN ScrectEnding -----------------------
.alias SED_WAIT_COUNTER   $001A
.alias SED_TEXT_OFFSET    $0042

.alias SED_DIALOG_LO      $855B
.alias SED_DIALOG_HI      $855C

.alias SED_POS_LO         $0043
.alias SED_POS_HI         $0044

; END ScrectEnding -------------------------

Contra.inc.s 里面定义了主程序用到的各种数据,尽量避免偏移计算造成的人为错误。

.org $AB70
.require "Contra.inc.s"
; --------------------------
; 内存地址            04:AB70
; 文件地址             012B80
; --------------------------



; BEGIN Functions --------------------------------------------------------------
; 每一条函数占用 3 个字节

; From:   01180D / 04:97FD
; Target:          04:AB70
_Prologue_Dialog:
  JMP PrologueDialog

; From:   011044 / 04:9034
; Target:          04:AB73
_Contra_Intro:
  JMP ContraIntro

; From:   012175 / 04:A165
; Target:          04:AB76
_Level_Clear_Dialog:
  JMP LevelClearDialog

; From:   010515 / 04:8505
; Target:          04:AB79
_Screct_Ending:
  JMP ScrectEnding

; END Functions ----------------------------------------------------------------



; BEGIN G_UpdatePPU ------------------------------------------------------------
; 输入:
;   * Y: 当前偏移
; 更改:
;   * X: BANK 序号
;   * Y: 下一个字符的偏移
;   * A: 下一个字符
; 清理:
;   * STY YOUR_OFFSET
;   * INC YOUR_OFFSET
G_UpdatePPU:
  ; 开始读后面的数据
  ; 获取下一个字符: LDA ($00), Y
  ; 修复偏移 INC LCD_TEXT_OFFSET

_G_UPDATEPPU_CHECK_NEXT_CHAR:
  INY
  LDA (DIALOG_ADDR), Y
  AND #CHS_CTRL_MASK
  CMP #CHS_CTRL_FLAG
  BNE _G_UPDATEPPU_END_CTRL
    LDA (DIALOG_ADDR), Y
    AND #$07
    TAX           ; X = BANK

    INY
    LDA (DIALOG_ADDR), Y
    STA CHR_BANK_BASE, X
    JMP _G_UPDATEPPU_CHECK_NEXT_CHAR

_G_UPDATEPPU_END_CTRL:
  LDA (DIALOG_ADDR), Y
  RTS

; END G_UpdatePPU --------------------------------------------------------------



; BEGIN G_DisplayCharacter -----------------------------------------------------
; 输出一个字符到图案输出缓冲区 (稍后在 NMI 函数显示到屏幕)
; 输入: A = 需要显示的字符
; 影响: A = 乱码
G_DisplayCharacter:
  LDX PPU_BUFF_OFFSET
  PHA

  AND #CHS_CHAR_MASK
  CMP #CHS_CHAR_FLAG
  BEQ _DISPLAY_CHINESE_CHR
    ; 不是中文字符,只需要写出这一个 TILE 即可
  LDA #$01
  STA PPU_BUFF_TYPE, X

    LDA POSITION_HI
    STA PPU_BUFF_HI_ADDR, X

    LDA POSITION_LO
    STA PPU_BUFF_LO_ADDR, X

    ; 获取需要打印的字符
    PLA
    STA PPU_BUFF_TILE

    LDA #$FF
    STA PPU_BUFF_END, X

    ; 计算 X 偏移 (8 cycle)
    ; 非中文字符一共写出了 5 个字节
    CLC
    TXA
    ADC #$05

    JMP _END_ADD_CHAR

  _DISPLAY_CHINESE_CHR:
    LDA #$01
    STA CHS_BUFF_TYPE1, X
    STA CHS_BUFF_TYPE2, X

    ; 写出 & 计算定位
    CLC
    LDA POSITION_LO
    STA CHS_BUFF_LO_TOP, X
    ADC #$20  ; #$20 - 刚好换到第二行的相同位置
    STA CHS_BUFF_LO_BOT, X

    LDA POSITION_HI
    STA CHS_BUFF_HI_TOP, X
    ADC #$00  ; #$00 - 如果之前的加法溢出了,此时便会 +1
    STA CHS_BUFF_HI_BOT, X

    ; 写出贴图块
    CLC
    PLA

    ; ID = A * 4
    ASL
    ASL

    STA CHS_BUFF_TILE1, X

    ADC #$01
    STA CHS_BUFF_TILE2, X

    ADC #$01
    STA CHS_BUFF_TILE3, X

    ADC #$01
    STA CHS_BUFF_TILE4, X

    ; 写出结束符
    LDA #$FF
    STA CHS_BUFF_END1, X
    STA CHS_BUFF_END2, X

    INC POSITION_LO

    ; 计算 X 偏移
    TXA
    ADC #$0C

_END_ADD_CHAR:
  ; 跳转前: 请计算写出长度并赋值到寄存器

  ; 修复 PPU 偏移
  STA PPU_BUFF_OFFSET

  ; 下一个写出地址 +1
  INC POSITION_LO
  BCC _NO_INC_POS_HI
    INC POSITION_HI

_NO_INC_POS_HI:
  ; 好像没了

  RTS
; END G_DisplayCharacter -------------------------------------------------------



; BEGIN ContraIntro ------------------------------------------------------------
; 原始内存        04:9034
; 文件地址         011044
; 修改方案            JMP

ContraIntro:
  LDA CI_CURRENT_CHAR
  ; 检查 3x3 字符标记
  AND #$40
  ; 如果没有 (A = 0), 那么就是 2x2
  BEQ _CI_2x2_LETTER
    LDA CI_CURRENT_CHAR
    CLC
    SBC #$40

    ; 跳回去原本的代码
    JMP $90A0

_CI_2x2_LETTER:
  ; Y = (char << 2) & 0x7F
  LDA CI_CURRENT_CHAR
  ASL
  ASL
  AND #$7F
  TAY

  LDA CI_CURRENT_CHAR
  AND #$20
  CLC

  ; 计算坐标 (代码直接拷贝自程序)
  ADC $0042
  STA $0000

  LDA #$00
  ADC $0043
  STA $0001

  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 _DATA_CI_TITLE_TABLE + 0, Y
  STA $0703,X

  LDA _DATA_CI_TITLE_TABLE + 1, Y
  STA $0704,X

  LDA _DATA_CI_TITLE_TABLE + 2, Y
  STA $0709,X

  LDA _DATA_CI_TITLE_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

_DATA_CI_TITLE_TABLE:
  ; 00
  .byte $00,$00,$00,$00   ; [空白]
  .byte $02,$03,$12,$13   ;  .byte $04,$05,$14,$15   ;  .byte $06,$07,$16,$17   ;  .byte $08,$09,$18,$19   ;  .byte $00,$00,$00,$00   ; [未使用]
  .byte $0c,$0d,$1c,$1d   ;  .byte $0e,$0f,$1e,$1f   ;  ; 08
  .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 $0B,$00,$00,$00   ; [前引号]
  .byte $00,$00,$1B,$00   ; [逗号]
  ; 10
  .byte $00,$00,$0A,$00   ; [句号]
  .byte $F7,$F8,$F9,$FA   ;  .byte $FB,$FC,$FD,$FE   ;  .byte $00,$00,$00,$00   ; [未使用]
  .byte $48,$49,$58,$59   ;  .byte $4a,$4b,$5a,$5b   ;  .byte $4c,$4d,$5c,$5d   ;  .byte $4e,$4f,$5e,$5f   ;  ; 18
  .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   ;  ; 20
; END ContraIntro --------------------------------------------------------------



; --------------------------
; Level Clear Dialog
;       过关剧情文字
; --------------------------

LevelClearDialog:
  DEC LCD_WAIT_COUNTER
  BEQ _LCD_NO_WAIT
_LCD_EXIT_DIALOG_INCOMPLETE:
    CLC
    RTS

_LCD_NO_WAIT:
  LDA #$06    ; A = 06
  STA LCD_WAIT_COUNTER   ; [0047] = 06


  LDA $0030   ; A = [0030]
  ASL       ; A <<= 1
  TAY       ; Y = A

  ; 对话偏移写出到 00, 01 位置
  LDA LCD_DIALOG_LO, Y
  STA ALL_DIALOG_LO
  LDA LCD_DIALOG_HI, Y
  STA ALL_DIALOG_HI

  ; 读取对话偏移
_LCD_GET_NEXT_CHAR:
  LDY LCD_TEXT_OFFSET    ; Y = [0046]
  INC LCD_TEXT_OFFSET

_LCD_CHECK_CHAR:
  LDA (DIALOG_ADDR), Y

  ; 检查控制符: 结束 -----
  CMP #CTRL_END
  BEQ _LCD_END_DIALOG_COMPLETE


  ; 检查控制符: 清屏 -----
  CMP #CTRL_CLEAR
  BNE _LCD_SKIP_CLEAR_SCREEN
    ; 清屏

    ; 首先重置光标位置, 然后清屏
    JSR LCD_ResetPosition
    JSR LCD_ClearLine
    JSR LCD_ResetPosition
    JMP _LCD_EXIT_DIALOG_INCOMPLETE
_LCD_SKIP_CLEAR_SCREEN:

  CMP #CTRL_CLEARLINE
  BNE _LCD_SKIP_CLEARLINE
    JSR LCD_ClearLine
    JMP _LCD_EXIT_DIALOG_INCOMPLETE
_LCD_SKIP_CLEARLINE:


  ; 检查控制符: 换行 -----
  CMP #CTRL_NEWLINE
  BNE _LCD_SKIP_NEWLINE
    INY
    JSR LCD_NewLine
    JMP _LCD_GET_NEXT_CHAR
_LCD_SKIP_NEWLINE:

  ; 检查控制符: 暂停 -----
  CMP #CTRL_PAUSE
  BNE _LCD_SKIP_PAUSE
    LDA #$40
    STA LCD_WAIT_COUNTER
    ; INC LCD_TEXT_OFFSET
    JMP _LCD_EXIT_DIALOG_INCOMPLETE
_LCD_SKIP_PAUSE:

  ; 检查控制符: 中文 -----

  ; 检查是否为中文符号
  ; 如果是, 在传递之前调用一次 [重置位置] 函数。
  ; 因为为了配合通用中文写字程序,需要调整坐标使用的内存地址。
  CMP #CTRL_UPDATE_PPU
  BNE _LCD_SKIP_RESET
    JSR LCD_ResetPosition

    ; 更新 PPU
    JSR G_UpdatePPU

    ; 根据函数说明, 储存当前的对话偏移
    STY LCD_TEXT_OFFSET
    INC LCD_TEXT_OFFSET
    JMP _LCD_CHECK_CHAR

_LCD_SKIP_RESET:

  ; 在屏幕写字~
  CMP #$00
  BEQ _LCG_SKIP_SOUND
    PHA
    LDA #$10
    JSR _fn_PlaySound
    PLA

_LCG_SKIP_SOUND:
  JSR G_DisplayCharacter
  RTS

_LCD_END_DIALOG_COMPLETE:
  SEC
  RTS

; BEGIN LCD_ResetPosition ------------------------------------------------------
LCD_ResetPosition:
  ; 默认写出位置
  LDA #LCD_RESET_HI
  STA LCD_BACKUP_HI
  STA POSITION_HI

  LDA #LCD_RESET_LO
  STA LCD_BACKUP_LO
  STA POSITION_LO

  RTS
; END LCD_ResetPosition --------------------------------------------------------

; BEGIN LCD_NewLine ------------------------------------------------------------
LCD_NewLine:
  CLC
  LDA LCD_BACKUP_LO
  ADC #$40
  STA LCD_BACKUP_LO
  STA POSITION_LO

  LDA LCD_BACKUP_HI
  ADC #$00
  STA LCD_BACKUP_HI
  STA POSITION_HI
  RTS
; END LCD_NewLine --------------------------------------------------------------


; BEGIN LCD_ClearLine --------------------------------------------------------
LCD_ClearLine:
  ; 准备环境

  LDX PPU_BUFF_OFFSET
  LDA #$03

  _LCD_CS_NEXT_LINE:
    PHA

    ; 打标记
    LDA #$01
    STA PPU_BUFF_TYPE, X

    ; 获取当前坐标, 并计算下一次的写出坐标
    CLC
    LDA LCD_BACKUP_LO
    STA PPU_BUFF_LO_ADDR, X
    ADC #$20
    STA POSITION_LO
    STA LCD_BACKUP_LO

    LDA LCD_BACKUP_HI
    STA PPU_BUFF_HI_ADDR, X
    ADC #$00
    STA LCD_BACKUP_HI
    STA POSITION_HI


    ; 写出 16 个空白字符
    LDY #$D
    LDA #$00
_LCD_CS_LOOP_CHAR:
      STA PPU_BUFF_TILE, X
      INX
      DEY
      BNE _LCD_CS_LOOP_CHAR

    ; 打上结束标记
    LDA #$FF
    STA PPU_BUFF_TILE, X

    INX
    INX
    INX
    INX

    ; 清理一行的控制符打上了
    ; 检查循环
    PLA
    SEC
    SBC #$01
    BNE _LCD_CS_NEXT_LINE

  ; X 被修改了,记录长度
  STX PPU_BUFF_OFFSET

  RTS
; END LCD_ClearLine ----------------------------------------------------------



; BEGIN PrologueDialog ---------------------------------------------------------
PrologueDialog:
  DEC PLD_WAIT_COUNTER
  BNE _PLD_END

  ; 设定下个字符的等待时间
  LDA #$08
  STA PLD_WAIT_COUNTER

  ; 取得当前对话的序号并计算偏移
  ; Y = [PLD_CUR_DIALOG] << 1
  LDA PLD_CUR_DIALOG
  ASL
  TAY

  ; 取得当前对话指针
  LDA PLD_DIALOGS_LO,Y
  STA ALL_DIALOG_LO
  LDA PLD_DIALOGS_HI, Y
  STA ALL_DIALOG_HI

  ; 取得在当前对话的偏移
_PLD_NEXT_CHAR:
  LDY PLD_TEXT_OFFSET
  INC PLD_TEXT_OFFSET

_PLD_CHECK_CHAR:
  LDA (DIALOG_ADDR), Y
  CMP #CTRL_END
  BEQ _PLD_DIALOG_FINISH

  CMP #CTRL_NEWLINE
  BNE _PLD_NOT_NEWLINE
    ; 换行符号
    INC PLD_LINE_COUNT
    JSR PLD_NewLine
    JMP _PLD_NEXT_CHAR

_PLD_NOT_NEWLINE:
  CMP #CTRL_UPDATE_PPU
  BNE _PLD_SKIP_PPU
    ; 中文符号
    ; 1. 检查并切换 PPU
    ; 2. 显示下一个字符

    ; 更新 PPU
    JSR G_UpdatePPU

    ; 根据函数说明, 储存当前的对话偏移
    STY PLD_TEXT_OFFSET
    INC PLD_TEXT_OFFSET

    JMP _PLD_CHECK_CHAR
_PLD_SKIP_PPU:

  ; 检查是否为空格
  ; 如果是空格就不发出打字音
  CMP #$00
  BEQ _PLD_SKIP_SOUND
    PHA
    LDA #$10
    JSR _fn_PlaySound
    PLA

_PLD_SKIP_SOUND:
  ; 结束控制符检查
  ; 显示字符到屏幕
  JSR G_DisplayCharacter
  RTS


_PLD_END:
  CLC
  RTS

_PLD_DIALOG_FINISH:
  SEC
  RTS


; END PrologueDialog -----------------------------------------------------------



; BEGIN PLD_NewLine ------------------------------------------------------------
; 输入:; 影响:
;   * Y: 换行次数
;   * A: PPU 地址高位
PLD_NewLine:
  ; 读取下一行的位置的偏移地址
  LDA PLD_CUR_DIALOG
  ASL
  TAY

  LDA PLD_DIALOG_POS_LO,Y
  STA PLD_TMP_POS_LO
  LDA PLD_DIALOG_POS_HI,Y
  STA PLD_TMP_POS_HI

  ; 写出 PPU 定位地址
  ; Y = [PLD_LINE_COUNT] << 1
  LDA PLD_LINE_COUNT
  ASL
  TAY

  LDA (PLD_TMP_POS_LO),Y
  STA POSITION_LO
  INY
  LDA (PLD_TMP_POS_LO),Y
  STA POSITION_HI
  RTS
; END PLD_NewLine --------------------------------------------------------------



; BEGIN ScrectEnding -----------------------------------------------------------
ScrectEnding:
  LDA #PPU_RENDER_TILE
  STA G_PPU_RENDER_TYPE

  LDA SED_DIALOG_LO, Y
  STA ALL_DIALOG_LO
  LDA SED_DIALOG_HI, Y
  STA ALL_DIALOG_HI

_SED_GET_NEXT_CHAR:
 LDY SED_TEXT_OFFSET
 INC SED_TEXT_OFFSET

_SED_CHECK_CHAR:
  LDA (DIALOG_ADDR), Y

  ; 如果是空格
  CMP #CTRL_PAUSE
  BNE _SED_NOT_PAUSE
    ; 这部分的程序等待是向上计时的,重置为 01 刚好。
    ; 如果 A = 00 就认为是结束了
    LDA #$01
    STA SED_WAIT_COUNTER
    RTS
_SED_NOT_PAUSE:

  CMP #CTRL_END
  BEQ _SED_EXIT_COMPLETE

  CMP #CTRL_NEWLINE
  BNE _SED_NOT_NEWLINE
    ; 换行操作
    JSR SED_NewLine
    JMP _SED_GET_NEXT_CHAR

_SED_NOT_NEWLINE:
  CMP #CTRL_UPDATE_PPU
  BNE _SED_NOT_UPDATE_PPU
    ; 重置坐标
    JSR SED_ResetPosition

    JSR G_UpdatePPU
    ; 根据函数说明进行清理工作
    STY SED_TEXT_OFFSET
    INC SED_TEXT_OFFSET
    JMP _SED_CHECK_CHAR

_SED_NOT_UPDATE_PPU:

  CMP #$00
  BEQ _SED_SKIP_SOUND
    PHA
    LDA #$10
    JSR _fn_PlaySound
    PLA

_SED_SKIP_SOUND:

  ; 开始显示字符
  JSR G_DisplayCharacter


_SED_EXIT:
  RTS

_SED_EXIT_COMPLETE:
  LDA #$00
  RTS

; END ScrectEnding -------------------------------------------------------------



; BEGIN SED_NewLine -----
SED_NewLine:
  CLC
  LDA SED_POS_LO
  ADC #$40
  STA SED_POS_LO
  STA POSITION_LO

  LDA SED_POS_HI
  ADC #$00
  STA SED_POS_HI
  STA POSITION_HI

  RTS
; END SED_NewLine -------

; BEGIN SED_ResetPosition -----
SED_ResetPosition:
  ; 将地址重置为 20 C3
  LDA #$20
  STA POSITION_HI
  STA SED_POS_HI

  LDA #$C3
  STA POSITION_LO
  STA SED_POS_LO
  RTS

; END SED_ResetPosition -------

GenericDisplayCharacter.s 负责提供函数以及导出
  ※ 每一个导出占用 3 个字节

导入进游戏后,可以发现地图界面的卡顿没了,也不会产生乱码了。

当然,这个版本并非完美,有时间的话我会继续跟进完善的。

发布 #

最后就是发布了,汉化版除了在本站,只在下述两个网站发布:

  • 贴吧:魂斗罗 (J) 中文大字汉化 该帖已被删除
  • RHDN:Contra (ZH)

欢迎转载,注明出处与汉化者即可。

知识共享许可协议 本作品采用知识共享署名-相同方式共享 4.0 国际许可协议进行许可。

评论区