/*
Copyright (C) 2006 yopyop
Copyright (C) 2008-2012 DeSmuME team
This file 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 file 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 the this software. If not, see .
*/
#ifndef NDSSYSTEM_H
#define NDSSYSTEM_H
#include
#include "armcpu.h"
#include "MMU.h"
//#include "driver.h"
//#include "GPU.h"
#include "SPU.h"
#include "mem.h"
//#include "wifi.h"
#include "emufile.h"
#include "firmware.h"
#include
#if defined(_WINDOWS) && !defined(WXPORT)
#include "pathsettings.h"
#endif
template
struct buttonstruct {
union {
struct {
// changing the order of these fields would break stuff
//fRLDUTSBAYXWEg
Type G; // debug
Type E; // right shoulder
Type W; // left shoulder
Type X;
Type Y;
Type A;
Type B;
Type S; // start
Type T; // select
Type U; // up
Type D; // down
Type L; // left
Type R; // right
Type F; // lid
};
Type array[14];
};
};
//extern buttonstruct Turbo;
extern buttonstruct TurboTime;
//extern buttonstruct AutoHold;
//int NDS_WritePNG(const char *fname);
extern volatile bool execute;
//extern bool click;
/*
* The firmware language values
*/
/*#define NDS_FW_LANG_JAP 0
#define NDS_FW_LANG_ENG 1
#define NDS_FW_LANG_FRE 2
#define NDS_FW_LANG_GER 3
#define NDS_FW_LANG_ITA 4
#define NDS_FW_LANG_SPA 5
#define NDS_FW_LANG_CHI 6
#define NDS_FW_LANG_RES 7*/
//#define LOG_ARM9
//#define LOG_ARM7
struct NDS_header
{
char gameTile[12];
char gameCode[4];
uint16_t makerCode;
uint8_t unitCode;
uint8_t deviceCode;
uint8_t cardSize;
uint8_t cardInfo[8];
uint8_t flags;
uint8_t romversion;
uint32_t ARM9src;
uint32_t ARM9exe;
uint32_t ARM9cpy;
uint32_t ARM9binSize;
uint32_t ARM7src;
uint32_t ARM7exe;
uint32_t ARM7cpy;
uint32_t ARM7binSize;
uint32_t FNameTblOff;
uint32_t FNameTblSize;
uint32_t FATOff;
uint32_t FATSize;
uint32_t ARM9OverlayOff;
uint32_t ARM9OverlaySize;
uint32_t ARM7OverlayOff;
uint32_t ARM7OverlaySize;
uint32_t unknown2a;
uint32_t unknown2b;
uint32_t IconOff;
uint16_t CRC16;
uint16_t ROMtimeout;
uint32_t ARM9unk;
uint32_t ARM7unk;
uint8_t unknown3c[8];
uint32_t ROMSize;
uint32_t HeaderSize;
uint8_t unknown5[56];
uint8_t logo[156];
uint16_t logoCRC16;
uint16_t headerCRC16;
uint8_t reserved[160];
};
//extern void debug();
//void emu_halt();
extern uint64_t nds_timer;
void NDS_Reschedule();
//void NDS_RescheduleGXFIFO(uint32_t cost);
void NDS_RescheduleDMA();
void NDS_RescheduleTimers();
/*enum ENSATA_HANDSHAKE
{
ENSATA_HANDSHAKE_none = 0,
ENSATA_HANDSHAKE_query = 1,
ENSATA_HANDSHAKE_ack = 2,
ENSATA_HANDSHAKE_confirm = 3,
ENSATA_HANDSHAKE_complete = 4
};*/
enum NDS_CONSOLE_TYPE
{
NDS_CONSOLE_TYPE_FAT,
NDS_CONSOLE_TYPE_LITE,
NDS_CONSOLE_TYPE_IQUE,
NDS_CONSOLE_TYPE_DSI
};
struct NDSSystem
{
//int32_t wifiCycle;
int32_t cycles;
uint64_t timerCycle[2][4];
uint32_t VCount;
uint32_t old;
//uint16_t touchX;
//uint16_t touchY;
//bool isTouch;
//uint16_t pad;
uint8_t *FW_ARM9BootCode;
uint8_t *FW_ARM7BootCode;
uint32_t FW_ARM9BootCodeAddr;
uint32_t FW_ARM7BootCodeAddr;
uint32_t FW_ARM9BootCodeSize;
uint32_t FW_ARM7BootCodeSize;
bool sleeping;
bool cardEjected;
uint32_t freezeBus;
//this is not essential NDS runtime state.
//it was perhaps a mistake to put it here.
//it is far less important than the above.
//maybe I should move it.
//int32_t idleCycles[2];
//int32_t runCycleCollector[2][16];
//int32_t idleFrameCounter;
//int32_t cpuloopIterationCount; //counts the number of times during a frame that a reschedule happened
//if the game was booted on a debug console, this is set
//bool debugConsole;
//console type must be copied in when the system boots. it can't be changed on the fly.
int ConsoleType;
bool Is_DSI() { return ConsoleType == NDS_CONSOLE_TYPE_DSI; }
//set if the user requests ensata emulation
//bool ensataEmulation;
//there is a hack in the ipc sync for ensata. this tracks its state
//uint32_t ensataIpcSyncCounter;
//maintains the state of the ensata handshaking protocol
//uint32_t ensataHandshake;
/*struct {
uint8_t lcd, gpuMain, gfx3d_render, gfx3d_geometry, gpuSub, dispswap;
} power1;*/ //POWCNT1
/*struct {
uint8_t speakers, wifi*/ /*(initial value=0)*//*;
} power2;*/ //POWCNT2
bool isInVblank() const { return VCount >= 192; }
bool isIn3dVblank() const { return VCount >= 192 && VCount<215; }
};
/** /brief A touchscreen calibration point.
*/
/*struct NDS_fw_touchscreen_cal {
uint16_t adc_x;
uint16_t adc_y;
uint8_t screen_x;
uint8_t screen_y;
};*/
#define MAX_FW_NICKNAME_LENGTH 10
#define MAX_FW_MESSAGE_LENGTH 26
struct NDS_fw_config_data {
NDS_CONSOLE_TYPE ds_type;
uint8_t fav_colour;
uint8_t birth_month;
uint8_t birth_day;
uint16_t nickname[MAX_FW_NICKNAME_LENGTH];
uint8_t nickname_len;
uint16_t message[MAX_FW_MESSAGE_LENGTH];
uint8_t message_len;
uint8_t language;
/* touchscreen calibration */
//struct NDS_fw_touchscreen_cal touch_cal[2];
};
extern NDSSystem nds;
#ifdef GDB_STUB
int NDS_Init( struct armcpu_memory_iface *arm9_mem_if,
struct armcpu_ctrl_iface **arm9_ctrl_iface,
struct armcpu_memory_iface *arm7_mem_if,
struct armcpu_ctrl_iface **arm7_ctrl_iface);
#else
int NDS_Init ();
#endif
//void Desmume_InitOnce();
void NDS_DeInit();
bool NDS_SetROM(uint8_t * rom, uint32_t mask);
NDS_header * NDS_getROMHeader();
struct RomBanner
{
RomBanner(bool defaultInit);
uint16_t version; //Version (0001h)
uint16_t crc16; //CRC16 across entries 020h..83Fh
uint8_t reserved[0x1C]; //Reserved (zero-filled)
uint8_t bitmap[0x200]; //Icon Bitmap (32x32 pix) (4x4 tiles, each 4x8 bytes, 4bit depth)
uint16_t palette[0x10]; //Icon Palette (16 colors, 16bit, range 0000h-7FFFh) (Color 0 is transparent, so the 1st palette entry is ignored)
enum { NUM_TITLES = 6 };
union {
struct {
uint16_t title_jp[0x80]; //Title 0 Japanese (128 characters, 16bit Unicode)
uint16_t title_en[0x80]; //Title 1 English ("")
uint16_t title_fr[0x80]; //Title 2 French ("")
uint16_t title_de[0x80]; //Title 3 German ("")
uint16_t title_it[0x80]; //Title 4 Italian ("")
uint16_t title_es[0x80]; //Title 5 Spanish ("")
};
uint16_t titles[NUM_TITLES][0x80];
};
uint8_t end0xFF[0x1C0];
//840h ? (Maybe newer/chinese firmware do also support chinese title?)
//840h - End of Icon/Title structure (next 1C0h bytes usually FFh-filled)
};
struct GameInfo
{
GameInfo()
: romdata(NULL)
{}
void loadData(char* buf, int size)
{
resize(size);
memcpy(romdata,buf,size);
romsize = (uint32_t)size;
fillGap();
}
void fillGap()
{
memset(romdata+romsize,0xFF,allocatedSize-romsize);
}
void resize(int size) {
if(romdata != NULL) delete[] romdata;
//calculate the necessary mask for the requested size
mask = size-1;
mask |= (mask >>1);
mask |= (mask >>2);
mask |= (mask >>4);
mask |= (mask >>8);
mask |= (mask >>16);
//now, we actually need to over-allocate, because bytes from anywhere protected by that mask
//could be read from the rom
allocatedSize = mask+4;
romdata = new char[allocatedSize];
romsize = size;
}
uint32_t crc;
NDS_header header;
char ROMserial[20];
char ROMname[20];
//char ROMfullName[7][0x100];
//void populate();
char* romdata;
uint32_t romsize;
uint32_t allocatedSize;
uint32_t mask;
//const RomBanner& getRomBanner();
//bool hasRomBanner();
bool isHomebrew;
};
/*typedef struct TSCalInfo
{
struct adc
{
uint16_t x1, x2;
uint16_t y1, y2;
uint16_t width;
uint16_t height;
} adc;
struct scr
{
uint8_t x1, x2;
uint8_t y1, y2;
uint16_t width;
uint16_t height;
} scr;
} TSCalInfo;*/
extern GameInfo gameInfo;
struct UserButtons : buttonstruct
{
};
struct UserTouch
{
uint16_t touchX;
uint16_t touchY;
bool isTouch;
};
struct UserMicrophone
{
uint32_t micButtonPressed;
};
struct UserInput
{
UserButtons buttons;
UserTouch touch;
UserMicrophone mic;
};
// set physical user input
// these functions merely request the input to be changed.
// the actual change happens later at a specific time during the frame.
// this is to minimize the risk of desyncs.
//void NDS_setTouchPos(uint16_t x, uint16_t y);
//void NDS_releaseTouch();
//void NDS_setPad(bool right,bool left,bool down,bool up,bool select,bool start,bool B,bool A,bool Y,bool X,bool leftShoulder,bool rightShoulder,bool debug, bool lid);
//void NDS_setMic(bool pressed);
// get physical user input
// not including the results of autofire/etc.
// the effects of calls to "set physical user input" functions will be immediately reflected here though.
//const UserInput& NDS_getRawUserInput();
//const UserInput& NDS_getPrevRawUserInput();
// get final (fully processed) user input
// this should match whatever was or would be sent to the game
//const UserInput& NDS_getFinalUserInput();
// set/get to-be-processed or in-the-middle-of-being-processed user input
// to process input, simply call this function and edit the return value.
// (applying autofire is one example of processing the input.)
// (movie playback is another example.)
// this must be done after the raw user input is set
// and before that input is sent to the game's memory.
//UserInput& NDS_getProcessingUserInput();
//bool NDS_isProcessingUserInput();
// call once per frame to prepare input for processing
//void NDS_beginProcessingInput();
// call once per frame to copy the processed input to the final input
//void NDS_endProcessingInput();
// this is in case something needs reentrancy while processing input
//void NDS_suspendProcessingInput(bool suspend);
//int NDS_LoadROM(const char *filename, const char* logicalFilename=0);
void NDS_FreeROM();
void NDS_Reset();
//int NDS_ImportSave(const char *filename);
//bool NDS_ExportSave(const char *filename);
//void nds_savestate(EMUFILE* os);
bool nds_loadstate(EMUFILE* is, int size);
//int NDS_WriteBMP(const char *filename);
void NDS_Sleep();
//void NDS_ToggleCardEject();
//void NDS_SkipNextFrame();
//#define NDS_SkipFrame(s) if(s) NDS_SkipNext2DFrame();
//void NDS_OmitFrameSkip(int force=0);
//void NDS_debug_break();
//void NDS_debug_continue();
//void NDS_debug_step();
void execHardware_doAllDma(EDMAMode modeNum);
template void NDS_exec(int32_t nb = 560190<<1);
//extern int lagframecounter;
/*static INLINE void NDS_swapScreen()
{
uint16_t tmp = MainScreen.offset;
MainScreen.offset = SubScreen.offset;
SubScreen.offset = tmp;
}*/
//int NDS_WriteBMP_32bppBuffer(int width, int height, const void* buf, const char *filename);
extern struct TCommonSettings {
TCommonSettings()
: //GFX3D_HighResolutionInterpolateColor(true)
//, GFX3D_EdgeMark(true)
//, GFX3D_Fog(true)
//, GFX3D_Texture(true)
//, GFX3D_Zelda_Shadow_Depth_Hack(0)
/*,*/ UseExtBIOS(false)
, SWIFromBIOS(false)
, PatchSWI3(false)
, UseExtFirmware(false)
, BootFromFirmware(false)
, ConsoleType(NDS_CONSOLE_TYPE_FAT)
//, DebugConsole(false)
//, EnsataEmulation(false)
//, cheatsDisable(false)
//, num_cores(1)
, rigorous_timing(false)
, advanced_timing(true)
//, micMode(InternalNoise)
, spuInterpolationMode(SPUInterpolation_Linear)
, manualBackupType(0)
, spu_captureMuted(false)
, spu_advanced(false)
{
strcpy(ARM9BIOS, "biosnds9.bin");
strcpy(ARM7BIOS, "biosnds7.bin");
strcpy(Firmware, "firmware.bin");
NDS_FillDefaultFirmwareConfigData(&InternalFirmConf);
/* WIFI mode: adhoc = 0, infrastructure = 1 */
//wifi.mode = 1;
//wifi.infraBridgeAdapter = 0;
for(int i=0;i<16;i++)
spu_muteChannels[i] = false;
/*for(int g=0;g<2;g++)
for(int x=0;x<5;x++)
dispLayers[g][x]=true;*/
}
//bool GFX3D_HighResolutionInterpolateColor;
//bool GFX3D_EdgeMark;
//bool GFX3D_Fog;
//bool GFX3D_Texture;
//int GFX3D_Zelda_Shadow_Depth_Hack;
bool UseExtBIOS;
char ARM9BIOS[256];
char ARM7BIOS[256];
bool SWIFromBIOS;
bool PatchSWI3;
bool UseExtFirmware;
char Firmware[256];
bool BootFromFirmware;
struct NDS_fw_config_data InternalFirmConf;
NDS_CONSOLE_TYPE ConsoleType;
//bool DebugConsole;
//bool EnsataEmulation;
//bool cheatsDisable;
//int num_cores;
//bool single_core() { return num_cores==1; }
bool rigorous_timing;
//bool dispLayers[2][5];
/*FAST_ALIGN*/ bool advanced_timing;
/*struct _Wifi {
int mode;
int infraBridgeAdapter;
} wifi;*/
/*enum MicMode
{
InternalNoise = 0,
Sample = 1,
Random = 2,
Physical = 3
} micMode;*/
SPUInterpolationMode spuInterpolationMode;
//this is a temporary hack until we straighten out the flushing logic and/or gxfifo
//int gfx3d_flushMode;
//this is the user's choice of manual backup type, for cases when the autodetection can't be trusted
int manualBackupType;
bool spu_muteChannels[16];
bool spu_captureMuted;
bool spu_advanced;
/*struct _ShowGpu {
_ShowGpu() : main(true), sub(true) {}
union {
struct { bool main,sub; };
bool screens[2];
};
} showGpu;*/
/*struct _Hud {
_Hud()
: ShowInputDisplay(false)
, ShowGraphicalInputDisplay(false)
, FpsDisplay(false)
, FrameCounterDisplay(false)
, ShowLagFrameCounter(false)
, ShowMicrophone(false)
, ShowRTC(false)
{}
bool ShowInputDisplay, ShowGraphicalInputDisplay, FpsDisplay, FrameCounterDisplay, ShowLagFrameCounter, ShowMicrophone, ShowRTC;
} hud;*/
} CommonSettings;
//extern std::string InputDisplayString;
//extern int LagFrameFlag;
//extern int lastLag, TotalLagFrames;
//void MovieSRAM();
//void ClearAutoHold();
//bool ValidateSlot2Access(uint32_t procnum, uint32_t demandSRAMSpeed, uint32_t demand1stROMSpeed, uint32_t demand2ndROMSpeed, int clockbits);
#endif