shithub: zelda3

Download patch

ref: d4f9f78c9d7e54c6fa22aec76987cbcec97ab653
parent: 18c351f101ddcd572360dc21be029ba3e62d45d0
author: Snesrev <snesrev@protonmail.com>
date: Wed Oct 19 13:44:46 EDT 2022

Show widescreen world map

--- a/messaging.c
+++ b/messaging.c
@@ -17,6 +17,8 @@
 #include "nmi.h"
 #include "assets.h"
 
+static void WorldMap_AddSprite(int spr, uint8 big, uint8 flags, uint8 ch, uint16 x, uint16 y);
+static bool WorldMap_CalculateOamCoordinates(Point16U *pt);
 
 static const int8 kDungMap_Tab0[14] = {-1, -1, -1, -1, -1, 2, 0, 10, 4, 8, -1, 6, 12, 14};
 static const uint16 kDungMap_Tab1[8] = {0x2108, 0x2109, 0x2109, 0x210a, 0x210b, 0x210c, 0x210d, 0x211d};
@@ -1068,7 +1070,7 @@
 }
 
 void FluteMenu_HandleSelection() {  // 8ab78b
-  PointU8 pt;
+  Point16U pt;
 
   if (some_menu_ctr == 0) {
     if ((joypad1L_last | joypad1H_last) & 0xc0) {
@@ -1092,7 +1094,7 @@
   }
   birdtravel_var1[0] = birdtravel_var1[0] & 7;
   if (frame_counter & 0x10 && WorldMap_CalculateOamCoordinates(&pt))
-    WorldMap_HandleSpriteBlink(16, 2, 0x3e, 0, pt.x - 4, pt.y - 4);
+    WorldMap_AddSprite(16, 2, 0x3e, 0, pt.x - 4, pt.y - 4);
 
   uint16 ybak = link_y_coord_spexit;
   uint16 xbak = link_x_coord_spexit;
@@ -1106,7 +1108,7 @@
     link_y_coord_spexit = kBirdTravel_y_hi[i] << 8 | kBirdTravel_y_lo[i];
 
     if (WorldMap_CalculateOamCoordinates(&pt))
-      WorldMap_HandleSpriteBlink(i, 0, (i == birdtravel_var1[0]) ? 0x30 + (frame_counter & 6) : 0x32, kBirdTravel_tab1[i], pt.x, pt.y);
+      WorldMap_AddSprite(i, 0, (i == birdtravel_var1[0]) ? 0x30 + (frame_counter & 6) : 0x32, kBirdTravel_tab1[i], pt.x, pt.y);
   }
   link_x_coord_spexit = xbak;
   link_y_coord_spexit = ybak;
@@ -1396,10 +1398,10 @@
 }
 
 void WorldMap_HandleSprites() {  // 8abf66
-  PointU8 pt;
+  Point16U pt;
 
   if (frame_counter & 0x10 && WorldMap_CalculateOamCoordinates(&pt))
-    WorldMap_HandleSpriteBlink(0, 2, 0x3e, 0, pt.x - 4, pt.y - 4);
+    WorldMap_AddSprite(0, 2, 0x3e, 0, pt.x - 4, pt.y - 4);
 
   uint16 ybak = link_y_coord_spexit;
   uint16 xbak = link_x_coord_spexit;
@@ -1411,7 +1413,7 @@
     link_x_coord_spexit = bird_travel_x_hi[k] << 8 | bird_travel_x_lo[k];
     link_y_coord_spexit = bird_travel_y_hi[k] << 8 | bird_travel_y_lo[k];
     if (WorldMap_CalculateOamCoordinates(&pt))
-      WorldMap_HandleSpriteBlink(15, 2, kOverworldMap_Table4[frame_counter >> 1 & 3], 0x6a, pt.x, pt.y);
+      WorldMap_AddSprite(15, 2, kOverworldMap_Table4[frame_counter >> 1 & 3], 0x6a, pt.x, pt.y);
   }
 
   if (save_ow_event_info[0x5b] & 0x20 || (((savegame_map_icons_indicator >= 6) ^ is_in_dark_world) & 1))
@@ -1433,7 +1435,7 @@
       uint8 ext = 2;
       if (!(info >> 8))
         info = kOwMap_tab2[frame_counter >> 3 & 3] << 8 | 0x32, ext = 0;
-      WorldMap_HandleSpriteBlink(14, ext, (uint8)info, (uint8)(info >> 8), pt.x, pt.y);
+      WorldMap_AddSprite(14, ext, (uint8)info, (uint8)(info >> 8), pt.x, pt.y);
     }
   endif_crystal0:;
   }
@@ -1452,7 +1454,7 @@
       uint8 ext = 2;
       if (!(info >> 8))
         info = kOwMap_tab2[frame_counter >> 3 & 3] << 8 | 0x32, ext = 0;
-      WorldMap_HandleSpriteBlink(13, ext, (uint8)info, (uint8)(info >> 8), pt.x, pt.y);
+      WorldMap_AddSprite(13, ext, (uint8)info, (uint8)(info >> 8), pt.x, pt.y);
     }
   endif_crystal1:;
   }
@@ -1471,7 +1473,7 @@
       uint8 ext = 2;
       if (!(info >> 8))
         info = kOwMap_tab2[frame_counter >> 3 & 3] << 8 | 0x32, ext = 0;
-      WorldMap_HandleSpriteBlink(12, ext, (uint8)info, (uint8)(info >> 8), pt.x, pt.y);
+      WorldMap_AddSprite(12, ext, (uint8)info, (uint8)(info >> 8), pt.x, pt.y);
     }
   endif_crystal2:;
   }
@@ -1490,7 +1492,7 @@
       uint8 ext = 2;
       if (!(info >> 8))
         info = kOwMap_tab2[frame_counter >> 3 & 3] << 8 | 0x32, ext = 0;
-      WorldMap_HandleSpriteBlink(11, ext, (uint8)info, (uint8)(info >> 8), pt.x, pt.y);
+      WorldMap_AddSprite(11, ext, (uint8)info, (uint8)(info >> 8), pt.x, pt.y);
     }
   endif_crystal3:;
   }
@@ -1509,7 +1511,7 @@
       uint8 ext = 2;
       if (!(info >> 8))
         info = kOwMap_tab2[frame_counter >> 3 & 3] << 8 | 0x32, ext = 0;
-      WorldMap_HandleSpriteBlink(10, ext, (uint8)info, (uint8)(info >> 8), pt.x, pt.y);
+      WorldMap_AddSprite(10, ext, (uint8)info, (uint8)(info >> 8), pt.x, pt.y);
     }
   endif_crystal4:;
   }
@@ -1528,7 +1530,7 @@
       uint8 ext = 2;
       if (!(info >> 8))
         info = kOwMap_tab2[frame_counter >> 3 & 3] << 8 | 0x32, ext = 0;
-      WorldMap_HandleSpriteBlink(9, ext, (uint8)info, (uint8)(info >> 8), pt.x, pt.y);
+      WorldMap_AddSprite(9, ext, (uint8)info, (uint8)(info >> 8), pt.x, pt.y);
     }
   endif_crystal5:;
   }
@@ -1547,7 +1549,7 @@
       uint8 ext = 2;
       if (!(info >> 8))
         info = kOwMap_tab2[frame_counter >> 3 & 3] << 8 | 0x32, ext = 0;
-      WorldMap_HandleSpriteBlink(8, ext, (uint8)info, (uint8)(info >> 8), pt.x, pt.y);
+      WorldMap_AddSprite(8, ext, (uint8)info, (uint8)(info >> 8), pt.x, pt.y);
     }
   endif_crystal6:;
   }
@@ -1557,13 +1559,11 @@
   link_y_coord_spexit = ybak;
 }
 
-bool WorldMap_CalculateOamCoordinates(PointU8 *pt) {  // 8ac39f
-  uint8 r14, r15;
-
+static bool WorldMap_CalculateOamCoordinates(Point16U *pt) {  // 8ac39f
   if (overworld_map_flags == 0) {
     int j = -(link_y_coord_spexit >> 4) + M7Y_copy + (link_y_coord_spexit >> 3 & 1) - 0xc0;
     uint8 t0 = kOverworldMap_tab1[j];
-    r15 = 13 * t0 >> 4;
+    uint8 yval = 13 * t0 >> 4;
 
     uint8 at = link_x_coord_spexit >> 4;
     bool below = at < 0x80;
@@ -1570,12 +1570,12 @@
     at -= 0x80;
     if (sign8(at)) at = ~at;
 
-    uint8 t1 = ((r15 < 224 ? r15 : 0) * 0x54 >> 8) + 0xb2;
+    uint8 t1 = ((yval < 224 ? yval : 0) * 0x54 >> 8) + 0xb2;
     uint8 t2 = at * t1 >> 8;
     uint8 t3 = (below) ? 0x80 - t2 : t2 + 0x80;
 
     pt->x = t3 - BG1HOFS_copy2 + 0x80;
-    pt->y = r15 + 12;
+    pt->y = yval + 12;
     return true;
   } else {
     uint16 t0 = -(link_y_coord_spexit >> 4) + M7Y_copy - 0x80;
@@ -1584,13 +1584,13 @@
     uint16 t1 = t0 * 37 >> 4;
     if (t1 >= 333)
       return false;
-    r15 = kOverworldMap_tab1[t1];
+    uint8 yval = kOverworldMap_tab1[t1];
     uint16 t2 = link_x_coord_spexit;
     bool below = t2 < 0x7F8;
     t2 -= 0x7f8;
     if (sign16(t2))
       t2 = -t2;
-    uint8 t3 = r15 < 226 ? r15 : 0;
+    uint8 t3 = yval < 226 ? yval : 0;
     uint8 t4 = (t3 * 84 >> 8) + 178;  // r0
     uint8 t5 = (uint8)t2 * t4 >> 8; // r1
     uint16 t6 = (uint8)(t2 >> 8) * t4 + t5;
@@ -1601,27 +1601,29 @@
     uint8 t9 = (uint8)t8 * 45 >> 8;
     uint16 t10 = ((t8 >> 8) * 45) + t9;
     uint16 t11 = below2 ? 0x80 - t10 : t10 + 0x80;
-    r14 = t11 - BG1HOFS_copy2;
-    uint16 t12 = t11 - 0xFF80 - BG1HOFS_copy2;
-    if (t12 >= 0x100)
+    uint16 xval = t11 - BG1HOFS_copy2;
+    int xt = enhanced_features0 & kFeatures0_ExtendScreen64 ? 0x48 : 0;
+    if ((uint16)(xval + 0x80 + xt) >= (0x100 + xt * 2))
       return false;
-    pt->x = r14 + 0x81;
-    pt->y = r15 + 16;
+    pt->x = xval + 0x81;
+    pt->y = yval + 16;
     return true;
   }
 }
 
-void WorldMap_HandleSpriteBlink(int spr, uint8 r11_ext, uint8 r12_flags, uint8 r13_char, uint8 r14_x, uint8 r15_y) {  // 8ac51c
-  if (!(frame_counter & 0x10) && r13_char == 100) {
+static void WorldMap_AddSprite(int spr, uint8 big, uint8 flags, uint8 ch, uint16 x, uint16 y) {  // 8ac51c
+  if (!(frame_counter & 0x10) && ch == 100) {
     assert(spr >= 8);
-    r13_char = kOverworldMapData[spr - 8];
-    r12_flags = 0x32;
-    r11_ext = 0;
+    ch = kOverworldMapData[spr - 8];
+    flags = 0x32;
+    big = 0;
   } else {
-    r14_x -= 4;
-    r15_y -= 4;
+    x -= 4;
+    y -= 4;
   }
-  SetOamPlain(&oam_buf[spr], r14_x, r15_y, r13_char, r12_flags, r11_ext);
+  if (enhanced_features0 & kFeatures0_ExtendScreen64)
+    big |= (x >> 8 & 1);
+  SetOamPlain(&oam_buf[spr], x, y, ch, flags, big);
 }
 
 bool OverworldMap_CheckForPendant(int k) {  // 8ac5a9
--- a/messaging.h
+++ b/messaging.h
@@ -63,8 +63,6 @@
 void WorldMap_SetUpHDMA();
 void WorldMap_FillTilemapWithEF();
 void WorldMap_HandleSprites();
-bool WorldMap_CalculateOamCoordinates(PointU8 *pt);
-void WorldMap_HandleSpriteBlink(int spr, uint8 r11_ext, uint8 r12_flags, uint8 r13_char, uint8 r14_x, uint8 r15_y);
 bool OverworldMap_CheckForPendant(int k);
 bool OverworldMap_CheckForCrystal(int k);
 void Module0E_03_DungeonMap();
--- a/snes/ppu.c
+++ b/snes/ppu.c
@@ -714,9 +714,6 @@
   uint32 xCenter = ((int16_t)(ppu->m7matrix[4] << 3)) >> 3, yCenter = ((int16_t)(ppu->m7matrix[5] << 3)) >> 3;
   uint32 clippedH = (((int16_t)(ppu->m7matrix[6] << 3)) >> 3) - xCenter;
   uint32 clippedV = (((int16_t)(ppu->m7matrix[7] << 3)) >> 3) - yCenter;
-  uint32 m0 = ppu->m7matrix[0];  // xpos increment per horiz movement
-  uint32 m3 = ppu->m7matrix[3];  // ypos increment per vert movement
-  uint8 *dst_start = &ppu->renderBuffer[(y - 1) * 4 * ppu->renderPitch], *dst_end, *dst = dst_start + ppu->extraLeftRight * 4 * 4;
   int32 m0v[4];
   if (*(uint32*)&ppu->mode7PerspectiveLow == 0) {
     m0v[0] = m0v[1] = m0v[2] = m0v[3] = ppu->m7matrix[0] << 12;
@@ -725,11 +722,15 @@
     for (int i = 0; i < 4; i++)
       m0v[i] = 4096.0f / FloatInterpolate((int)y + kInterpolateOffsets[i], 0, 223, ppu->mode7PerspectiveLow, ppu->mode7PerspectiveHigh);
   }
-
+  size_t pitch = ppu->renderPitch;
+  uint8 *render_buffer_ptr = &ppu->renderBuffer[(y - 1) * 4 * pitch];
+  uint8 *dst_start = render_buffer_ptr + (ppu->extraLeftRight - ppu->extraLeftCur) * 16;
+  size_t draw_width = 256 + ppu->extraLeftCur + ppu->extraRightCur;
+  uint8 *dst_curline = dst_start;
+  uint32 m1 = ppu->m7matrix[1] << 12;  // xpos increment per vert movement
+  uint32 m2 = ppu->m7matrix[2] << 12;  // ypos increment per horiz movement
   for (int j = 0; j < 4; j++) {
-    m0 = m3 = m0v[j];
-    uint32 m1 = ppu->m7matrix[1] << 12;  // xpos increment per vert movement
-    uint32 m2 = ppu->m7matrix[2] << 12;  // ypos increment per horiz movement
+    uint32 m0 = m0v[j], m3 = m0;
     uint32 xpos = m0 * clippedH + m1 * (clippedV + y) + (xCenter << 20), xcur;
     uint32 ypos = m2 * clippedH + m3 * (clippedV + y) + (yCenter << 20), ycur;
 
@@ -738,11 +739,17 @@
     ypos -= (m2 + m3) >> 1;
     xcur = (xpos << 2) + j * m1;
     ycur = (ypos << 2) + j * m3;
-    dst_end = dst + 4096;
 
+    xcur -= ppu->extraLeftCur * 4 * m0;
+    ycur -= ppu->extraLeftCur * 4 * m2;
+
+    uint8 *dst = dst_curline;
+    uint8 *dst_end = dst_curline + draw_width * 16;
+
 #define DRAW_PIXEL(mode) \
     tile = ppu->vram[(ycur >> 25 & 0x7f) * 128 + (xcur >> 25 & 0x7f)] & 0xff;  \
     pixel = ppu->vram[tile * 64 + (ycur >> 22 & 7) * 8 + (xcur >> 22 & 7)] >> 8; \
+    pixel = (xcur & 0x80000000) ? 0 : pixel; \
     *(uint32*)dst = (mode ? (ppu->colorMapRgb[pixel] & 0xfefefe) >> 1 : ppu->colorMapRgb[pixel]); \
     xcur += m0, ycur += m2, dst += 4;
 
@@ -760,18 +767,17 @@
         DRAW_PIXEL(1);
         DRAW_PIXEL(1);
       } while (dst != dst_end);
-
     }
 #undef DRAW_PIXEL
-    dst += (ppu->renderPitch - 4096);
+
+    dst_curline += pitch;
   }
 
   if (ppu->lineHasSprites) {
-    PpuZbufType *pixels = ppu->objBuffer.data;
-    size_t pitch = ppu->renderPitch;
-    uint8 *dst = dst_start + ppu->extraLeftRight * 16;
-    for (size_t i = 0; i < 256; i++, dst += 16) {
-      uint32 pixel = pixels[i + kPpuExtraLeftRight] & 0xff;
+    uint8 *dst = dst_start;
+    PpuZbufType *pixels = ppu->objBuffer.data + (kPpuExtraLeftRight - ppu->extraLeftCur);
+    for (size_t i = 0; i < draw_width; i++, dst += 16) {
+      uint32 pixel = pixels[i] & 0xff;
       if (pixel) {
         uint32 color = ppu->colorMapRgb[pixel];
         ((uint32 *)dst)[3] = ((uint32 *)dst)[2] = ((uint32 *)dst)[1] = ((uint32 *)dst)[0] = color;
@@ -784,15 +790,13 @@
 
   if (ppu->extraLeftRight - ppu->extraLeftCur != 0) {
     size_t n = 4 * sizeof(uint32) * (ppu->extraLeftRight - ppu->extraLeftCur);
-    size_t pitch = ppu->renderPitch;
     for(int i = 0; i < 4; i++)
-      memset(dst_start + pitch * i, 0, n);
+      memset(render_buffer_ptr + pitch * i, 0, n);
   }
   if (ppu->extraLeftRight - ppu->extraRightCur != 0) {
     size_t n = 4 * sizeof(uint32) * (ppu->extraLeftRight - ppu->extraRightCur);
-    size_t pitch = ppu->renderPitch;
     for (int i = 0; i < 4; i++)
-      memset(dst_start + pitch * i + (256 + ppu->extraLeftRight * 2 - (ppu->extraLeftRight - ppu->extraRightCur)) * 4 * sizeof(uint32), 0, n);
+      memset(render_buffer_ptr + pitch * i + (256 + ppu->extraLeftRight * 2 - (ppu->extraLeftRight - ppu->extraRightCur)) * 4 * sizeof(uint32), 0, n);
   }
 #undef DRAW_PIXEL
 }
--- a/zelda_rtl.c
+++ b/zelda_rtl.c
@@ -145,10 +145,16 @@
   if (mod == 14)
     mod = saved_module_for_menu;
   if (mod == 9) {
-    // outdoors
-    extra_left = BG2HOFS_copy2 - ow_scroll_vars0.xstart;
-    extra_right = ow_scroll_vars0.xend - BG2HOFS_copy2;
-    extra_bottom = ow_scroll_vars0.yend - BG2VOFS_copy2;
+    if (main_module_index == 14 && submodule_index == 7 && overworld_map_state >= 4) {
+      // World map
+      extra_left = kPpuExtraLeftRight, extra_right = kPpuExtraLeftRight;
+      extra_bottom = 16;
+    } else {
+      // outdoors
+      extra_left = BG2HOFS_copy2 - ow_scroll_vars0.xstart;
+      extra_right = ow_scroll_vars0.xend - BG2HOFS_copy2;
+      extra_bottom = ow_scroll_vars0.yend - BG2VOFS_copy2;
+    }
   } else if (mod == 7) {
     // indoors, except when the light cone is in use
     if (!(hdr_dungeon_dark_with_lantern && TS_copy != 0)) {