summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorMarcus Huderle <huderlem@gmail.com>2018-01-11 18:09:25 -0800
committerGitHub <noreply@github.com>2018-01-11 18:09:25 -0800
commit6a2e39eb97db47b542eea76c1e45df37184a0705 (patch)
tree3d6a4208a965d358154edc4b7f52a64eb18b027f /src
parente7672a1aeb5e42d6f4e416ede9f6220122d11743 (diff)
parentf658a355e5434a647153d76087b50eec0d5041b1 (diff)
Merge pull request #495 from ProjectRevoTPP/assert
Add NDEBUG support to pokeruby.
Diffstat (limited to 'src')
-rw-r--r--src/engine/main.c12
-rwxr-xr-xsrc/libs/libisagbprn.c177
2 files changed, 189 insertions, 0 deletions
diff --git a/src/engine/main.c b/src/engine/main.c
index 1bed4080b..54a443e80 100644
--- a/src/engine/main.c
+++ b/src/engine/main.c
@@ -83,6 +83,10 @@ static void WaitForVBlank(void);
#define B_START_SELECT (B_BUTTON | START_BUTTON | SELECT_BUTTON)
+#ifndef NDEBUG
+ #include <stdlib.h> // don't include if not needed.
+#endif
+
void AgbMain()
{
RegisterRamReset(RESET_ALL);
@@ -98,6 +102,14 @@ void AgbMain()
gSoftResetDisabled = FALSE;
+// In Fire Red, AGBPrintInit is called at this spot. For user convenience, I
+// opt to initialize the print area here. It is up to the user where they choose
+// to print stuff from, as anything else declared is NOT authoritative.
+#ifndef NDEBUG
+ AGBPrintInit();
+ __mb_cur_max = 1; // fix for AGBPrintf
+#endif
+
if (gFlashMemoryPresent != TRUE)
SetMainCallback2(NULL);
diff --git a/src/libs/libisagbprn.c b/src/libs/libisagbprn.c
new file mode 100755
index 000000000..e0e979e95
--- /dev/null
+++ b/src/libs/libisagbprn.c
@@ -0,0 +1,177 @@
+#include <stdarg.h>
+#include <stdio.h>
+#include "gba/gba.h"
+#include "config.h"
+
+#define AGB_PRINT_FLUSH_ADDR 0x9FE209D
+#define AGB_PRINT_STRUCT_ADDR 0x9FE20F8
+#define AGB_PRINT_PROTECT_ADDR 0x9FE2FFE
+#define WSCNT_DATA (WAITCNT_PHI_OUT_16MHZ | WAITCNT_WS0_S_2 | WAITCNT_WS0_N_4)
+
+// originally for auto no$gba support, the string "no$gba" should be at this address,
+// the user needs to read this string out as the memory viewer won't show it.
+#define NOCASHGBAIDADDR 0x4FFFA00
+#define NOCASHGBAPRINTADDR1 0x4FFFA10 // automatically adds a newline after the string has finished
+#define NOCASHGBAPRINTADDR2 0x4FFFA14 // does not automatically add the newline. by default, NOCASHGBAPRINTADDR2 is used. this is used to keep strings consistent between no$gba and VBA-RR, but a user can choose to forgo this.
+
+struct AGBPrintStruct
+{
+ u16 m_nRequest;
+ u16 m_nBank;
+ u16 m_nGet;
+ u16 m_nPut;
+};
+
+typedef void (*LPFN_PRINT_FLUSH)(void);
+
+#ifndef NDEBUG
+
+void AGBPrintFlush1Block(void);
+
+void AGBPrintInit(void)
+{
+ volatile struct AGBPrintStruct *pPrint = (struct AGBPrintStruct *)AGB_PRINT_STRUCT_ADDR;
+ u16 *pWSCNT = (u16 *)REG_ADDR_WAITCNT;
+ u16 *pProtect = (u16 *)AGB_PRINT_PROTECT_ADDR;
+ u16 nOldWSCNT = *pWSCNT;
+ *pWSCNT = WSCNT_DATA;
+ *pProtect = 0x20;
+ pPrint->m_nRequest = pPrint->m_nGet = pPrint->m_nPut = 0;
+ pPrint->m_nBank = 0xFD;
+ *pProtect = 0;
+ *pWSCNT = nOldWSCNT;
+}
+
+static void AGBPutcInternal(const char cChr)
+{
+ volatile struct AGBPrintStruct *pPrint = (struct AGBPrintStruct *)AGB_PRINT_STRUCT_ADDR;
+ u16 *pPrintBuf = (u16 *)(0x8000000 + (pPrint->m_nBank << 16));
+ u16 *pProtect = (u16 *)AGB_PRINT_PROTECT_ADDR;
+ u16 nData = pPrintBuf[pPrint->m_nPut / 2];
+ *pProtect = 0x20;
+ nData = (pPrint->m_nPut & 1) ? (nData & 0xFF) | (cChr << 8) : (nData & 0xFF00) | cChr;
+ pPrintBuf[pPrint->m_nPut / 2] = nData;
+ pPrint->m_nPut++;
+ *pProtect = 0;
+}
+
+void AGBPutc(const char cChr)
+{
+ u16 *pWSCNT = (u16 *)REG_ADDR_WAITCNT;
+ u16 nOldWSCNT = *pWSCNT;
+ volatile struct AGBPrintStruct *pPrint;
+ *pWSCNT = WSCNT_DATA;
+ AGBPutcInternal(cChr);
+ *pWSCNT = nOldWSCNT;
+ pPrint = (struct AGBPrintStruct *)AGB_PRINT_STRUCT_ADDR;
+ if (pPrint->m_nPut == ((pPrint->m_nGet - 1) & 0xFFFF))
+ AGBPrintFlush1Block();
+}
+
+void AGBPrint(const char *pBuf)
+{
+ volatile struct AGBPrintStruct *pPrint = (struct AGBPrintStruct *)AGB_PRINT_STRUCT_ADDR;
+ u16 *pWSCNT = (u16 *)REG_ADDR_WAITCNT;
+ u16 nOldWSCNT = *pWSCNT;
+ *pWSCNT = WSCNT_DATA;
+ while (*pBuf)
+ {
+ AGBPutc(*pBuf);
+ pBuf++;
+ }
+ *pWSCNT = nOldWSCNT;
+}
+
+void AGBPrintf(const char *pBuf, ...)
+{
+ char bufPrint[0x100];
+ va_list vArgv;
+ va_start(vArgv, pBuf);
+ vsprintf(bufPrint, pBuf, vArgv);
+ va_end(vArgv);
+ AGBPrint(bufPrint);
+}
+
+static void AGBPrintTransferDataInternal(u32 bAllData)
+{
+ LPFN_PRINT_FLUSH lpfnFuncFlush;
+ u16 *pIME;
+ u16 nIME;
+ u16 *pWSCNT;
+ u16 nOldWSCNT;
+ u16 *pProtect;
+ volatile struct AGBPrintStruct *pPrint;
+
+ pProtect = (u16 *)AGB_PRINT_PROTECT_ADDR;
+ pPrint = (struct AGBPrintStruct *)AGB_PRINT_STRUCT_ADDR;
+ lpfnFuncFlush = (LPFN_PRINT_FLUSH)AGB_PRINT_FLUSH_ADDR;
+ pIME = (u16 *)REG_ADDR_IME;
+ nIME = *pIME;
+ pWSCNT = (u16 *)REG_ADDR_WAITCNT;
+ nOldWSCNT = *pWSCNT;
+ *pIME = nIME & ~1;
+ *pWSCNT = WSCNT_DATA;
+
+ if (bAllData)
+ {
+ while (pPrint->m_nPut != pPrint->m_nGet)
+ {
+ *pProtect = 0x20;
+ lpfnFuncFlush();
+ *pProtect = 0;
+ }
+ }
+ else if (pPrint->m_nPut != pPrint->m_nGet)
+ {
+ *pProtect = 0x20;
+ lpfnFuncFlush();
+ *pProtect = 0;
+ }
+
+ *pWSCNT = nOldWSCNT;
+ *pIME = nIME;
+}
+
+void AGBPrintFlush1Block(void)
+{
+ AGBPrintTransferDataInternal(FALSE);
+}
+
+void AGBPrintFlush(void)
+{
+ AGBPrintTransferDataInternal(TRUE);
+}
+
+void AGBAssert(const char *pFile, int nLine, const char *pExpression, int nStopProgram)
+{
+ if (nStopProgram)
+ {
+ AGBPrintf("ASSERTION FAILED FILE=[%s] LINE=[%d] EXP=[%s] \n", pFile, nLine, pExpression);
+ AGBPrintFlush();
+ asm(".hword 0xEFFF");
+ }
+ else
+ {
+ AGBPrintf("WARING FILE=[%s] LINE=[%d] EXP=[%s] \n", pFile, nLine, pExpression);
+ }
+}
+
+// no$gba print functions, uncomment to use
+/*
+void NoCashGBAPrint(const char *pBuf)
+{
+ *(volatile u32*)NOCASHGBAPRINTADDR2 = (u32)pBuf;
+}
+
+void NoCashGBAPrintf(const char *pBuf, ...)
+{
+ char bufPrint[0x100];
+ va_list vArgv;
+ va_start(vArgv, pBuf);
+ vsprintf(bufPrint, pBuf, vArgv);
+ va_end(vArgv);
+ NoCashGBAPrint(bufPrint);
+}
+*/
+
+#endif