diff --git a/cbp/Module.cbp b/cbp/Module.cbp
index 27bb62f5..ffd08044 100644
--- a/cbp/Module.cbp
+++ b/cbp/Module.cbp
@@ -445,6 +445,8 @@
+
+
diff --git a/source/Base/ScriptSrc.cpp b/source/Base/ScriptSrc.cpp
new file mode 100644
index 00000000..20e03f6f
--- /dev/null
+++ b/source/Base/ScriptSrc.cpp
@@ -0,0 +1,160 @@
+// ------------------------------------------------------------------------------------------------
+#include "Base/ScriptSrc.hpp"
+
+// ------------------------------------------------------------------------------------------------
+#include
+#include
+#include
+
+// ------------------------------------------------------------------------------------------------
+namespace SqMod {
+
+/* ------------------------------------------------------------------------------------------------
+ * Helper class to ensure the file handle is closed regardless of the situation.
+*/
+class FileHandle
+{
+public:
+
+ // --------------------------------------------------------------------------------------------
+ std::FILE * mFile; // Handle to the opened file.
+
+ /* --------------------------------------------------------------------------------------------
+ * Default constructor.
+ */
+ FileHandle(CSStr path)
+ : mFile(std::fopen(path, "rb"))
+ {
+ if (!mFile)
+ {
+ throw std::runtime_error(ToStrF("Unable to open script source (%s)", path));
+ }
+ }
+
+ /* --------------------------------------------------------------------------------------------
+ * Copy constructor. (disabled)
+ */
+ FileHandle(const FileHandle & o) = delete;
+
+ /* --------------------------------------------------------------------------------------------
+ * Move constructor. (disabled)
+ */
+ FileHandle(FileHandle && o) = delete;
+
+ /* --------------------------------------------------------------------------------------------
+ * Destructor.
+ */
+ ~FileHandle()
+ {
+ if (mFile)
+ {
+ std::fclose(mFile);
+ }
+ }
+
+ /* --------------------------------------------------------------------------------------------
+ * Copy assignment operator. (disabled)
+ */
+ FileHandle & operator = (const FileHandle & o) = delete;
+
+ /* --------------------------------------------------------------------------------------------
+ * Move assignment operator. (disabled)
+ */
+ FileHandle & operator = (FileHandle && o) = delete;
+
+ /* --------------------------------------------------------------------------------------------
+ * Implicit conversion to the managed file handle.
+ */
+ operator std::FILE * ()
+ {
+ return mFile;
+ }
+
+ /* --------------------------------------------------------------------------------------------
+ * Implicit conversion to the managed file handle.
+ */
+ operator std::FILE * () const
+ {
+ return mFile;
+ }
+};
+
+
+// ------------------------------------------------------------------------------------------------
+void ScriptSrc::Process()
+{
+ // Attempt to open the specified file
+ FileHandle fp(mPath.c_str());
+ // First 2 bytes of the file will tell if this is a compiled script
+ std::uint16_t tag;
+ // Read the first 2 bytes of the file and determine the file type
+ if (std::fread(&tag, 1, 2, fp) != 2 || tag == SQ_BYTECODE_STREAM_TAG)
+ {
+ return; // Probably an empty file or compiled script
+ }
+ // Go to the end of the file
+ std::fseek(fp, 0, SEEK_END);
+ // Calculate buffer size from beginning to current position
+ const LongI length = std::ftell(fp);
+ // Go back to the beginning
+ std::fseek(fp, 0, SEEK_SET);
+ // Allocate enough space to hold the file data
+ mData.resize(length, 0);
+ // Read the file contents into allocated data
+ std::fread(&mData[0], 1, length, fp);
+ // Where the last line ended
+ unsigned line = 0;
+ // Process the file data and locate new lines
+ for (String::const_iterator itr = mData.cbegin(); itr != mData.cend();)
+ {
+ // Is this a Unix style line ending?
+ if (*itr == '\n')
+ {
+ // Store the beginning of the line
+ mLine.push_back(line);
+ // Advance to the next line
+ line = std::distance(mData.cbegin(), ++itr);
+ }
+ // Is this a Windows style line ending?
+ else if (*itr == '\r')
+ {
+ if (*(++itr) == '\n')
+ {
+ // Store the beginning of the line
+ mLine.push_back(line);
+ // Advance to the next line
+ line = std::distance(mData.cbegin(), ++itr);
+ }
+ }
+ else
+ {
+ ++itr;
+ }
+ }
+ // Should we add the last line as well?
+ if (line)
+ {
+ mLine.push_back(line);
+ }
+}
+
+// ------------------------------------------------------------------------------------------------
+ScriptSrc::ScriptSrc(HSQUIRRELVM vm, const String & path, bool info)
+ : mExec(vm)
+ , mPath(path)
+ , mData()
+ , mLine()
+{
+ // Is the specified path empty?
+ if (mPath.empty())
+ {
+ throw std::runtime_error("Invalid or empty script path");
+ }
+ // Should we load the file contents for debugging purposes?
+ if (info)
+ {
+ Process();
+ }
+}
+
+} // Namespace:: SqMod
diff --git a/source/Base/ScriptSrc.hpp b/source/Base/ScriptSrc.hpp
new file mode 100644
index 00000000..e935da9e
--- /dev/null
+++ b/source/Base/ScriptSrc.hpp
@@ -0,0 +1,75 @@
+#ifndef _BASE_SCRIPTSRC_HPP_
+#define _BASE_SCRIPTSRC_HPP_
+
+// ------------------------------------------------------------------------------------------------
+#include "Base/Utility.hpp"
+
+// ------------------------------------------------------------------------------------------------
+#include
+#include
+
+// ------------------------------------------------------------------------------------------------
+namespace SqMod {
+
+// ------------------------------------------------------------------------------------------------
+class Core;
+
+/* ------------------------------------------------------------------------------------------------
+ * Hold a information about loaded scripts as it's contents and executable code.
+*/
+class ScriptSrc
+{
+ // --------------------------------------------------------------------------------------------
+ friend class Core;
+
+public:
+
+ // --------------------------------------------------------------------------------------------
+ typedef std::vector< Uint32 > Line;
+
+ // --------------------------------------------------------------------------------------------
+ Script mExec; // Reference to the script object.
+ String mPath; // Path to the script file.
+ String mData; // The contents of the script file.
+ Line mLine; // List of lines of code in the data.
+
+private:
+
+ /* --------------------------------------------------------------------------------------------
+ * Read file contents and calculate information about the lines of code.
+ */
+ void Process();
+
+ /* --------------------------------------------------------------------------------------------
+ * Default constructor.
+ */
+ ScriptSrc(HSQUIRRELVM vm, const String & path, bool info = false);
+
+public:
+
+ /* --------------------------------------------------------------------------------------------
+ * Copy constructor.
+ */
+ ScriptSrc(const ScriptSrc & o) = default;
+
+ /* --------------------------------------------------------------------------------------------
+ * Move constructor.
+ */
+ ScriptSrc(ScriptSrc && o) = default;
+
+ /* --------------------------------------------------------------------------------------------
+ * Copy assignment operator.
+ */
+ ScriptSrc & operator = (const ScriptSrc & o) = default;
+
+ /* --------------------------------------------------------------------------------------------
+ * Move assignment operator.
+ */
+ ScriptSrc & operator = (ScriptSrc && o) = default;
+
+};
+
+
+} // Namespace:: SqMod
+
+#endif // _BASE_SCRIPTSRC_HPP_