diff --git a/Makefile b/Makefile
index 3ec3682..ab926eb 100644
--- a/Makefile
+++ b/Makefile
@@ -8,7 +8,7 @@ else
   ROOTLIBDIR = $(shell root-config --libdir)
 endif
 
-CFLAGS = -Wall -Wextra -pedantic
+CFLAGS = -Wall -Wextra -pedantic -fcolor-diagnostics
 INC = -Ithird_party -Ithird_party/imgui
 LIBS = -lglfw
 
diff --git a/src/hover.cpp b/src/hover.cpp
index 113543e..ff8426c 100644
--- a/src/hover.cpp
+++ b/src/hover.cpp
@@ -1080,8 +1080,13 @@ struct Sec_Hover_Fn {
   void free_slot()
   {
     titled_section("Free Slot", [this] {
-      u32 keylen = tkey();
-      range("Freed Data", section.range.len - section.post_size - keylen); 
+      // Sometimes a free slot has a leading TKey, but in general the only bytes that are
+      // guaranteed to be valid are the first 4.
+      field<i32>("NBytes: %d", [] (Arena *arena, String8_Node *prev, const char *fmt, i32 x) {
+        x = bswap(x);
+        return push_str8_node_child(arena, prev, fmt, abs(x));
+      });
+      range("Freed Data", section.range.len - sizeof(i32)); 
     });
   }
 };
diff --git a/src/render.cpp b/src/render.cpp
index c0e7d75..2b3f547 100644
--- a/src/render.cpp
+++ b/src/render.cpp
@@ -236,14 +236,19 @@ void viewer_jump_to_page_list(App_State &app, u64 page_list_idx)
 internal
 void viewer_jump_to_free_slot(App_State &app, u64 free_slot_idx)
 {
-  assert(app.tfile_data.n_free_slots > 0);
+  u64 n_free_slots = app.tfile_data.sections[Sec_Free_Slot].count;
+  assert(n_free_slots > 0);
 
-  u64 idx = (free_slot_idx + app.tfile_data.n_free_slots) % app.tfile_data.n_free_slots;
+  u64 idx = (free_slot_idx + n_free_slots) % n_free_slots;
   
-  Byte_Range free_slot = app.tfile_data.free_slots[idx];
+  Section *sec = app.tfile_data.sections[Sec_Free_Slot].head;
+  for (u64 i = 0; i < idx; ++i) {
+    sec = sec->next;
+    assert(sec);
+  }
 
   app.viewer.latest_section_gone_to[Sec_Free_Slot] = idx;
-  viewer_jump_to(app, free_slot.start);
+  viewer_jump_to(app, sec->range.start);
 }
 
 internal
@@ -479,7 +484,7 @@ void update_and_render(Arena *arena, App_State &app, f32 delta_time_ms)
         }
       }
 
-      if (app.tfile_data.n_free_slots) {
+      if (app.tfile_data.sections[Sec_Free_Slot].count) {
         ImGui::ColorEdit3("_Free Slot", app.viewer.col_section[Sec_Free_Slot], edit_flags);
         ImGui::SameLine(); 
         if (ImGui::Button("Free Slot"))
diff --git a/src/rntuple.cpp b/src/rntuple.cpp
index 1612111..8c06040 100644
--- a/src/rntuple.cpp
+++ b/src/rntuple.cpp
@@ -4,6 +4,7 @@ Section *push_section(Arena *arena, TFile_Data &tdata, Section_Id id)
   Section *sec = arena_push<Section>(arena);
   sec->id = id;
   push_to_sll(tdata.sections[id].head, tdata.sections[id].tail, sec);
+  tdata.sections[id].count += 1;
   return sec;
 }
 
@@ -194,7 +195,8 @@ RNTuple_Data get_rntuple_data(Arena *arena, const Inspected_File &file, const TF
   Page_Info_Node *pinfo_head = nullptr, *pinfo_tail = nullptr;
   Page_Info_Node *last_inserted_pinfo = nullptr;
 
-  RNTupleDescriptor *descriptors = arena_push_array_nozero<RNTupleDescriptor>(arena, tfile_data.n_anchors);
+  u64 n_anchors = tfile_data.sections[Sec_RNTuple_Anchor].count;
+  RNTupleDescriptor *descriptors = arena_push_array_nozero<RNTupleDescriptor>(arena, n_anchors);
   u32 anchor_idx = 0;
   u64 n_tot_cluster_groups = 0;
   u64 n_tot_clusters = 0;
@@ -205,7 +207,7 @@ RNTuple_Data get_rntuple_data(Arena *arena, const Inspected_File &file, const TF
     n_tot_cluster_groups += desc.GetNClusterGroups();
     n_tot_clusters += desc.GetNActiveClusters();
   }
-  assert(anchor_idx == tfile_data.n_anchors);
+  assert(anchor_idx == n_anchors);
 
   // Allocate space for clusters/cluster groups infos
   Cluster_Info *clusters = arena_push_array<Cluster_Info>(arena, n_tot_clusters);
@@ -217,7 +219,6 @@ RNTuple_Data get_rntuple_data(Arena *arena, const Inspected_File &file, const TF
   
   /// Load all RNTuple data ///
   anchor_idx = 0;
-  printf("%p\n", tfile_data.sections[Sec_RNTuple_Anchor].head);
   for (Section *sec_anchor = tfile_data.sections[Sec_RNTuple_Anchor].head; sec_anchor; sec_anchor = sec_anchor->next, ++anchor_idx) {
     const ROOT::RNTuple &anchor = *(const ROOT::RNTuple *)sec_anchor->info;
     if (!anchor.GetNBytesHeader())
@@ -362,14 +363,14 @@ RNTuple_Data get_rntuple_data(Arena *arena, const Inspected_File &file, const TF
   }
 
   // destruct all descriptors
-  for (u64 i = 0; i < tfile_data.n_anchors; ++i)
+  for (u64 i = 0; i < n_anchors; ++i)
     descriptors[i].~RNTupleDescriptor();
 
   chr::time_point end_t = chr::high_resolution_clock::now();
   u64 time_spent_ms = chr::duration_cast<chr::milliseconds>(end_t - start_t).count();
 
-  fprintf(stderr, "Loaded %" PRIu64 " pages from %u anchors in %" PRIu64 " ms (%" PRIu64 " duplicates).\nGenerating groups...\n", 
-          n_pages, tfile_data.n_anchors, time_spent_ms, n_duplicate_page_ranges);
+  fprintf(stderr, "Loaded %" PRIu64 " pages from %" PRIu64 " anchors in %" PRIu64 " ms (%" PRIu64 " duplicates).\nGenerating groups...\n", 
+          n_pages, n_anchors, time_spent_ms, n_duplicate_page_ranges);
 
   // Create page groups and chunks.
   // Each page group is a grouping of GROUP_SIZE page infos whose range is equal to the combined ranges
@@ -479,15 +480,6 @@ Section find_section(App_State &app, u64 off, i64 hilite_cluster = -1)
   const RNTuple_Data &rdata = app.rndata;
 
   Section sec {};
-  // Check free slots
-  for (u64 i = 0; i < app.tfile_data.n_free_slots; ++i) {
-    Byte_Range rng = app.tfile_data.free_slots[i];
-    if (rng.start <= off && off < rng.end()) {
-      sec.id = Sec_Free_Slot;
-      sec.range = rng;
-      return sec;
-    }
-  }
 
   for (u32 i = 1; i < Sec_COUNT; ++i) {   
     for (Section *sec = app.tfile_data.sections[i].head; sec; sec = sec->next) {
diff --git a/src/rntuple.h b/src/rntuple.h
index 075772f..cb2b0e9 100644
--- a/src/rntuple.h
+++ b/src/rntuple.h
@@ -65,13 +65,7 @@ enum Section_Id {
   Sec_RNTuple_Header,
   Sec_RNTuple_Footer,
   Sec_Page_List,
-
-  // By 'Unique' we mean that we only highlight one section of that type.
-  // In the future we might want to improve this and support properly highlighting
-  // multiple RNTuples (in which case anchor/header/footer/page list would become non-unique)
-  Sec_COUNT_UNIQUE,
-  Sec_FIRST_NON_UNIQUE = Sec_COUNT_UNIQUE,
-  Sec_Page = Sec_FIRST_NON_UNIQUE, 
+  Sec_Page, 
   Sec_RNTuple_Anchor,
   Sec_Free_Slot,
   // any other object stored in a TKey
@@ -150,12 +144,7 @@ struct TFile_Data {
   u32 compression;
 
   Sections sections[Sec_COUNT];
-
   TKeys_Data tkeys_data;
-  // Sorted list of free slots in the TFile
-  Byte_Range *free_slots;
-  u64 n_free_slots;
-  u32 n_anchors; // XXX: remove me?
 };
 
 // @Volatile: when changed, remember to update merge_rntuple_data()
@@ -167,10 +156,6 @@ struct RNTuple_Data {
   u64 tot_page_comp_size;
   u64 tot_page_uncomp_size;
 
-  // TODO
-  Range_Seq *checksums;
-  u64        n_checksums;
-
   Cluster_Group_Info *cluster_groups;
   u64 n_cluster_groups;
   u64 tot_page_list_size;
diff --git a/src/tfile.cpp b/src/tfile.cpp
index b82edb0..9d6ff61 100644
--- a/src/tfile.cpp
+++ b/src/tfile.cpp
@@ -239,12 +239,9 @@ b8 walk_tkeys(Arena *arena, const u8 *data, u64 data_len, u32 flags, TFile_Data
       ++n_keys;
     }
 
-    printf("cur: 0x%lX\n", cur);
-
     if (is_free_slot) {
       // don't try to read the rest of the data
       cur += n_bytes;
-      printf("skipping %u bytes\n", n_bytes);
       continue;
     }
 
@@ -308,8 +305,6 @@ b8 walk_tkeys(Arena *arena, const u8 *data, u64 data_len, u32 flags, TFile_Data
         sec_anchor->range.len = n_bytes - keylen;
         sec_anchor->pre_size = keylen;
         sec_anchor->post_size = 8;
-
-        ++tfile_data.n_anchors;
         
       } else if (key_has_class_name("RBlob")) {
         if (!sections[Sec_Page].head) {
@@ -361,37 +356,25 @@ b8 walk_tkeys(Arena *arena, const u8 *data, u64 data_len, u32 flags, TFile_Data
   u64 free_slots_start = sec_tfile_freelist->range.start;
   u64 free_slots_end = sec_tfile_freelist->range.end();
   u64 n_free_slots = (free_slots_end - free_slots_start) / free_slot_size;
-  if (n_free_slots) {
-    tfile_data.free_slots = arena_push_array_nozero<Byte_Range>(arena, n_free_slots);
-    u64 cur = free_slots_start;
-    for (u64 i = 0; i < n_free_slots; ) {
-      memcpy(&fs, data + cur, free_slot_size);
-      Byte_Range *free_slot = &tfile_data.free_slots[i];
-      u64 start, end;
-      if (is_big_file) {
-        start = bswap(fs.rng.rng_long.start);
-        end = min(data_len, bswap(fs.rng.rng_long.end));
-      } else {
-        start = bswap(fs.rng.rng_short.start);
-        end = min(data_len, bswap(fs.rng.rng_short.end));
-      }
-
-      cur += free_slot_size;
-
-      printf("0x%lX - 0x%lX\n", start, end);
-
-      // The free slot might not be a "real" slot (if its end is lower than its start or if it starts past the end of
-      // the file): in this case, don't add it to the list.
-      if (end >= start && start < data_len) {
-        free_slot->start = start;
-        free_slot->len = end - start + 1; // +1 because `end` is inclusive
-        ++i;
-      } else {
-        assert(n_free_slots > 0);
-        --n_free_slots;
-      }
+  for (u64 i = 0; i < n_free_slots; ++i) {
+    u64 cur = free_slots_start + i * free_slot_size;
+    memcpy(&fs, data + cur, free_slot_size);
+    u64 start, end;
+    if (is_big_file) {
+      start = bswap(fs.rng.rng_long.start);
+      end = min(data_len, bswap(fs.rng.rng_long.end));
+    } else {
+      start = bswap(fs.rng.rng_short.start);
+      end = min(data_len, bswap(fs.rng.rng_short.end));
+    }
+
+    // The free slot might not be a "real" slot (if its end is lower than its start or if it starts past the end of
+    // the file): in this case, don't add it to the list.
+    if (end >= start && start < data_len) {
+      Section *sec_free_slot = push_section(arena, tfile_data, Sec_Free_Slot);
+      sec_free_slot->range.start = start;
+      sec_free_slot->range.len = end - start + 1; // +1 because `end` is inclusive
     }
-    tfile_data.n_free_slots = n_free_slots;
   }
 
   return true;
@@ -404,11 +387,12 @@ void map_rntuple_rblobs(Arena *arena, TFile_Data &tfile_data)
   defer { scratch_end(scratch); };
   
   TKeys_Data &tkeys_data = tfile_data.tkeys_data;
+  u64 n_anchors = tfile_data.sections[Sec_RNTuple_Anchor].count;
 
   // 0: header, 1: footer
   b8 *found[2] = {
-    arena_push_array<b8>(scratch.arena, tfile_data.n_anchors),
-    arena_push_array<b8>(scratch.arena, tfile_data.n_anchors)
+    arena_push_array<b8>(scratch.arena, n_anchors),
+    arena_push_array<b8>(scratch.arena, n_anchors)
   };
 
   for (Byte_Range_Node *tkey = tkeys_data.rblob_keys; tkey; tkey = tkey->next) {
@@ -444,7 +428,7 @@ void map_rntuple_rblobs(Arena *arena, TFile_Data &tfile_data)
     }
   }
 
-  for (u64 i = 0; i < tfile_data.n_anchors; ++i) {
+  for (u64 i = 0; i < n_anchors; ++i) {
     if (!found[0][i]) {
       fprintf(stderr, "Didn't found header for RNTuple %" PRIu64 "\n", i);
     }