diff --git a/README.md b/README.md
index 31a2607..aafae44 100644
--- a/README.md
+++ b/README.md
@@ -1,3 +1,7 @@
 Cave Story Randomizer
 =====================
 
+Issues
+------
+
+- Bubbler (and other weapons?) can't break blocks in the First Cave.
diff --git a/src/conf.lua b/src/conf.lua
new file mode 100644
index 0000000..7a22133
--- /dev/null
+++ b/src/conf.lua
@@ -0,0 +1,41 @@
+if io then
+  io.stdout:setvbuf("no")
+end
+
+local seed = os.time()
+math.randomseed(seed)
+
+function love.conf(t)
+  t.window = {
+    title = "Cave Story Randomizer",
+    -- icon = 'icon.png',
+    width = 640,
+    height = 480,
+    resizable = false,
+  }
+  t.version = '11.1'
+  t.console = false
+  t.identity = 'CaveStoryRandomizer'
+  t.accelerometerjoystick = false
+  t.gammacorrect = false
+
+  -- t.releases = {
+  --   -- This is the name of the zip archive which contains your game.
+  --   title = 'Cave Story Randomizer',
+  --   -- This is the name of your game's executable.
+  --   package = 'Cave Story Randomizer',
+  --   loveVersion = '11.1',
+  --   version = nil,
+  --   author = 'shru',
+  --   email = nil,
+  --   description = nil,
+  --   homepage = 'https://shru.itch.io/cave-story-randomizer',
+  --   -- MacOS needs this.
+  --   identifier = 'CaveStoryRandomizer',
+  --   excludeFileList = {
+  --     -- '.+%.ase',
+  --   },
+  --   compile = false,
+  --   releaseDirectory = 'releases',
+  -- }
+end
diff --git a/src/database/items.lua b/src/database/items.lua
index 35bf472..d67685f 100644
--- a/src/database/items.lua
+++ b/src/database/items.lua
@@ -1,5 +1,21 @@
 return {
   -- Weapons
+  -- wXXX = {
+  --   name = "",
+  --   map = "",
+  --   getText = "",
+  --   command = "",
+  --   displayCmd = "",
+  --   kind = "weapon",
+  -- },
+  wBubbler = {
+    name = "Bubbler",
+    map = "Comu",
+    getText = "Got the =Bubbler=!",
+    command = "<AM+0007:0100",
+    displayCmd = "<GIT0007",
+    kind = "weapon",
+  },
   wPolar = {
     name = "Polar Star",
     map = "Pole",
@@ -12,10 +28,21 @@ return {
   iPanties = {
     name = "Curly's Panties",
     map = "CurlyS",
-    -- getText = "Found =Curly's Underwear=.",
-    getText = "Found =Curly's Panties=.",
+    getText = "Found =Curly's Underwear=.",
+    -- getText = "Found =Curly's Panties=.", -- Grrr
     command = "<IT+0035",
     displayCmd = "<GIT1035",
     kind = "item",
   },
 }
+
+-- #0200
+-- <KEY<FLJ1640:0201<FL+1640<SOU0022<CNP0200:0021:0000
+-- <MSGOpened the chest.<NOD<GIT0002<AM+0002:0000<CLR
+-- <CMU0010Got the =Polar Star=!<WAI0160<NOD<GIT0000<CLO<RMU
+-- <MSG
+-- From somewhere, a transmission...<FAO0004<NOD<TRA0018:0501:0002:0000
+
+-- #0420
+-- <KEY<DNP0420<MSG<GIT1035<IT+0035
+-- Found Curly's Panties.<NOD<END
diff --git a/src/item_deck.lua b/src/item_deck.lua
index 2207320..754710c 100644
--- a/src/item_deck.lua
+++ b/src/item_deck.lua
@@ -4,11 +4,9 @@ local ITEM_DATA = require 'database.items'
 
 function C:new()
   self._left = {}
-  self._indexMap = {}
   for k, v in pairs(ITEM_DATA) do
     local item = _.clone(v)
     table.insert(self._left, item)
-    self._indexMap[item] = #self._left
   end
 end
 
@@ -26,18 +24,19 @@ end
 function C:_getItem(filterFn)
   -- Filter down to only applicable items.
   local applicable = {}
-  for _, item in ipairs(self._left) do
+  local indexMap = {}
+  for index, item in ipairs(self._left) do
     if filterFn(item) then
       table.insert(applicable, item)
+      indexMap[item] = index
     end
   end
   assert(#applicable >= 1, 'No applicable items!')
 
   -- Select an item.
   local selected = _.sample(applicable)
-  local index = self._indexMap[selected]
+  local index = indexMap[selected]
   table.remove(self._left, index)
-  self._indexMap[selected] = nil
 
   return selected
 end
diff --git a/src/main.lua b/src/main.lua
index 0037285..15b39c0 100644
--- a/src/main.lua
+++ b/src/main.lua
@@ -1,5 +1,3 @@
-io.stdout:setvbuf("no")
-
 require 'lib.strict'
 
 Class   = require 'lib.classic'
@@ -8,7 +6,7 @@ Serpent = require 'lib.serpent'
 
 lf = love.filesystem
 
-local LOG_LEVEL = 5
+local LOG_LEVEL = 4
 local function _log(level, prefix, text, ...)
   if LOG_LEVEL >= level then
     print(prefix .. text, ...)
@@ -20,9 +18,16 @@ function logNotice(...)  _log(3, 'NOTICE: ',  ...) end
 function logInfo(...)    _log(4, 'INFO: ',    ...) end
 function logDebug(...)   _log(5, 'DEBUG: ',   ...) end
 
-local TSC_FILES = {
-  'Pole.tsc',
-}
+local TSC_FILES = {}
+do
+  local ITEM_DATA = require 'database.items'
+  for k, v in pairs(ITEM_DATA) do
+    local filename = v.map .. '.tsc'
+    if _.contains(TSC_FILES, filename) == false then
+      table.insert(TSC_FILES, filename)
+    end
+  end
+end
 
 -- function love.load()
 --   -- readPXM('Pole.pxm')
@@ -32,32 +37,42 @@ local TSC_FILES = {
 -- end
 
 function love.directorydropped(path)
-  -- Mount
-  assert(lf.mount(path, 'data'))
-  local items = lf.getDirectoryItems('/data')
+  -- Mount.
+  local mountPath = 'mounted-data'
+  assert(lf.mount(path, mountPath))
+  local items = lf.getDirectoryItems('/' .. mountPath)
   local containsStage = _.contains(items, 'Stage')
   assert(containsStage)
-  local dirStage = '/data/Stage'
+  local dirStage = '/' .. mountPath .. '/Stage'
 
   local tscFiles = {}
   for _, filename in ipairs(TSC_FILES) do
     local path = dirStage .. '/' .. filename
     local TscFile = require 'tsc_file'
     tscFiles[filename] = TscFile(path)
-
-    -- decoded = stringReplace(decoded, ITEM_DATA.wPolar.command, ITEM_DATA.iPanties.command)
-    -- decoded = stringReplace(decoded, ITEM_DATA.wPolar.getText, ITEM_DATA.iPanties.getText)
-    -- decoded = stringReplace(decoded, ITEM_DATA.wPolar.displayCmd, ITEM_DATA.iPanties.displayCmd)
   end
 
+  -- Create ItemDeck.
   local ItemDeck = require 'item_deck'
   local itemDeck = ItemDeck()
-  print(Serpent.line(itemDeck:getWeapon()))
-  print(Serpent.line(itemDeck:getAny()))
 
-  tscFiles['Pole.tsc']:writeTo('Testing.tsc')
+  -- Place random weapon in Hermit Gunsmith.
+  tscFiles['Pole.tsc']:replaceItem(itemDeck:getWeapon())
 
-  -- Unmount
+  -- Replace all items.
+  for _, tscFile in pairs(tscFiles) do
+    while tscFile:hasUnreplacedItems() do
+      tscFile:replaceItem(itemDeck:getAny())
+    end
+  end
+
+  -- Write modified files.
+  for filename, tscFile in pairs(tscFiles) do
+    local path = '/data/Stage/' .. filename
+    tscFile:writeTo(path)
+  end
+
+  -- Unmount.
   assert(lf.unmount(path))
 end
 
@@ -66,14 +81,3 @@ function love.keypressed(key)
     love.event.push('quit')
   end
 end
-
--- #0200
--- <KEY<FLJ1640:0201<FL+1640<SOU0022<CNP0200:0021:0000
--- <MSGOpened the chest.<NOD<GIT0002<AM+0002:0000<CLR
--- <CMU0010Got the =Polar Star=!<WAI0160<NOD<GIT0000<CLO<RMU
--- <MSG
--- From somewhere, a transmission...<FAO0004<NOD<TRA0018:0501:0002:0000
-
--- #0420
--- <KEY<DNP0420<MSG<GIT1035<IT+0035
--- Found Curly's Panties.<NOD<END
diff --git a/src/tsc_file.lua b/src/tsc_file.lua
index e47f10f..8705762 100644
--- a/src/tsc_file.lua
+++ b/src/tsc_file.lua
@@ -1,7 +1,11 @@
 local C = Class:extend()
 
--- local MODE_READ_BINARY = 'rb'
-local MODE_WRITE_BINARY = 'wb'
+-- https://www.lua.org/manual/5.1/manual.html#5.7
+-- w+: Update mode, all previous data is erased;
+-- b:  Binary mode, forces Windows to save with Unix endings.
+MODE_WRITE_ERASE_EXISTING = 'w+b'
+
+local ITEM_DATA = require 'database.items'
 
 function C:new(path)
   logInfo('reading TSC: ' .. path)
@@ -14,16 +18,61 @@ function C:new(path)
 
   assert(file:close())
   assert(file:release())
+
+  -- Determine set of items which can be replaced later.
+  self._unreplaced = {}
+  self._mapName = path:match("^.+/(.+)$")
+  for k, v in pairs(ITEM_DATA) do repeat
+    if (v.map .. '.tsc') ~= self._mapName then
+      break -- continue
+    end
+    local item = _.clone(v)
+    table.insert(self._unreplaced, item)
+  until true end
+  self._unreplaced = _.shuffle(self._unreplaced)
+end
+
+function C:hasUnreplacedItems()
+  return #self._unreplaced >= 1
+end
+
+local function _stringReplace(text, needle, replacement)
+  local i = text:find(needle, 1, true)
+  if i == nil then
+    logWarning(('Unable to replace "%s" with "%s"'):format(needle, replacement))
+    return text
+  end
+  local len = needle:len()
+  local j = i + len - 1
+  assert((i % 1 == 0) and (i > 0) and (i <= j), tostring(i))
+  assert((j % 1 == 0), tostring(j))
+  local a = text:sub(1, i - 1)
+  local b = text:sub(j + 1)
+  return a .. replacement .. b
+end
+
+function C:replaceItem(replacement)
+  assert(self:hasUnreplacedItems())
+  local original = table.remove(self._unreplaced)
+  self._text = _stringReplace(self._text, original.command, replacement.command)
+  self._text = _stringReplace(self._text, original.getText, replacement.getText)
+  self._text = _stringReplace(self._text, original.displayCmd, replacement.displayCmd)
+
+  local template = "[%s] %s -> %s"
+  logNotice(template:format(self._mapName, original.name, replacement.name))
 end
 
 function C:writeTo(path)
   local encoded = self:_codec(self._text, 'encode')
 
-  local tmpFile, err = io.open(path, MODE_WRITE_BINARY)
+  local filepath = lf.getSourceBaseDirectory() .. path
+  logInfo('writing TSC to: ' .. filepath)
+
+  local file, err = io.open(filepath, MODE_WRITE_ERASE_EXISTING)
   assert(err == nil, err)
-  tmpFile:write(encoded)
-  tmpFile:flush()
-  tmpFile:close()
+  file:write(encoded)
+  file:flush()
+  file:close()
 end
 
 function C:_codec(text, mode)
@@ -66,18 +115,4 @@ function C:_codec(text, mode)
   return decoded
 end
 
-local function stringReplace(text, needle, replacement)
-  local i = text:find(needle, 1, true)
-  if i == nil then
-    return text
-  end
-  local len = needle:len()
-  local j = i + len - 1
-  assert((i % 1 == 0) and (i > 0) and (i <= j), tostring(i))
-  assert((j % 1 == 0), tostring(j))
-  local a = text:sub(1, i - 1)
-  local b = text:sub(j + 1)
-  return a .. replacement .. b
-end
-
 return C