For my next project I'm using the 8bpp palette from this link: https://wikiti.brandonw.net/index.php?title=84PCE:Ports:4000

Thus, Register A and Register D create a colour in the palette.

I'm trying to get a "fade to black" effect by changing the palette over time. But my palette jumps all over the place instead of simply "fading." Here's my code, as unoptimized as it may be. What am I doing wrong?

Code:
```    ;B is how much to subtract from the BGR colors.  B gradually gets larger and larger.    and %01111100  ;The LSB part of "green" does not matter to me    rrca \ rrca ;Now A = the blue amount    sub b    jr c, BlueABelowZero    cp 32    jr c, DoneBlueA    ld a, 31    jr DoneBlueA BlueABelowZero:    xor a DoneBlueA:    ld (TB),a  ;TB = Where to store the blue value while we work with red and green    ld a, d ; D = the GGGRRRRR part    and %00011111       sub b    jr c, RedABelowZero    cp 32    jr c, DoneRedA    ld a, 31    jr DoneRedA RedABelowZero:    xor a DoneRedA:    ld (TR),a  ;Temporary red    srl c \ rr d    srl c \ rr d    ld a, d    and %11111000    rrca \ rrca \ rrca    call DoPaletteGreen    ld c, a    ld a, (TB)    sla c \ sla c \ sla c    sla c \ rla    sla c \ rla    push af    ld a, (TR)    add a, c    ld d, a    pop af ; At this point, registers A and D should be the newly-updated palette values DoPaletteGreen:    sub b    jr c, GreenABelowZero    cp 32    jr c, DoneGreenA    ld a, 31    jr DoneGreenA GreenABelowZero:    xor a DoneGreenA:    ret ```
Here is a function that can do this automatically - arguments are pushed onto the stack:

Code:
```;------------------------------------------------------------------------------- gfx_Darken: ; Darkens a 16 bit 1555 color (0 = black, 255 = same color) ; Arguments: ;  arg0 : 16 bit color ;  arg1 : 8 bit change amount ; Returns: ;  16 bit color value    pop   de         ; de = return vector    pop   bc         ; bc = color    ex   (sp),hl         ; l = amt    push   bc    push   de         ; Comments assume 1555 RGB color _Darken:    push   bc         ; Calculate the output blue value    ld   a,c         ; a = color & \$FF    ld   c,l         ; c = amt    and   a,31    ld   h,a         ; h = blue    mlt   hl         ; hl = blue * amt    ld   de,128         ; de = 128    add   hl,de         ; hl = blue * amt + 128    ld   l,h    ld   h,d         ; hl = (blue * amt + 128) / 256 = blue_out    ex   (sp),hl         ; hl = color, tmp1 = blue_out                ; Isolate the input red value    ld   a,h         ; a = color >> 8    rra            ; a = color >> 9    and   a,62    ld   b,a         ; b = red << 1                ; Calculate the output green value    add.s   hl,hl    rla            ; a & 1 = green & 1    add   hl,hl    add   hl,hl         ; hl = color << 3    rra    ld   a,h    rla    and   a,63    ld   h,a         ; h = green    ld   l,c         ; l = amt    mlt   hl         ; hl = green * amt    add   hl,de         ; hl = green * amt + 128    ld   l,h         ; l = (green * amt + 128) / 256 = green_out                ; Calculate the output red value    mlt   bc         ; bc = red * amt << 1    inc   b         ; b = (red * amt + 128 << 1) / 256    srl   b         ; b = (red * amt + 128) / 256 = red_out                ; Position the output red and green bits    add   hl,hl    add   hl,hl         ; l = green_out << 2    ld   h,b         ; h = red_out    add   hl,hl    add   hl,hl         ; hl = (red_out << 10) | (green_out << 4)    bit   4,l    jr   z,.out    set   7,h    res   4,l         ; hl = (green_out & 1 << 15) | (red_out << 10) | (green_out >> 1 << 5) .out:                ; Add the output blue value (no positioning necessary) for the final output color    pop   bc         ; bc = blue_out    add   hl,bc         ; hl = color_out    ret```
Thanks MateoConLechuga, but unfortunately, my ASM skills aren't so advanced that I can work with pushing arguments onto a stack -- I tried getting your code to work, and I couldn't. I'm used to routines where the arguments are stored in registers. And in addition, I'd like the routine to change the colours in both directions -- not just to black, but to white, too. Does yours do that?
Okay so get rid of the stack stuff... use it like this:

Code:
```    ld l,128 ; darken/lighten amount 0-255     ld bc,\$AA55 ; 1555 color     call gfx_Darken ; output in hl     ld de,palette_address     ld (de),hl```

Here is both lighten and darken:

Code:
```;------------------------------------------------------------------------------- gfx_Lighten: ; Lightens a 16 bit 1555 color (0 = white, 255 = same color) ; Arguments: ;  bc = 1555 color ;  l = amount to change ; Returns: ;  hl = 16 bit color value                ; Strategy: lighten(color, amt) = ~darken(~color, amt)                ; Darken the inverted color    ld   a,c    cpl    ld   c,a    ld   a,b    cpl    ld   b,a         ; bc = ~color    call   _Darken         ; hl = darken(~color, amt)    ld   a,l         ; Invert the darken result for the lighten result    cpl    ld   l,a    ld   a,h    cpl    ld   h,a         ; hl = ~darken(~color, amt) = lighten(color, amt)    ret ;------------------------------------------------------------------------------- gfx_Darken: ; Darkens a 16 bit 1555 color (0 = black, 255 = same color) ; Arguments: ;  bc = 1555 color ;  l = amount to change ; Returns: ;  hl = 16 bit color value    push   bc         ; Calculate the output blue value    ld   a,c         ; a = color & \$FF    ld   c,l         ; c = amt    and   a,31    ld   h,a         ; h = blue    mlt   hl         ; hl = blue * amt    ld   de,128         ; de = 128    add   hl,de         ; hl = blue * amt + 128    ld   l,h    ld   h,d         ; hl = (blue * amt + 128) / 256 = blue_out    ex   (sp),hl         ; hl = color, tmp1 = blue_out                ; Isolate the input red value    ld   a,h         ; a = color >> 8    rra            ; a = color >> 9    and   a,62    ld   b,a         ; b = red << 1                ; Calculate the output green value    add.s   hl,hl    rla            ; a & 1 = green & 1    add   hl,hl    add   hl,hl         ; hl = color << 3    rra    ld   a,h    rla    and   a,63    ld   h,a         ; h = green    ld   l,c         ; l = amt    mlt   hl         ; hl = green * amt    add   hl,de         ; hl = green * amt + 128    ld   l,h         ; l = (green * amt + 128) / 256 = green_out                ; Calculate the output red value    mlt   bc         ; bc = red * amt << 1    inc   b         ; b = (red * amt + 128 << 1) / 256    srl   b         ; b = (red * amt + 128) / 256 = red_out                ; Position the output red and green bits    add   hl,hl    add   hl,hl         ; l = green_out << 2    ld   h,b         ; h = red_out    add   hl,hl    add   hl,hl         ; hl = (red_out << 10) | (green_out << 4)    bit   4,l    jr   z,.out    set   7,h    res   4,l         ; hl = (green_out & 1 << 15) | (red_out << 10) | (green_out >> 1 << 5) .out:                ; Add the output blue value (no positioning necessary) for the final output color    pop   bc         ; bc = blue_out    add   hl,bc         ; hl = color_out    ret```
Thanks! I'll give those a try.

EDIT: Thanks again, MateoConLechuga! These are great!

Register to Join the Conversation
Have your own thoughts to add to this or any other topic? Want to ask a question, offer a suggestion, share your own programs and projects, upload a file to the file archives, get help with calculator and computer programming, or simply chat with like-minded coders and tech and calculator enthusiasts via the site-wide AJAX SAX widget? Registration for a free Cemetech account only takes a minute.

»
» All times are UTC - 5 Hours

You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum