; DMGTRIS ; Copyright (C) 2023 - Randy Thiemann ; This program is free software: you can redistribute it and/or modify ; it under the terms of the GNU General Public License as published by ; the Free Software Foundation, either version 3 of the License, or ; (at your option) any later version. ; This program is distributed in the hope that it will be useful, ; but WITHOUT ANY WARRANTY; without even the implied warranty of ; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ; GNU General Public License for more details. ; You should have received a copy of the GNU General Public License ; along with this program. If not, see . IF !DEF(RGB555_ASM) DEF RGB555_ASM EQU 1 INCLUDE "hardware.inc" ; Macro to define an RGB555 color to be used in CGB mode. ; Will result in a symbol named COLORNAME, COLORNAME_A and COLORNAME_C being created. ; Usage: ; DEF_RGB555 COLORNAME, R, G, B MACRO DEF_RGB555 ASSERT (\2) >= 0 && (\2) <= 31, "ERROR in DEF_RGB555: R value given was not in the range [0; 31]." ASSERT (\3) >= 0 && (\3) <= 31, "ERROR in DEF_RGB555: G value given was not in the range [0; 31]." ASSERT (\4) >= 0 && (\4) <= 31, "ERROR in DEF_RGB555: B value given was not in the range [0; 31]." DEF COLOR EQUS "\1" ; Uncorrected DEF R_A EQU (\2 & $1F) DEF G_A EQU (\3 & $1F) DEF B_A EQU (\4 & $1F) DEF {COLOR} EQU (R_A << 0) | (G_A << 5) | (B_A << 10) DEF {COLOR}_A EQU (R_A << 0) | (G_A << 5) | (B_A << 10) ; Transfer function. DEF GAMMA EQU 2.0q25 DEF INVGAMMA EQU DIV(1.0q25, 2.0q25, 25) DEF RGBMAX EQU 31.0q25 DEF INVRGBMAX EQU DIV(1.0q25, 31.0q25, 25) ; From display gamma. DEF R_C0 EQU POW(MUL(R_A << 25, INVRGBMAX), GAMMA, 25) DEF G_C0 EQU POW(MUL(G_A << 25, INVRGBMAX), GAMMA, 25) DEF B_C0 EQU POW(MUL(B_A << 25, INVRGBMAX), GAMMA, 25) ; To convert a color as displayed on a game boy color to the original color, the following formulas must be applied: ; R' = (0.86629 * R) + (0.13361 * G) + (0.00000 * B) ; G' = (0.02429 * R) + (0.70857 * G) + (0.25714 * B) ; B' = (0.11337 * R) + (0.11448 * G) + (0.77215 * B) ; We need the inverted matrix here. DEF R_C1 EQU (MUL(R_C0, +1.15039q25, 25) + MUL(G_C0, -0.22976q25, 25) + MUL(B_C0, +0.07949q25, 25)) DEF G_C1 EQU (MUL(R_C0, +0.02568q25, 25) + MUL(G_C0, +1.48972q25, 25) + MUL(B_C0, -0.51540q25, 25)) DEF B_C1 EQU (MUL(R_C0, -0.17271q25, 25) + MUL(G_C0, -0.18713q25, 25) + MUL(B_C0, +1.35983q25, 25)) ; DEF R_C1 EQU (MUL(R_C0, +1.0q25, 25) + MUL(G_C0, +0.0q25, 25) + MUL(B_C0, +0.0q25, 25)) ; DEF G_C1 EQU (MUL(R_C0, +0.0q25, 25) + MUL(G_C0, +1.0q25, 25) + MUL(B_C0, +0.0q25, 25)) ; DEF B_C1 EQU (MUL(R_C0, +0.0q25, 25) + MUL(G_C0, +0.0q25, 25) + MUL(B_C0, +1.0q25, 25)) ; To display gamma. DEF R_C2 EQU MUL(RGBMAX, POW(R_C1, INVGAMMA, 25), 25) DEF G_C2 EQU MUL(RGBMAX, POW(G_C1, INVGAMMA, 25), 25) DEF B_C2 EQU MUL(RGBMAX, POW(B_C1, INVGAMMA, 25), 25) ; To display color. DEF R_C3 = (FLOOR(R_C2 + 0.5q25, 25) >> 25) DEF G_C3 = (FLOOR(G_C2 + 0.5q25, 25) >> 25) DEF B_C3 = (FLOOR(B_C2 + 0.5q25, 25) >> 25) ; Clamping IF (R_C3) < 0 DEF R_C3 = 0 ENDC IF (R_C3) > 31 DEF R_C3 = 31 ENDC IF (G_C3) < 0 DEF G_C3 = 0 ENDC IF (G_C3) > 31 DEF G_C3 = 31 ENDC IF (B_C3) < 0 DEF B_C3 = 0 ENDC IF (B_C3) > 31 DEF B_C3 = 31 ENDC DEF R_C EQU (R_C3 & $1F) DEF G_C EQU (G_C3 & $1F) DEF B_C EQU (B_C3 & $1F) DEF {COLOR}_C EQU (R_C << 0) | (G_C << 5) | (B_C << 10) PURGE COLOR, R_A, G_A, B_A, GAMMA, INVGAMMA, RGBMAX, INVRGBMAX, R_C0, G_C0, B_C0, R_C1, G_C1, B_C1, R_C2, G_C2, B_C2, R_C3, G_C3, B_C3, R_C, G_C, B_C ENDM ; Macro to define an RGB555 color to be used in CGB mode using standard 32 bit color semantics. ; Will result in a symbol named COLORNAME, COLORNAME_A and COLORNAME_C being created. ; Usage: ; DEF_RGB555_FROM24 COLORNAME, R, G, B MACRO DEF_RGB555_FROM24 ASSERT (\2) >= 0 && (\2) <= 255, "ERROR in DEF_RGB555_FROM24: R value given was not in the range [0; 255]." ASSERT (\3) >= 0 && (\3) <= 255, "ERROR in DEF_RGB555_FROM24: G value given was not in the range [0; 255]." ASSERT (\4) >= 0 && (\4) <= 255, "ERROR in DEF_RGB555_FROM24: B value given was not in the range [0; 255]." DEF COLOR EQUS "\1" ; Uncorrected DEF R_A EQU ((\2 >> 3) & $1F) DEF G_A EQU ((\3 >> 3) & $1F) DEF B_A EQU ((\4 >> 3) & $1F) DEF {COLOR} EQU (R_A << 0) | (G_A << 5) | (B_A << 10) DEF {COLOR}_A EQU (R_A << 0) | (G_A << 5) | (B_A << 10) ; Transfer function. DEF GAMMA EQU 2.0q25 DEF INVGAMMA EQU DIV(1.0q25, 2.0q25, 25) DEF RGBMAX EQU 31.0q25 DEF INVRGBMAX EQU DIV(1.0q25, 31.0q25, 25) ; From display gamma. DEF R_C0 EQU POW(MUL(R_A << 25, INVRGBMAX), GAMMA, 25) DEF G_C0 EQU POW(MUL(G_A << 25, INVRGBMAX), GAMMA, 25) DEF B_C0 EQU POW(MUL(B_A << 25, INVRGBMAX), GAMMA, 25) ; To convert a color as displayed on a game boy color to the original color, the following formulas must be applied: ; R' = (0.86629 * R) + (0.13361 * G) + (0.00000 * B) ; G' = (0.02429 * R) + (0.70857 * G) + (0.25714 * B) ; B' = (0.11337 * R) + (0.11448 * G) + (0.77215 * B) ; We need the inverted matrix here. DEF R_C1 EQU (MUL(R_C0, +1.15039q25, 25) + MUL(G_C0, -0.22976q25, 25) + MUL(B_C0, +0.07949q25, 25)) DEF G_C1 EQU (MUL(R_C0, +0.02568q25, 25) + MUL(G_C0, +1.48972q25, 25) + MUL(B_C0, -0.51540q25, 25)) DEF B_C1 EQU (MUL(R_C0, -0.17271q25, 25) + MUL(G_C0, -0.18713q25, 25) + MUL(B_C0, +1.35983q25, 25)) ; DEF R_C1 EQU (MUL(R_C0, +0.86629q25, 25) + MUL(G_C0, +0.13361q25, 25) + MUL(B_C0, +0.00000q25, 25)) ; DEF G_C1 EQU (MUL(R_C0, +0.02429q25, 25) + MUL(G_C0, +0.70857q25, 25) + MUL(B_C0, +0.25714q25, 25)) ; DEF B_C1 EQU (MUL(R_C0, +0.11337q25, 25) + MUL(G_C0, +0.11448q25, 25) + MUL(B_C0, +0.77215q25, 25)) ; To display gamma. DEF R_C2 EQU MUL(RGBMAX, POW(R_C1, INVGAMMA, 25), 25) DEF G_C2 EQU MUL(RGBMAX, POW(G_C1, INVGAMMA, 25), 25) DEF B_C2 EQU MUL(RGBMAX, POW(B_C1, INVGAMMA, 25), 25) ; To display color. DEF R_C3 = (FLOOR(R_C2 + 0.5q25, 25) >> 25) DEF G_C3 = (FLOOR(G_C2 + 0.5q25, 25) >> 25) DEF B_C3 = (FLOOR(B_C2 + 0.5q25, 25) >> 25) ; Clamping IF (R_C3) < 0 DEF R_C3 = 0 ENDC IF (R_C3) > 31 DEF R_C3 = 31 ENDC IF (G_C3) < 0 DEF G_C3 = 0 ENDC IF (G_C3) > 31 DEF G_C3 = 31 ENDC IF (B_C3) < 0 DEF B_C3 = 0 ENDC IF (B_C3) > 31 DEF B_C3 = 31 ENDC DEF R_C EQU (R_C3 & $1F) DEF G_C EQU (G_C3 & $1F) DEF B_C EQU (B_C3 & $1F) DEF {COLOR}_C EQU (R_C << 0) | (G_C << 5) | (B_C << 10) PURGE COLOR, R_A, G_A, B_A, GAMMA, INVGAMMA, RGBMAX, INVRGBMAX, R_C0, G_C0, B_C0, R_C1, G_C1, B_C1, R_C2, G_C2, B_C2, R_C3, G_C3, B_C3, R_C, G_C, B_C ENDM ; Macro to write a set of 4 colors to a CGB background palette. ; Usage: ; WRITEPAL_B ID, COLOR0, COLOR1, COLOR2, COLOR3 MACRO WRITEPAL_B ASSERT (\1) >= 0 && (\1) <= 7, "ERROR in WRITEPAL_B: ID value given was not in the range [0; 7]." ld a, BCPSF_AUTOINC | (\1 * 8) ldh [rBCPS], a ld bc, \2 ld a, c ldh [rBCPD], a ld a, b ldh [rBCPD], a ld bc, \3 ld a, c ldh [rBCPD], a ld a, b ldh [rBCPD], a ld bc, \4 ld a, c ldh [rBCPD], a ld a, b ldh [rBCPD], a ld bc, \5 ld a, c ldh [rBCPD], a ld a, b ldh [rBCPD], a ENDM ; Macro to write a set of 4 colors to a CGB object palette. ; Usage: ; WRITEPAL_O ID, COLOR0, COLOR1, COLOR2, COLOR3 MACRO WRITEPAL_O ASSERT (\1) >= 0 && (\1) <= 7, "ERROR in WRITEPAL_O: ID value given was not in the range [0; 7]." ld a, 0CPSF_AUTOINC | (\1 * 8) ldh [rOCPS], a ld bc, \2 ld a, c ldh [rOCPD], a ld a, b ldh [rOCPD], a ld bc, \3 ld a, c ldh [rOCPD], a ld a, b ldh [rOCPD], a ld bc, \4 ld a, c ldh [rOCPD], a ld a, b ldh [rOCPD], a ld bc, \5 ld a, c ldh [rOCPD], a ld a, b ldh [rOCPD], a ENDM ; Macro to write a set of 4 colors to a CGB object and background palette. ; Usage: ; WRITEPAL_A ID, COLOR0, COLOR1, COLOR2, COLOR3 MACRO WRITEPAL_A ASSERT (\1) >= 0 && (\1) <= 7, "ERROR in WRITEPAL_O: ID value given was not in the range [0; 7]." ld a, OCPSF_AUTOINC | (\1 * 8) ldh [rOCPS], a ldh [rBCPS], a ld bc, \2 ld a, c ldh [rOCPD], a ldh [rBCPD], a ld a, b ldh [rOCPD], a ldh [rBCPD], a ld bc, \3 ld a, c ldh [rOCPD], a ldh [rBCPD], a ld a, b ldh [rOCPD], a ldh [rBCPD], a ld bc, \4 ld a, c ldh [rOCPD], a ldh [rBCPD], a ld a, b ldh [rOCPD], a ldh [rBCPD], a ld bc, \5 ld a, c ldh [rOCPD], a ldh [rBCPD], a ld a, b ldh [rOCPD], a ldh [rBCPD], a ENDM ENDC