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

世嘉Genesis执行VRAM DMA填充后精灵位移问题排查

编辑注:最终确认问题并非DMA导致,而是编写的子程序意外覆盖了其他寄存器的值,是我个人疏忽。

Sega Genesis平台DMA填充操作导致精灵位移异常问题

我正在研究Sega Genesis平台DMA(Direct Memory Access,直接内存访问)的工作机制,目前VRAM填充模式已基本可按预期运行,但存在一个异常问题:执行DMA操作会导致游戏精灵在屏幕上发生位移,无法定位原因。
DMA触发前游戏在Fusion模拟器中的运行参考截图如下:
DMA触发前正常运行截图

基础配置说明

  • 画面元素说明:图中的小狗为精灵对象,其余图形均为瓦片元素,其中箱子、青柠、红色方块为前景瓦片,云朵和天空为背景瓦片,窗口层处于屏幕外
  • VRAM地址配置:
    • 前景层位于VDP地址$C000(世嘉编码$40000003)
    • 精灵属性表位于$D800($58000003)
    • 背景层位于$E000($60000003)
    • 窗口层位于$F000($7000003)
  • 触发逻辑:按下手柄C键即可启动DMA,执行DMA命令的子程序代码如下:
dma_fill:
    ;宏与定义常量说明:
    ;pushRegs = MOVEM.L ___,-(SP)
    ;popRegs  = MOVEM.L (SP)+,____
    ;DI = MOVE #$2300,SR
    ;pushf = MOVE SR,-(SP)
    ;popf  = MOVE (SP)+,SR
    ;CD5 = %10000000
    ;VDP_CTRL = $00C00004
    ;VDP_DATA = $00C00000

    ;传入参数:
    ;D2.L = 写入目标地址
    ;D1.W = DMA长度
    ;D0 = VRAM填充所用数据
    pushRegs D3-D7
    pushf
        DI      ;DMA执行期间屏蔽中断

        MOVEQ.L #-109,D3            ;快速向D3写入#$FFFFFF93
        LSL.W #8,D3
        OR.B D1,D3                  
        ;d3值为$93xx,xx是DMA长度低字节,为VDP要求的正确命令格式
        
        
        LSR.W #8,D1 ;将DMA长度高字节移位到低字节位
        
        MOVEQ.L #-108,D4            ;快速向D4写入#$FFFFFF94
        LSL.W #8,D4                 ;D4 = #$FFFF9400
        OR.B D1,D4
        ;d4值为$94xx,xx是DMA长度高字节,为VDP要求的正确命令格式
        OR.L #CD5,D2        ;告知VDP下一次写入为DMA写入操作
        
.wait:
        move.w VDP_ctrl,d7
        and.w #%0000000000001000,d7     ;检查当前是否处于VBlank周期
        bne .wait                       ;非VBlank则循环等待
        
        MOVE.W #($8100|%01110100),(VDP_CTRL)    ;使能DMA
        move.w #$8F01,(vdp_ctrl)                ;设置地址自增步长为1
        MOVE.W #$9780,(vdp_ctrl)                ;启用DMA VRAM填充模式
        MOVE.W D3,(vdp_ctrl)                    ;写入DMA长度低字节
        MOVE.W D4,(vdp_ctrl)                    ;写入DMA长度高字节
        MOVE.L D2,(vdp_ctrl)                    ;写入目标地址
        
        MOVE.W D0,(vdp_data)                    ;写入填充值,DMA从这一步启动
        ;是否需要等待DMA执行完成再继续后续代码?
; .waitDma:
        ; MOVE.W (vdp_ctrl),d6
        ; btst #1,d6
        ; bne .waitDma
        
    
        move.w #($8100|%01100100),(VDP_CTRL)    ;禁用DMA
        move.w #$8F02,(vdp_ctrl)                ;恢复地址自增步长为2
    popf        ;恢复状态寄存器与中断优先级
    popRegs D3-D7
    RTS

异常现象

测试传入参数配置为:D0填充值为0(对应空白8x8瓦片的瓦片编号),D1填充长度为$0400,目标地址为$40000003(前景瓦片表),预期VRAM的$C000-$C400区域会被填充为空白瓦片,实际运行效果如下:
DMA触发后运行效果截图

实际运行时大约前4行元瓦片被清空(项目中每个“元瓦片”由4个8x8瓦片组成),从填充长度来看该部分表现符合预期,但小狗精灵的位置发生了偏移。由于精灵属性表设置在VDP地址$D800处,不在本次DMA填充的地址范围内,该现象完全不符合逻辑。
后续出于测试目的,将长度参数修改为$0200重复测试,此时没有任何瓦片被清空,但精灵依然会位移到屏幕上的同一位置,现象十分反常。目前查阅到的现有文档要么英文翻译质量较差,要么没有说明内存层面的实际运行细节(大多仅讲解DMA触发方式,这部分已实现,但无法解释DMA操作导致精灵位移的原因)。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.30 18:25:25