Add shadows and light effects
[mercenary-reloaded.git] / src / mercenary / mercenary2.c
index c93a3ec..6fb054e 100644 (file)
@@ -99,7 +99,7 @@ const struct cpu_stop mercenary_stop_at[] = {
        { 0x52B36,      STOP_AT_DRAW_PLANET },                  /* planet's sphere is rendered, D0 is color (viewed from universe) */
        { 0x4F4E6,      STOP_AT_DRAW_COMET },                   /* comet's sphere is rendered */
        { 0x50006,      STOP_AT_DRAW_STARS_SPACE },             /* stars are rendered (viewed from universe) */
-       { 0x4FF4C,      STOP_AT_DRAW_STARS_GROUND },            /* stars are rendered (viewed from ground) */
+       { 0x4FF4C + 4,  STOP_AT_DRAW_STARS_GROUND },            /* stars are rendered (viewed from ground) */ // + 4 because the actual adress is set by patching, which does not allow to break
        { 0x4FE24,      STOP_AT_DRAW_STARS_FLYING },            /* stars are rendered (viewed from planet when flying) */
        { 0x4FCAC,      STOP_AT_DRAW_STARS_FLYING2 },           /* same as above, but stars when upside down (above zenit) */
        { 0x50FC2,      STOP_AT_DRAW_STARS_INTERSTELLAR },      /* interstellar star flight */
@@ -117,6 +117,8 @@ const struct cpu_stop mercenary_stop_at[] = {
        { 0x528C4,      STOP_AT_PATCH_RENDER },                 /* patch away planet check (behind observer) */
        { 0x45806,      STOP_AT_PATCH_RENDER },                 /* patch away planet rendering (would crash without check above) */
        { 0x53276,      STOP_AT_PATCH_RENDER },                 /* patch away beacon check (not visible on screen) */
+       { 0x4FD8E,      STOP_AT_PATCH_RENDER },                 /* always render stars, also at day */
+       { 0x4FF4A,      STOP_AT_PATCH_RENDER },
        { 0x59622,      STOP_AT_PATCH_VR },                     /* we are walking/taxi */
        { 0x597CA,      STOP_AT_PATCH_VR },                     /* we are on a craft */
        { 0x597F2,      STOP_AT_PATCH_VR },                     /* we are ??? */
@@ -124,6 +126,9 @@ const struct cpu_stop mercenary_stop_at[] = {
        { 0x58EA8,      STOP_AT_PATCH_VR },                     /* step that moves player on surface */
        { 0x58060,      STOP_AT_PATCH_VR },                     /* soft pitch over planet */
        { 0x58918,      STOP_AT_PATCH_VR },                     /* soft pitch in space */
+
+       { 0x53872,      STOP_AT_SHADOW_BUILDING },              /* paint shadow from building ot of game data */
+
        { 0x0,          STOP_AT_END },                          /* end */
 };
 
@@ -182,7 +187,7 @@ void mercenary_patch(void)
 }
 
 /* skip certain parts when rendering improved graphics */
-void mercenary_patch_render(void)
+void mercenary_patch_render(int shadows)
 {
        switch (REG_PC) {
        case 0x52C42: /* take that branch, so planets get rendered behind obersver */
@@ -200,6 +205,12 @@ void mercenary_patch_render(void)
        case 0x53284: /* skip point render, because projected coordinates may be invalid outside screen */
                REG_PC += 4;
                break;
+       case 0x4FD8E: /* render stars at day, required for shadow calculation */
+       case 0x4FF4A:
+               if (!shadows)
+                       break;
+               REG_PC += 2;
+               break;
        }
 }
 
@@ -252,6 +263,12 @@ uint32_t mercenary_palette_stars(void)
        return 0x500C4+66;
 }
 
+void mercenary_get_sky_colors(uint16_t *day, uint16_t *night)
+{
+       *day = m68k_read_memory_16(0x7946);
+       *night = m68k_read_memory_16(0x7948);
+}
+
 void mercenary_get_orientation(double *roll, double *pitch, double *yaw)
 {
        int16_t r;
@@ -321,6 +338,31 @@ void mercenary_get_object_info(int *id, int32_t *east, int32_t *height, int32_t
        *north = (int32_t)m68k_read_memory_32(REG_A[0] + 27560);
 }
 
+void mercenary_get_building_exterior_info(int32_t *loc_x, int32_t *loc_z, int32_t *scale_x, int32_t *scale_y, int32_t *scale_z, uint16_t *anim_flag, uint16_t *anim_x, uint16_t *anim_y, uint16_t *anim_z, uint16_t *anim_phase, uint32_t *a4, uint32_t *a0, uint32_t *a5)
+{
+       /* location of building relative to the observer */
+       *loc_x = (int32_t)m68k_read_memory_32(0x63A8);
+       *loc_z = (int32_t)m68k_read_memory_32(0x6BA8);
+       /* scale of building */
+       *scale_x = (int16_t)m68k_read_memory_16(0x5357E + 0);
+       *scale_y = (int16_t)m68k_read_memory_16(0x5357E + 2);
+       *scale_z = (int16_t)m68k_read_memory_16(0x5357E + 4);
+       /* animation flag (axis to rotate about) */
+       *anim_flag = m68k_read_memory_16(0x53584);
+       /* animation offset */
+       *anim_x = m68k_read_memory_16(0x53582 + 0);
+       *anim_y = m68k_read_memory_16(0x53582 + 2);
+       *anim_z = m68k_read_memory_16(0x53582 + 4);
+       /* animation angle */
+       *anim_phase = m68k_read_memory_16(0x7888);
+       /* vertex list of building's exterior */
+       *a4 = m68k_read_memory_32(0x53638);
+       /* pointer to all datasets */
+       *a0 = 0x0000C13C;
+       /* primitive pointer array */
+       *a5 = 0x0000C03C;
+}
+
 void mercenary_coord_building_interior(int16_t *east, int32_t *height1, int32_t *height2, int32_t *height3, int32_t *height4, int16_t *north)
 {
        *east = (int16_t)m68k_read_memory_16(5698+REG_A[0]) - (int16_t)REG_A[2];