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

Amstrad CPC模拟器(WinApe)中Gameboy Logo演示出现异常杂色像素

Amstrad CPC模式1下Gameboy Logo动画杂色问题修复

问题描述

用Z80汇编在Amstrad CPC模拟器WinApe的视频模式1中制作Gameboy Logo演示,单独绘制Logo显示正常,但添加绘制-擦除循环动画后,出现未绘制过的杂色像素,Logo最后一行本该只有红色,却混入其他颜色。

问题截图

Gameboy Logo杂色效果

原代码

;; testlogo.asm
;;
.cls    equ &BC14   ;; Clear screen
org &4000
run &4000
;;
call cls
ld hl, #c020        ;; initial position of video
ld a,#05        ;; times logo down      
call loop1      ;; call main loop
jr $
;;
loop1:
   ld bc,logo       ;; initial position of logo
                    ;; bc remains until logo
                    ;; is fully painted
   ld e,#08
   call loop_paint
   ld de, #c050
   add hl,de
                    ;; the second 8 row group pixels
   ld e,#08
   call loop_paint
   ld de,#c050
   add hl,de
                    ;; wait until 'down' logo
   ld b,#cc
   call wait
   ld de, #ff60     ;; recover hl position 
                    ;; to 'erase' upward logo
   add hl,de
   ld e,#08
   call loop_erase1 ;; call to 'erase' pixels
                    ;; from logo
                    ;; (it could be optimized in one calling)
   ld de, #c050
   add hl,de
   ld e,#08
   call loop_erase1
   ld de, #c050
   add hl,de
   dec a
jr nz, loop1
ret
;;
loop_paint:
   ld d,#0b
   call loop_logo   ;; call to paint logo
   push bc          ;; save bc in stack
                    ;; for using adding in bc
   ld bc,#07f5      ;; 800 for next row (minus) 0b last column
   add hl,bc
   pop bc 
   dec e
jr nz, loop_paint
ret
;;
loop_logo:          ;; finally 'paints' logo
                    ;; in memory video
   push af          ;; save 'a' register
                    ;; because is used
                    ;; as counter in main loop
   ld a, (bc)
   ld (hl), a
   pop af
   inc l
   inc c
   dec d
jr nz,loop_logo
ret
;;
loop_erase1:        ;; row by row in mode 1 video
   ld d,#0b     
   call loop_erase2
   ld bc,#07f5      ;;800 next row - 0b last column
   add hl,bc
   dec e
jr nz,loop_erase1
ret
;;
loop_erase2:        ;; column by column in mode 1 video
   ld (hl), #00 
   inc l
   dec d
jr nz,loop_erase2
ret
;;
logo:
db #00, #00, #00, #00, #00, #00, #00, #00, #00, #00, #00
db #00, #00, #00, #00, #00, #00, #00, #00, #00, #00, #00
db #00, #FF, #FF, #FF, #FF, #FF, #FF, #FF, #FF, #88, #00
db #33, #FF, #FF, #FF, #FF, #FF, #FF, #FF, #FF, #EE, #00
db #33, #F0, #F0, #F0, #F0, #F0, #F0, #F0, #F0, #E6, #00
db #FC, #F0, #F0, #F0, #F0, #F0, #F0, #F0, #F0, #F1, #88
db #FD, #F5, #FB, #F5, #FE, #FF, #F3, #F3, #FB, #FD, #88
db #FD, #F9, #FB, #FD, #F0, #F8, #F4, #FA, #F1, #F1, #88
db #FD, #F1, #FA, #FD, #F6, #FF, #F4, #FB, #F9, #F1, #88
db #FD, #F9, #FA, #F5, #F2, #F1, #F4, #FA, #F1, #F1, #88
db #FD, #F5, #FA, #F5, #FE, #FF, #F3, #F2, #F1, #F1, #88
db #FC, #F0, #F0, #F0, #F0, #F0, #F0, #F0, #F0, #F1, #88
db #33, #F0, #F0, #F0, #F0, #F0, #F0, #F0, #F0, #E6, #00
db #33, #FF, #FF, #FF, #FF, #FF, #FF, #FF, #FF, #EE, #00
db #00, #FF, #FF, #FF, #FF, #FF, #FF, #FF, #FF, #88, #00
db #00, #00, #00, #00, #00, #00, #00, #00, #00, #00, #00
ret
;;
wait:
  halt
  dec b
jr nz,wait
ret

问题根源

  1. 换行偏移计算错误:Amstrad CPC模式1每行占80字节(0x50),绘制11字节(0xB)后,下一行起始地址需偏移0x50 - 0xB = 0x45,原代码错误使用0x07f5,导致绘制行偏离到视频内存错误区域,擦除时无法覆盖这些区域,残留杂色。
  2. 擦除阶段HL位置恢复错误:手动计算偏移易出错,导致擦除区域与绘制区域不匹配。

修复后的代码

;; testlogo_fixed.asm
;;
.cls    equ &BC14   ;; Clear screen
org &4000
run &4000
;;
call cls
ld hl, #c020        ;; initial position of video
ld a,#05            ;; times logo down      
call loop1          ;; call main loop
jr $
;;
loop1:
   push hl          ;; 保存初始视频位置,擦除时恢复
   ld bc,logo       ;; initial position of logo
   ld e,#08
   call loop_paint
   ld de, #c050
   add hl,de
                    ;; the second 8 row group pixels
   ld e,#08
   call loop_paint
   ld de,#c050
   add hl,de
                    ;; wait until 'down' logo
   ld b,#cc
   call wait
   pop hl           ;; 恢复初始视频位置,确保擦除区域正确
   ld e,#08
   call loop_erase1 ;; call to 'erase' pixels
   ld de, #c050
   add hl,de
   ld e,#08
   call loop_erase1
   ld de, #c050
   add hl,de
   dec a
jr nz, loop1
ret
;;
loop_paint:
   ld d,#0b
   call loop_logo   ;; call to paint logo
   push bc          ;; save bc in stack
   ld bc,#0045      ;; 模式1每行80字节(0x50),减去已绘制的11字节(0xB),得到下一行偏移
   add hl,bc
   pop bc 
   dec e
jr nz, loop_paint
ret
;;
loop_logo:          ;; finally 'paints' logo
                    ;; in memory video
   push af          ;; save 'a' register
   ld a, (bc)
   ld (hl), a
   pop af
   inc l
   inc c
   dec d
jr nz,loop_logo
ret
;;
loop_erase1:        ;; row by row in mode 1 video
   ld d,#0b     
   call loop_erase2
   ld bc,#0045      ;; 同绘制阶段的换行偏移
   add hl,bc
   dec e
jr nz,loop_erase1
ret
;;
loop_erase2:        ;; column by column in mode 1 video
   ld (hl), #00 
   inc l
   dec d
jr nz,loop_erase2
ret
;;
logo:
db #00, #00, #00, #00, #00, #00, #00, #00, #00, #00, #00
db #00, #00, #00, #00, #00, #00, #00, #00, #00, #00, #00
db #00, #FF, #FF, #FF, #FF, #FF, #FF, #FF, #FF, #88, #00
db #33, #FF, #FF, #FF, #FF, #FF, #FF, #FF, #FF, #EE, #00
db #33, #F0, #F0, #F0, #F0, #F0, #F0, #F0, #F0, #E6, #00
db #FC, #F0, #F0, #F0, #F0, #F0, #F0, #F0, #F0, #F1, #88
db #FD, #F5, #FB, #F5, #FE, #FF, #F3, #F3, #FB, #FD, #88
db #FD, #F9, #FB, #FD, #F0, #F8, #F4, #FA, #F1, #F1, #88
db #FD, #F1, #FA, #FD, #F6, #FF, #F4, #FB, #F9, #F1, #88
db #FD, #F9, #FA, #F5, #F2, #F1, #F4, #FA, #F1, #F1, #88
db #FD, #F5, #FA, #F5, #FE, #FF, #F3, #F2, #F1, #F1, #88
db #FC, #F0, #F0, #F0, #F0, #F0, #F0, #F0, #F0, #F1, #88
db #33, #F0, #F0, #F0, #F0, #F0, #F0, #F0, #F0, #E6, #00
db #33, #FF, #FF, #FF, #FF, #FF, #FF, #FF, #FF, #EE, #00
db #00, #FF, #FF, #FF, #FF, #FF, #FF, #FF, #FF, #88, #00
db #00, #00, #00, #00, #00, #00, #00, #00, #00, #00, #00
ret
;;
wait:
  halt
  dec b
jr nz,wait
ret

修复说明

  • 将loop_paint和loop_erase1中的换行偏移0x07f5改为0x0045,匹配模式1的视频内存行布局。
  • 在loop1中用push hl/pop hl保存和恢复初始绘制位置,确保擦除区域与绘制区域完全对应,避免手动计算偏移的错误。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.20 00:05:20