From a1e5f50e5840529b8a189a8cbb966bbbda863845 Mon Sep 17 00:00:00 2001
From: Miloslav Ciz <drummyfish@disroot.org>
Date: Tue, 11 Mar 2025 16:49:11 +0100
Subject: [PATCH] Check map errors

---
 TODO.txt |  8 ++++----
 data     | 11 -----------
 game.h   | 45 +++++++++++++++++++++++++++++++--------------
 map.h    | 41 +++++++++++++++++++++++++++++++++++++----
 4 files changed, 72 insertions(+), 33 deletions(-)

diff --git a/TODO.txt b/TODO.txt
index 06ff15f..a5ba10e 100644
--- a/TODO.txt
+++ b/TODO.txt
@@ -1,10 +1,7 @@
 =========== GENERAL ==============
 
-- on tiny map 1 maybe add a few block below the first sharp ramp to prevent
-  those nasty piercing bugs
 - car deglitch idea: deglitch only if the middle joint collided this frame?
 - some kinda easteregg in menu or smt
-- make the U-ramp map taller due to new physics
 - on 1st map the camera is obscured by the wall at the start, fix it somehow
   (not the best first impression)
 - culling is very slow now, it showed that distance bailout can accelerate it
@@ -43,7 +40,7 @@
     - U-ramp to build speed and jump up to catch a CP (done)
     - jump through air ring with CP
 - try to speed up the slow culling
-- make a small txt game menual
+- make a small txt game manual
 - test:
   - long replay
   - replay stretching works
@@ -70,7 +67,10 @@
 
 - sometimes getting a SLIGHTLY slower time counts as beating it (prolly
   conversion fail) (SEEMS FIXED NOW)
+- on tiny map 1 maybe add a few block below the first sharp ramp to prevent
+  those nasty piercing bugs
 - replays are bugged, seem to not steer
+- make the U-ramp map taller due to new physics
 - replay format should probably record game version
   - also there should probably be some version system that says version of
     physics vs version of everything else; replay could only record physics
diff --git a/data b/data
index 2850e2c..080c909 100644
--- a/data
+++ b/data
@@ -32,14 +32,3 @@ ramps
 
 finish
 :!vdt :!vdA
-#RLCtiny1;00LCtiny1;8ecff5c0 000381:00a1:02b9:0041:0265:0061:029:0141:0263:0041:0043:0051:003:0041:0033:0031:0033:0052:00260042:0096:0092:0026:0022:0086:02e:001c:0072:0043:00f1:0033:012:0039:0061:0069:0041:00b5:0021:263:0031:00c9:0011
-#BLCtiny1;
-#RLCtiny1;00LCtiny1;8ecff5c0 000585:00c1:0179:0031:0119:0021:2d5:0039:00d1:0079:0051:00e9:001:0123:0041:0083:00b1:0199:01b101d0:00d1:0063:0072:0040:00c2:033:0011:00d3:00e1:00d3:0122:002:0081:0023:0091:0040:0051:0039:011:0050:0038:003c:0128:0012:003:01e1:0069:0071:00c5:0049:00380059:0151:0053:00c1:0219:0021
-#Rtestmap;00testmap;88676224 000193:0011:0029:0121:0019:0061:0f9:0051:0049:0081:00f9:0028:000:0078:0049:0011:0039:0051:00f00044:0026:0122:0020:0052:0070:038:0029:00c8:0159
-#RLCtiny1;00LCtiny1;8ecff5c0 000531:0011:03a9:0041:0179:0021:059:0031:0039:0091:0049:0031:023:0041:0013:0051:0053:0041:00230051:0043:0031:0064:0016:0022:026:01a4:002c:0040:0042:0013:008:0053:0102:0050:0021:0049:00e1:043:0091:0049:01a8:0119:0130:002:0026:0082:0048:0039:0111:00500022:0036:0132:0018:0049:0151:033:0121:00c3:0041:0059:0041:00d:0048:0050
-#RLCtiny1;00LCtiny1;8ecff5c0 0000513:04f1:0199:0031:01e9:0021:01a9:00e1:0069:0011:0193:0041:00a3:0031:0093:0061:0033:0071:0095:0071:0019:0038:0149:0068:0069:00b8:0129:0068:0010:0032:0026:00d2:002a:0018:0079:0141:0043:0061:0073:0071:00b5:0041:0049:0098:0089:00d1:0049:0071:0053:0041:00a3:0031:00b9:0041
-#RLCtiny1;00LCtiny1;7e39e006 0000355:0011:0339:0031:0159:0031:00d9:0071:0039:0061:0079:0051:0039:0031:01d3:0061:0023:0041:0033:0031:0063:0025:0037:0022:00b6:00bc:0050:0032:0013:0151:0023:00b1:0089:0041:0093:0031:0085:0031:0033:0081:00d3:0031:00a3:0041:0099:0031:00a3:0031
-#RLCtiny3;00LCtiny3;fd8b8070 0000128:0011:01a3:00e1:0053:0051:0043:0041:0053:0031
-#BLCtiny3;
-#RLCtiny3;00LCtiny3;31438a8e 0000557:0011:0173:0071:0023:0061:0063:0051:0023:0051:0033:0041:0023:0041:0053:0031:0023:0061:0023:0101:02b9:0051:0103:0051:0023:0041:0023:0121:00a3:0061:0033:00a1:0249:0041:0143:0011:0023:0181:00a5:0031:0043:0181:00b9:0011:00e3:0041:0023:0041:0053:0091:0033:0041:0023:0041:0023:0031:0023:0041:0053:0061:0033:0041:0203:0041:00b9:0011
-#RLCtiny3;00LCtiny3;3fdcf185 0001606:4d01:00a3:0061:0043:0071:0053:0041:0043:0031:0033:0091:0053:0171:0053:0041:0075:0031:0053:0031:0033:0091:0033:0071:0089:0031:0083:0031:0023:01b1:00d3:00a1:0043:0061:0023:0061:0103:01c1:0025:0051:0043:00f1:00c9:0041:0059:0041:00c9:0021:0089:0041
diff --git a/game.h b/game.h
index 63c4e4b..30c61f8 100644
--- a/game.h
+++ b/game.h
@@ -775,8 +775,9 @@ uint8_t LCR_mapIsBeaten(const char *name)
   return 0;
 }
 
-void LCR_gameLoadMap(unsigned int mapIndex)
+uint8_t LCR_gameLoadMap(unsigned int mapIndex)
 {
+  uint8_t result;
   char name[LCR_MAP_NAME_MAX_LEN + 1];
   name[0] = 0;
 
@@ -794,8 +795,9 @@ void LCR_gameLoadMap(unsigned int mapIndex)
     name[i + 1] = 0;
   }
 
-  LCR_mapLoadFromStr(LCR_gameGetNextDataStrChar,name);
+  result = LCR_mapLoadFromStr(LCR_gameGetNextDataStrChar,name);
   LCR_game.mapBeaten = LCR_mapIsBeaten(LCR_currentMap.name);
+  return result;
 }
 
 /**
@@ -846,13 +848,12 @@ unsigned int LCR_gameLoadReplay(unsigned int replayIndex)
           nameHash == _LCR_simpleStrHash(LCR_gameGetNextDataStrChar,';'))
         {
           LCR_LOG2("map name hash matches");
-          LCR_gameLoadMap(mapIndex);
-
-          if (mapHash == LCR_currentMap.hash)
+          
+          if (LCR_gameLoadMap(mapIndex) && mapHash == LCR_currentMap.hash)
             return mapIndex;
           else
           {
-            LCR_LOG2("map hash doesn't match");
+            LCR_LOG2("bad map");
             // map hash doesn't match
             skipTo = mapIndex + 1;
             break;
@@ -1058,10 +1059,17 @@ void LCR_gameInit(int argc, const char **argv)
     
   if (quickLoad == 1)
   {
-    LCR_gameLoadMap(LCR_countData('M') - 1);
-    LCR_gameSetState(LCR_GAME_STATE_LOADING);
-    LCR_game.menu.selectedTab = 1;
-    LCR_gameLoadDataFileChunk(0,'M');
+    if (LCR_gameLoadMap(LCR_countData('M') - 1))
+    {
+      LCR_gameSetState(LCR_GAME_STATE_LOADING);
+      LCR_game.menu.selectedTab = 1;
+      LCR_gameLoadDataFileChunk(0,'M');
+    }
+    else
+    {
+      LCR_LOG0("couldn't load map");
+      LCR_gameSetState(LCR_GAME_STATE_END);
+    }
   }
   else if (quickLoad == 2 || quickLoad == 3)
   {
@@ -1480,9 +1488,15 @@ void LCR_gameHandleInput(void)
           break;
 
         case 1: // maps
-          LCR_gameLoadMap(LCR_game.dataFile.firstItemIndex +
-            LCR_game.menu.selectedItem);
-          LCR_gameSetState(LCR_GAME_STATE_LOADING);
+          if (LCR_gameLoadMap(LCR_game.dataFile.firstItemIndex +
+            LCR_game.menu.selectedItem))
+            LCR_gameSetState(LCR_GAME_STATE_LOADING);
+          else
+          {
+            LCR_LOG0("couldn't load map");
+            LCR_gamePopupMessage(LCR_texts[LCR_TEXTS_FAIL]);
+          }
+
           break;
 
         case 2: // view replay
@@ -1534,6 +1548,9 @@ uint8_t LCR_gameStep(uint32_t time)
 
   LCR_game.time = time;
 
+  if (LCR_game.state == LCR_GAME_STATE_END)
+    return 0;
+
   for (int i = 0; i < LCR_KEYS_TOTAL; ++i)
     LCR_game.keyStates[i] = LCR_keyPressed(i) ?
       (LCR_game.keyStates[i] < 255 ? LCR_game.keyStates[i] + 1 : 255) : 0;
@@ -1694,7 +1711,7 @@ uint8_t LCR_gameStep(uint32_t time)
   LCR_game.frame++;
   LCR_LOG2("game step (end)");
 
-  return LCR_game.state != LCR_GAME_STATE_END;
+  return 1;
 }
 
 uint8_t LCR_gameGetNextAudioSample(void)
diff --git a/map.h b/map.h
index dfac4d5..ed1d510 100644
--- a/map.h
+++ b/map.h
@@ -85,6 +85,7 @@
 
 // normal blocks:
 #define LCR_BLOCK_FULL              '='  ///< completely filled block
+
 #define LCR_BLOCK_BOTTOM            '-'  ///< filled bottom half
 #define LCR_BLOCK_LEFT              ';'  ///< filled left half
 #define LCR_BLOCK_BOTTOM_LEFT       ','  ///< filled bottom left quarter
@@ -669,10 +670,39 @@ uint8_t LCR_mapLoadFromStr(char (*getNextCharFunc)(void), const char *name)
           LCR_currentMap.startPos[3] = trans;
           break;
 
+                                            // kek, is this legit?  
         case LCR_BLOCK_CHECKPOINT_0:
-          LCR_currentMap.checkpointCount++;
-          // fall through
-        default: // normal block
+          LCR_currentMap.checkpointCount++; // fall through
+        case LCR_BLOCK_FULL:                // fall through
+        case LCR_BLOCK_BOTTOM:              // fall through
+        case LCR_BLOCK_LEFT:                // fall through
+        case LCR_BLOCK_BOTTOM_LEFT:         // fall through
+        case LCR_BLOCK_BOTTOM_LEFT_FRONT:   // fall through
+        case LCR_BLOCK_LEFT_FRONT:          // fall through
+        case LCR_BLOCK_RAMP:                // fall through
+        case LCR_BLOCK_RAMP_34:             // fall through 
+        case LCR_BLOCK_RAMP_12:             // fall through
+        case LCR_BLOCK_RAMP_14:             // fall through
+        case LCR_BLOCK_RAMP_12_UP:          // fall through
+        case LCR_BLOCK_RAMP_CORNER:         // fall through
+        case LCR_BLOCK_RAMP_CURVED_PLAT:    // fall through
+        case LCR_BLOCK_RAMP_CURVED:         // fall through
+        case LCR_BLOCK_RAMP_CURVED_WALL:    // fall through
+        case LCR_BLOCK_RAMP_STEEP:          // fall through
+        case LCR_BLOCK_CORNER:              // fall through
+        case LCR_BLOCK_CORNER_12:           // fall through
+        case LCR_BLOCK_HILL:                // fall through
+        case LCR_BLOCK_BUMP:                // fall through
+        case LCR_BLOCK_CORNER_CONVEX:       // fall through
+        case LCR_BLOCK_CORNER_CONCAVE:      // fall through
+        case LCR_BLOCK_FULL_ACCEL:          // fall through
+        case LCR_BLOCK_BOTTOM_ACCEL:        // fall through
+        case LCR_BLOCK_RAMP_ACCEL:          // fall through
+        case LCR_BLOCK_FULL_FAN:            // fall through
+        case LCR_BLOCK_RAMP_FAN:            // fall through
+        case LCR_BLOCK_CHECKPOINT_1:        // fall through
+        case LCR_BLOCK_FINISH:              // fall through
+        case LCR_BLOCK_NONE:                // fall through
         {
           LCR_makeMapBlock(block,coords[0],coords[1],coords[2],mat,trans,
             prevBlock);
@@ -682,7 +712,10 @@ uint8_t LCR_mapLoadFromStr(char (*getNextCharFunc)(void), const char *name)
           break;
         }
 
-        // TODO: check for invalid blocks?
+        default:
+          LCR_LOG0("bad block type");
+          return 0;
+          break;
       }
     }
     else