#ifndef _MAIN_H_
#define _MAIN_H_
//-----------------------#DEFINES-----------------------
#define MEMZERO(buf, len) memset(buf, 0, len)
#define KEY_DEBUG BIT(14)
#define WIFI_FRAME_COUNT (5*60) //how many frames to wait for a response to a command
#define MENU_STACK_MAX 32
#define OPTIONS_PER_PAGE 18 //number of menu options that can fit on the screen at once.
#define SCHANNEL_WAVEDUTY(n) (n << 24)
#define LESSEROF(x, y) (x < y ? x : y)
#define GREATEROF(x, y) (x > y ? x : y)
#define CONSOLEFLAGS (CONSOLE_32x32 | CONSOLE_BG(0) | CONSOLE_SCREENBASE(15) | CONSOLE_CHARBASE(0) | CONSOLE_GRADIENT)
#if ARM9 //these are only defined for ARM7
#define PM_SOUND_PWR BIT(0) // Power the sound hardware (needed to hear stuff in GBA mode too)
#define PM_SOUND_VOL BIT(1) // ?
#define PM_BACKLIGHT_BOTTOM BIT(2) // Enable the top backlight if set
#define PM_BACKLIGHT_TOP BIT(3) // Enable the bottom backlight if set
#define PM_SYSTEM_PWR BIT(6) // Turn the power *off* if set
#define GBA_BORDER_DATA ((u16*)0x6020000) //VRAM address our borders will be stored at
#endif
//Copied from Moonshell
#define PM_NDSLITE_ADR (4)
#define PM_NDSLITE_ISLITE BIT(6)
#define PM_NDSLITE_BRIGHTNESS(x) ((x & 0x03)<<0)
#define PM_NDSLITE_BRIGHTNESS_MASK (PM_NDSLITE_BRIGHTNESS(3))
//Bits of system info in A9_INIT
#define SI_GBAONBOTTOM 0x00000001 //GBA screen is on bottom
#define SI_DSLITE 0x00000002 //Running on DS Lite
//Wifi control
#define WIFIPARAM_SYNC 0
#define WIFIPARAM_INIT 1
#define WIFIPARAM_STOP 2
//Debug
#define A7_STACK_DUMP_NUMWORDS 138 //Number of words that can be displayed in an ARM7 stack dump
//-----------------------LIBRARY INCLUDES-----------------------
#include <nds.h>
#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>
#include <string.h>
//#include <cartreset_nolibfat.h>
//#include <cartreset.h>
#if ARM9
#include <stdarg.h>
#include <dswifi9.h>
#include <nds/arm9/libConsole.h>
#include <fat.h>
#include <sys/dir.h>
#include <unistd.h>
#else //ARM7
#include <dswifi7.h>
#endif //ARM7
//-----------------------STRUCT DEFINITIONS-----------------------
typedef struct {
u32 A7MessageCount; //ARM7 messages processed
u32 A9MessageCount; //ARM9 messages processed
u32 A7FrameCount; //Number of frames executed on ARM7
u32 A9FrameCount; //Number of frames executed on ARM9
u32 TickCount; //System run time in msec
bool WifiEnabled; //Whether wifi is enabled
u32 ButtonsPressed; //Buttons pressed this frame
u32 ButtonsHeld; //Buttons held >1 frame
s16 TouchX, TouchY; //Touch X/Y position
s16 TouchZ1, TouchZ2; //Touch Z panels
u32 Temperature; //System temperature
union { //Current time
struct {
u8 Time_Command;
u8 Time_Year;
u8 Time_Month;
u8 Time_Day;
u8 Time_Incr;
u8 Time_Hour;
u8 Time_Minute;
u8 Time_Second;
};
u8 TimeData[8];
};
u32 SysInfo; //Information about system settings passed from ARM7 at bootup (any of SI_xxx).
} CustomIPCData;
static inline CustomIPCData volatile * getIPC2() {
return (CustomIPCData volatile *)(IPC + sizeof(TransferRegion));
}
#define IPC2 getIPC2()
//Information for the Quickboot menu
typedef struct {
char Name[30]; //Name to show in menu
char Desc[129]; //Description to show in menu.
char Section[129]; //Name of INI section.
} QuickbootData;
//Keys for KeyRepeat[]
typedef enum {
KR_A = 0,
KR_B,
KR_SELECT,
KR_START,
KR_RIGHT,
KR_LEFT,
KR_UP,
KR_DOWN,
KR_R,
KR_L,
KR_X,
KR_Y,
NUM_KEYS
} KeyID;
//ARM7 messages
/* Messages are in this format: 1 byte message ID, 1 byte # of parameters,
2 bytes not used yet, then parameters (each 32 bits).
Return values are the parameters of an A7_RETURN or A9_RETURN message. */
typedef enum {
A7_NULL, //Dummy message, no parameters.
A7_INIT, //Used to pass some data from ARM9 at startup. Param1=Pointer to ARM7StackDump.
A7_RETURN, //Return value from a message; param1=message being responded to, others=return value.
A7_CHECK, //Used to check that ARM7 is still responding. Return value=anything; just returns a value to let ARM9 know it's still going.
A7_ERROR, //Notification that something bad happened; usually an invalid message was received. Param1=0 if invalid message.
A7_GBAMODE, //Reboot into GBA mode, no parameters.
A7_SETPOWER, //Change power settings; param1=0 to write, 1 to AND, 2 to OR, 3 to XOR; param2=bitflags. Note that System Power bit is reversed; 1=turn off.
A7_GETPOWER, //Retrieve power settings; no parameters, returns power bitflags. Note that System Power bit is 0 on Phat and 1 on Lite(?).
A7_SETVOLUME, //Set sound volume; param1=bits 0-6 set master sound volume, 7=1 to enable sound, 0 to disable.
A7_GETVOLUME, //Retrieve sound volume; return bits 0-6=master volume, 7=1 if enabled, 0 if disabled.
A7_SETSOUND, //Set flags for a sound channel; param1=channel (low 4 bits), param2=flags, param3=source, param4=length.
A7_GETSOUNDFLAGS, //Get flags for a sound channel; param1=channel (low 4 bits), return1=flags, return2=source, return3=length.
A7_BOOTNDS, //Enter wait loop to boot .nds file on GBAMP.
A7_WIFICTRL, //Wifi control messages; see below for params.
//Higher-level system control commands
A7_BACKLIGHT //Set backlight brightness. Param1=Top light, Param2=Bottom light (-1=no change, 0=off, 1=on), Param3=Brightness (0-3 or -1 for no change, ignored if not DSLite)
} A7_MESSAGE;
/*
Bitmask for A7_SETSOUND and A7_GETSOUND:
evvvvvvv pppppppw wwffffff ffffffft
e=enable (1) or disable (0)
v=volume, 0=silent to 127=max
p=pan, 64=middle
w=wave duty, 0 to 6 (7=no sound)
f=frequqncy, 8 to 65528h
t=0 for standard mode, 1 for PSG (tone) mode (channels 8-13) or white noise (channel 14, 15)
Source and Length parameters are optional, and aren't used in PSG mode.
Parameters for A7_WIFICTRL:
WIFIPARAM_SYNC: Call Wifi_Sync().
WIFIPARAM_INIT: Pass Param2 to Wifi_Init(); turn on wifi hardware.
WIFIPARAM_STOP: Turn off wifi hardware.
*/
//ARM9 messages (same format as ARM7)
typedef enum {
A9_NULL, //Dummy message, no parameters.
A9_INIT, //ARM7 ready notification at startup, no parameters. IPC2->SysInfo is valid once this arrives.
A9_RETURN, //Return value from a message; param1=message being responded to, others=return value.
A9_CHECK, //Used to check that ARM9 is still responding. Return value=anything; just returns a value to let ARM7 know it's still going.
A9_ERROR, //Notification that something bad happened, usually an invalid message was received. Param1=0 if invalid message, 1-4 if invalid parameter..
A9_FATALERROR, //Notification that ARM7 has crashed. Param1=Error code, Param2=Stack pointer, Param3=Pointer to stack dump in main RAM since ARM9 can't read the real stack
A9_WIFISYNC //Signal that Wifi_Sync() needs to be called.
} A9_MESSAGE;
#if ARM9
enum Border {
BD_SOLID = -1,
BD_FILE,
BD_RED,
BD_GREEN,
BD_BLUE,
BD_YELLOW,
BD_PURPLE,
BD_MAX
};
//BootFile(), BootMenu() etc return codes
typedef enum {
BE_UNKNOWN_ERROR = 0,
BE_NOT_FOUND, //File not found
BE_FMT_NOT_SUPPORTED, //File format not supported
BE_CARD_NOT_SUPPORTED, //Card not supported (also if e.g. .GBA file when no Slot-2 RAM)
BE_INVALID_FILE, //Corrupt or invalid file
BE_NO_CARD, //No DS card inserted
BE_NULL_PTR, //NULL pointer passed
BE_INVALID_LOADER, //Invalid loader specified
BE_MAX //Last item (not actually returned)
} BOOTERROR;
#endif //ARM9
//Loaders
typedef enum {
LOAD_REBOOTLIB = 0, //Rebootlib
LOAD_GBAMP, //GBAMP hack loader
LOAD_MAX //Last item
} LOADER;
typedef struct {
char SSID[33];
char WEPKey[16];
bool AutoIP;
u32 IPAddr;
u32 SubnetMask;
u32 Gateway;
bool AutoDNS;
u32 PrimaryDNS;
u32 SecondaryDNS;
} APSettings;
//-----------------------OTHER HEADER INCLUDES-----------------------
//#include "..\..\general\memory.h"
//#include "..\..\general\_memory.h"
#include "reboot.h"
#if ARM7
#else //ARM9
#include "menu.h"
#endif //ARM9
//-----------------------CONSTANTS-----------------------
#if ARM7 //ndslib only declares this for ARM9 <_<
typedef enum KEYPAD_BITS {
KEY_A = BIT(0), /*!< keypad A button */
KEY_B = BIT(1), /*!< keypad B button */
KEY_SELECT = BIT(2), /*!< keypad SELECT button*/
KEY_START = BIT(3), /*!< keypad START button*/
KEY_RIGHT = BIT(4), /*!< keypad RIGHT button*/
KEY_LEFT = BIT(5), /*!< keypad LEFT button*/
KEY_UP = BIT(6), /*!< keypad UP button*/
KEY_DOWN = BIT(7), /*!< keypad DOWN button*/
KEY_R = BIT(8), /*!< RIGHT shoulder button*/
KEY_L = BIT(9), /*!< LEFT shoulder button*/
KEY_X = BIT(10), /*!< keypad X button*/
KEY_Y = BIT(11), /*!< keypad Y button*/
KEY_TOUCH = BIT(12), /*!< touchscreen pendown*/
KEY_LID = BIT(13), /*!< lid state*/
} KEYPAD_BITS;
#else
const char* OnOff[] = {"Off", "On"};
const char* LightLevelStr[] = {"Low", "Med", "High", "Max"};
const char* MainScreenStr[] = {"Bottom", "Top"};
const char* BootError[] = {
"Unknown error.",
"File not found.",
"File type not supported.",
"Not supported on this card.",
"Corrupt or invalid file.",
"No card inserted.",
"NULL pointer passed (bug!)",
"Invalid loader specified."
};
const char* LoaderName[] = {"Rebootlib", "GBAMP"};
#endif //ARM9
//-----------------------GLOBAL VARS-----------------------
#if ARM9
volatile bool A7Init = false;
//System settings
s8 GBABorder = BD_SOLID;
char GBABorderFile[1024]; //Path to border file
u8 BorderR = 0, BorderG = 0, BorderB = 0; //Colours for solid border
bool TopLight = true, BottomLight = true; //Backlights on/off
s8 LightBright = 3; //Brightness level
bool EnableSound = true;
bool GBAROMOwner = true, GBASRAMOwner = true, NDSCardOwner = true; //false=ARM7 true=ARM9
bool MainScreenTop = true; //False = main screen on bottom
char SaveDownloadPath[1024]; //Path to save wireless downloads to; empty string = don't save
bool UseINI = true; //Whether settings in bootmenu.ini for the current game should override current ones
//Menu state
//Note: No checks are done to ensure the menu stack does not overflow, so ensure it doesn't.
u16 MenuStack[MENU_STACK_MAX]; //Array of which menus have been opened
u16 MenuSel[MENU_STACK_MAX];//Which option was selected on each
u16 MenuNumOptions[MENU_STACK_MAX]; //How many options are in the current menu
u8 MenuStackPos = 0;
s16 MenuOptionTouched = -1; //Which option was touched, -1 = none.
s8 TouchXTile = -1, TouchYTile = -1; //Tile coords touched, -1 = not touched.
QuickbootData* Quickboot = NULL;
u32 NumQuickboot = 0; //Number of Quickboot entries in INI
//Files
bool FATMounted = false;
char** Filename = NULL; //pointer to array of pointers to file names
u32 NumFiles = 0;
char CurrentDir[256];
FILE* File = NULL;
//Booting
LOADER DefaultLoader = LOAD_REBOOTLIB;
//Wifi
u8 MACAddress[6];
u8 WifiAPNum = 1; //0 = custom AP, 1-3 = firmware APs
APSettings WifiAP[4]; //WifiAPNum = index into this
s32 NumAPsFound = 0; //Number of APs found when scanning
//Keys
u16 KeysPressed = 0, KeysHeld = 0;
u16 KeyRepeatDelay = 256, KeyRepeatSpeed = 100; //milliseconds
u16 KeyRepeat[NUM_KEYS];
bool EnableKeyRepeat[NUM_KEYS];
char Password[17]; //Digit string: 0=A 1=B 2=Right 3=Left 4=Up 5=Down 6=L 7=R 8=X 9=Y
u32 PwdTries = 3; //Number of attempts allowed
bool PwdPowerOff = true; //After all attempts expired: true=power off, false=reject even correct password
//Startup message
char* StartMsg = NULL; //Text to show below password prompt
bool ForceStartMsg = false; //If true and no password, the message is shown anyway (press any key to continue).
bool ScrollStartMsg = false; //If true the message will scroll by on the menu screen.
u32 StartMsgDelay = 10; //How many frames to wait before advancing to next letter when scrolling
//Debug
bool DebugMode = false;
u32 ARM7StackDump[A7_STACK_DUMP_NUMWORDS]; //ARM7 will dump its stack into here on failure
#else //ARM7
u32 ASMHackery; //Global variable doing what should be done by a local one if I could figure out how >_>
u32* ARM7StackDump = 0; //Pointer to the real ARM7StackDump
#endif
//-----------------------FUNCTION PROTOTYPES-----------------------
#if ARM7
int main(int argc, char** argv);
void DoA7Message(A7_MESSAGE Message, u8 NumParams, u32 Param1, u32 Param2, u32 Param3, u32 Param4, bool FromA9);
void SendA9Message(A9_MESSAGE Message, u8 NumParams, u32 Param1, u32 Param2, u32 Param3, u32 Param4);
void VBlankInterrupt();
void Timer3Interrupt();
void WifiInterrupt();
void syncRTC();
bool A7InitWifi(u32 A9Param);
void _A7WifiSync();
void FatalError(u32 Code);
#elif ARM9
int main(int argc, char** argv);
void DrawMenu(u32 ID, u32 Selected);
void EnterMenu(u32 ID);
void PasswordPrompt();
bool ReadConfigFile(char* Section);
s32 ListDirectory(char* Dir);
s32 filenamecmpi(char* str1, char* str2);
void ApplySystemSettings(bool NoUnmount);
void CheckMessages();
void DoA9Message(A9_MESSAGE Message, u8 NumParams, u32 Param1, u32 Param2, u32 Param3, u32 Param4, bool FromA7);
void SendA7Message(A7_MESSAGE Message, u8 NumParams, u32 Param1, u32 Param2, u32 Param3, u32 Param4);
void VBlankInterrupt();
bool InitWifi();
bool StopWifi();
void _A9WifiSync();
//boot.c
BOOTERROR BootFile(LOADER Loader, char* File);
bool IsLoaderSupported(LOADER Loader);
BOOTERROR BootMenu();
void BootGBAMode();
BOOTERROR BootDSCard();
void PowerOff();
#endif //not ARM7
#endif //_MAIN_H_
|