diff --git a/arm11/link.ld b/arm11/link.ld
index b1ca2a9..a0f3845 100644
--- a/arm11/link.ld
+++ b/arm11/link.ld
@@ -4,7 +4,7 @@ ENTRY(__boot)
MEMORY
{
- AXIWRAM (RWX) : ORIGIN = 0x1FF80000, LENGTH = 96K
+ AXIWRAM (RWX) : ORIGIN = 0x1FF80000, LENGTH = 128K
HIGHRAM (RWX) : ORIGIN = 0xFFFF0000, LENGTH = 4K
}
diff --git a/arm11/source/main.c b/arm11/source/main.c
index c0d22f4..9e7424e 100644
--- a/arm11/source/main.c
+++ b/arm11/source/main.c
@@ -31,6 +31,7 @@
#include "hw/nvram.h"
#include "system/sys.h"
+#include "system/xalloc.h"
static GlobalSharedMemory SharedMemory_State;
@@ -57,7 +58,7 @@ void VBlank_Handler(u32 __attribute__((unused)) irqn)
#endif
// the state should probably be stored on its own
- // setion without caching enabled, since it must
+ // section without caching enabled, since it must
// be readable by the ARM9 at all times anyway
SharedMemory_State.hid_state = HID_GetState();
ARM_WbDC_Range(&SharedMemory_State, sizeof(SharedMemory_State));
@@ -158,6 +159,12 @@ void PXI_RX_Handler(u32 __attribute__((unused)) irqn)
break;
}
+ case PXI_XALLOC:
+ {
+ ret = (u32)XAlloc(args[0]);
+ break;
+ }
+
/* New CMD template:
case CMD_ID:
{
diff --git a/arm11/source/system/xalloc.c b/arm11/source/system/xalloc.c
new file mode 100755
index 0000000..3850ea8
--- /dev/null
+++ b/arm11/source/system/xalloc.c
@@ -0,0 +1,37 @@
+/*
+ * This file is part of GodMode9
+ * Copyright (C) 2019 Wolfvak
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+// super simple watermark allocator for ARM9 <-> ARM11 xfers
+// designed to be request once, free never
+
+#include "system/xalloc.h"
+
+static char xalloc_buf[XALLOC_BUF_SIZE];
+static size_t mark = 0;
+
+void *XAlloc(size_t size)
+{ // not thread-safe at all
+ void *ret;
+ size_t end = size + mark;
+ if (end >= XALLOC_BUF_SIZE)
+ return NULL;
+
+ ret = &xalloc_buf[mark];
+ mark = end;
+ return ret;
+}
diff --git a/arm11/source/system/xalloc.h b/arm11/source/system/xalloc.h
new file mode 100755
index 0000000..02bcd60
--- /dev/null
+++ b/arm11/source/system/xalloc.h
@@ -0,0 +1,25 @@
+/*
+ * This file is part of GodMode9
+ * Copyright (C) 2019 Wolfvak
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+#pragma once
+
+#include "types.h"
+
+#define XALLOC_BUF_SIZE (16384)
+
+void *XAlloc(size_t size);
diff --git a/arm9/source/common/touchcal.c b/arm9/source/common/touchcal.c
index d4f874e..91d0d66 100644
--- a/arm9/source/common/touchcal.c
+++ b/arm9/source/common/touchcal.c
@@ -106,7 +106,9 @@ bool CalibrateTouchFromFlash(void) {
// check NVRAM console ID
u32 console_id = 0;
- spiflash_read(0x001C, 4, (u8*)&console_id);
+ if (!spiflash_read(0x001C, 4, (u8*)&console_id))
+ return false;
+
if (((console_id >> 8) & 0xFF) != 0x57)
return false; // not a 3DS
@@ -114,7 +116,9 @@ bool CalibrateTouchFromFlash(void) {
// see: https://problemkaputt.de/gbatek.htm#dsfirmwareusersettings
u32 fw_usercfg_buf[0x100 / 0x4];
u8* fw_usercfg = (u8*) fw_usercfg_buf;
- spiflash_read(0x1FE00, 0x100, fw_usercfg);
+ if (!spiflash_read(0x1FE00, 0x100, fw_usercfg))
+ return false;
+
if (getle16(fw_usercfg + 0x72) != crc16_quick(fw_usercfg, 0x70))
return false;
diff --git a/arm9/source/system/i2c.c b/arm9/source/system/i2c.c
index 0a1844a..d9a3586 100755
--- a/arm9/source/system/i2c.c
+++ b/arm9/source/system/i2c.c
@@ -4,63 +4,57 @@
#include "i2c.h"
#include "pxi.h"
-/*
- disgusting hack that deserves to die in hell
- ideally all buffers would be able to be accessed
- by the ARM11, but those in ARM9 RAM are inaccessible
- (.data, .rodata & .bss)
+// buffer is allocated only once and remains through runtime
+static char *i2c_xfer_buf = NULL;
- the current hack assumes all buffers in the heap are
- located in FCRAM, which is accessible to both processors
- but it's horrendous, and hopefully temporary
-*/
+static bool I2C_AllocBuffer(void)
+{
+ if (!i2c_xfer_buf) {
+ u32 xbuf = PXI_DoCMD(PXI_XALLOC, (u32[]){256}, 1);
+ if (xbuf == 0 || xbuf == 0xFFFFFFFF)
+ return false;
+ i2c_xfer_buf = (char*)xbuf;
+ }
+ return true;
+}
-static char *i2c_fcram_buf = NULL;
bool I2C_readRegBuf(I2cDevice devId, u8 regAddr, u8 *out, u32 size)
{
- if (!i2c_fcram_buf)
- i2c_fcram_buf = malloc(256);
-
int ret;
- u32 args[] = {devId, regAddr, (u32)i2c_fcram_buf, size};
+ u32 *args;
- ARM_WbDC_Range(i2c_fcram_buf, size);
+ if (!I2C_AllocBuffer())
+ return false;
+
+ args = (u32[]){devId, regAddr, (u32)i2c_xfer_buf, size};
+
+ ARM_WbDC_Range(i2c_xfer_buf, size);
ARM_DSB();
ret = PXI_DoCMD(PXI_I2C_READ, args, 4);
- ARM_InvDC_Range(i2c_fcram_buf, size);
- memcpy(out, i2c_fcram_buf, size);
+ ARM_InvDC_Range(i2c_xfer_buf, size);
+ memcpy(out, i2c_xfer_buf, size);
return ret;
}
bool I2C_writeRegBuf(I2cDevice devId, u8 regAddr, const u8 *in, u32 size)
{
- if (!i2c_fcram_buf)
- i2c_fcram_buf = malloc(256);
-
int ret;
- u32 args[] = {devId, regAddr, (u32)i2c_fcram_buf, size};
- memcpy(i2c_fcram_buf, in, size);
- ARM_WbDC_Range(i2c_fcram_buf, size);
+ if (!I2C_AllocBuffer())
+ return false;
+
+ u32 args[] = {devId, regAddr, (u32)i2c_xfer_buf, size};
+
+ memcpy(i2c_xfer_buf, in, size);
+ ARM_WbDC_Range(i2c_xfer_buf, size);
ARM_DSB();
ret = PXI_DoCMD(PXI_I2C_WRITE, args, 4);
return ret;
}
-/*bool I2C_readRegBuf(I2cDevice devId, u8 regAddr, u8 *out, u32 size)
-{
- int ret;
- u32 args[] = {devId, regAddr, (u32)out, size};
- cpu_writeback_invalidate_dc_range(out, size);
- cpu_membarrier();
- ret = PXI_DoCMD(PXI_I2C_READ, args, 4);
- cpu_invalidate_dc_range(out, size);
- return ret;
-}*/
-
u8 I2C_readReg(I2cDevice devId, u8 regAddr)
{
u8 data;
@@ -69,16 +63,6 @@ u8 I2C_readReg(I2cDevice devId, u8 regAddr)
return data;
}
-/*bool I2C_writeRegBuf(I2cDevice devId, u8 regAddr, const u8 *in, u32 size)
-{
- int ret;
- u32 args[] = {devId, regAddr, (u32)in, size};
- cpu_writeback_dc_range(in, size);
- cpu_membarrier();
- ret = PXI_DoCMD(PXI_I2C_WRITE, args, 4);
- return ret;
-}*/
-
bool I2C_writeReg(I2cDevice devId, u8 regAddr, u8 data)
{
return I2C_writeRegBuf(devId, regAddr, &data, 1);
diff --git a/arm9/source/system/spiflash.c b/arm9/source/system/spiflash.c
new file mode 100755
index 0000000..4dbb830
--- /dev/null
+++ b/arm9/source/system/spiflash.c
@@ -0,0 +1,44 @@
+#include "common.h"
+#include "arm.h"
+#include "pxi.h"
+
+#define SPIFLASH_CHUNK_SIZE (0x1000)
+
+static char *spiflash_xalloc_buf = NULL;
+
+bool spiflash_get_status(void)
+{
+ return PXI_DoCMD(PXI_NVRAM_ONLINE, NULL, 0);
+}
+
+bool spiflash_read(u32 offset, u32 size, u8 *buf)
+{
+ u32 args[3];
+
+ if (!spiflash_xalloc_buf) {
+ u32 xbuf = PXI_DoCMD(PXI_XALLOC, (u32[]){SPIFLASH_CHUNK_SIZE}, 1);
+ if (xbuf == 0 || xbuf == 0xFFFFFFFF)
+ return false;
+ spiflash_xalloc_buf = (char*)xbuf;
+ }
+
+ args[1] = (u32)spiflash_xalloc_buf;
+
+ while(size > 0) {
+ u32 rem = min(size, SPIFLASH_CHUNK_SIZE);
+
+ args[0] = offset;
+ args[2] = rem;
+
+ ARM_DSB();
+ PXI_DoCMD(PXI_NVRAM_READ, args, 3);
+ ARM_InvDC_Range(spiflash_xalloc_buf, rem);
+ memcpy(buf, spiflash_xalloc_buf, rem);
+
+ buf += rem;
+ size -= rem;
+ offset += rem;
+ }
+
+ return true;
+}
diff --git a/arm9/source/system/spiflash.h b/arm9/source/system/spiflash.h
index a3af1c6..9cea180 100644
--- a/arm9/source/system/spiflash.h
+++ b/arm9/source/system/spiflash.h
@@ -25,16 +25,6 @@
#define NVRAM_SIZE 0x20000 // 1 Mbit (128kiB)
// true if spiflash is installed, false otherwise
-static inline bool spiflash_get_status(void)
-{ // there should probably be a command for this...
- return PXI_DoCMD(PXI_NVRAM_ONLINE, NULL, 0);
-}
+bool spiflash_get_status(void);
-static inline void spiflash_read(u32 offset, u32 size, u8 *buf)
-{
- u32 args[] = {offset, (u32)buf, size};
- ARM_WbDC_Range(buf, size);
- ARM_DSB();
- PXI_DoCMD(PXI_NVRAM_READ, args, 3);
- ARM_InvDC_Range(buf, size);
-}
+bool spiflash_read(u32 offset, u32 size, u8 *buf);
diff --git a/arm9/source/virtual/vmem.c b/arm9/source/virtual/vmem.c
index 5a18180..dd59cef 100644
--- a/arm9/source/virtual/vmem.c
+++ b/arm9/source/virtual/vmem.c
@@ -165,8 +165,9 @@ int ReadVMemNVRAM(const VirtualFile* vfile, void* buffer, u64 offset, u64 count)
wififlash_initialized = spiflash_get_status();
if (!wififlash_initialized) return 1;
}
-
- spiflash_read((u32) offset, (u32) count, buffer);
+
+ if (!spiflash_read((u32) offset, (u32) count, buffer))
+ return 1;
return 0;
}
diff --git a/common/pxi.h b/common/pxi.h
index 8d8cf84..f302fb4 100644
--- a/common/pxi.h
+++ b/common/pxi.h
@@ -40,6 +40,8 @@ enum {
PXI_NOTIFY_LED,
PXI_BRIGHTNESS,
+
+ PXI_XALLOC,
};
/*