Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/assembly/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Assembly GameBoy Z80中位操作算法的优化_Assembly_Bit Manipulation_Z80_Gameboy - Fatal编程技术网

Assembly GameBoy Z80中位操作算法的优化

Assembly GameBoy Z80中位操作算法的优化,assembly,bit-manipulation,z80,gameboy,Assembly,Bit Manipulation,Z80,Gameboy,这不是家庭作业问题,这是我正在开发的游戏 我有两个16位RGB颜色,并希望根据其他六个四位数量改变它们的六个通道。算法简单但繁琐;我正在寻找一种方法,通过同时做更多有用的工作来优化它 高级别概览: hl指向四个颜色字节[hl]=%GGGRRRR,[hl+1]=%0bbbbbgg,[hl+2]=%GGGRRRR,[hl+3]=%0bbbbbgg。(这是两种颜色,rgb和rgb) bc指向三个增量字节[bc]=%hhhaaaa,[bc+1]=%ddddsss,[bc+2]=%ppppqqq。(这是

这不是家庭作业问题,这是我正在开发的游戏

我有两个16位RGB颜色,并希望根据其他六个四位数量改变它们的六个通道。算法简单但繁琐;我正在寻找一种方法,通过同时做更多有用的工作来优化它

高级别概览:

  • hl
    指向四个颜色字节<代码>[hl]=%GGGRRRR,
    [hl+1]=%0bbbbbgg
    [hl+2]=%GGGRRRR
    [hl+3]=%0bbbbbgg
    。(这是两种颜色,
    rgb
    rgb
  • bc
    指向三个增量字节<代码>[bc]=%hhhaaaa,
    [bc+1]=%ddddsss
    [bc+2]=%ppppqqq
    。(这是六个增量值,
    h
    a
    d
    s
    p
    q
  • 因此有六个5位颜色通道值和六个4位增量值。我想将每个颜色通道C与delta值D配对,并像这样改变CC'=C+(D&%11)− ((D和%1100)>>2),但将C保持在其5位范围内[0,31]。我并不在乎它们是如何配对的:任何方便的一对一配对都可以。如果C+(D&%1100)>>2)− (D&%11)允许某种更优雅的算法,我不介意
如果我在寄存器
d
中分离出一个颜色通道C,在寄存器
e
中分离出一个增量值d,则此例程将对该对进行变异:

VaryColorChannelByDV:
; d = color, e = DV
; a <- d + (e & %11) - (e >> 2), clamped to [0, 31]
    ld a, e
    and %11   ; a <- (e & %11)
    add d   ; a <- d + (e & %11)
    srl e
    srl e   ; e <- e >> 2
    sub e   ; a <- d + (e & %11) - (e >> 2)
    jr c, .zero   ; a < 0, clamp to 0
    cp 32
    ret c   ; 0 <= a < 32
    ld a, 31   ; a >= 32, clamp to 31
    ret
.zero
    xor a
    ret
VaryColorChannelByDV:
; d=颜色,e=DV
; a>2),钳制到[0,31]
ld a,e
及百分之十一;;a(2)
jr c,.0;a<0,钳位为0
cp 32
retc;0=32,夹紧至31
ret
.零
异或a
ret
到目前为止,我有一个通用例程,可以将任何DV应用于任何颜色通道;然后是三个例程,用于隔离红色、绿色或蓝色通道并对其应用给定的DV;最后是一个主例程,它选择六个DV并调用相应的通道修改例程。这是“足够好”,但我确信还有改进的余地。执行速度似乎不是问题,但我想减少代码大小(当然,删除冗余指令也会稍微提高速度)。是否有任何asm位操作技巧会有所帮助

以下是完整的代码:

GetColorChannelVariedByDV:
; d = color, e = DV
; a <- d + (e & %11) - (e & %1100 >> 2), clamped to [0, 31]
    ld a, e
    and %11
    add d
    srl e
    srl e
    sub e
    jr c, .zero
    cp 32
    ret c
    ld a, 31
    ret
.zero
    xor a
    ret

VaryRedByDV:
;;; e = DV
;;; [hl+0] = gggr:rrrr
;;; [hl+1] = 0bbb:bbgg
; store red in d
    ld a, [hl]
    and %00011111
    ld d, a
; vary d according to e
    call GetColorChannelVariedByDV
; store a back in red
    ld d, a
    ld a, [hl]
    and %11100000
    or d
    ld [hl], a
    ret

VaryGreenByDV:
;;; e = DV
;;; [hl+0] = gggr:rrrr
;;; [hl+1] = 0bbb:bbgg
; store green in d
    ld a, [hli]
    and %11100000
    srl a
    swap a
    ld d, a ; d = 00000ggg
    ld a, [hld]
    and %00000011
    swap a
    srl a
    or d
    ld d, a
; vary d according to e
    call GetColorChannelVariedByDV
; store a back in green
    sla a
    swap a
    ld d, a
    and %11100000
    ld e, a
    ld a, d
    and %00000011
    ld d, a
    ld a, [hl]
    and %00011111
    or e
    ld [hli], a
    ld a, [hl]
    and %11111100
    or d
    ld [hld], a
    ret

VaryBlueByDV:
;;; e = DV
;;; [hl+0] = gggr:rrrr
;;; [hl+1] = 0bbb:bbgg
; store blue in d
    inc hl
    ld a, [hl]
    and %01111100
    srl a
    srl a
    ld d, a
; vary d according to e
    call GetColorChannelVariedByDV
; store a back in blue
    ld d, a
    sla d
    sla d
    ld a, [hl]
    and %10000011
    or d
    ld [hl], a
    dec hl
    ret

VaryColorsByDVs::
; hl = colors
; [hl+0] = gggr:rrrr
; [hl+1] = 0bbb:bbgg
; [hl+2] = GGGR:RRRR
; [hl+3] = 0BBB:BBGG
; bc = DVs
; [bc+0] = hhhh:aaaa
; [bc+1] = dddd:ssss
; [bc+2] = pppp:qqqq

;;; LiteRed ~ hDV, aka, rrrrr ~ hhhh
; store hDV in e
    ld a, [bc]
    swap a
    and %1111
    ld e, a
; vary LiteRed by e
    call VaryRedByDV

;;; LiteGrn ~ aDV, aka, ggggg ~ aaaa
; store aDV in e
    ld a, [bc]
    and %1111
    ld e, a
; vary LiteGrn by e
    call VaryGreenByDV

;;; move from h/a DV to d/s DV
    inc bc

;;; LiteBlu ~ dDV, aka, bbbbb ~ dddd
; store dDV in e
    ld a, [bc]
    swap a
    and %1111
    ld e, a
; vary LiteBlu by e
    call VaryBlueByDV

;;; Move from Lite color to Dark color
    inc hl
    inc hl

;;; DarkRed ~ sDV, aka, RRRRR ~ ssss
; store sDV in e
    ld a, [bc]
    and %1111
    ld e, a
; vary DarkRed by e
    call VaryRedByDV

;;; move from d/s DV to p/q DV
    inc bc

;;; DarkGrn ~ pDV, aka, GGGGG ~ pppp
; store pDV in e
    ld a, [bc]
    swap a
    and %1111
    ld e, a
; vary DarkGrn by e
    call VaryGreenByDV

;;; DarkBlu ~ qDV, aka, BBBBB ~ qqqq
; store qDV in e
    ld a, [bc]
    and %1111
    ld e, a
; vary DarkBlu by e
    call VaryBlueByDV

    ret
GetColorChannelVariedByDV:
; d=颜色,e=DV
; a>2),钳制到[0,31]
ld a,e
和%11
加d
srl e
srl e
次级e
jr c,.0
cp 32
ret c
劳工处,31岁
ret
.零
异或a
ret
VaryRedByDV:
;;; e=DV
;;; [hl+0]=gggr:rrrr
;;; [hl+1]=0bbb:bbgg
; 将红色储存在d中
ld a[hl]
和%0001111
劳工处
; 根据e改变d
调用GetColorChannelVariedByDV
; 以红色储存背面
劳工处
ld a[hl]
和11100000%
或d
ld[hl],a
ret
VaryGreenByDV:
;;; e=DV
;;; [hl+0]=gggr:rrrr
;;; [hl+1]=0bbb:bbgg
; 在d中存储绿色
劳工处[hli]
和11100000%
srl a
交换
劳工处处长,a;d=00000千兆克
劳工处[hld]
和%00000011
交换
srl a
或d
劳工处
; 根据e改变d
调用GetColorChannelVariedByDV
; 以绿色储存背面
sla a
交换
劳工处
和11100000%
ld e,a
ld a,d
和%00000011
劳工处
ld a[hl]
和%0001111
或e
ld[hli],a
ld a[hl]
和%111100
或d
ld[hld],a
ret
VaryBlueByDV:
;;; e=DV
;;; [hl+0]=gggr:rrrr
;;; [hl+1]=0bbb:bbgg
; 将蓝色储存在d中
公司hl
ld a[hl]
和%0111100
srl a
srl a
劳工处
; 根据e改变d
调用GetColorChannelVariedByDV
; 以蓝色存储背面
劳工处
sla d
sla d
ld a[hl]
和%1000011
或d
ld[hl],a
dec hl
ret
VaryColorsByDVs::
; hl=颜色
; [hl+0]=gggr:rrrr
; [hl+1]=0bbb:bbgg
; [hl+2]=GGGR:RRRR
; [hl+3]=0BBB:BBGG
; bc=DVs
; [bc+0]=hhhh:aaaa
; [bc+1]=dddd:ssss
; [bc+2]=pppp:qqqq
;;; LiteRed~hDV,又名rrrrrrr~hhh
; 将hDV存储在e中
劳工处[bc]
交换
和%1111
ld e,a
; 用e表示变化
调用VaryRedByDV
;;; LiteGrn~aDV,aka,ggggg~aaaa
; 在e中存储aDV
劳工处[bc]
和%1111
ld e,a
; 用e改变字母
调用VaryGreenByDV
;;; 从h/a DV移动到d/s DV
不列颠哥伦比亚公司
;;; LiteBlu~dDV,又名,bbbbb~dddd
; 将dDV存储在e中
劳工处[bc]
交换
和%1111
ld e,a
; 用e改变LiteBlu
调用VaryBlueByDV
;;; 从浅色移到深色
公司hl
公司hl
;;; 暗礁~sDV,又名,RRRRR~ssss
; 将sDV存储在e中
劳工处[bc]
和%1111
ld e,a
; 用e变暗
调用VaryRedByDV
;;; 从d/s DV移动到p/q DV
不列颠哥伦比亚公司
;;; DarkGrn~pDV,又名GGGGG~pppp
; 将pDV存储在e中
劳工处[bc]
交换
和%1111
ld e,a
; 用e改变黑暗
调用VaryGreenByDV
;;; 暗黑的~qDV,又名,BBBBB~qqq
; 将qDV存储在e中
劳工处[bc]
和%1111
ld e,a
; 用e改变暗色
调用VaryBlueByDV
ret

嗯。。。如果您可以进一步预处理这些数据,您应该向我们提供有关这些数据来源的更多信息,因为
+(d&3)-(d>>2)
看起来很不幸,如果可能的话,我会尽量避免。实际上,整个5:5:5 RGB的东西可能有点超出Z80的范围,但是如果你知道它对你有用,那就继续吧(我是根据我的ZX频谱经验说的,3.5MHz几乎不足以操控1位黑白像素)

但就目前而言,通过删除两条
ld
指令,可以立即简化您已经获得的内容:

VaryColorChannelByDV:
    ...
    add d
;    ld d, a   ; d <- d + (e & %11)
    srl e
    srl e
;    ld a, d   ;### A didn't change, still contains C + DV&3
    sub e   ; a <- d + (e & %11) - (e & %1100 >> 2)
    ...
VaryColorChannelByDV:
...
加d

; 劳工处处长,a;d我现在能想到的最小值是57字节:

VaryColorsByDVs::
; hl = colors
; [hl+0] = gggr:rrrr
; [hl+1] = 0bbb:bbgg
; [hl+2] = GGGR:RRRR
; [hl+3] = 0BBB:BBGG
; bc = DVs
; [bc+0] = hhhh:aaaa
; [bc+1] = dddd:ssss
; [bc+2] = pppp:qqqq
    ld a, 2 ; -floor($100/3)*6 mod $100
.next:
    sla [hl]
    inc hl
    rl [hl]
.loop:
    push af
    rrca
    ld a, [bc]
    jr nc, .skip
    swap a
    inc bc
.skip:
    rlca
    ld d, a
    and %00011000
    ld e, a
    ld a, d
    rlca
    rlca
    and %00011000
    add a, [hl]
    jr nc, .noOverflow
    or %11111000
.noOverflow:
    sub e
    jr nc, .noUnderflow
    and %00000111
.noUnderflow:
    dec hl
    ld de, 5
.rotate:
    add a, a
    rl [hl]
    adc a, d
    dec e
    jr nz, .rotate
    inc hl
    ld [hl], a
    pop af
    add a, 85 ; floor($100/3)
    jr nc, .loop
    ret z
    inc hl
    jr .next
仅修复Ped7g的评论
VaryColorsByDVs::
; hl = colors
; [hl+0] = gggr:rrrr
; [hl+1] = 0bbb:bbgg
; [hl+2] = GGGR:RRRR
; [hl+3] = 0BBB:BBGG
; bc = DVs
; [bc+0] = hhhh:aaaa
; [bc+1] = dddd:ssss
; [bc+2] = pppp:qqqq
    ld a, 2 ; -floor($100/3)*6 mod $100
.next:
    sla [hl]
    inc hl
    rl [hl]
.loop:
    push af
    rrca
    ld a, [bc]
    jr nc, .skip
    swap a
    inc bc
.skip:
    ld d, a
    and %00001100
    ld e, a
    ld a, d
    rlca
    rlca
    and %00001100
    sub e
    add a, a
    jr nc, .positive
.negative:
    add a, [hl]
    jr c, .continue
    and %00000111
    db $38 ; jr c,
.positive:
    add a, [hl]
    jr nc, .continue
    or %11111000
.continue:
    dec hl
    ld de, 5
.rotate:
    add a, a
    rl [hl]
    adc a, d
    dec e
    jr nz, .rotate
    inc hl
    ld [hl], a
    pop af
    add a, 85 ; floor($100/3)
    jr nc, .loop
    ret z
    inc hl
    jr .next