diff --git a/config/rel_slices.yml b/config/rel_slices.yml index c7b9ff28..6da4390a 100644 --- a/config/rel_slices.yml +++ b/config/rel_slices.yml @@ -48,6 +48,10 @@ m_kabu_manager.c: .text: [0x803B5CC4, 0x803B6280] .rodata: [0x80642480, 0x806424C0] .data: [0x80655D48, 0x80655D78] +m_lights.c: + .text: [0x803BB960, 0x803BC510] + .rodata: [0x80642680, 0x806426D8] + .bss: [0x81297B18, 0x81297CA0] m_malloc.c: .text: [0x803BC510, 0x803BC70C] .bss: [0x81297CA0, 0x81297CD0] diff --git a/include/libforest/gbi_extensions.h b/include/libforest/gbi_extensions.h index 99486f4a..841e1f37 100644 --- a/include/libforest/gbi_extensions.h +++ b/include/libforest/gbi_extensions.h @@ -336,7 +336,7 @@ typedef struct { unsigned char col[3]; unsigned char kc; unsigned char colc[3]; - unsigned char k1; + unsigned char kl; signed short pos[3]; /* position of light */ unsigned char kq; } Light_pos_t; diff --git a/include/m_lights.h b/include/m_lights.h index 522ae2e0..42ef4d5a 100644 --- a/include/m_lights.h +++ b/include/m_lights.h @@ -2,25 +2,81 @@ #define M_LIGHTS_H #include "types.h" -#include "PR/mbi.h" +#include "libforest/gbi_extensions.h" +#include "m_lib.h" +#include "m_play_h.h" #ifdef __cplusplus extern "C" { #endif -typedef struct lightsn_s { - u8 diffuse_count; - Lights7 lights; -} LightsN; +typedef struct { + /* 0x0 */ s16 x; + /* 0x2 */ s16 y; + /* 0x4 */ s16 z; + /* 0x6 */ u8 color[3]; + /* 0x9 */ u8 drawGlow; + /* 0xA */ s16 radius; +} LightPoint; // size = 0xC +typedef struct { + /* 0x0 */ s8 x; + /* 0x1 */ s8 y; + /* 0x2 */ s8 z; + /* 0x3 */ u8 color[3]; +} LightDiffuse; // size = 0x6 + +typedef union { + LightPoint point; + LightDiffuse diffuse; +} LightParams; // size = 0xC + +typedef struct lights_s { + u8 type; + LightParams lights; +} Lights; + + +typedef struct LightNode { + /* 0x0 */ Lights* info; + /* 0x4 */ struct LightNode* prev; + /* 0x8 */ struct LightNode* next; +} LightNode; // size = 0xC + +typedef struct light_buf_s{ + int current; + int idx; + LightNode lights[32]; +}Light_buffer; + + +typedef struct lightsn_s{ + u8 diffuse_count; + Ambient a; + Light_new l[7]; +}LightsN; typedef struct global_light_s { - /* 0x0 */ void* list; + /* 0x0 */ LightNode* list; /* 0x4 */ u8 ambientColor[3]; /* 0x7 */ u8 fogColor[3]; /* 0xA */ s16 fogNear; /* 0xC */ s16 fogFar; -} Global_light; +} Global_light; // size = 0x10 + +typedef void (*light_point_proc)(LightsN*, LightParams*, xyz_t*); +typedef void (*light_P_point_proc)(LightsN*, LightParams*, xyz_t*); + +extern void Light_point_ct(Lights* lights, s16 x, s16 y, s16 z, u8 r, u8 g, u8 b, s16 radius); +extern void Light_diffuse_ct(Lights* lights, s8 x, s8 y, s8 z, u8 r, u8 g, u8 b); +extern void LightsN_disp_BG(LightsN* lights, GRAPH* graph); +extern void LightsN_disp(LightsN* lights, GRAPH* graph); +extern void LightsN_list_check(LightsN* lights, LightNode* node, xyz_t* pos); +extern void Global_light_ct(Global_light* glight); +extern void Global_light_read(Global_light* glight, GRAPH* graph); +extern void Global_light_list_new(GAME_PLAY*, Global_light* glight, Lights* light); +extern void Global_light_list_delete(Global_light* glight, LightNode* light); +extern void Light_list_point_draw(GAME_PLAY* play); #ifdef __cplusplus } diff --git a/rel/m_lights.c b/rel/m_lights.c new file mode 100644 index 00000000..7bb98515 --- /dev/null +++ b/rel/m_lights.c @@ -0,0 +1,406 @@ +#include "m_lights.h" + +#include "m_rcp.h" +#include "libultra/libultra.h" +#include "m_play.h" +#include "sys_matrix.h" +Light_buffer light_list_buf; + +extern Gfx point_light_init_model[]; +extern Gfx point_light_model[]; + +static void Light_point_color_set(Lights* lights, u8 r, u8 g, u8 b, s16 radius); +static void Global_light_list_ct(Global_light* light); +static void Global_light_ambient_set(Global_light* light, u8 r,u8 g,u8 b); +static void Global_light_fog_set(Global_light* light ,u8 r,u8 g,u8 b,s16 near,s16 far); +static LightsN* new_LightsN(GRAPH*, u8 r, u8 g, u8 b); + + +static void point_data_set(Lights* lights, s16 x, s16 y, s16 z,u8 r, u8 g, u8 b, s16 radius, int type ){ + + lights->type = type; + lights->lights.point.x = x; + lights->lights.point.y = y; + lights->lights.point.z = z; + Light_point_color_set(lights,r,g,b,radius); +} + +extern void Light_point_ct(Lights* lights, s16 x, s16 y, s16 z, u8 r, u8 g, u8 b, s16 radius){ + + point_data_set(lights, x, y, z, r,g,b,radius,0); +} + +static void Light_point_color_set(Lights* lights, u8 r, u8 g, u8 b, s16 radius){ + + lights->lights.point.color[0] = r; + lights->lights.point.color[1] = g; + lights->lights.point.color[2] = b; + lights->lights.point.radius = radius; +} + +extern void Light_diffuse_ct(Lights* lights, s8 x, s8 y, s8 z, u8 r, u8 g, u8 b){ + + lights->type = 1; + lights->lights.diffuse.x = x; + lights->lights.diffuse.y = y; + lights->lights.diffuse.z = z; + lights->lights.diffuse.color[0] = r; + lights->lights.diffuse.color[1] = g; + lights->lights.diffuse.color[2] = b; + +} + +extern void LightsN_disp_BG(LightsN* lights, GRAPH* graph){ + + Light_new* light; + int i; + + OPEN_DISP(graph); + + gSPNumLights(NOW_BG_OPA_DISP++, lights->diffuse_count); + + + light = lights->l; + + for(i = 0; i < lights->diffuse_count; i){ + i++; + gSPLight(NOW_BG_OPA_DISP++, light, i); + gSPLight(NOW_BG_XLU_DISP++, light, i); + light++; + } + + i++; + gSPLight(NOW_BG_OPA_DISP++, &lights->a.l, i); + gSPLight(NOW_BG_XLU_DISP++, &lights->a.l, i); + + CLOSE_DISP(graph); +} + +extern void LightsN_disp(LightsN* lights, GRAPH* graph){ + + Light_new* light; + int i; + Gfx* opa_gfx; + Gfx* xlu_gfx; + + + OPEN_DISP(graph); + opa_gfx = NOW_POLY_OPA_DISP; + xlu_gfx = NOW_POLY_XLU_DISP; + + gSPNumLights(opa_gfx++, lights->diffuse_count); + gSPNumLights(xlu_gfx++, lights->diffuse_count); + + light = lights->l; + + for(i = 0; i < lights->diffuse_count;){ + i++; + gSPLight(opa_gfx++, light, i); + gSPLight(xlu_gfx++, light, i); + light++; + } + + i++; + gSPLight(opa_gfx++, &lights->a.l, i); + gSPLight(xlu_gfx++, &lights->a.l, i); + + SET_POLY_OPA_DISP(opa_gfx); + SET_POLY_XLU_DISP(xlu_gfx); + CLOSE_DISP(graph); +} + +static Light_new* LightsN_new_diffuse(LightsN* lights){ + + if(lights->diffuse_count >= 7){ + return NULL; + } + + return &lights->l[lights->diffuse_count++]; +} + +static void LightsN__point_proc(LightsN* lights, LightParams* lightInfo, xyz_t* point){ + f32 xdiff; + f32 ydiff; + f32 zdiff; + f32 pointd; + f32 rad; + Light_new* light; + + if((point != NULL) && (lightInfo->point.radius > 0)){ + xdiff = lightInfo->point.x - point->x; + ydiff = lightInfo->point.y - point->y; + zdiff = lightInfo->point.z - point->z; + pointd = (xdiff * xdiff) + (ydiff * ydiff) + (zdiff * zdiff); + + rad = lightInfo->point.radius; + + if(pointd < (rad * rad)){ + light = LightsN_new_diffuse(lights); + + if(light != NULL){ + pointd = sqrtf(pointd); + rad = pointd / rad; + rad = 1 - (rad* rad); + + light->l.col[0] = light->l.colc[0] = lightInfo->point.color[0] * rad; + light->l.col[1] = light->l.colc[1] = lightInfo->point.color[1] * rad; + light->l.col[2] = light->l.colc[2] = lightInfo->point.color[2] * rad; + + rad = (pointd < 1) ? 120.0f : 120.0f / pointd; + + light->l.dir[0] = xdiff * rad; + light->l.dir[1] = ydiff * rad; + light->l.dir[2] = zdiff * rad; + + } + } + } +} + +static void LightsN__P_point_proc(LightsN* lights, LightParams* lightInfo, xyz_t*){ + + f32 rad; + xyz_t point; + Light_new* light; + f32 kq; + + if(lightInfo->point.radius > 0){ + light = LightsN_new_diffuse(lights); + + if(light != NULL){ + rad = lightInfo->point.radius; + kq = 4500000.0f / (rad * rad); + if(kq > 255.0f){ + kq = 255.0f; + } + else if(kq < 20.0f){ + kq = 20.0f; + } + light->l.col[0] = lightInfo->point.color[0]; + light->l.colc[0] = light->l.col[0]; + + light->l.col[1] = lightInfo->point.color[1]; + light->l.colc[1] = light->l.col[1]; + + light->l.col[2] = lightInfo->point.color[2]; + light->l.colc[2] = light->l.col[2]; + + light->p.pos[0] = lightInfo->point.x; + light->p.pos[1] = lightInfo->point.y; + light->p.pos[2] = lightInfo->point.z; + light->p.kc = 8; + light->p.kl = -1; + light->p.kq = kq; + + } + } +} + + +static void LightsN__diffuse_proc(LightsN* lights, LightParams* lightInfo){ + + Light_new* light; + + light = LightsN_new_diffuse(lights); + + if(light != NULL){ + light->l.col[0] = light->l.colc[0] = lightInfo->diffuse.color[0]; + light->l.col[1] = light->l.colc[1] = lightInfo->diffuse.color[1]; + light->l.col[2] = light->l.colc[2] = lightInfo->diffuse.color[2]; + light->l.dir[0] = lightInfo->diffuse.x; + light->l.dir[1] = lightInfo->diffuse.y; + light->l.dir[2] = lightInfo->diffuse.z; + + } +} + + +extern void LightsN_list_check(LightsN* lights, LightNode* node, xyz_t* pos){ + + const static light_point_proc poslight_type_proc[] = { + LightsN__point_proc, + (light_point_proc)LightsN__diffuse_proc, + LightsN__point_proc + }; + + const static light_P_point_proc light_type_proc[] = { + LightsN__P_point_proc, + (light_P_point_proc)LightsN__diffuse_proc, + LightsN__P_point_proc + }; + + if(pos == NULL){ + while(node != NULL) { + light_type_proc[node->info->type](lights, &node->info->lights, pos); + node = node->next; + } + } + else{ + while(node != NULL) { + poslight_type_proc[node->info->type](lights, &node->info->lights, pos); + node = node->next; + } + } +} + +static LightNode* Light_list_buf_new(){ + + LightNode* light; + + if(light_list_buf.current >= 32){ + return NULL; + } + + light = &light_list_buf.lights[light_list_buf.idx]; + + while(light->info != NULL){ + light_list_buf.idx++; + if(light_list_buf.idx < 32){ + light++; + } + else{ + light_list_buf.idx = 0; + light = &light_list_buf.lights[0]; + } + } + + light_list_buf.current++; + return light; +} + +static void Light_list_buf_delete(LightNode* light){ + if(light != NULL){ + light_list_buf.current--; + light->info = NULL; + light_list_buf.idx = (light - light_list_buf.lights) / (int)(sizeof(LightNode)); + } +} + +extern void Global_light_ct(Global_light* glight){ + + Global_light_list_ct(glight); + Global_light_ambient_set(glight, 80,80,80); + Global_light_fog_set(glight, 0,0,0, 996, 1600); + bzero(&light_list_buf, sizeof(Light_buffer)); +} + +static void Global_light_ambient_set(Global_light* glight, u8 r, u8 g, u8 b){ + + glight->ambientColor[0] = r; + glight->ambientColor[1] = g; + glight->ambientColor[2] = b; + +} + +static void Global_light_fog_set(Global_light* glight, u8 r, u8 g, u8 b, s16 near, s16 far){ + + glight->fogColor[0] = r; + glight->fogColor[1] = g; + glight->fogColor[2] = b; + glight->fogNear = near; + glight->fogFar = far; + +} + + +extern void Global_light_read(Global_light* glight, GRAPH* graph){ + + new_LightsN(graph, glight->ambientColor[0], glight->ambientColor[1], glight->ambientColor[2]); +} + +static void Global_light_list_ct(Global_light* glight){ + + glight->list = NULL; +} + +extern void Global_light_list_new(GAME_PLAY*, Global_light* glight, Lights* light){ + + LightNode* clight; + + clight = Light_list_buf_new(); + + if(clight != NULL){ + clight->info = light; + clight->prev = NULL; + clight->next = glight->list; + + if(glight->list != NULL){ + glight->list->prev = clight; + } + + glight->list = clight; + } +} + +extern void Global_light_list_delete(Global_light* glight, LightNode* light){ + + if(light != NULL){ + if(light->prev != NULL){ + light->prev->next = light->next; + } + else{ + glight->list = light->next; + } + + if(light->next != NULL){ + light->next->prev = light->prev; + } + Light_list_buf_delete(light); + } +} + +static LightsN* new_LightsN(GRAPH* graph, u8 r, u8 g, u8 b){ + + LightsN* light; + + light = GRAPH_ALLOC(graph, sizeof(LightsN)); + + light->a.l.col[0] = light->a.l.colc[0] = r; + light->a.l.col[1] = light->a.l.colc[1] = g; + light->a.l.col[2] = light->a.l.colc[2] = b; + + light->diffuse_count = 0; + + return light; +} + + + +extern void Light_list_point_draw(GAME_PLAY* play){ + LightPoint* lightInfo; + LightNode* light; + GRAPH* g = play->game.graph; + f32 rad; + Gfx* dl; + + light = play->global_light.list; + + + OPEN_DISP(g); + dl = gfx_softsprite_prim_xlu(NOW_POLY_XLU_DISP); + + gDPSetAlphaDither(dl++, G_AD_NOISE); + gDPSetColorDither(dl++, G_CD_MAGICSQ); + gSPDisplayList(dl++,point_light_init_model); + + while(light != NULL) { + if(light->info->type == 2){ + lightInfo = &light->info->lights.point; + if(lightInfo->drawGlow){ + rad = (lightInfo->radius * lightInfo->radius) * 2.60000001617e-06f; + gDPSetPrimColor(dl++, 0, 0, lightInfo->color[0], lightInfo->color[1], lightInfo->color[2], 50); + + Matrix_translate(lightInfo->x, lightInfo->y, lightInfo->z, 0); + Matrix_scale(rad,rad,rad, 1); + + gSPMatrix(dl++, _Matrix_to_Mtx_new(play->game.graph),G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); + + gSPDisplayList(dl++,point_light_model); + } + } + light = light->next; + } + + SET_POLY_XLU_DISP(dl); + CLOSE_DISP(g); +} \ No newline at end of file diff --git a/tools/ppcdis b/tools/ppcdis index 29c3a248..396925fc 160000 --- a/tools/ppcdis +++ b/tools/ppcdis @@ -1 +1 @@ -Subproject commit 29c3a24832f4c56daf54714f0c298e503a881bb8 +Subproject commit 396925fc9863001532501a1e0a86689389c2deda