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.
Hmmm…that’s not quite right. Let’s try again.
Thanks @SD9000
Once more, with fury!
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!