GBA-Exploader/libraries/libnds32/include/nds/system.h
ApacheThunder 540515c7fc Add game specific gbaframe support ...
* Can now use gbaframes specific to a gba rom being loaded to ram/flash.
Have a bmp file with filename matching the game rom being flashed in
GBA_SIGN path. If it finds a matching BMP it will use that before
falling back to the default gbaframe.bmp paths.
* nds-bootstrap now used for booting retail NDS roms from file browser.
Note that currently GBA-Exploader does not create new save files so only
games with existing save files (currently hardcoded to GBA_SAV path like
with GBA games) can be booted with this.
2024-11-17 15:44:06 -06:00

452 lines
13 KiB
C

/*---------------------------------------------------------------------------------
Power control, keys, and HV clock registers
Copyright (C) 2005
Jason Rogers (dovoto)
Dave Murphy (WinterMute)
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any
damages arising from the use of this software.
Permission is granted to anyone to use this software for any
purpose, including commercial applications, and to alter it and
redistribute it freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you
must not claim that you wrote the original software. If you use
this software in a product, an acknowledgment in the product
documentation would be appreciated but is not required.
2. Altered source versions must be plainly marked as such, and
must not be misrepresented as being the original software.
3. This notice may not be removed or altered from any source
distribution.
---------------------------------------------------------------------------------*/
/*! \file system.h
\brief NDS hardware definitions.
These definitions are usually only touched during
the initialization of the program.
*/
#ifndef NDS_SYSTEM_INCLUDE
#define NDS_SYSTEM_INCLUDE
#include "ndstypes.h"
//! LCD status register.
#define REG_DISPSTAT (*(vu16*)0x04000004)
//! LCD Status register bitdefines
typedef enum
{
DISP_IN_VBLANK = BIT(0), //!< The display currently in a vertical blank.
DISP_IN_HBLANK = BIT(1), //!< The display currently in a horizontal blank.
DISP_YTRIGGERED = BIT(2), //!< Current scanline and %DISP_Y match.
DISP_VBLANK_IRQ = BIT(3), //!< Interrupt on vertical blank.
DISP_HBLANK_IRQ = BIT(4), //!< Interrupt on horizontal blank.
DISP_YTRIGGER_IRQ = BIT(5) //!< Interrupt when current scanline and %DISP_Y match.
}DISP_BITS;
//! Current display scanline.
#define REG_VCOUNT (*(vu16*)0x4000006)
//! Halt control register.
/*! Writing 0x40 to HALT_CR activates GBA mode.
%HALT_CR can only be accessed via the BIOS.
*/
#define HALT_CR (*(vu16*)0x04000300)
//! Power control register.
/*! This register controls what hardware should
be turned on or off.
*/
#define REG_POWERCNT *(vu16*)0x4000304
#define REG_SCFG_ROM *(vu16*)0x4004000
#ifdef ARM7
#define REG_SCFG_A9ROM *(vu8*)0x4004000
#define REG_SCFG_A7ROM *(vu8*)0x4004001 // ??
#endif
#define REG_SCFG_CLK *(vu16*)0x4004004
#define REG_SCFG_RST *(vu16*)0x4004006
#define REG_SCFG_EXT *(vu32*)0x4004008
#define REG_SCFG_MC *(vu16*)0x4004010
static inline
/*!
\brief sets the Y trigger(?)
\param Yvalue the value for the Y trigger.
*/
void SetYtrigger(int Yvalue) {
REG_DISPSTAT = (REG_DISPSTAT & 0x007F ) | (Yvalue << 8) | (( Yvalue & 0x100 ) >> 1) ;
}
#define PM_ARM9_DIRECT BIT(16)
//! Power Management control bits
typedef enum
{
PM_SOUND_AMP = BIT(0), //!< Power the sound hardware (needed to hear stuff in GBA mode too).
PM_SOUND_MUTE = BIT(1), //!< Mute the main speakers, headphone output will still work.
PM_BACKLIGHT_BOTTOM = BIT(2), //!< Enable the bottom backlight if set.
PM_BACKLIGHT_TOP = BIT(3), //!< Enable the top backlight if set.
PM_SYSTEM_PWR = BIT(6), //!< Turn the power *off* if set.
POWER_LCD = PM_ARM9_DIRECT | BIT(0), //!< Controls the power for both LCD screens.
POWER_2D_A = PM_ARM9_DIRECT | BIT(1), //!< Controls the power for the main 2D core.
POWER_MATRIX = PM_ARM9_DIRECT | BIT(2), //!< Controls the power for the 3D matrix.
POWER_3D_CORE = PM_ARM9_DIRECT | BIT(3), //!< Controls the power for the main 3D core.
POWER_2D_B = PM_ARM9_DIRECT | BIT(9), //!< Controls the power for the sub 2D core.
POWER_SWAP_LCDS = PM_ARM9_DIRECT | BIT(15), //!< Controls which screen should use the main core.
POWER_ALL_2D = PM_ARM9_DIRECT | POWER_LCD | POWER_2D_A | POWER_2D_B, //!< power just 2D hardware.
POWER_ALL = PM_ARM9_DIRECT | POWER_ALL_2D | POWER_3D_CORE | POWER_MATRIX //!< power everything.
}PM_Bits;
/*! \brief Causes the nds to go to sleep.
The nds will be reawakened when the lid is opened.
\note By default, this is automatically called when closing the lid.
*/
void systemSleep(void);
/*! Set the LED blink mode
\param bm What to power on.
*/
void ledBlink(int bm);
//! Checks whether the application is running in DSi mode.
static inline bool isDSiMode() {
extern bool __dsimode;
return __dsimode;
}
//--------------------------------------------------------------
// ARM9 section
//--------------------------------------------------------------
#ifdef ARM9
//! Turns on specified hardware.
/*! May be called from arm7 or arm9 (arm9 power bits will be ignored by arm7, arm7 power bits
will be passed to the arm7 from the arm9).
\param bits What to power on.
*/
void powerOn(int bits);
//! Turns off specified hardware.
/*! May be called from arm7 or arm9 (arm9 power bits will be ignored by arm7, arm7 power bits
will be passed to the arm7 from the arm9).
\param bits What to power on.
*/
void powerOff(int bits);
//internal fifo handlers
void systemMsgHandler(int bytes, void* user_data);
void systemValueHandler(u32 value, void* data);
//! Switches the screens.
static inline void lcdSwap(void) { REG_POWERCNT ^= POWER_SWAP_LCDS; }
//! Forces the main core to display on the top.
static inline void lcdMainOnTop(void) { REG_POWERCNT |= POWER_SWAP_LCDS; }
//! Forces the main core to display on the bottom.
static inline void lcdMainOnBottom(void) { REG_POWERCNT &= ~POWER_SWAP_LCDS; }
//! Powers down the DS
static inline
void systemShutDown(void) {
powerOn(PM_SYSTEM_PWR);
}
void readFirmware(u32 address, void *buffer, u32 length);
int writeFirmware(u32 address, void *buffer, u32 length);
//! gets the DS Battery level
u32 getBatteryLevel();
//! Set the arm9 vector base
/*! Arm9 only
\param highVector high vector
*/
void setVectorBase(int highVector);
/*! \brief A struct with all the CPU exeption vectors.
each member contains an ARM instuction that will be executed when an exeption occured.
See gbatek for more information.
*/
typedef struct sysVectors_t {
VoidFn reset; //!< CPU reset.
VoidFn undefined; //!< undefined instruction.
VoidFn swi; //!< software interrupt.
VoidFn prefetch_abort; //!< prefetch abort.
VoidFn data_abort; //!< data abort.
VoidFn fiq; //!< fast interrupt.
} sysVectors;
extern sysVectors SystemVectors;
void setSDcallback(void(*callback)(int));
/*!
\brief Sets the ARM9 clock speed, only possible in DSi mode
\param speed CPU speed (false = 67.03MHz, true = 134.06MHz)
\return The old CPU speed value
*/
bool setCpuClock(bool speed);
// Helper functions for heap size
//! returns current start of heap space
u8* getHeapStart();
//! returns current end of heap space
u8* getHeapEnd();
//! returns current heap limit
u8* getHeapLimit();
#endif //ARM9
//--------------------------------------------------------------
// ARM7 section
//--------------------------------------------------------------
#ifdef ARM7
#define REG_CONSOLEID (*(vu64*)0x04004D00)
//! Power-controlled hardware devices accessable to the ARM7.
/*! Note that these should only be used when programming for
the ARM7. Trying to boot up these hardware devices via
the ARM9 would lead to unexpected results.
ARM7 only.
*/
typedef enum {
POWER_SOUND = BIT(0), //!< Controls the power for the sound controller.
PM_CONTROL_REG = 0, //!< Selects the PM control register
PM_BATTERY_REG = 1, //!< Selects the PM battery register
PM_AMPLIFIER_REG = 2, //!< Selects the PM amplifier register
PM_READ_REGISTER = (1<<7), //!< Selects the PM read register
PM_AMP_OFFSET = 2, //!< Selects the PM amp register
PM_GAIN_OFFSET = 3, //!< Selects the PM gain register
PM_BACKLIGHT_LEVEL = 4, //!< Selects the DS Lite backlight register
PM_GAIN_20 = 0, //!< Sets the mic gain to 20db
PM_GAIN_40 = 1, //!< Sets the mic gain to 40db
PM_GAIN_80 = 2, //!< Sets the mic gain to 80db
PM_GAIN_160 = 3, //!< Sets the mic gain to 160db
PM_AMP_ON = 1, //!< Turns the sound amp on
PM_AMP_OFF = 0 //!< Turns the sound amp off
} ARM7_power;
//!< PM control register bits - LED control
#define PM_LED_CONTROL(m) ((m)<<4)
//install the fifo power handler
void installSystemFIFO(void);
//cause the ds to enter low power mode
void systemSleep(void);
//internal can check if sleep mode is enabled
int sleepEnabled(void);
// Warning: These functions use the SPI chain, and are thus 'critical'
// sections, make sure to disable interrupts during the call if you've
// got a VBlank IRQ polling the touch screen, etc...
// Read/write a power management register
int writePowerManagement(int reg, int command);
static inline
int readPowerManagement(int reg) {
return writePowerManagement((reg)|PM_READ_REGISTER, 0);
}
static inline
void powerOn(int bits) {
REG_POWERCNT |= bits;
}
static inline
void powerOff(PM_Bits bits) {
REG_POWERCNT &= ~bits;
}
void readUserSettings();
void systemShutDown();
#endif /* ARM7 */
/*! \brief Backlight level settings.
Note, these are only available on DS Lite.
*/
typedef enum {
BACKLIGHT_LOW, //!< low backlight setting.
BACKLIGHT_MED, //!< medium backlight setting.
BACKLIGHT_HIGH, //!< high backlight setting.
BACKLIGHT_MAX //!< max backlight setting.
} BACKLIGHT_LEVELS;
// Common functions
/*!
\brief User's DS settings.
Defines the structure the DS firmware uses for transfer
of the user's settings to the booted program.
Theme/Color values:
- 0 = Gray
- 1 = Brown
- 2 = Red
- 3 = Pink
- 4 = Orange
- 5 = Yellow
- 6 = Yellow/Green-ish
- 7 = Green
- 8 = Dark Green
- 9 = Green/Blue-ish
- 10 = Light Blue
- 11 = Blue
- 12 = Dark Blue
- 13 = Dark Purple
- 14 = Purple
- 15 = Purple/Red-ish
Language values:
- 0 = Japanese
- 1 = English
- 2 = French
- 3 = German
- 4 = Italian
- 5 = Spanish
- 6 = Chinese(?)
- 7 = Unknown/Reserved
*/
typedef struct tPERSONAL_DATA
{
u8 RESERVED0[2]; // ??? (0x05 0x00). (version according to gbatek)
u8 theme; //!< The user's theme color (0-15).
u8 birthMonth; //!< The user's birth month (1-12).
u8 birthDay; //!< The user's birth day (1-31).
u8 RESERVED1[1]; // ???
s16 name[10]; //!< The user's name in UTF-16 format.
u16 nameLen; //!< The length of the user's name in characters.
s16 message[26]; //!< The user's message.
u16 messageLen; //!< The length of the user's message in characters.
u8 alarmHour; //!< What hour the alarm clock is set to (0-23).
u8 alarmMinute; //!< What minute the alarm clock is set to (0-59).
//0x02FFFCD3 alarm minute
u8 RESERVED2[4]; // ??? 0x02FFFCD4 ??
u16 calX1; //!< Touchscreen calibration: first X touch
u16 calY1; //!< Touchscreen calibration: first Y touch
u8 calX1px; //!< Touchscreen calibration: first X touch pixel
u8 calY1px; //!< Touchscreen calibration: first X touch pixel
u16 calX2; //!< Touchscreen calibration: second X touch
u16 calY2; //!< Touchscreen calibration: second Y touch
u8 calX2px; //!< Touchscreen calibration: second X touch pixel
u8 calY2px; //!< Touchscreen calibration: second Y touch pixel
struct {
unsigned int language : 3; //!< User's language.
unsigned int gbaScreen : 1; //!< GBA screen selection (lower screen if set, otherwise upper screen).
unsigned int defaultBrightness : 2; //!< Brightness level at power on, dslite.
unsigned int autoMode : 1; //!< The DS should boot from the DS cart or GBA cart automatically if one is inserted.
unsigned int RESERVED5 : 2; // ???
unsigned int settingsLost : 1; //!< User Settings Lost (0=Normal, 1=Prompt/Settings Lost)
unsigned int RESERVED6 : 6; // ???
} PACKED;
u16 RESERVED3; // ???
u32 rtcOffset; //!< Real Time Clock offset.
u32 RESERVED4; // ???
} PACKED PERSONAL_DATA ;
//! Default location for the user's personal data (see %PERSONAL_DATA).
#define PersonalData ((PERSONAL_DATA*)0x2FFFC80)
//! struct containing time and day of the real time clock.
typedef struct {
u8 year; //!< add 2000 to get 4 digit year
u8 month; //!< 1 to 12
u8 day; //!< 1 to (days in month)
u8 weekday; //!< day of week
u8 hours; //!< 0 to 11 for AM, 52 to 63 for PM
u8 minutes; //!< 0 to 59
u8 seconds; //!< 0 to 59
} RTCtime;
// argv struct magic number
#define ARGV_MAGIC 0x5f617267
//structure used to set up argc/argv on the DS
struct __argv {
int argvMagic; // argv magic number, set to 0x5f617267 ('_arg') if valid
char *commandLine; // base address of command line, set of null terminated strings
int length; // total length of command line
int argc; // internal use, number of arguments
char **argv; // internal use, argv pointer
int dummy; // internal use
u32 host; // internal use, host ip for dslink
};
#define __system_argv ((struct __argv *)0x02FFFE70)
#define BOOTSIG 0x62757473746F6F62ULL // 'bootstub'
struct __bootstub {
u64 bootsig;
VoidFn arm9reboot;
VoidFn arm7reboot;
u32 bootsize;
};
#ifdef ARM9
/*!
\brief returns a cached mirror of an address.
\param address an address.
\return a pointer to the cached mirror of that address.
*/
void *memCached(void *address);
/*!
\brief returns an uncached mirror of an address.
\param address an address.
\return a pointer to the uncached mirror of that address.
*/
void *memUncached(void *address);
void resetARM7(u32 address);
#endif
#ifdef ARM7
void resetARM9(u32 address);
#endif
#endif