Funky color stuff

For context, @circleseverywhere and I were talking about a hack where things get progressively whackier as time goes on. Inventories get shuffled around, units move, the controls get switched, and…

So I did. And it actually looks kinda cool!

Color reversal images

https://i.imgur.com/vn18PGe.png
https://i.imgur.com/OfHyy47.png
https://i.imgur.com/s7Fr4Cg.png

Color reversal code
PUSH

ORG $DB8
BYTE $10 $B5 $49 $10 $49 $00 $09 $4B $C9 $18 $52 $08 $08 $4C $03 $88 $63 $40 $0B $80 $02 $30 $02 $31 $01 $3A $00 $2A $F7 $DC $05 $48 $01 $21 $01 $70 $10 $BC $01 $BC $00 $47 $00 $00 $A8 $28 $02 $02 $FF $7F $00 $00 $0E $00 $00 $03

POP

Is that all? Of course not! A quick edit to that code makes RedFE, now with extra red.

Red lobster, standing by

https://i.imgur.com/7gMptcS.png

PUSH

ORG $DB8
BYTE $10 $B5 $49 $10 $49 $00 $09 $4B $C9 $18 $52 $08 $1F $24 $03 $88 $23 $40 $0B $80 $02 $30 $02 $31 $01 $3A $00 $2A $F7 $DC $04 $48 $01 $21 $01 $70 $10 $BC $01 $BC $00 $47 $00 $00 $A8 $28 $02 $02 $0E $00 $00 $03

POP

Next, @Kirb suggested sepia, because why not? First, I had to figure out how the heck you sepia-ize an image. This is the source i used, and here are the results.

Take 1

https://i.imgur.com/Oldc60U.png

Hmmm…that’s not quite right. Let’s try again.

Take 2

https://i.imgur.com/npr3gUd.png

Thanks @SD9000

Once more, with fury!

https://i.imgur.com/fAE7MKk.png

Close enough.

Here's the code
PUSH
ORG $DB8
jumpToHack(Sepia)
POP
Sepia:
BYTE $70 $B5 $04 $1C $4D $10 $6D $00 $08 $4E $AD $19 $56 $08 $20 $88 $00 $F0 $10 $F8 $28 $80 $02 $34 $02 $35 $01 $3E $00 $2E $F6 $DC $03 $48 $01 $21 $01 $70 $70 $BC $01 $BC $00 $47 $A8 $28 $02 $02 $0E $00 $00 $03 $F0 $B5 $C4 $06 $E4 $0E $85 $05 $ED $0E $46 $04 $F6 $0E $00 $27 $65 $20 $60 $43 $00 $0A $C5 $21 $69 $43 $09 $0A $40 $18 $61 $21 $71 $43 $49 $0A $40 $18 $1F $28 $00 $DD $1F $20 $07 $1C $B3 $20 $60 $43 $40 $0A $B0 $21 $69 $43 $09 $0A $40 $18 $0B $21 $71 $43 $89 $09 $40 $18 $1F $28 $00 $DD $1F $20 $40 $01 $07 $43 $23 $20 $60 $43 $C0 $09 $89 $21 $69 $43 $09 $0A $40 $18 $11 $21 $71 $43 $C9 $09 $40 $18 $1F $28 $00 $DD $1F $20 $80 $02 $38 $43 $F0 $BC $02 $BC $08 $47

Source:

.thumb

@r0=pointer to palette, r1 = palette bank offset, r2 = number of bytes to copy

push	{r4-r6,r14}
mov		r4,r0
asr		r5,r1,#1
lsl		r5,#1
ldr		r6,=#0x20228A8
add		r5,r6
lsr		r6,r2,#1
Loop1:
ldrh	r0,[r4]
bl		GetSepia
strh	r0,[r5]
add		r4,#2
add		r5,#2
sub		r6,#1
cmp		r6,#0
bgt		Loop1
ldr		r0,=#0x300000E
mov		r1,#1
strb	r1,[r0]
pop		{r4-r6}
pop		{r0}
bx		r0

.ltorg

@r = r*101/256 + g*197/256 + b*97/512
@g = r*179/512 + g*176/256 + b*11/64
@b = b*35/128 + g*137/256 + b*17/128

GetSepia:
push	{r4-r7,r14}
lsl		r4,r0,#27
lsr		r4,#27			@red
lsl		r5,r0,#22
lsr		r5,#27			@green
lsl		r6,r0,#17
lsr		r6,#27			@blue
mov		r7,#0			@new number
@new red
mov		r0,#101
mul		r0,r4
lsr		r0,#8
mov		r1,#197
mul		r1,r5
lsr		r1,#8
add		r0,r1
mov		r1,#97
mul		r1,r6
lsr		r1,#9
add		r0,r1		@red done
cmp		r0,#31
ble		Label1
mov		r0,#31
Label1:
mov		r7,r0
@new blue
mov		r0,#179
mul		r0,r4
lsr		r0,#9
mov		r1,#176
mul		r1,r5
lsr		r1,#8
add		r0,r1
mov		r1,#11
mul		r1,r6
lsr		r1,#6
add		r0,r1
cmp		r0,#31
ble		Label2
mov		r0,#31
Label2:
lsl		r0,#5
orr		r7,r0			@blue done
@new green
mov		r0,#35
mul		r0,r4
lsr		r0,#7
mov		r1,#137
mul		r1,r5
lsr		r1,#8
add		r0,r1
mov		r1,#17
mul		r1,r6
lsr		r1,#7
add		r0,r1
cmp		r0,#31
ble		Label3
mov		r0,#31
Label3:
lsl		r0,#10
orr		r0,r7			@new color
pop		{r4-r7}
pop		{r1}
bx		r1

We can’t really multiply by decimals in assembly code, so I approximated by each value by a number and dividing by a power of 2 (which is very easy to do, compared to dividing by non-powers of 2). That rose-tinted image earlier was caused by dividing the green value in the green color by 512 instead of 256. You can probably make cool variants yourself if you’d like)

Note that this affects all palettes (except the health and safety screen and the Nintendo logo). It works by editing the function that copies palettes from the rom to the palette buffer in ram. Normally it’s just a straight copy and paste job; here, I modify the colors before storing them.
This means that if you want this to happen only under certain circumstances (like, say, you want a specific chapter to be entirely in flashback mode or whatever), you’ll need to do more work.
Modifying colors is pretty easy; each color is 16 bits (2 bytes), with the bottom 5 bits being the red component, the next 5 the green, and the final 5 bits being the blue component (that leaves the topmost bit unused). The entirely red picture was made by stripping the blue and green bits, leaving only red, while negative mode xor’s (exclusive-or) each color with 0x7FFF.
Let me know if you do something cool with this!

16 Likes

I remembered this topic after finishing this, so it probably works a bit differently, but here:

FilterPalette.asm
@ Apply filter to palette before
@ copying to palette buffer. Args:
@   r0: PaletteSlot (0x0, 0x20, 0x40, etc..)
@   r1: RModifier, [-31, 31]
@   r2: GModifier, [-31, 31]
@   r3: BModifier, [-31, 31]
@   [sp]: Palette address
.thumb

push  {r4-r7, r14}
mov   r4, r8
mov   r5, r9
mov   r6, r10
mov   r7, r11
push  {r4-r7}
mov   r8, r1
mov   r9, r2
mov   r10, r3


ldr   r3, =palette_buffer @ 0x020228A8
add   r3, r0
mov   r0, sp
ldr   r4, [r0, #0x24]
mov   r5, #0x1F
mov   r6, #0x0

Loop:
  @ Pick next colour
  ldrh  r7, [r4, r6]
  
  
  @ Red
  mov   r0, r7
  and   r0, r5
  add   r0, r8
  cmp   r0, #0x1F
  bgt   L7
    cmp   r0, #0x0
    blt   L8
      b     L9
  L7:
  mov   r0, #0x1F
  b     L9
  L8:
  mov   r0, #0x0
  L9:
  mov   r1, r0
  
  
  @ Green
  lsr   r0, r7, #0x5
  and   r0, r5
  add   r0, r9
  cmp   r0, #0x1F
  bgt   L4
    cmp   r0, #0x0
    blt   L5
      b     L6
  L4:
  mov   r0, #0x1F
  b     L6
  L5:
  mov   r0, #0x0
  L6:
  lsl   r0, #0x5
  add   r1, r0
  
  
  @ Blue
  lsr   r0, r7, #0xA
  add   r0, r10
  cmp   r0, #0x1F
  bgt   L1
    cmp   r0, #0x0
    blt   L2
      b     L3
  L1:
  mov   r0, #0x1F
  b     L3
  L2:
  mov   r0, #0x0
  L3:
  lsl   r0, #0xA
  add   r1, r0
  
  
  @ New colour
  strh  r1, [r3, r6]
  
  add   r6, #0x2
  cmp   r6, #0x20
  blt   Loop


pop   {r4-r7}
mov   r8, r4
mov   r9, r5
mov   r10, r6
mov   r11, r7
pop   {r4-r7}
pop   {r0}
bx    r0

If one wouldn’t want to hook into CopyToPaletteBuffer, one could call this routine and give it specific modifiers for each colour’s R, G and B values to apply a filter.

Top-to-bottom: Original, Red +8 Blue -8 Green -8, Red -8 Blue -8 Green +8,



3 Likes