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.

» Go to Registration page
Page 1 of 1
» 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

 

Advertisement