diff --git a/source/common/cache.h b/source/common/cache.h
new file mode 100644
index 0000000..92257a5
--- /dev/null
+++ b/source/common/cache.h
@@ -0,0 +1,43 @@
+/*
+* This file is part of Luma3DS
+* Copyright (C) 2016-2017 Aurora Wright, TuxSH
+*
+* 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 3 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 .
+*
+* Additional Terms 7.b and 7.c of GPLv3 apply to this file:
+* * Requiring preservation of specified reasonable legal notices or
+* author attributions in that material or in the Appropriate Legal
+* Notices displayed by works containing it.
+* * Prohibiting misrepresentation of the origin of that material,
+* or requiring that modified versions of such material be marked in
+* reasonable ways as different from the original version.
+*/
+
+#pragma once
+
+#include "common.h"
+
+/***
+ The following functions flush the data cache, then waits for all memory transfers to be finished.
+ The data cache and/or the instruction cache MUST be flushed before doing one of the following:
+ - rebooting
+ - powering down
+ - setting the ARM11 entrypoint to execute a function
+ - jumping to a payload
+***/
+
+void flushEntireDCache(void); //actually: "clean and flush"
+void flushDCacheRange(void *startAddress, u32 size);
+void flushEntireICache(void);
+void flushICacheRange(void *startAddress, u32 size);
diff --git a/source/common/cache.s b/source/common/cache.s
new file mode 100644
index 0000000..fcc55dc
--- /dev/null
+++ b/source/common/cache.s
@@ -0,0 +1,93 @@
+@ This file is part of Luma3DS
+@ Copyright (C) 2016-2017 Aurora Wright, TuxSH
+@
+@ 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 3 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 .
+@
+@ Additional Terms 7.b and 7.c of GPLv3 apply to this file:
+@ * Requiring preservation of specified reasonable legal notices or
+@ author attributions in that material or in the Appropriate Legal
+@ Notices displayed by works containing it.
+@ * Prohibiting misrepresentation of the origin of that material,
+@ or requiring that modified versions of such material be marked in
+@ reasonable ways as different from the original version.
+
+.text
+.arm
+.align 4
+
+.global flushEntireDCache
+.type flushEntireDCache, %function
+flushEntireDCache:
+ @ Adapted from http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ddi0155a/ch03s03s05.html,
+ @ and https://github.com/gemarcano/libctr9_io/blob/master/src/ctr_system_ARM.c#L39 as well
+ @ Note: ARM's example is actually for a 8KB DCache (which is what the 3DS has)
+
+ @ Implemented in bootROM at address 0xffff0830
+ mov r1, #0 @ segment counter
+ outer_loop:
+ mov r0, #0 @ line counter
+
+ inner_loop:
+ orr r2, r1, r0 @ generate segment and line address
+ mcr p15, 0, r2, c7, c14, 2 @ clean and flush the line
+ add r0, #0x20 @ increment to next line
+ cmp r0, #0x400
+ bne inner_loop
+
+ add r1, #0x40000000
+ cmp r1, #0
+ bne outer_loop
+
+ mcr p15, 0, r1, c7, c10, 4 @ drain write buffer
+ bx lr
+
+.global flushDCacheRange
+.type flushDCacheRange, %function
+flushDCacheRange:
+ @ Implemented in bootROM at address 0xffff08a0
+ add r1, r0, r1 @ end address
+ bic r0, #0x1f @ align source address to cache line size (32 bytes)
+
+ flush_dcache_range_loop:
+ mcr p15, 0, r0, c7, c14, 1 @ clean and flush the line corresponding to the address r0 is holding
+ add r0, #0x20
+ cmp r0, r1
+ blo flush_dcache_range_loop
+
+ mov r0, #0
+ mcr p15, 0, r0, c7, c10, 4 @ drain write buffer
+ bx lr
+
+.global flushEntireICache
+.type flushEntireICache, %function
+flushEntireICache:
+ @ Implemented in bootROM at address 0xffff0ab4
+ mov r0, #0
+ mcr p15, 0, r0, c7, c5, 0
+ bx lr
+
+.global flushICacheRange
+.type flushICacheRange, %function
+flushICacheRange:
+ @ Implemented in bootROM at address 0xffff0ac0
+ add r1, r0, r1 @ end address
+ bic r0, #0x1f @ align source address to cache line size (32 bytes)
+
+ flush_icache_range_loop:
+ mcr p15, 0, r0, c7, c5, 1 @ flush the line corresponding to the address r0 is holding
+ add r0, #0x20
+ cmp r0, r1
+ blo flush_icache_range_loop
+
+ bx lr
diff --git a/source/common/power.c b/source/common/power.c
new file mode 100644
index 0000000..18b90bb
--- /dev/null
+++ b/source/common/power.c
@@ -0,0 +1,19 @@
+#include "power.h"
+#include "i2c.h"
+#include "cache.h"
+#include "ui.h"
+
+void Reboot() {
+ ClearScreenF(true, true, COLOR_STD_BG);
+ flushEntireDCache();
+ i2cWriteRegister(I2C_DEV_MCU, 0x20, 1 << 2);
+ while(true);
+}
+
+void PowerOff()
+{
+ ClearScreenF(true, true, COLOR_STD_BG);
+ flushEntireDCache();
+ i2cWriteRegister(I2C_DEV_MCU, 0x20, 1 << 0);
+ while (true);
+}
diff --git a/source/common/power.h b/source/common/power.h
index 12c86b3..b37f020 100644
--- a/source/common/power.h
+++ b/source/common/power.h
@@ -1,12 +1,6 @@
-#include "i2c.h"
+#pragma once
-inline static void Reboot() {
- i2cWriteRegister(I2C_DEV_MCU, 0x20, 1 << 2);
- while(true);
-}
+#include "common.h"
-inline static void PowerOff()
-{
- i2cWriteRegister(I2C_DEV_MCU, 0x20, 1 << 0);
- while (true);
-}
+void Reboot();
+void PowerOff();
diff --git a/source/main.c b/source/main.c
index 7fb3384..0cfc161 100644
--- a/source/main.c
+++ b/source/main.c
@@ -19,6 +19,5 @@ void main(int argc, char** argv)
bottom_screen = (u8*)(*(u32*)0x23FFFE08);
}
u32 godmode_exit = GodMode();
- ClearScreenF(true, true, COLOR_STD_BG);
(godmode_exit == GODMODE_EXIT_REBOOT) ? Reboot() : PowerOff();
}