You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

PEPE-16汇编实现Pacman精灵:字节表重构与优化问询

PEPE-16模拟器Pacman精灵绘制优化方案

需求说明

对已有Pacman绘制代码做以下修改:

  • 将原WORD类型的DEF_PACMAN像素表改为BYTE格式:0代表透明、1代表黄色、2代表循环切换透明/黄色(实现嘴巴开合动效)
  • 新增SCALE参数,支持精灵按比例缩放

修改后的数据表结构

DEF_PACMAN:             ; Pacman定义表(宽度、缩放比例、像素数据)
    WORD PACMAN_LENGTH  ; 原始宽度(4)
    WORD SCALE          ; 缩放比例(比如2表示放大2倍)
    BYTE 0,1,1,0        ; 第1行像素
    BYTE 1,1,1,1        ; 第2行像素
    BYTE 1,2,2,2        ; 第3行像素(2为动态切换位)
    BYTE 1,1,1,1        ; 第4行像素
    BYTE 0,1,1,0        ; 第5行像素

核心实现逻辑

1. BYTE类型像素数据读取

原代码每次读取WORD(+2地址偏移),修改为每次读取BYTE(+1地址偏移),并根据BYTE值映射为实际颜色:

  • 0 → 透明(跳过绘制)
  • 1 → 固定黄色(YELLOW常量)
  • 2 → 根据MOUTH_STATE变量动态切换:0(透明)或1(黄色)

2. 缩放功能实现

针对每个原始像素,绘制SCALE × SCALE个像素块:

  • 列方向:每个原始像素重复绘制SCALE次
  • 行方向:每一行原始像素重复绘制SCALE次

3. 嘴巴开合动效控制

新增全局变量MOUTH_STATE(0或1),通过定时循环切换状态,实现嘴巴的开合:

  • 0 → 嘴巴张开(2对应透明)
  • 1 → 嘴巴闭合(2对应黄色)

完整优化代码

DEFINE_LINE            EQU 600AH      ; 定义行指令地址
DEFINE_COLUMN          EQU 600CH      ; 定义列指令地址
DEFINE_PIXEL           EQU 6012H      ; 绘制像素指令地址
CLEAR_NOTICE           EQU 6040H      ; 清除提示指令地址
CLEAR_SCREEN           EQU 6002H      ; 清屏指令地址
SELECT_BACKGROUND_SCENARIO EQU 6042H  ; 选择背景指令地址

; 地图边界
MIN_COLUMN             EQU 0         ; 最左列
MAX_COLUMN             EQU 63        ; 最右列
DELAY                  EQU 400H      ; 移动速度延迟
MOUTH_DELAY            EQU 800H      ; 嘴巴动效切换延迟

LINE                   EQU 14        ; 初始行
COLUMN                 EQU 31        ; 初始列
PACMAN_LENGTH          EQU 4
PACMAN_HEIGHT          EQU 5
SCALE                  EQU 2         ; 默认缩放比例(可修改)

WHITE                  EQU 0FFFFH    ; 白色
YELLOW                 EQU 0FFF0H    ; 黄色
GREEN                  EQU 0F090H 
BLUE                   EQU 0F36FH    ; 蓝色

; *********************************************************************************
; * 数据段
; *********************************************************************************
PLACE       1000H
stack_:
    STACK 100H          ; 栈空间(200字节)
initial_SP:             ; SP初始值(1200H)

MOUTH_STATE:            ; 嘴巴状态:0=张开,1=闭合
    WORD 0

DEF_PACMAN:             ; Pacman定义表
    WORD PACMAN_LENGTH
    WORD SCALE
    BYTE 0,1,1,0
    BYTE 1,1,1,1
    BYTE 1,2,2,2
    BYTE 1,1,1,1
    BYTE 0,1,1,0

; *********************************************************************************
; * 代码段
; *********************************************************************************
PLACE   0               ; 代码起始地址0000H
start:
    MOV  SP, initial_SP  ; 初始化栈指针
    MOV  [CLEAR_NOTICE], R1  ; 清除提示
    MOV  [CLEAR_SCREEN], R1  ; 清屏
    MOV  R1, 1            ; 选择背景场景1
    MOV  [SELECT_BACKGROUND_SCENARIO], R1
    
    MOV  R1, LINE          ; 初始绘制行
    MOV  R2, COLUMN        ; 初始绘制列
    MOV  R0, 1             ; 绘制模式:1=绘制,0=擦除
loop_main:
    CALL draw_pacman
    CALL mouth_toggle      ; 切换嘴巴状态
    CALL delay             ; 动效延迟
    JMP loop_main

end:
    JMP  end                 ; 程序结束

; 延迟子程序
delay:
    MOV R6, DELAY
delay_loop:
    SUB R6, 1
    JNZ delay_loop
    RET

; 嘴巴状态切换子程序
mouth_toggle:
    MOV R6, MOUTH_DELAY
mouth_delay_loop:
    SUB R6, 1
    JNZ mouth_delay_loop
    ; 切换状态
    MOV R6, [MOUTH_STATE]
    CMP R6, 0
    JZ set_closed
    MOV [MOUTH_STATE], 0
    RET
set_closed:
    MOV [MOUTH_STATE], 1
    RET

draw_pacman:
    MOV  R4, DEF_PACMAN
    MOV  R7, [R4]          ; 读取原始宽度到R7
    ADD  R4, 2
    MOV  R8, [R4]          ; 读取缩放比例到R8
    ADD  R4, 2              ; 指向第一行像素数据
    MOV  R5, PACMAN_HEIGHT ; 原始高度
    MOV  R9, R1             ; 保存初始行
    MOV  R10, R2            ; 保存初始列

draw_row_loop:
    MOV  R6, R7             ; 当前行像素数
    MOV  R2, R10            ; 重置当前列
draw_col_loop:
    ; 读取当前BYTE像素值
    MOVB R3, [R4]           ; PEPE-16专用BYTE读取指令
    ; 处理像素值映射
    CMP R3, 0
    JZ skip_pixel           ; 透明,跳过
    CMP R3, 1
    JZ set_yellow
    ; 处理值为2的动态像素
    MOV R3, [MOUTH_STATE]
    CMP R3, 0
    JZ skip_pixel
set_yellow:
    MOV R3, YELLOW
    ; 绘制SCALE×SCALE的像素块
    CALL draw_scaled_pixel
skip_pixel:
    ADD  R4, 1              ; 下一个BYTE像素
    ADD  R2, R8             ; 列偏移增加缩放比例
    SUB  R6, 1
    JNZ draw_col_loop
    ; 处理行缩放:重复当前行SCALE次
    MOV R11, R8
row_scale_loop:
    ADD  R1, 1
    SUB  R11, 1
    JNZ row_scale_loop
    SUB  R5, 1
    JNZ draw_row_loop
    ; 恢复初始行
    MOV R1, R9
    RET

; 绘制缩放后的像素块(SCALE×SCALE)
draw_scaled_pixel:
    MOV R12, R1             ; 保存当前行
    MOV R13, R2             ; 保存当前列
    MOV R14, R8             ; 行缩放计数
scaled_row_loop:
    MOV R15, R8             ; 列缩放计数
    MOV R2, R13
scaled_col_loop:
    CALL write_pixel
    ADD R2, 1
    SUB R15, 1
    JNZ scaled_col_loop
    ADD R1, 1
    SUB R14, 1
    JNZ scaled_row_loop
    ; 恢复行和列
    MOV R1, R12
    MOV R2, R13
    RET

write_pixel:
    MOV  [DEFINE_LINE], R1    ; 选择行
    MOV  [DEFINE_COLUMN], R2  ; 选择列
    MOV  [DEFINE_PIXEL], R3   ; 绘制像素
    RET

代码优化建议

  • 寄存器复用:将常用参数(如SCALE、MOUTH_STATE)常驻寄存器,减少内存访问次数,提升执行效率
  • 边界检查:添加缩放后精灵的屏幕边界校验,避免绘制超出屏幕范围的无效像素
  • 模块化拆分:将动效控制、缩放绘制等逻辑拆分为独立子程序,提升代码可读性和可维护性
  • 延迟优化:使用硬件定时器替代软件延迟,降低CPU资源占用
  • 透明处理:若模拟器支持直接跳过透明像素绘制,可减少无效的write_pixel调用,提升绘制性能

内容的提问来源于stack exchange,提问作者baptzera

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.24 06:35:00