{"id":2022,"date":"2023-06-03T19:39:31","date_gmt":"2023-06-03T19:39:31","guid":{"rendered":"https:\/\/writingagame.com\/?p=2022"},"modified":"2026-04-08T17:02:51","modified_gmt":"2026-04-08T17:02:51","slug":"chapter-6-external-files-windows","status":"publish","type":"post","link":"https:\/\/writingagame.com\/index.php\/2023\/06\/03\/chapter-6-external-files-windows\/","title":{"rendered":"Chapter 6. External files, Windows"},"content":{"rendered":"\n<p><strong>Tags:<\/strong> <em>Visual Studio, File I\/O, Resource Management, Win32 API, Build Events, C++, Data-Driven Design<\/em><\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<p>Now, having a cross-platform solution, we can start thinking about our Graphics Engine. However, the first question will be <strong>not<\/strong> about graphics, but how we gonna handle data files (like shaders, models, textures and so on)?<\/p>\n\n\n\n<p>For example, currently our triangle model (verts array) and 2 shaders (1 vertex and 1 fragment) are <strong>hardcoded <\/strong>in <em>TheApp.cpp<\/em>. Obviously not the best solution, but was quite reasonable for simplicity. In our turn, we want all data files <strong>outside <\/strong>of the executable.<\/p>\n\n\n\n<p>Let&#8217;s make a test sample.<\/p>\n\n\n\n<p>1. In <strong>Windows File Explorer<\/strong> (not in VS), in <em>C:\\CPP\\a999hello\\<\/em> folder add sub-folder \u201cdt\u201d (for &#8220;data&#8221;).<\/p>\n\n\n\n<p>In a <strong>Text Editor<\/strong> create a simple txt file for testing, just couple lines, such as<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: plain; title: ; notranslate\" title=\"\">\ntest 1\ntest 2\n<\/pre><\/div>\n\n\n<p><br>Save it as <em>C:\\CPP\\<em>a999hello<\/em>\\dt\\<strong>test0.txt<\/strong><\/em><\/p>\n\n\n\n<hr class=\"wp-block-separator has-css-opacity\"\/>\n\n\n\n<p><\/p>\n\n\n\n<p>2. Now we need to pass this file to the executable. There are couple options such as including files into &#8220;resources&#8221; or directly into the project. However, we don&#8217;t want data files &#8220;inside&#8221; of the project. Instead, we will instruct Visual Studio to copy data folder to the same place as executable.<\/p>\n\n\n\n<p>Start Visual Studio, open <em>C:\\CPP\\a999hello\\pw\\pw.sln<\/em> solution.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-css-opacity\"\/>\n\n\n\n<p><\/p>\n\n\n\n<p>3. Open  <em>pw<\/em> project Properties, <strong>All Configurations \/ x64<\/strong>, <\/p>\n\n\n\n<p><em>Configuration Properties -&gt; Build events -&gt; Post-Build Event<\/em>, open <em>Command Line -&gt; Edit<\/em>.<\/p>\n\n\n\n<p>Add (copy-paste) following command:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>xcopy \"..\\dt\\*.*\" \"$(TargetDir)dt\\\" \/E \/R \/D \/y<\/code><\/pre>\n\n\n\n<p><\/p>\n\n\n\n<p>Then &#8211; <strong>Ok, Apply, Ok<\/strong>.<\/p>\n\n\n\n<p>Clarification:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>xcopy <\/strong>&#8211; doesn&#8217;t really need an explanation (I guess)<\/li>\n\n\n\n<li><strong>..\\dt\\*.*<\/strong> \u2013 copy what and from. Refers to <em>C:\\CPP\\<em>a999hello<\/em>\\dt<\/em>, just in relative form from  <em>pw<\/em>  project root folder<\/li>\n\n\n\n<li><strong>$(TargetDir)dt\\<\/strong> &#8211; copy to where. We want a copy of \u201cdt\u201d folder in the same place as executable<\/li>\n<\/ul>\n\n\n\n<p>Keys:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>\/E<\/strong> &#8211; Copy directories and subdirectories, including empty ones<\/li>\n\n\n\n<li><strong>\/R<\/strong> &#8211; Overwrite read-only files<\/li>\n\n\n\n<li><strong>\/D<\/strong> &#8211; Copy files only if newer<\/li>\n\n\n\n<li><strong>\/y<\/strong> &#8211; Don&#8217;t ask if exists\/overwrite<\/li>\n<\/ul>\n\n\n\n<hr class=\"wp-block-separator has-css-opacity\"\/>\n\n\n\n<p><\/p>\n\n\n\n<p>4. Now pick <em>Debug <\/em>config in VS top menu and run the program (green arrow). Runs. Now &#8211; close the program OR: <em>VS top menu -&gt; Debug -&gt; Stop Debugging<\/em>.<\/p>\n\n\n\n<p>Go to <strong>Windows File Explorer<\/strong>, open <em>C:\\CPP\\a999hello\\pw\\x64\\Debug<\/em>. Perfect, the copy of the &#8220;dt&#8221; folder with all it&#8217;s content is there, in the same folder as <em>HelloWindows.exe<\/em>:<\/p>\n\n\n\n<p><img decoding=\"async\" src=\"https:\/\/writingagame.com\/img\/b04\/c06\/01.jpg\"><\/p>\n\n\n\n<p><\/p>\n\n\n\n<hr class=\"wp-block-separator has-css-opacity\"\/>\n\n\n\n<p>5. Now let&#8217;s try to read our test file (test0.txt). For that we need to specify the file&#8217;s <strong>full<\/strong> path. However, it can vary depending on where program was installed. So, will need to find it out, to detect application&#8217;s root folder.<\/p>\n\n\n\n<p>The code:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: cpp; title: ; notranslate\" title=\"\">\n    \/\/find application root folder\n    char path&#91;256];\n    GetModuleFileNameA(NULL, path, 256);\n    filesRoot.assign(path);\n    int lastSlashPos = filesRoot.find_last_of(&#039;\\\\&#039;);\n    if (lastSlashPos &lt; 0)\n        lastSlashPos = filesRoot.find_last_of(&#039;\/&#039;);\n    filesRoot = filesRoot.substr(0, lastSlashPos);\n    mylog(&quot;App path = %s\\n&quot;, filesRoot.c_str());\n\n<\/pre><\/div>\n\n\n<p><\/p>\n\n\n\n<p>Insert it in <em>main.cpp<\/em> right before <em>theApp.run()<\/em>.<\/p>\n\n\n\n<p>Scroll up and add to the end of include section:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: cpp; title: ; notranslate\" title=\"\">\n#include &lt;windows.h&gt;\n#include &lt;string&gt;\n#include &lt;fstream&gt;      \/\/ std::ifstream\nstd::string filesRoot;\n\n<\/pre><\/div>\n\n\n<p><\/p>\n\n\n\n<p>Run. Result (in Console window):<\/p>\n\n\n\n<p><strong>App path = C:\\CPP\\a999hello\\pw\\x64\\Debug<\/strong><\/p>\n\n\n\n<p>Just what we need. <\/p>\n\n\n\n<hr class=\"wp-block-separator has-css-opacity\"\/>\n\n\n\n<p>6. Now let&#8217;s try to open our test file and read it.<\/p>\n\n\n\n<p>Right before <em>theApp.run()<\/em> add following code:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: cpp; title: ; notranslate\" title=\"\">\n    \/\/reading test file\n    std::ifstream myFile(filesRoot + &quot;\/dt\/test0.txt&quot;);\n    std::string line;\n    if (myFile.is_open())\n    {\n        while (getline(myFile, line))\n            mylog(&quot;%s\\n&quot;, line.c_str());\n    }\n    else mylog(&quot;Unable to open file\\n&quot;);\n\n<\/pre><\/div>\n\n\n<p><\/p>\n\n\n\n<p>Run. Result:<\/p>\n\n\n\n<p><strong>App path = C:\\CPP\\a999hello\\pw\\x64\\Debug<\/strong><br><strong>test 1<br>test 2<\/strong><\/p>\n\n\n\n<hr class=\"wp-block-separator has-css-opacity\"\/>\n\n\n\n<p>7. After removing testing code, <em>main.cpp<\/em> (with new <em>filesRoot <\/em>variable and with corresponding code) is:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: cpp; highlight: [12,51,52,53,54,55,56,57,58,59]; title: ; notranslate\" title=\"\">\n#define GLFW_INCLUDE_NONE\n#include &lt;GLFW\/glfw3.h&gt;\n#include &lt;stdlib.h&gt;\n#include &quot;TheApp.h&quot;\n#include &quot;platform.h&quot;\n#include &lt;windows.h&gt;\n#include &lt;string&gt;\nstd::string filesRoot;\nstatic void error_callback(int error, const char* description)\n{\n    mylog(&quot;Error: %s\\n&quot;, description);\n}\nstatic void key_callback(GLFWwindow* window, int key, int scancode, int action, int mods)\n{\n    if (key == GLFW_KEY_ESCAPE &amp;&amp; action == GLFW_PRESS)\n        glfwSetWindowShouldClose(window, GLFW_TRUE);\n}\nTheApp theApp;\nGLFWwindow* myMainWindow;\nint main(void)\n{\n    glfwSetErrorCallback(error_callback);\n    if (!glfwInit())\n        exit(EXIT_FAILURE);\n    glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);\n    glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 2);\n    myMainWindow = glfwCreateWindow(640, 480, &quot;Hello Windows&quot;, NULL, NULL);\n    if (!myMainWindow)\n    {\n        glfwTerminate();\n        exit(EXIT_FAILURE);\n    }\n    glfwSetKeyCallback(myMainWindow, key_callback);\n    glfwMakeContextCurrent(myMainWindow);\n    gladLoadGLES2Loader((GLADloadproc)glfwGetProcAddress); \/\/gladLoadGL(glfwGetProcAddress);\n    glfwSwapInterval(1);\n    \/\/find application root folder\n    char path&#91;256];\n    GetModuleFileNameA(NULL, path, 256);\n    filesRoot.assign(path);\n    int lastSlashPos = filesRoot.find_last_of(&#039;\\\\&#039;);\n    if (lastSlashPos &lt; 0)\n        lastSlashPos = filesRoot.find_last_of(&#039;\/&#039;);\n    filesRoot = filesRoot.substr(0, lastSlashPos);\n    mylog(&quot;App path = %s\\n&quot;, filesRoot.c_str());\n    theApp.run();\n    glfwDestroyWindow(myMainWindow);\n    glfwTerminate();\n    exit(EXIT_SUCCESS);\n}\n\n<\/pre><\/div>\n\n\n<p><\/p>\n\n\n\n<p>Replace  <em>main.cpp<\/em> code by this one.<\/p>\n\n\n\n<p>Save All.<\/p>\n\n\n\n<p>Cool. What&#8217;s next? &#8211; external data files on Android.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-css-opacity\"\/>\n\n\n\n<p><\/p>\n","protected":false},"excerpt":{"rendered":"<p class=\"mb-2\">Tags: Visual Studio, File I\/O, Resource Management, Win32 API, Build Events, C++, Data-Driven Design Now, having a cross-platform solution, we can start thinking about our Graphics Engine. However, the first question will be not about graphics, but how we gonna handle data files (like shaders, models, textures and so on)? For example, currently our triangle [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[4],"tags":[],"class_list":["post-2022","post","type-post","status-publish","format-standard","hentry","category-cross-platform-3d"],"_links":{"self":[{"href":"https:\/\/writingagame.com\/index.php\/wp-json\/wp\/v2\/posts\/2022","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/writingagame.com\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/writingagame.com\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/writingagame.com\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/writingagame.com\/index.php\/wp-json\/wp\/v2\/comments?post=2022"}],"version-history":[{"count":20,"href":"https:\/\/writingagame.com\/index.php\/wp-json\/wp\/v2\/posts\/2022\/revisions"}],"predecessor-version":[{"id":4282,"href":"https:\/\/writingagame.com\/index.php\/wp-json\/wp\/v2\/posts\/2022\/revisions\/4282"}],"wp:attachment":[{"href":"https:\/\/writingagame.com\/index.php\/wp-json\/wp\/v2\/media?parent=2022"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/writingagame.com\/index.php\/wp-json\/wp\/v2\/categories?post=2022"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/writingagame.com\/index.php\/wp-json\/wp\/v2\/tags?post=2022"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}