From f040fc54a4486d97fe43de337525bc1c86b2ccf6 Mon Sep 17 00:00:00 2001
From: archshift <admin@archshift.com>
Date: Sun, 14 Dec 2014 02:37:52 -0800
Subject: [PATCH] Add logging to file, and cleaned up text.h/cpp.

---
 source/{text.cpp => draw.cpp} | 38 +++++++++++-----
 source/draw.h                 | 18 ++++++++
 source/main.cpp               |  9 ++--
 source/output.cpp             | 81 ++++++++++++++++++++++-------------
 source/output.h               | 20 +++++++--
 source/tests/test.cpp         |  8 +++-
 source/tests/test.h           | 10 ++++-
 source/text.h                 |  9 ----
 8 files changed, 137 insertions(+), 56 deletions(-)
 rename source/{text.cpp => draw.cpp} (60%)
 create mode 100644 source/draw.h
 delete mode 100644 source/text.h

diff --git a/source/text.cpp b/source/draw.cpp
similarity index 60%
rename from source/text.cpp
rename to source/draw.cpp
index 1dcf8aa..0d0cdce 100644
--- a/source/text.cpp
+++ b/source/draw.cpp
@@ -1,13 +1,20 @@
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
+#include "draw.h"
+
+#include <cstdlib>
+#include <cstdio>
+#include <cstring>
+
 #include <3ds.h>
-#include "text.h"
 
 #include "font.h"
 
-//this code is not meant to be readable
-int drawCharacter(u8* fb, font_s* font, char c, s16 x, s16 y, u16 w, u16 h)
+Rect GetScreenSize(gfxScreen_t screen)
+{
+    return { (screen == GFX_TOP) ? 400 : 320, 240 };
+}
+
+// This code is not meant to be readable -- Smea
+int DrawCharacter(u8* fb, font_s* font, char c, s16 x, s16 y, u16 w, u16 h)
 {
     Glyph* cd = &font->desc[(int)c];
 
@@ -52,7 +59,7 @@ int drawCharacter(u8* fb, font_s* font, char c, s16 x, s16 y, u16 w, u16 h)
     return cd->xa;
 }
 
-void drawString(u8* fb, font_s* f, const std::string& str, s16 x, s16 y, u16 w, u16 h)
+void DrawString(u8* fb, font_s* f, const std::string& str, s16 x, s16 y, u16 w, u16 h)
 {
     if (!f || !fb)
         return;
@@ -60,7 +67,7 @@ void drawString(u8* fb, font_s* f, const std::string& str, s16 x, s16 y, u16 w,
     int dx = 0, dy = 0;
     for (const char& c : str)
     {
-        dx += drawCharacter(fb, f, c, x + dx, y + dy, w, h);
+        dx += DrawCharacter(fb, f, c, x + dx, y + dy, w, h);
         if (c == '\n') {
             dx = 0;
             dy -= f->height;
@@ -68,7 +75,7 @@ void drawString(u8* fb, font_s* f, const std::string& str, s16 x, s16 y, u16 w,
     }
 }
 
-void gfxDrawText(gfxScreen_t screen, gfx3dSide_t side, font_s* font, const std::string& str, s16 x, s16 y)
+void DrawText(gfxScreen_t screen, gfx3dSide_t side, font_s* font, const std::string& str, s16 x, s16 y)
 {
     if (!font)
         font = &fontDefault;
@@ -76,5 +83,16 @@ void gfxDrawText(gfxScreen_t screen, gfx3dSide_t side, font_s* font, const std::
     u16 fbWidth, fbHeight;
     u8* fbAdr = gfxGetFramebuffer(screen, side, &fbWidth, &fbHeight);
 
-    drawString(fbAdr, font, str, y, x, fbHeight, fbWidth);
+    DrawString(fbAdr, font, str, y, x, fbHeight, fbWidth);
+}
+
+void FillScreen(gfxScreen_t screen, u8 bg_r, u8 bg_g, u8 bg_b)
+{
+    Rect screen_size = GetScreenSize(screen);
+    u8* fb_addr = gfxGetFramebuffer(screen, GFX_LEFT, nullptr, nullptr);
+    for (int i = 0; i < screen_size.w * screen_size.h * 3; i += 3) {
+        fb_addr[i]   = bg_b;
+        fb_addr[i+1] = bg_g;
+        fb_addr[i+2] = bg_r;
+    }
 }
diff --git a/source/draw.h b/source/draw.h
new file mode 100644
index 0000000..c2b78ad
--- /dev/null
+++ b/source/draw.h
@@ -0,0 +1,18 @@
+#pragma once
+
+#include <string>
+
+#include <3ds.h>
+
+#include "font.h"
+
+struct Rect {
+    int w, h;
+};
+
+Rect GetScreenSize(gfxScreen_t screen);
+
+int DrawCharacter(u8* fb, font_s* f, char c, s16 x, s16 y, u16 w, u16 h);
+void DrawString(u8* fb, font_s* f, const std::string& str, s16 x, s16 y, u16 w, u16 h);
+void DrawText(gfxScreen_t screen, gfx3dSide_t side, font_s* f, const std::string& str, s16 x, s16 y);
+void FillScreen(gfxScreen_t screen, u8 bg_r, u8 bg_g, u8 bg_b);
diff --git a/source/main.cpp b/source/main.cpp
index 91d8edf..b39d285 100644
--- a/source/main.cpp
+++ b/source/main.cpp
@@ -19,18 +19,19 @@ int main(int argc, char** argv)
     gfxInit();
     gfxSet3D(false);
     fsInit();
+    InitOutput();
 
     ClearScreens();
     Print(GFX_TOP, "Press A to begin...\n");
 
     while (aptMainLoop()) {
-        DrawFrames();
+        DrawBuffers();
 
         hidScanInput();
         if (hidKeysDown() & KEY_START) {
             break;
         } else if (hidKeysDown() & KEY_A) {
-            ClearScreen(GFX_TOP);
+            ClearScreens();
 
             if (test_counter < (sizeof(tests) / sizeof(tests[0]))) {
                 tests[test_counter]();
@@ -39,7 +40,7 @@ int main(int argc, char** argv)
                 break;
             }
 
-            Print(GFX_TOP, "\n");
+            Log(GFX_TOP, "\n");
             Print(GFX_TOP, "Press A to continue...\n");
         }
 
@@ -47,6 +48,8 @@ int main(int argc, char** argv)
     }
 
     ClearScreens();
+    
+    DeinitOutput();
     fsExit();
     gfxExit();
     hidExit();
diff --git a/source/output.cpp b/source/output.cpp
index f6ecb43..aa9c937 100644
--- a/source/output.cpp
+++ b/source/output.cpp
@@ -1,12 +1,15 @@
+#include <3ds.h>
+
 #include "output.h"
 
 #include <cmath>
+#include <fstream>
 
-#include <3ds.h>
-
-#include "text.h"
+#include "draw.h"
 #include "common/string_funcs.h"
 
+static FILE* log_file;
+
 static std::string buffer_top;
 static std::string buffer_bottom;
 
@@ -19,51 +22,71 @@ static std::string& GetTextBuffer(gfxScreen_t screen)
     return buffer_top;
 }
 
-static void DrawFrame(gfxScreen_t screen, char b, char g, char r)
+static void DrawBuffer(gfxScreen_t screen)
 {
-    int screen_height = 240;
-    int screen_width = (screen == GFX_TOP) ? 400 : 320;
+    Rect screen_size = GetScreenSize(screen);
     std::string& text_buffer = GetTextBuffer(screen);
 
-    u8* fb_addr = gfxGetFramebuffer(screen, GFX_LEFT, nullptr, nullptr);
-    for (int i = 0; i < screen_width * screen_height * 3; i += 3) {
-        fb_addr[i]   = b;
-        fb_addr[i+1] = g;
-        fb_addr[i+2] = r;
-    }
-
     int lines = Common::CountLines(text_buffer);
-    while (lines > (screen_height / fontDefault.height - 3)) {
+    while (lines > (screen_size.h / fontDefault.height - 3)) {
         Common::DeleteFirstLine(&text_buffer);
         lines--;
     }
-    gfxDrawText(screen, GFX_LEFT, nullptr, text_buffer, screen_height - fontDefault.height * 3, 10);
+    DrawText(screen, GFX_LEFT, nullptr, text_buffer, screen_size.h - fontDefault.height * 3, 10);
 }
 
-void DrawFrames()
+void InitOutput()
 {
-    DrawFrame(GFX_TOP, 0x88, 0x66, 0x00);
-    DrawFrame(GFX_BOTTOM, 0x00, 0x00, 0x00);
+    sdmcInit();
+    log_file = fopen("hwtest_log.txt", "w");
+}
+
+void DrawBuffers()
+{
+    FillScreen(GFX_TOP, 0x00, 0x66, 0x88);
+    DrawBuffer(GFX_TOP);
+    
+    FillScreen(GFX_BOTTOM, 0x00, 0x00, 0x00);
+    DrawBuffer(GFX_BOTTOM);
+    
     gfxFlushBuffers();
     gfxSwapBuffers();
 }
 
+void ClearScreen(gfxScreen_t screen, u8 bg_r, u8 bg_g, u8 bg_b)
+{
+    FillScreen(screen, bg_r, bg_g, bg_b);
+    GetTextBuffer(screen).clear();
+    gfxFlushBuffers();
+    gfxSwapBuffers();
+}
+
+void ClearScreens()
+{
+    ClearScreen(GFX_TOP, 0x00, 0x66, 0x88);
+    ClearScreen(GFX_BOTTOM, 0x00, 0x00, 0x00);
+}
+
 void Print(gfxScreen_t screen, const std::string& text)
 {
     GetTextBuffer(screen) += text;
+    DrawBuffers();
+}
+
+void Log(gfxScreen_t screen, const std::string& text)
+{
+    Print(screen, text);
+    LogToFile(text);
+}
+
+void LogToFile(const std::string& text)
+{
     svcOutputDebugString(text.c_str(), text.length());
-
-    DrawFrames();
+    fprintf(log_file, "%s", text.c_str());
 }
 
-void ClearScreen(gfxScreen_t screen)
+void DeinitOutput()
 {
-    GetTextBuffer(screen).clear();
-    DrawFrames();
-}
-
-void ClearScreens()
-{
-    ClearScreen(GFX_TOP);
-    ClearScreen(GFX_BOTTOM);
+    fclose(log_file);
+    sdmcExit();
 }
diff --git a/source/output.h b/source/output.h
index 5219bcd..8c59056 100644
--- a/source/output.h
+++ b/source/output.h
@@ -1,9 +1,23 @@
 #pragma once
 
-#include <3ds.h>
 #include <string>
 
-void DrawFrames();
+#include <3ds.h>
+
+void InitOutput();
+
+void DrawBuffers();
+
+/// Prints `text` to `screen`.
 void Print(gfxScreen_t screen, const std::string& text);
-void ClearScreen(gfxScreen_t screen);
+
+/// Prints `text` to `screen`, and logs it in the log file.
+void Log(gfxScreen_t screen, const std::string& text);
+
+/// Logs `text` to the log file.
+void LogToFile(const std::string& text);
+
+void ClearScreen(gfxScreen_t screen, u8 bg_r, u8 bg_g, u8 bg_b);
 void ClearScreens();
+
+void DeinitOutput();
diff --git a/source/tests/test.cpp b/source/tests/test.cpp
index 4a92cab..03df339 100644
--- a/source/tests/test.cpp
+++ b/source/tests/test.cpp
@@ -5,7 +5,13 @@
 #include "output.h"
 #include "common/string_funcs.h"
 
+void SoftAssertLog(const std::string& function, int line, const std::string& condition)
+{
+    LogToFile(Common::FormatString("SOFTASSERT FAILURE: `%s`\n", condition.c_str()));
+    LogToFile(Common::FormatString("    At `%s` L%i\n", function.c_str(), line));
+}
+
 void PrintSuccess(const std::string& group, const std::string& name, bool val)
 {
-    Print(GFX_TOP, Common::FormatString("%s: %s - %s\n", group.c_str(), name.c_str(), val ? "SUCCESS" : "FAILURE"));
+    Log(GFX_TOP, Common::FormatString("%s: [%s] %s\n", val ? "SUCCESS" : "FAILURE", group.c_str(), name.c_str()));
 }
diff --git a/source/tests/test.h b/source/tests/test.h
index c50c20e..e0e1080 100644
--- a/source/tests/test.h
+++ b/source/tests/test.h
@@ -4,8 +4,16 @@
 
 typedef void (*TestCaller)(void);
 
+void SoftAssertLog(const std::string& function, int line, const std::string& condition);
+
 // If the condition fails, return false
-#define SoftAssert(cond) do { if (!(cond)) { return false; } } while (0)
+#define SoftAssert(cond) \
+    do { \
+        if (!(cond)) { \
+            SoftAssertLog(__PRETTY_FUNCTION__, __LINE__, #cond); \
+            return false; \
+        } \
+    } while (0)
 
 void PrintSuccess(const std::string& group, const std::string& name, bool val);
 
diff --git a/source/text.h b/source/text.h
deleted file mode 100644
index 719d5c3..0000000
--- a/source/text.h
+++ /dev/null
@@ -1,9 +0,0 @@
-#pragma once
-
-#include <string>
-
-#include "font.h"
-
-int drawCharacter(u8* fb, font_s* f, char c, s16 x, s16 y, u16 w, u16 h);
-void drawString(u8* fb, font_s* f, const std::string& str, s16 x, s16 y, u16 w, u16 h);
-void gfxDrawText(gfxScreen_t screen, gfx3dSide_t side, font_s* f, const std::string& str, s16 x, s16 y);