From b1e493442134a8aa3f2eb4d438e0f15992497f91 Mon Sep 17 00:00:00 2001 From: zeromus Date: Fri, 19 Sep 2008 08:08:34 +0000 Subject: [PATCH] - Change savestate code to support loosely bound chunks and more easily other parts of the emu (GE, GPU; also we need SPU eventually). The savestate format is changed, but from now on it is in principle more resilient (it will continue to break though) - Remove 16MB of WRAM at 0x01****** from arm9 --- desmume/ChangeLog | 3 + desmume/INSTALL | 5 +- desmume/src/ARM9.h | 1 - desmume/src/GPU.cpp | 31 +- desmume/src/GPU.h | 18 +- desmume/src/GPU_osd.cpp | 4 +- desmume/src/MMU.cpp | 5 +- desmume/src/Makefile.am | 3 + desmume/src/NDSSystem.h | 6 +- desmume/src/OGLRender.cpp | 22 +- desmume/src/gfx3d.cpp | 374 ++++++++------ desmume/src/gfx3d.h | 22 +- desmume/src/memorystream.h | 303 +++++++++++ desmume/src/readwrite.cpp | 117 +++++ desmume/src/readwrite.h | 16 + desmume/src/saves.cpp | 653 +++++++++++++++--------- desmume/src/saves.h | 33 +- desmume/src/types.h | 29 ++ desmume/src/windows/DeSmuME_2005.vcproj | 16 +- desmume/src/windows/console.cpp | 5 +- desmume/src/windows/disView.cpp | 9 +- desmume/src/windows/main.cpp | 210 ++++---- desmume/src/windows/memView.cpp | 9 +- 23 files changed, 1344 insertions(+), 550 deletions(-) create mode 100644 desmume/src/memorystream.h create mode 100644 desmume/src/readwrite.cpp create mode 100644 desmume/src/readwrite.h diff --git a/desmume/ChangeLog b/desmume/ChangeLog index 828272635..423b14cfe 100644 --- a/desmume/ChangeLog +++ b/desmume/ChangeLog @@ -14,6 +14,9 @@ - Added gfx3d module which emulates the whole GE as part of the core emu. Moved the windows/cocoa OGLRender to the emu core and replace ogl_collector. Now every platform shares the same 3d code. [zeromus] - Add in some crude interpolation in the SPU (conditionally compiled) so that I can bear to listen to it. [zeromus] + - Change savestate code to support loosely bound chunks and more easily other parts of the emu (GE, GPU). + The savestate format is changed, but from now on it is in principle more resilient (it will continue to break though) [zeromus] + - Remove 16MB of WRAM at 0x01****** from arm9. Maped to unusued instead. What was this? [zeromus] Mac OS X port: - Fixed: Filenames and paths with unicode characters now work. [Jeff] - Fixed: Load state from file button works again. [Jeff] diff --git a/desmume/INSTALL b/desmume/INSTALL index d3c5b40a9..5458714e1 100644 --- a/desmume/INSTALL +++ b/desmume/INSTALL @@ -2,7 +2,7 @@ Installation Instructions ************************* Copyright (C) 1994, 1995, 1996, 1999, 2000, 2001, 2002, 2004, 2005, -2006, 2007 Free Software Foundation, Inc. +2006 Free Software Foundation, Inc. This file is free documentation; the Free Software Foundation gives unlimited permission to copy, distribute and modify it. @@ -67,9 +67,6 @@ The simplest way to compile this package is: all sorts of other programs in order to regenerate files that came with the distribution. - 6. Often, you can also type `make uninstall' to remove the installed - files again. - Compilers and Options ===================== diff --git a/desmume/src/ARM9.h b/desmume/src/ARM9.h index 849f045c8..d5f832242 100644 --- a/desmume/src/ARM9.h +++ b/desmume/src/ARM9.h @@ -7,7 +7,6 @@ typedef struct { //ARM9 mem u8 ARM9_ITCM[0x8000]; u8 ARM9_DTCM[0x4000]; - u8 ARM9_WRAM[0x1000000]; u8 MAIN_MEM[0x400000]; u8 ARM9_REG[0x1000000]; u8 ARM9_BIOS[0x8000]; diff --git a/desmume/src/GPU.cpp b/desmume/src/GPU.cpp index f4568910b..957895dae 100644 --- a/desmume/src/GPU.cpp +++ b/desmume/src/GPU.cpp @@ -40,9 +40,11 @@ // GRAPHICS CORE // GPU_ligne +#include #include #include #include +#include #include "MMU.h" #include "GPU.h" #include "debug.h" @@ -545,9 +547,9 @@ static BOOL setFinalColorSpecialBlend (const GPU *gpu, u32 passing, u8 bgnum, u8 targetG = (((color>>5) & 0x1F) * targetFraction) >> 4 ; targetB = (((color>>10) & 0x1F) * targetFraction) >> 4 ; // limit combined components to 31 max - sourceR = min(0x1F,targetR+sourceR) ; - sourceG = min(0x1F,targetG+sourceG) ; - sourceB = min(0x1F,targetB+sourceB) ; + sourceR = std::min(0x1F,targetR+sourceR) ; + sourceG = std::min(0x1F,targetG+sourceG) ; + sourceB = std::min(0x1F,targetB+sourceB) ; //} } color = (sourceR & 0x1F) | ((sourceG & 0x1F) << 5) | ((sourceB & 0x1F) << 10) | 0x8000 ; @@ -660,9 +662,9 @@ static BOOL setFinalColorSpecialBlendWnd (const GPU *gpu, u32 passing, u8 bgnum, targetG = (((color>>5) & 0x1F) * targetFraction) >> 4 ; targetB = (((color>>10) & 0x1F) * targetFraction) >> 4 ; // limit combined components to 31 max - sourceR = min(0x1F,targetR+sourceR) ; - sourceG = min(0x1F,targetG+sourceG) ; - sourceB = min(0x1F,targetB+sourceB) ; + sourceR = std::min(0x1F,targetR+sourceR) ; + sourceG = std::min(0x1F,targetG+sourceG) ; + sourceB = std::min(0x1F,targetB+sourceB) ; //} } color = (sourceR & 0x1F) | ((sourceG & 0x1F) << 5) | ((sourceB & 0x1F) << 10) | 0x8000 ; @@ -789,7 +791,7 @@ INLINE void renderline_textBG(const GPU * gpu, u8 num, u8 * dst, u32 Y, u16 XBG, yoff = ((YBG&7)<<2); xfin = 8 - (xoff&7); - for(x = 0; x < LG; xfin = min(x+8, LG)) + for(x = 0; x < LG; xfin = std::min(x+8, LG)) { u8 pt = 0, save = 0; tmp = ((xoff&(lg-1))>>3); @@ -848,7 +850,7 @@ INLINE void renderline_textBG(const GPU * gpu, u8 num, u8 * dst, u32 Y, u16 XBG, } else { /* no mosaic mode */ yoff = ((YBG&7)<<2); xfin = 8 - (xoff&7); - for(x = 0; x < LG; xfin = min(x+8, LG)) + for(x = 0; x < LG; xfin = std::min(x+8, LG)) { u16 tilePalette = 0; tmp = ((xoff&(lg-1))>>3); @@ -918,7 +920,7 @@ INLINE void renderline_textBG(const GPU * gpu, u8 num, u8 * dst, u32 Y, u16 XBG, yoff = ((YBG&7)<<3); xfin = 8 - (xoff&7); - for(x = 0; x < LG; xfin = min(x+8, LG)) + for(x = 0; x < LG; xfin = std::min(x+8, LG)) { tmp = (xoff & (lg-1))>>3; mapinfo = map + (tmp & 31) * 2; @@ -2431,3 +2433,14 @@ void GPU_ligne(NDS_Screen * screen, u16 l) } #endif } + +void gpu_savestate(std::ostream* os) +{ + os->write((char*)GPU_screen,sizeof(GPU_screen)); +} + +bool gpu_loadstate(std::istream* is) +{ + is->read((char*)GPU_screen,sizeof(GPU_screen)); + return !is->fail(); +} \ No newline at end of file diff --git a/desmume/src/GPU.h b/desmume/src/GPU.h index 7580bf4c9..781a49574 100644 --- a/desmume/src/GPU.h +++ b/desmume/src/GPU.h @@ -32,6 +32,10 @@ #include "FIFO.h" #include "MMU.h" #include "GPU_osd.h" +#include + +void gpu_savestate(std::ostream* os); +bool gpu_loadstate(std::istream* is); /******************************************************************************* this structure is for display control, @@ -385,20 +389,6 @@ typedef struct _reg_dispx { } REG_DISPx ; - - - - - - -#ifndef min -#define min(a,b) (((a)<(b))?(a):(b)) -#endif - -#ifndef max -#define max(a,b) (((a)>(b))?(a):(b)) -#endif - typedef BOOL (*fun_gl_Begin) (int screen); typedef void (*fun_gl_End) (int screen); // the GUI should use this function prior to all gl calls diff --git a/desmume/src/GPU_osd.cpp b/desmume/src/GPU_osd.cpp index b40190f06..5044a78d7 100644 --- a/desmume/src/GPU_osd.cpp +++ b/desmume/src/GPU_osd.cpp @@ -63,12 +63,12 @@ OSDCLASS::OSDCLASS(u8 core) } - printlog("OSD_Init (%s)\n",name); + LOG("OSD_Init (%s)\n",name); } OSDCLASS::~OSDCLASS() { - printlog("OSD_Deinit (%s)\n",name); + LOG("OSD_Deinit (%s)\n",name); delete old_msg; } diff --git a/desmume/src/MMU.cpp b/desmume/src/MMU.cpp index 6a616536d..271377a96 100644 --- a/desmume/src/MMU.cpp +++ b/desmume/src/MMU.cpp @@ -69,7 +69,7 @@ MMU_struct MMU; u8 * MMU_ARM9_MEM_MAP[256]={ /* 0X*/ DUP16(ARM9Mem.ARM9_ITCM), /* 1X*/ //DUP16(ARM9Mem.ARM9_ITCM) -/* 1X*/ DUP16(ARM9Mem.ARM9_WRAM), +/* 1X*/ DUP16(MMU.UNUSED_RAM), /* 2X*/ DUP16(ARM9Mem.MAIN_MEM), /* 3X*/ DUP16(MMU.SWIRAM), /* 4X*/ DUP16(ARM9Mem.ARM9_REG), @@ -93,7 +93,7 @@ u8 * MMU_ARM9_MEM_MAP[256]={ u32 MMU_ARM9_MEM_MASK[256]={ /* 0X*/ DUP16(0x00007FFF), /* 1X*/ //DUP16(0x00007FFF) -/* 1X*/ DUP16(0x00FFFFFF), +/* 1X*/ DUP16(0x00000003), /* 2X*/ DUP16(0x003FFFFF), /* 3X*/ DUP16(0x00007FFF), /* 4X*/ DUP16(0x00FFFFFF), @@ -253,7 +253,6 @@ void MMU_clearMem() memset(ARM9Mem.ARM9_OAM, 0, 0x0800); memset(ARM9Mem.ARM9_REG, 0, 0x01000000); memset(ARM9Mem.ARM9_VMEM, 0, 0x0800); - memset(ARM9Mem.ARM9_WRAM, 0, 0x01000000); memset(ARM9Mem.MAIN_MEM, 0, 0x400000); memset(ARM9Mem.blank_memory, 0, 0x020000); diff --git a/desmume/src/Makefile.am b/desmume/src/Makefile.am index 844c7ba22..a43957660 100644 --- a/desmume/src/Makefile.am +++ b/desmume/src/Makefile.am @@ -13,8 +13,11 @@ libdesmume_a_SOURCES = \ Disassembler.cpp Disassembler.h \ dscard.h fat.h FIFO.cpp FIFO.h \ GPU.cpp GPU.h \ + GPU_osd.cpp GPU_osd.h \ gl_vertex.cpp gl_vertex.h \ mem.h mc.cpp mc.h \ + memorystream.h \ + readwrite.cpp readwrite.h \ wifi.cpp wifi.h \ MMU.cpp MMU.h NDSSystem.cpp NDSSystem.h registers.h \ OGLRender.cpp OGLRender.h \ diff --git a/desmume/src/NDSSystem.h b/desmume/src/NDSSystem.h index a0b3690e2..8e3af9b6b 100644 --- a/desmume/src/NDSSystem.h +++ b/desmume/src/NDSSystem.h @@ -119,11 +119,13 @@ typedef struct u16 touchX; u16 touchY; + //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. s32 idleCycles; s32 runCycleCollector[16]; s32 idleFrameCounter; - - } NDSSystem; /** /brief A touchscreen calibration point. diff --git a/desmume/src/OGLRender.cpp b/desmume/src/OGLRender.cpp index 31425b1d0..2a1976402 100644 --- a/desmume/src/OGLRender.cpp +++ b/desmume/src/OGLRender.cpp @@ -24,6 +24,7 @@ //so, it doesnt composite to 2d correctly. //(re: new super mario brothers renders the stormclouds at the beginning) +#include #include #include #include @@ -78,7 +79,6 @@ static const unsigned short map3d_cull[4] = {GL_FRONT_AND_BACK, GL_FRONT, GL_BAC static const int texEnv[4] = { GL_MODULATE, GL_DECAL, GL_MODULATE, GL_MODULATE }; static const int depthFunc[2] = { GL_LESS, GL_EQUAL }; static bool needRefreshFramebuffer = false; -static unsigned short matrixMode[2] = {GL_PROJECTION, GL_MODELVIEW}; static unsigned char texMAP[1024*2048*4]; static unsigned int textureMode=0; @@ -508,7 +508,7 @@ void setTexture(unsigned int format, unsigned int texpal) { //TODO - we need to compare the palette also. //TODO - this doesnt correctly span bank boundaries. in fact, it seems quite dangerous. - if (!texcache[i].suspectedInvalid || !memcmp(adr,texcache[i].texture,min(imageSize,sizeof(texcache[i].texture)))) + if (!texcache[i].suspectedInvalid || !memcmp(adr,texcache[i].texture,std::min(imageSize,sizeof(texcache[i].texture)))) { texcache[i].suspectedInvalid = false; texcache_count=i; @@ -550,7 +550,7 @@ void setTexture(unsigned int format, unsigned int texpal) texcache[i].invSizeX=1.0f/((float)sizeX*(1<<4)); texcache[i].invSizeY=1.0f/((float)sizeY*(1<<4)); //memcpy(texcache[i].texture,adr,imageSize); //======================= copy - memcpy_fast(texcache[i].texture,adr,min(imageSize,sizeof(texcache[i].texture))); //======================= copy + memcpy_fast(texcache[i].texture,adr,std::min(imageSize,sizeof(texcache[i].texture))); //======================= copy texcache[i].numcolors=palSize[texcache[i].mode]; texcache[i].frm=format; @@ -798,7 +798,7 @@ void setTexture(unsigned int format, unsigned int texpal) texcache[i].sizeX, texcache[i].sizeY, 0, GL_RGBA, GL_UNSIGNED_BYTE, texMAP); - DebugDumpTexture(i); + //DebugDumpTexture(i); //============================================================================================ @@ -992,6 +992,12 @@ static void Render() glBegin(type==3?GL_TRIANGLES:GL_QUADS); for(int j=0;jlist[poly->vertIndexes[j]]; + u8 color[4] = { + material_5bit_to_8bit[vert->color[0]], + material_5bit_to_8bit[vert->color[1]], + material_5bit_to_8bit[vert->color[2]], + material_5bit_to_8bit[vert->color[3]] + }; //float tempCoord[4]; //Vector4Copy(tempCoord,vert->coord); @@ -1004,7 +1010,7 @@ static void Render() //todo - edge flag? glTexCoord2fv(vert->texcoord); - glColor4iv((GLint*)vert->color); + glColor4ubv((GLubyte*)color); //glVertex3fv(tempCoord); glVertex3fv(vert->coord); } @@ -1101,9 +1107,9 @@ static void GetLine (int line, u16* dst) g = (g*a + oldg*(255-a)) >> 8; b = (b*a + oldb*(255-a)) >> 8; - r=min(255,r); - g=min(255,g); - b=min(255,b); + r=std::min(255ul,r); + g=std::min(255ul,g); + b=std::min(255ul,b); //debug: display alpha channel //u32 r = screen3D[t+3]; diff --git a/desmume/src/gfx3d.cpp b/desmume/src/gfx3d.cpp index 01ea132b3..bf457195f 100644 --- a/desmume/src/gfx3d.cpp +++ b/desmume/src/gfx3d.cpp @@ -22,6 +22,7 @@ //This handles almost all of the work of 3d rendering, leaving the renderer // plugin responsible only for drawing primitives. +#include #include "debug.h" #include "gfx3d.h" #include "matrix.h" @@ -29,18 +30,11 @@ #include "MMU.h" #include "render3D.h" #include "types.h" +#include "saves.h" +#include "readwrite.h" GFX3D gfx3d; -#ifndef max -#define max(a,b) (((a) > (b)) ? (a) : (b)) -#endif - -#ifndef min -#define min(a,b) (((a) < (b)) ? (a) : (b)) -#endif - - //tables that are provided to anyone u32 color_15bit_to_24bit[32768]; @@ -81,7 +75,7 @@ static float normalTable[1024]; static ALIGN(16) MatrixStack mtxStack[4]; static ALIGN(16) float mtxCurrent [4][16]; static ALIGN(16) float mtxTemporal[16]; -static short mode = 0; +static u32 mode = 0; // Indexes for matrix loading/multiplication static char ML4x4ind = 0; @@ -93,7 +87,7 @@ static char MM3x3_c = 0, MM3x3_l = 0; // Data for vertex submission static ALIGN(16) float coord[4] = {0.0, 0.0, 0.0, 0.0}; static char coordind = 0; -static unsigned int vtxFormat; +static u32 vtxFormat; // Data for basic transforms static ALIGN(16) float trans[4] = {0.0, 0.0, 0.0, 0.0}; @@ -102,45 +96,43 @@ static ALIGN(16) float scale[4] = {0.0, 0.0, 0.0, 0.0}; static char scaleind = 0; //various other registers -static float fogColor[4] = {0.f}; -static float fogOffset = 0.f; -static float alphaTestRef = 0.01f; -static int colorRGB[4] = { 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff}; -static int texCoordinateTransform = 0; static int _t=0, _s=0; static float last_t, last_s; -static float alphaTestBase = 0; -static unsigned long clCmd = 0; -static unsigned long clInd = 0; -static unsigned long clInd2 = 0; -static int alphaDepthWrite = 0; -static int colorAlpha=0; -static unsigned int polyID=0; -static unsigned int depthFuncMode=0; -static unsigned int envMode=0; -static unsigned int cullingMask=0; +static u32 clCmd = 0; +static u32 clInd = 0; +static u32 clInd2 = 0; //raw ds format poly attributes static u32 polyAttr=0,textureFormat=0, texturePalette=0; -//------lighting state -struct LightInformation -{ - unsigned int color; // Color in hardware format - unsigned int direction; // Direction in hardware format - float floatDirection[4]; -} ; +//the current vertex color, 5bit values +static u8 colorRGB[4] = { 31,31,31,31 }; -static LightInformation g_lightInfo[4] = { 0 }; -static unsigned int lightMask=0; +u32 control = 0; +//light state: +static u32 lightColor[4] = {0,0,0,0}; +static u32 lightDirection[4] = {0,0,0,0}; +//material state: static u16 dsDiffuse, dsAmbient, dsSpecular, dsEmission; -static int diffuse[4] = {0}, - ambient[4] = {0}, - specular[4] = {0}, - emission[4] = {0}; + + +//-----------cached things: +//these dont need to go into the savestate. they can be regenerated from HW registers +//from polygonattr: +static unsigned int cullingMask=0; +static u8 colorAlpha=0; +static u32 envMode=0; +static u32 lightMask=0; +//other things: +static int texCoordinateTransform = 0; +static float cacheLightDirection[4][4]; //------------------ +#define RENDER_FRONT_SURFACE 0x80 +#define RENDER_BACK_SURFACE 0X40 + + //-------------poly and vertex lists POLYLIST polylists[2]; POLYLIST* polylist = &polylists[0]; @@ -230,31 +222,28 @@ void gfx3d_glClearColor(unsigned long v) void gfx3d_glFogColor(unsigned long v) { - fogColor[0] = ((float)((v )&0x1F))/31.0f; - fogColor[1] = ((float)((v>> 5)&0x1F))/31.0f; - fogColor[2] = ((float)((v>>10)&0x1F))/31.0f; - fogColor[3] = ((float)((v>>16)&0x1F))/31.0f; + gfx3d.fogColor[0] = ((float)((v )&0x1F))/31.0f; + gfx3d.fogColor[1] = ((float)((v>> 5)&0x1F))/31.0f; + gfx3d.fogColor[2] = ((float)((v>>10)&0x1F))/31.0f; + gfx3d.fogColor[3] = ((float)((v>>16)&0x1F))/31.0f; } void gfx3d_glFogOffset (unsigned long v) { - fogOffset = (float)(v&0xffff); + gfx3d.fogOffset = (float)(v&0xffff); } void gfx3d_glClearDepth(unsigned long v) { - u32 depth24b; - - v &= 0x7FFFF; - //Thanks to NHerve - depth24b = (v*0x200)+((v+1)/0x8000)*0x01FF; + v &= 0x7FFFF; + u32 depth24b = (v*0x200)+((v+1)/0x8000)*0x01FF; gfx3d.clearDepth = depth24b / ((float)(1<<24)); } -void gfx3d_glMatrixMode(unsigned long v) +void gfx3d_glMatrixMode(u32 v) { - mode = (short)(v&3); + mode = (v&3); } @@ -467,15 +456,16 @@ void gfx3d_glEnd(void) void gfx3d_glColor3b(unsigned long v) { - colorRGB[0] = material_5bit_to_31bit[(v&0x1F)]; - colorRGB[1] = material_5bit_to_31bit[((v>>5)&0x1F)]; - colorRGB[2] = material_5bit_to_31bit[((v>>10)&0x1F)]; + colorRGB[0] = (v&0x1F); + colorRGB[1] = ((v>>5)&0x1F); + colorRGB[2] = ((v>>10)&0x1F); } //Submit a vertex to the GE static void SetVertex() { ALIGN(16) float coordTransformed[4] = { coord[0], coord[1], coord[2], 1 }; + ALIGN(16) float coordProjected[4]; if (texCoordinateTransform == 3) { @@ -496,8 +486,6 @@ static void SetVertex() //apply modelview matrix MatrixMultVec4x4 (mtxCurrent[1], coordTransformed); - //deferred rendering: - //todo - we havent got the whole pipeline working yet, so lets save the projection matrix and let opengl do it ////apply projection matrix //MatrixMultVec4x4 (mtxCurrent[0], coordTransformed); @@ -511,19 +499,19 @@ static void SetVertex() //TODO - culling should be done here. //TODO - viewport transform - //record the vertex - tempVertList.list[tempVertList.count].texcoord[0] = last_s; - tempVertList.list[tempVertList.count].texcoord[1] = last_t; - tempVertList.list[tempVertList.count].coord[0] = coordTransformed[0]; - tempVertList.list[tempVertList.count].coord[1] = coordTransformed[1]; - tempVertList.list[tempVertList.count].coord[2] = coordTransformed[2]; - tempVertList.list[tempVertList.count].coord[3] = coordTransformed[3]; - tempVertList.list[tempVertList.count].color[0] = colorRGB[0]; - tempVertList.list[tempVertList.count].color[1] = colorRGB[1]; - tempVertList.list[tempVertList.count].color[2] = colorRGB[2]; - tempVertList.list[tempVertList.count].color[3] = colorRGB[3]; - tempVertList.list[tempVertList.count].depth = 0x7FFF * coordTransformed[2]; + VERT &vert = tempVertList.list[tempVertList.count]; + vert.texcoord[0] = last_s; + vert.texcoord[1] = last_t; + vert.coord[0] = coordTransformed[0]; + vert.coord[1] = coordTransformed[1]; + vert.coord[2] = coordTransformed[2]; + vert.coord[3] = coordTransformed[3]; + vert.color[0] = colorRGB[0]; + vert.color[1] = colorRGB[1]; + vert.color[2] = colorRGB[2]; + vert.color[3] = colorRGB[3]; + vert.depth = 0x7FFF * coordTransformed[2]; tempVertList.count++; //possibly complete a polygon @@ -653,35 +641,34 @@ int gfx3d_GetNumVertex() return 0; } -static void InstallPolygonAttrib(unsigned long val) +static void gfx3d_glPolygonAttrib_cache() { // Light enable/disable - lightMask = (val&0xF); + lightMask = (polyAttr&0xF); // texture environment - //envMode = texEnv[(val&0x30)>>4]; - envMode = (val&0x30)>>4; + envMode = (polyAttr&0x30)>>4; //// overwrite depth on alpha pass - //alphaDepthWrite = BIT11(val); + //alphaDepthWrite = BIT11(polyAttr); //// depth test function - //depthFuncMode = depthFunc[BIT14(val)]; + //depthFuncMode = depthFunc[BIT14(polyAttr)]; //// back face culling - //cullingMask = (val&0xC0); + cullingMask = (polyAttr>>6)&3; // Alpha value, actually not well handled, 0 should be wireframe - colorRGB[3] = colorAlpha = material_5bit_to_31bit[((val>>16)&0x1F)]; + colorRGB[3] = colorAlpha = ((polyAttr>>16)&0x1F); //// polyID - //polyID = (val>>24)&0x1F; + //polyID = (polyAttr>>24)&0x1F; } void gfx3d_glPolygonAttrib (unsigned long val) { polyAttr = val; - InstallPolygonAttrib(polyAttr); + gfx3d_glPolygonAttrib_cache(); } /* @@ -698,21 +685,11 @@ void gfx3d_glMaterial0(unsigned long val) dsDiffuse = val&0xFFFF; dsAmbient = val>>16; - diffuse[0] = material_5bit_to_31bit[(val)&0x1F]; - diffuse[1] = material_5bit_to_31bit[(val>>5)&0x1F]; - diffuse[2] = material_5bit_to_31bit[(val>>10)&0x1F]; - diffuse[3] = 0x7fffffff; - - ambient[0] = material_5bit_to_31bit[(val>>16)&0x1F]; - ambient[1] = material_5bit_to_31bit[(val>>21)&0x1F]; - ambient[2] = material_5bit_to_31bit[(val>>26)&0x1F]; - ambient[3] = 0x7fffffff; - if (BIT15(val)) { - colorRGB[0] = diffuse[0]; - colorRGB[1] = diffuse[1]; - colorRGB[2] = diffuse[2]; + colorRGB[0] = (val)&0x1F; + colorRGB[1] = (val>>5)&0x1F; + colorRGB[2] = (val>>10)&0x1F; } } @@ -720,16 +697,6 @@ void gfx3d_glMaterial1(unsigned long val) { dsSpecular = val&0xFFFF; dsEmission = val>>16; - - specular[0] = material_5bit_to_31bit[(val)&0x1F]; - specular[1] = material_5bit_to_31bit[(val>>5)&0x1F]; - specular[2] = material_5bit_to_31bit[(val>>10)&0x1F]; - specular[3] = 0x7fffffff; - - emission[0] = material_5bit_to_31bit[(val>>16)&0x1F]; - emission[1] = material_5bit_to_31bit[(val>>21)&0x1F]; - emission[2] = material_5bit_to_31bit[(val>>26)&0x1F]; - emission[3] = 0x7fffffff; } void gfx3d_glShininess (unsigned long val) @@ -745,11 +712,14 @@ void gfx3d_UpdateToonTable(void* toonTable) gfx3d.rgbToonTable[i] = RGB15TO32(u16toonTable[i],255); } - +static void gfx3d_glTexImage_cache() +{ + texCoordinateTransform = (textureFormat>>30); +} void gfx3d_glTexImage(unsigned long val) { textureFormat = val; - texCoordinateTransform = (val>>30); + gfx3d_glTexImage_cache(); } void gfx3d_glTexPalette(unsigned long val) @@ -837,13 +807,13 @@ void gfx3d_glNormal(unsigned long v) continue; { - u8 lightColor[3] = { - (g_lightInfo[i].color)&0x1F, - (g_lightInfo[i].color>>5)&0x1F, - (g_lightInfo[i].color>>10)&0x1F }; + u8 _lightColor[3] = { + (lightColor[i])&0x1F, + (lightColor[i]>>5)&0x1F, + (lightColor[i]>>10)&0x1F }; - float dot = Vector3Dot(g_lightInfo[i].floatDirection,normal); - float diffuseComponent = max(0,dot); + float dot = Vector3Dot(cacheLightDirection[i],normal); + float diffuseComponent = std::max(0.f,dot); float specularComponent; //a specular formula which I couldnt get working @@ -863,28 +833,28 @@ void gfx3d_glNormal(unsigned long v) //a specular formula which seems to work float temp[4]; - float diff = Vector3Dot(normal,g_lightInfo[i].floatDirection); + float diff = Vector3Dot(normal,cacheLightDirection[i]); Vector3Copy(temp,normal); Vector3Scale(temp,-2*diff); - Vector3Add(temp,g_lightInfo[i].floatDirection); + Vector3Add(temp,cacheLightDirection[i]); Vector3Scale(temp,-1); - specularComponent = max(0,Vector3Dot(lineOfSight,temp)); + specularComponent = std::max(0.f,Vector3Dot(lineOfSight,temp)); //if the game isnt producing unit normals, then we can accidentally out of range components. so lets saturate them here //so we can at least keep for crashing. we're not sure what the hardware does in this case, but the game shouldnt be doing this. - specularComponent = max(0,min(1,specularComponent)); - diffuseComponent = max(0,min(1,diffuseComponent)); + specularComponent = std::max(0.f,std::min(1.f,specularComponent)); + diffuseComponent = std::max(0.f,std::min(1.f,diffuseComponent)); for(c=0;c<3;c++) { - vertexColor[c] += (diffuseComponent*lightColor[c]*diffuse[c])/31; - vertexColor[c] += (specularComponent*lightColor[c]*specular[c])/31; - vertexColor[c] += ((float)lightColor[c]*ambient[c])/31; + vertexColor[c] += (diffuseComponent*_lightColor[c]*diffuse[c])/31; + vertexColor[c] += (specularComponent*_lightColor[c]*specular[c])/31; + vertexColor[c] += ((float)_lightColor[c]*ambient[c])/31; } } } for(c=0;c<3;c++) - colorRGB[c] = material_5bit_to_31bit[min(31,vertexColor[c])]; + colorRGB[c] = std::min(31,vertexColor[c]); } } @@ -905,6 +875,16 @@ signed long gfx3d_GetDirectionalMatrix (unsigned int index) return (signed long)(mtxCurrent[2][(index)*(1<<12)]); } +void gfx3d_glLightDirection_cache(int index) +{ + u32 v = lightDirection[index]; + + // Convert format into floating point value + cacheLightDirection[index][0] = -normalTable[v&1023]; + cacheLightDirection[index][1] = -normalTable[(v>>10)&1023]; + cacheLightDirection[index][2] = -normalTable[(v>>20)&1023]; + cacheLightDirection[index][3] = 0; +} /* 0-9 Directional Vector's X component (1bit sign + 9bit fractional part) @@ -912,30 +892,18 @@ signed long gfx3d_GetDirectionalMatrix (unsigned int index) 20-29 Directional Vector's Z component (1bit sign + 9bit fractional part) 30-31 Light Number (0..3) */ -void gfx3d_glLightDirection (unsigned long v) +void gfx3d_glLightDirection (u32 v) { - int index = v>>30; - float direction[4]; + int index = v>>30; - // Convert format into floating point value - g_lightInfo[index].floatDirection[0] = -normalTable[v&1023]; - g_lightInfo[index].floatDirection[1] = -normalTable[(v>>10)&1023]; - g_lightInfo[index].floatDirection[2] = -normalTable[(v>>20)&1023]; - g_lightInfo[index].floatDirection[3] = 0; - - // Keep information for fightDirection function - g_lightInfo[index].direction = v; + lightDirection[index] = v; + gfx3d_glLightDirection_cache(index); } void gfx3d_glLightColor (unsigned long v) { - int lightColor[4] = { ((v) &0x1F)<<26, - ((v>> 5)&0x1F)<<26, - ((v>>10)&0x1F)<<26, - 0x7fffffff}; int index = v>>30; - - g_lightInfo[index].color = v; + lightColor[index] = v; } void gfx3d_glAlphaFunc(unsigned long v) @@ -1436,34 +1404,42 @@ void gfx3d_VBlankSignal() gpu3D->NDS_3D_Render(); } -void gfx3d_Control(unsigned long v) +void gfx3d_Control_cache() { - if(v&1) gfx3d.enableTexturing = true; - else gfx3d.enableTexturing = false; + u32 v = control; + + if(v&1) gfx3d.enableTexturing = TRUE; + else gfx3d.enableTexturing = FALSE; if((v>>1)&1) gfx3d.shading = GFX3D::HIGHLIGHT; else gfx3d.shading = GFX3D::TOON; - if((v>>2)&1) gfx3d.enableAlphaTest = true; - else gfx3d.enableAlphaTest = false; + if((v>>2)&1) gfx3d.enableAlphaTest = TRUE; + else gfx3d.enableAlphaTest = FALSE; - if((v>>3)&1) gfx3d.enableAlphaBlending = true; - else gfx3d.enableAlphaBlending = false; + if((v>>3)&1) gfx3d.enableAlphaBlending = TRUE; + else gfx3d.enableAlphaBlending = FALSE; - if((v>>4)&1) gfx3d.enableAntialiasing = true; - else gfx3d.enableAntialiasing = false; + if((v>>4)&1) gfx3d.enableAntialiasing = TRUE; + else gfx3d.enableAntialiasing = FALSE; - if((v>>5)&1) gfx3d.enableEdgeMarking = true; - else gfx3d.enableEdgeMarking = false; + if((v>>5)&1) gfx3d.enableEdgeMarking = TRUE; + else gfx3d.enableEdgeMarking = FALSE; //other junk - if (v&(1<<14)) { LOG("Enabled BITMAP background mode\n"); } } +void gfx3d_Control(u32 v) +{ + control = v; + gfx3d_Control_cache(); + +} + //-------------- //other misc stuff void gfx3d_glGetMatrix(unsigned int mode, unsigned int index, float* dest) @@ -1481,15 +1457,115 @@ void gfx3d_glGetMatrix(unsigned int mode, unsigned int index, float* dest) void gfx3d_glGetLightDirection(unsigned int index, unsigned int* dest) { - *dest = g_lightInfo[index].direction; + *dest = lightDirection[index]; } void gfx3d_glGetLightColor(unsigned int index, unsigned int* dest) { - *dest = g_lightInfo[index].color; + *dest = lightColor[index]; } //http://www.opengl.org/documentation/specs/version1.1/glspec1.1/node17.html //talks about the state required to process verts in quadlists etc. helpful ideas. //consider building a little state structure that looks exactly like this describes + + + +SFORMAT SF_GFX3D[]={ + { &control, 4|SS_RLSB, "GCTL" }, + { &polyAttr, 4|SS_RLSB, "GPAT" }, + { &textureFormat, 4|SS_RLSB, "GTFM" }, + { &texturePalette, 4|SS_RLSB, "GTPA" }, + { &mode, 4|SS_RLSB, "GMOD" }, + { mtxTemporal, 4|SS_MULT(16), "GMTM" }, + { mtxCurrent, 4|SS_MULT(64), "GMCU" }, + { &mtxStack[0].position, 4|SS_RLSB, "GM0P" }, + { mtxStack[0].matrix, 4|SS_MULT(16), "GM1M" }, + { &mtxStack[1].position, 4|SS_RLSB, "GM1P" }, + { mtxStack[1].matrix, 4|SS_MULT(16*31), "GM1M" }, + { &mtxStack[2].position, 4|SS_RLSB, "GM2P" }, + { mtxStack[2].matrix, 4|SS_MULT(16*31), "GM2M" }, + { &mtxStack[3].position, 4|SS_RLSB, "GM3P" }, + { mtxStack[3].matrix, 4|SS_MULT(16), "GM3M" }, + { &ML4x4ind, 1, "ML4I" }, + { &ML4x3_c, 1, "ML3C" }, + { &ML4x3_l, 1, "ML3L" }, + { &MM4x4ind, 1, "MM4I" }, + { &MM4x3_c, 1, "MM3C" }, + { &MM4x3_l, 1, "MM3L" }, + { &MM3x3_c, 1, "MMxC" }, + { &MM3x3_l, 1, "MMxL" }, + { coord, 4|SS_MULT(4), "GCOR" }, + { &coordind, 1, "GCOI" }, + { &vtxFormat, 4|SS_RLSB, "GCOI" }, + { trans, 4|SS_MULT(4), "GTRN" }, + { &transind, 1, "GTRI" }, + { scale, 4|SS_MULT(4), "GSCA" }, + { &scaleind, 1, "GSCI" }, + { &_t, 4|SS_RLSB, "G_T_" }, + { &_s, 4|SS_RLSB, "G_S_" }, + { &last_t, 4|SS_RLSB, "GL_T" }, + { &last_s, 4|SS_RLSB, "GL_S" }, + { &clCmd, 4|SS_RLSB, "GLCM" }, + { &clInd, 4|SS_RLSB, "GLIN" }, + { &clInd2, 4|SS_RLSB, "GLI2" }, + { colorRGB, 4, "GCOL" }, + { lightColor, 4|SS_MULT(4), "GLCO" }, + { lightDirection, 4|SS_MULT(4), "GLDI" }, + { &dsDiffuse, 2|SS_RLSB, "GMDI" }, + { &dsAmbient, 2|SS_RLSB, "GMAM" }, + { &dsSpecular, 2|SS_RLSB, "GMSP" }, + { &dsEmission, 2|SS_RLSB, "GMEM" }, + { &triStripToggle, 4|SS_RLSB, "GTST" }, + { &listTwiddle, 4|SS_RLSB, "GLTW" }, + { &gfx3d.enableTexturing, 4|SS_RLSB, "GSET" }, + { &gfx3d.enableAlphaTest, 4|SS_RLSB, "GSEA" }, + { &gfx3d.enableAlphaBlending, 4|SS_RLSB, "GSEB" }, + { &gfx3d.enableAntialiasing, 4|SS_RLSB, "GSEX" }, + { &gfx3d.enableEdgeMarking, 4|SS_RLSB, "GSEE" }, + { &gfx3d.shading, 4|SS_RLSB, "GSSH" }, + { &gfx3d.wbuffer, 4|SS_RLSB, "GSWB" }, + { &gfx3d.sortmode, 4|SS_RLSB, "GSSM" }, + { &gfx3d.alphaTestRef, 4|SS_RLSB, "GSAR" }, + { &gfx3d.viewport.x, 4|SS_RLSB, "GSVX" }, + { &gfx3d.viewport.y, 4|SS_RLSB, "GSVY" }, + { &gfx3d.viewport.width, 4|SS_RLSB, "GSVW" }, + { &gfx3d.viewport.height, 4|SS_RLSB, "GSVH" }, + { gfx3d.clearColor, 4|SS_MULT(4), "GSCC" }, + { &gfx3d.clearDepth , 4|SS_RLSB, "GSCD" }, + { gfx3d.fogColor, 4|SS_MULT(4), "GSFC" }, + { &gfx3d.fogOffset, 4|SS_RLSB, "GSFO" }, + { gfx3d.rgbToonTable, 4|SS_MULT(32), "GSTT" }, + { 0 } +}; + +//-------------savestate +void gfx3d_savestate(std::ostream* os) +{ + //dump the render lists + //TODO!!!! +} + +bool gfx3d_loadstate(std::istream* is) +{ + gfx3d_glPolygonAttrib_cache(); + gfx3d_glTexImage_cache(); + gfx3d_Control_cache(); + gfx3d_glLightDirection_cache(0); + gfx3d_glLightDirection_cache(1); + gfx3d_glLightDirection_cache(2); + gfx3d_glLightDirection_cache(3); + + //jiggle the lists. and also wipe them. this is clearly not the best thing to be doing. + polylist = &polylists[listTwiddle]; + vertlist = &vertlists[listTwiddle]; + polylist->count = 0; + vertlist->count = 0; + gfx3d.polylist = &polylists[listTwiddle^1]; + gfx3d.vertlist = &vertlists[listTwiddle^1]; + gfx3d.polylist->count=0; + gfx3d.vertlist->count=0; + + return true; +} \ No newline at end of file diff --git a/desmume/src/gfx3d.h b/desmume/src/gfx3d.h index f16f83312..ed070b804 100644 --- a/desmume/src/gfx3d.h +++ b/desmume/src/gfx3d.h @@ -22,6 +22,7 @@ #define _GFX3D_H_ #include "types.h" +#include void gfx3d_init(); void gfx3d_reset(); @@ -47,7 +48,7 @@ struct POLY { } }; -#define POLYLIST_SIZE 6000 +#define POLYLIST_SIZE 100000 //#define POLYLIST_SIZE 2048 struct POLYLIST { int count; @@ -57,11 +58,11 @@ struct POLYLIST { struct VERT { float coord[4]; float texcoord[2]; - int color[4]; + u8 color[4]; u32 depth; }; -#define VERTLIST_SIZE 30000 +#define VERTLIST_SIZE 400000 //#define VERTLIST_SIZE 10000 struct VERTLIST { int count; @@ -84,10 +85,12 @@ struct GFX3D , clearDepth(1) { clearColor[0] = clearColor[1] = clearColor[2] = clearColor[3] = 0; + fogColor[0] = fogColor[1] = fogColor[2] = fogColor[3] = 0; + fogOffset = 0; } - bool enableTexturing, enableAlphaTest, enableAlphaBlending, enableAntialiasing, enableEdgeMarking; + BOOL enableTexturing, enableAlphaTest, enableAlphaBlending, enableAntialiasing, enableEdgeMarking; - enum { + enum : u32 { TOON, HIGHLIGHT } shading; @@ -95,7 +98,7 @@ struct GFX3D VERTLIST* vertlist; int indexlist[POLYLIST_SIZE]; - bool wbuffer, sortmode; + BOOL wbuffer, sortmode; float alphaTestRef; @@ -108,6 +111,9 @@ struct GFX3D float clearColor[4]; float clearDepth; + float fogColor[4]; + float fogOffset; + u32 rgbToonTable[32]; }; @@ -187,5 +193,9 @@ void gfx3d_glGetMatrix(unsigned int mode, unsigned int index, float* dest); void gfx3d_glGetLightDirection(unsigned int index, unsigned int* dest); void gfx3d_glGetLightColor(unsigned int index, unsigned int* dest); +struct SFORMAT; +extern SFORMAT SF_GFX3D[]; +void gfx3d_savestate(std::ostream* os); +bool gfx3d_loadstate(std::istream* is); #endif diff --git a/desmume/src/memorystream.h b/desmume/src/memorystream.h new file mode 100644 index 000000000..82b6fbdda --- /dev/null +++ b/desmume/src/memorystream.h @@ -0,0 +1,303 @@ +#ifndef _memorystream_h_ +#define _memorystream_h_ + +#include +#include +#include +#include +#include +#include + +template +class memory_streambuf: public std::streambuf { +private: + + friend class memorystream; + + //the current buffer + T* buf; + + //the current allocated capacity of the buffer + size_t capacity; + + //whether the sequence is owned by the stringbuf + bool myBuf; + + //the logical length of the buffer + size_t length; + + //the current 'write window' starting position within the buffer for writing. + size_t ww; + + //a vector that we have been told to use + std::vector* usevec; + + +public: + + memory_streambuf(int _capacity) + : buf(new T[capacity=_capacity]) + , myBuf(true) + , length(_capacity) + , ww(0) + , usevec(0) + { + sync(); + } + + + memory_streambuf() + : buf(new T[capacity = 128]) + , myBuf(true) + , length(0) + , ww(0) + , usevec(0) + { + sync(); + } + + //constructs a non-expandable streambuf around the provided buffer + memory_streambuf(T* usebuf, int buflength) + : buf(usebuf) + , myBuf(false) + , length(buflength) + , ww(0) + , usevec(0) + { + sync(); + } + + //constructs an expandable streambuf around the provided buffer + memory_streambuf(std::vector* _usevec) + : capacity(_usevec->size()) + , myBuf(false) + , length(_usevec->size()) + , ww(0) + , usevec(_usevec) + { + if(length>0) + buf = &(*_usevec)[0]; + else buf = 0; + + sync(); + } + + ~memory_streambuf() + { + //only cleanup if we own the seq + if(myBuf) delete[] buf; + } + + //the logical length of the buffer + size_t size() + { + sync(); + return length; + } + + //to avoid copying, rebuilds the provided vector and copies the streambuf contents into it + void toVector(std::vector& out) + { + out.resize(length); + memcpy(&out[0],buf,length); + } + + //maybe the compiler can avoid copying, but maybe not: returns a vector representing the current streambuf + std::vector toVector() + { + return std::vector(buf,buf+length); + } + + //if the memorystream wraps a vector, the vector will be trimmed to the correct size,. + //you probably need to use this if you are using the vector wrapper + void trim() + { + if(!usevec) return; + usevec->resize(size()); + } + + //tells the current read or write position + std::streampos tell(std::ios::openmode which) + { + if(which == std::ios::in) + return tellRead(); + else if(which == std::ios::out) + return tellWrite(); + else return -1; + } + + //tells the current read position + std::streampos tellRead() + { + return gptr()-eback(); + } + + //tells the current write position + std::streampos tellWrite() + { + return pptr()-pbase() + ww; + } + + int sync() + { + dosync(-1); + return 0; + } + + T* getbuf() + { + sync(); + return buf; + } + + //if we were provided a buffer, then calling this gives us ownership of it + void giveBuf() { + myBuf = true; + } + +private: + + void dosync(int c) + { + size_t wp = tellWrite(); + size_t rp = tellRead(); + + //if we are supposed to insert a character.. + if(c != -1) + { + buf[wp] = c; + wp++; + } + + //the length is determined by the highest character that was ever inserted + length = std::max(length,wp); + + //the write window advances to begin at the current write insertion point + ww = wp; + + //set the new write and read windows + setp(buf+ww, buf + capacity); + setg(buf, buf+rp, buf + length); + } + + void expand(size_t upto) + { + if(!myBuf && !usevec) + throw new std::runtime_error("memory_streambuf is not expandable"); + + size_t newcapacity; + if(upto == -1) + newcapacity = capacity + capacity/2 + 2; + else + newcapacity = std::max(upto,capacity); + + if(newcapacity == capacity) return; + + //if we are supposed to use the vector, then do it now + if(usevec) + { + usevec->resize(newcapacity); + capacity = usevec->size(); + buf = &(*usevec)[0]; + } + else + { + //otherwise, manage our own buffer + T* newbuf = new T[newcapacity]; + memcpy(newbuf,buf,capacity); + delete[] buf; + capacity = newcapacity; + buf = newbuf; + } + } + +protected: + + int overflow(int c) + { + expand(-1); + dosync(c); + return 1; + } + + std::streambuf::pos_type seekpos(pos_type pos, std::ios::openmode which) + { + //extend if we are seeking the write cursor + if(which & std::ios_base::out) + expand(pos); + + sync(); + + if(which & std::ios_base::in) + setg(buf, buf+pos, buf + length); + if(which & std::ios_base::out) + { + ww = pos; + setp(buf+pos, buf + capacity); + } + + return pos; + } + + pos_type seekoff(off_type off, std::ios::seekdir way, std::ios::openmode which) + { + switch(way) { + case std::ios::beg: + return seekpos(off, which); + case std::ios::cur: + return seekpos(tell(which)+off, which); + case std::ios::end: + return seekpos(length+off, which); + default: + return -1; + } + } + +}; + +//an iostream that uses the memory_streambuf to effectively act much like a c# memorystream +//please call sync() after writing data if you want to read it back +class memorystream : public std::basic_iostream > +{ +public: + memorystream() + : std::basic_iostream >(&streambuf) + {} + + memorystream(int size) + : std::basic_iostream >(&streambuf) + , streambuf(size) + {} + + memorystream(char* usebuf, int buflength) + : std::basic_iostream >(&streambuf) + , streambuf(usebuf, buflength) + {} + + memorystream(std::vector* usevec) + : std::basic_iostream >(&streambuf) + , streambuf(usevec) + {} + + //the underlying memory_streambuf + memory_streambuf streambuf; + + +public: + + size_t size() { return streambuf.size(); } + char* buf() { return streambuf.getbuf(); } + //flushes all the writing state and ensures the stream is ready for reading + void sync() { streambuf.sync(); } + //rewinds the cursors to offset 0 + void rewind() { streambuf.seekpos(0,std::ios::in | std::ios::out); } + + //if the memorystream wraps a vector, the vector will be trimmed to the correct size,. + //you probably need to use this if you are using the vector wrapper + void trim() { streambuf.trim(); } + + void giveBuf() { streambuf.giveBuf(); } +}; + + +#endif diff --git a/desmume/src/readwrite.cpp b/desmume/src/readwrite.cpp new file mode 100644 index 000000000..d566587f4 --- /dev/null +++ b/desmume/src/readwrite.cpp @@ -0,0 +1,117 @@ +#include "readwrite.h" +#include "types.h" + +///writes a little endian 16bit value to the specified file +int write16le(u16 b, FILE *fp) +{ + u8 s[2]; + s[0]=b; + s[1]=b>>8; + return((fwrite(s,1,2,fp)<2)?0:2); +} + +///writes a little endian 32bit value to the specified file +int write32le(u32 b, FILE *fp) +{ + u8 s[4]; + s[0]=b; + s[1]=b>>8; + s[2]=b>>16; + s[3]=b>>24; + return((fwrite(s,1,4,fp)<4)?0:4); +} + +int write32le(u32 b, std::ostream* os) +{ + u8 s[4]; + s[0]=b; + s[1]=b>>8; + s[2]=b>>16; + s[3]=b>>24; + os->write((char*)&s,4); + return 4; +} + +int write64le(u64 b, std::ostream* os) +{ + u8 s[8]; + s[0]=b; + s[1]=b>>8; + s[2]=b>>16; + s[3]=b>>24; + s[4]=b>>32; + s[5]=b>>40; + s[6]=b>>48; + s[7]=b>>56; + os->write((char*)&s,8); + return 8; +} + + +///reads a little endian 32bit value from the specified file +int read32le(u32 *Bufo, FILE *fp) +{ + u32 buf; + if(fread(&buf,1,4,fp)<4) + return 0; +#ifdef LOCAL_LE + *(u32*)Bufo=buf; +#else + *(u32*)Bufo=((buf&0xFF)<<24)|((buf&0xFF00)<<8)|((buf&0xFF0000)>>8)|((buf&0xFF000000)>>24); +#endif + return 1; +} + +int read16le(u16 *Bufo, std::istream *is) +{ + u16 buf; + if(is->read((char*)&buf,2).gcount() != 2) + return 0; +#ifdef LOCAL_LE + *Bufo=buf; +#else + *Bufo = LE_TO_LOCAL_16(buf); +#endif + return 1; +} + +///reads a little endian 64bit value from the specified file +int read64le(u64 *Bufo, std::istream *is) +{ + u64 buf; + if(is->read((char*)&buf,8).gcount() != 8) + return 0; +#ifdef LOCAL_LE + *Bufo=buf; +#else + *Bufo = LE_TO_LOCAL_64(buf); +#endif + return 1; +} + + +int read32le(u32 *Bufo, std::istream *is) +{ + u32 buf; + if(is->read((char*)&buf,4).gcount() != 4) + return 0; +#ifdef LOCAL_LE + *(u32*)Bufo=buf; +#else + *(u32*)Bufo=((buf&0xFF)<<24)|((buf&0xFF00)<<8)|((buf&0xFF0000)>>8)|((buf&0xFF000000)>>24); +#endif + return 1; +} + +///reads a little endian 16bit value from the specified file +int read16le(char *d, FILE *fp) +{ +#ifdef LOCAL_LE + return((fread(d,1,2,fp)<2)?0:2); +#else + int ret; + ret=fread(d+1,1,1,fp); + ret+=fread(d,1,1,fp); + return ret<2?0:2; +#endif +} \ No newline at end of file diff --git a/desmume/src/readwrite.h b/desmume/src/readwrite.h new file mode 100644 index 000000000..2c0dd006a --- /dev/null +++ b/desmume/src/readwrite.h @@ -0,0 +1,16 @@ +#ifndef _READWRITE_H_ +#define _READWRITE_H_ + +#include "types.h" +#include + +int write16le(u16 b, FILE *fp); +int write32le(u32 b, FILE *fp); +int write32le(u32 b, std::ostream* os); +int write64le(u64 b, std::ostream* os); +int read64le(u64 *Bufo, std::istream *is); +int read32le(u32 *Bufo, std::istream *is); +int read32le(u32 *Bufo, FILE *fp); +int read16le(u16 *Bufo, std::istream *is); + +#endif diff --git a/desmume/src/saves.cpp b/desmume/src/saves.cpp index 19c82e99a..5876f00e2 100644 --- a/desmume/src/saves.cpp +++ b/desmume/src/saves.cpp @@ -29,15 +29,137 @@ #include "NDSSystem.h" #include #include +#include + +#include "memorystream.h" +#include "readwrite.h" +#include "gfx3d.h" + + +//void*v is actually a void** which will be indirected before reading +//since this isnt supported right now, it is declared in here to make things compile +#define SS_INDIRECT 0x80000000 savestates_t savestates[NB_STATES]; -#define SAVESTATE_VERSION 010 +#define SAVESTATE_VERSION 10 +static const char* magic = "DeSmuME SState\0"; #ifndef MAX_PATH #define MAX_PATH 256 #endif + +SFORMAT SF_ARM7[]={ + { &NDS_ARM7.instruction, 4|SS_RLSB, "7INS" }, + { &NDS_ARM7.instruct_adr, 4|SS_RLSB, "7INA" }, + { &NDS_ARM7.next_instruction, 4|SS_RLSB, "7INN" }, + { NDS_ARM7.R, 4|SS_MULT(16), "7REG" }, + { &NDS_ARM7.CPSR, 4|SS_RLSB, "7CPS" }, + { &NDS_ARM7.SPSR, 4|SS_RLSB, "7SPS" }, + { &NDS_ARM7.R13_usr, 4|SS_RLSB, "7DUS" }, + { &NDS_ARM7.R14_usr, 4|SS_RLSB, "7EUS" }, + { &NDS_ARM7.R13_svc, 4|SS_RLSB, "7DSV" }, + { &NDS_ARM7.R14_svc, 4|SS_RLSB, "7ESV" }, + { &NDS_ARM7.R13_abt, 4|SS_RLSB, "7DAB" }, + { &NDS_ARM7.R14_abt, 4|SS_RLSB, "7EAB" }, + { &NDS_ARM7.R13_und, 4|SS_RLSB, "7DUN" }, + { &NDS_ARM7.R14_und, 4|SS_RLSB, "7EUN" }, + { &NDS_ARM7.R13_irq, 4|SS_RLSB, "7DIR" }, + { &NDS_ARM7.R14_irq, 4|SS_RLSB, "7EIR" }, + { &NDS_ARM7.R8_fiq, 4|SS_RLSB, "78FI" }, + { &NDS_ARM7.R9_fiq, 4|SS_RLSB, "79FI" }, + { &NDS_ARM7.R10_fiq, 4|SS_RLSB, "7AFI" }, + { &NDS_ARM7.R11_fiq, 4|SS_RLSB, "7BFI" }, + { &NDS_ARM7.R12_fiq, 4|SS_RLSB, "7CFI" }, + { &NDS_ARM7.R13_fiq, 4|SS_RLSB, "7DFI" }, + { &NDS_ARM7.R14_fiq, 4|SS_RLSB, "7EFI" }, + { &NDS_ARM7.SPSR_svc, 4|SS_RLSB, "7SVC" }, + { &NDS_ARM7.SPSR_abt, 4|SS_RLSB, "7ABT" }, + { &NDS_ARM7.SPSR_und, 4|SS_RLSB, "7UND" }, + { &NDS_ARM7.SPSR_irq, 4|SS_RLSB, "7IRQ" }, + { &NDS_ARM7.SPSR_fiq, 4|SS_RLSB, "7FIQ" }, + { &NDS_ARM7.intVector, 4|SS_RLSB, "7int" }, + { &NDS_ARM7.LDTBit, 1, "7LDT" }, + { &NDS_ARM7.waitIRQ, 4|SS_RLSB, "7Wai" }, + { &NDS_ARM7.wIRQ, 4|SS_RLSB, "7wIR" }, + { &NDS_ARM7.wirq, 4|SS_RLSB, "7wir" }, + { 0 } +}; + +SFORMAT SF_ARM9[]={ + { &NDS_ARM9.instruction, 4|SS_RLSB, "9INS" }, + { &NDS_ARM9.instruct_adr, 4|SS_RLSB, "9INA" }, + { &NDS_ARM9.next_instruction, 4|SS_RLSB, "9INN" }, + { NDS_ARM9.R, 4|SS_MULT(16), "9REG" }, + { &NDS_ARM9.CPSR, 4|SS_RLSB, "9CPS" }, + { &NDS_ARM9.SPSR, 4|SS_RLSB, "9SPS" }, + { &NDS_ARM9.R13_usr, 4|SS_RLSB, "9DUS" }, + { &NDS_ARM9.R14_usr, 4|SS_RLSB, "9EUS" }, + { &NDS_ARM9.R13_svc, 4|SS_RLSB, "9DSV" }, + { &NDS_ARM9.R14_svc, 4|SS_RLSB, "9ESV" }, + { &NDS_ARM9.R13_abt, 4|SS_RLSB, "9DAB" }, + { &NDS_ARM9.R14_abt, 4|SS_RLSB, "9EAB" }, + { &NDS_ARM9.R13_und, 4|SS_RLSB, "9DUN" }, + { &NDS_ARM9.R14_und, 4|SS_RLSB, "9EUN" }, + { &NDS_ARM9.R13_irq, 4|SS_RLSB, "9DIR" }, + { &NDS_ARM9.R14_irq, 4|SS_RLSB, "9EIR" }, + { &NDS_ARM9.R8_fiq, 4|SS_RLSB, "98FI" }, + { &NDS_ARM9.R9_fiq, 4|SS_RLSB, "99FI" }, + { &NDS_ARM9.R10_fiq, 4|SS_RLSB, "9AFI" }, + { &NDS_ARM9.R11_fiq, 4|SS_RLSB, "9BFI" }, + { &NDS_ARM9.R12_fiq, 4|SS_RLSB, "9CFI" }, + { &NDS_ARM9.R13_fiq, 4|SS_RLSB, "9DFI" }, + { &NDS_ARM9.R14_fiq, 4|SS_RLSB, "9EFI" }, + { &NDS_ARM9.SPSR_svc, 4|SS_RLSB, "9SVC" }, + { &NDS_ARM9.SPSR_abt, 4|SS_RLSB, "9ABT" }, + { &NDS_ARM9.SPSR_und, 4|SS_RLSB, "9UND" }, + { &NDS_ARM9.SPSR_irq, 4|SS_RLSB, "9IRQ" }, + { &NDS_ARM9.SPSR_fiq, 4|SS_RLSB, "9FIQ" }, + { &NDS_ARM9.intVector, 4|SS_RLSB, "9int" }, + { &NDS_ARM9.LDTBit, 1, "9LDT" }, + { &NDS_ARM9.waitIRQ, 4|SS_RLSB, "9Wai" }, + { &NDS_ARM9.wIRQ, 4|SS_RLSB, "9wIR" }, + { &NDS_ARM9.wirq, 4|SS_RLSB, "9wir" }, + { 0 } +}; + +SFORMAT SF_MEM[]={ + { ARM9Mem.ARM9_ITCM, 0x8000, "ITCM" }, + { ARM9Mem.ARM9_DTCM, 0x4000, "DTCM" }, + { ARM9Mem.MAIN_MEM, 0x400000, "WRAM" }, + { ARM9Mem.ARM9_REG, 0x10000, "9REG" }, + { ARM9Mem.ARM9_VMEM, 0x800, "VMEM" }, + { ARM9Mem.ARM9_OAM, 0x800, "OAMS" }, + { ARM9Mem.ARM9_ABG, 0x80000, "ABGM" }, + { ARM9Mem.ARM9_BBG, 0x20000, "BBGM" }, + { ARM9Mem.ARM9_AOBJ, 0x40000, "AOBJ" }, + { ARM9Mem.ARM9_BOBJ, 0x20000, "BOBJ" }, + { ARM9Mem.ARM9_LCD, 0xA4000, "LCDM" }, + { MMU.ARM7_ERAM, 0x10000, "ERAM" }, + { MMU.ARM7_REG, 0x10000, "7REG" }, + { MMU.ARM7_WIRAM, 0x10000, "WIRA" }, + { MMU.SWIRAM, 0x8000, "SWIR" }, + { MMU.CART_RAM, SRAM_SIZE, "SRAM" }, + { 0 } +}; + +SFORMAT SF_NDS[]={ + { &nds.ARM9Cycle, 4|SS_RLSB, "_9CY" }, + { &nds.ARM7Cycle, 4|SS_RLSB, "_7CY" }, + { &nds.cycles, 4|SS_RLSB, "_CYC" }, + { nds.timerCycle, 4|SS_MULT(8), "_TCY" }, + { nds.timerOver, 4|SS_MULT(8), "_TOV" }, + { &nds.nextHBlank, 4|SS_RLSB, "_NHB" }, + { &nds.VCount, 4|SS_RLSB, "_VCT" }, + { &nds.old, 4|SS_RLSB, "_OLD" }, + { &nds.diff, 4|SS_RLSB, "_DIF" }, + { &nds.lignerendu, 4|SS_RLSB, "_LIG" }, + { &nds.touchX, 2|SS_RLSB, "_TPX" }, + { &nds.touchY, 2|SS_RLSB, "_TPY" }, + { 0 } +}; + /* Format time and convert to string */ char * format_time(time_t cal_time) { @@ -154,262 +276,319 @@ int sram_save (const char *file_name) { } -int savestate_load (const char *file_name) { +static SFORMAT *CheckS(SFORMAT *sf, u32 tsize, char *desc) +{ + while(sf->v) + { + if(sf->s==~0) // Link to another SFORMAT structure. + { + SFORMAT *tmp; + if((tmp= CheckS((SFORMAT *)sf->v, tsize, desc) )) + return(tmp); + sf++; + continue; + } + if(!memcmp(desc,sf->desc,4)) + { + if(tsize!=(sf->s)) + return(0); + return(sf); + } + sf++; + } + return(0); +} + + +static bool ReadStateChunk(std::istream* is, SFORMAT *sf, int size) +{ + SFORMAT *tmp; + int temp = is->tellg(); + + while(is->tellg()read(toa,4); + if(is->fail()) + return false; + + read32le(&tsize,is); + + if((tmp=CheckS(sf,tsize,toa))) + { + int count = SS_UNMULT(tsize); + int size = tsize & ~SS_FLAGS; + bool rlsb = (count!=0); + + if(count == 0) count=1; + + for(int i=0;is&SS_INDIRECT) + is->read(*(char **)tmp->v,size); + else + is->read((char *)tmp->v + i*size,size); + + #ifndef LOCAL_LE + if(rlsb) + FlipByteOrder((u8*)tmp->v + i*size,size); + #endif + } + } + else + is->seekg(tsize,std::ios::cur); + } // while(...) + return true; +} + + + +static int SubWrite(std::ostream* os, SFORMAT *sf) +{ + uint32 acc=0; + + while(sf->v) + { + if(sf->s==~0) //Link to another struct + { + uint32 tmp; + + if(!(tmp=SubWrite(os,(SFORMAT *)sf->v))) + return(0); + acc+=tmp; + sf++; + continue; + } + + int count = SS_UNMULT(sf->s); + int size = sf->s & ~SS_FLAGS; + bool rlsb = (count!=0); + + acc+=8; //Description + size + + if(count==0) count=1; + + acc += count * size; + + if(os) //Are we writing or calculating the size of this block? + { + os->write(sf->desc,4); + write32le(sf->s,os); + + for(int i=0;iv,sf->s&(~SS_FLAGS)); + #endif + + if(sf->s&SS_INDIRECT) + os->write(*(char **)sf->v,size); + else + os->write((char*)sf->v + i*size,size); + + //Now restore the original byte order. + #ifndef LOCAL_LE + if(rlsb) + FlipByteOrder(sf->v,sf->s&(~SS_FLAGS)); + #endif + + } + } + sf++; + } + + return(acc); +} + +static int savestate_WriteChunk(std::ostream* os, int type, SFORMAT *sf) +{ + write32le(type,os); + if(!sf) return 4; + int bsize = SubWrite((std::ostream*)0,sf); + write32le(bsize,os); + FILE* outf; + + if(!SubWrite(os,sf)) + { + return 8; + } + return (bsize+8); +} + +static void savestate_WriteChunk(std::ostream* os, int type, void (*saveproc)(std::ostream* os)) +{ + //get the size + memorystream mstemp; + saveproc(&mstemp); + mstemp.flush(); + u32 size = mstemp.size(); + + //write the type, size, and data + write32le(type,os); + write32le(size,os); + os->write(mstemp.buf(),size); +} + +static void writechunks(std::ostream* os); + +bool savestate_save(std::ostream* outstream, int compressionLevel) +{ + //generate the savestate in memory first + memorystream ms; + std::ostream* os = (std::ostream*)&ms; + writechunks(os); + ms.flush(); + + //save the length of the file + u32 len = ms.size(); + + u32 comprlen = -1; + u8* cbuf = (u8*)ms.buf(); + #ifdef HAVE_LIBZ - - gzFile file; - char idstring[30]; - u8 version; - int i; + //compress the data + int error = Z_OK; + if(compressionLevel != Z_NO_COMPRESSION) + { + //worst case compression. + //zlib says "0.1% larger than sourceLen plus 12 bytes" + comprlen = (len>>9)+12 + len; + cbuf = new u8[comprlen]; + error = compress2(cbuf,&comprlen,(u8*)ms.buf(),len,compressionLevel); + } +#endif - file = gzopen( file_name, "rb" ); - if( file == NULL ) - return 0; + //dump the header + outstream->write(magic,16); + write32le(SAVESTATE_VERSION,outstream); + write32le(DESMUME_VERSION_NUMERIC,outstream); //desmume version + write32le(len,outstream); //uncompressed length + write32le(comprlen,outstream); //compressed length (-1 if it is not compressed) + + outstream->write((char*)cbuf,comprlen==-1?len:comprlen); + if(cbuf != (uint8*)ms.buf()) delete[] cbuf; + return error == Z_OK; +} - memset(idstring, 0, 30); - gzgets(file, idstring, 23); +bool savestate_save (const char *file_name) +{ + memorystream ms; + if(!savestate_save(&ms, Z_DEFAULT_COMPRESSION)) + return false; + ms.flush(); + FILE* file = fopen(file_name,"wb"); + if(file) + { + fwrite(ms.buf(),1,ms.size(),file); + fclose(file); + return true; + } else return false; +} - if (strncmp("DeSmuME Savestate File", idstring, 22) != 0) - { - gzclose (file); - return 0; - } +//u8 GPU_screen[4*256*192]; - version = gzgetc(file); +static void writechunks(std::ostream* os) { + savestate_WriteChunk(os,1,SF_ARM9); + savestate_WriteChunk(os,2,SF_ARM7); + savestate_WriteChunk(os,3,SF_MEM); + savestate_WriteChunk(os,4,SF_NDS); + savestate_WriteChunk(os,5,gpu_savestate); + savestate_WriteChunk(os,60,SF_GFX3D); + savestate_WriteChunk(os,61,gfx3d_savestate); + savestate_WriteChunk(os,0xFFFFFFFF,(SFORMAT*)0); +} - // Read ARM7 cpu registers - gzread(file, &NDS_ARM7.proc_ID, sizeof(u32)); - gzread(file, &NDS_ARM7.instruction, sizeof(u32)); - gzread(file, &NDS_ARM7.instruct_adr, sizeof(u32)); - gzread(file, &NDS_ARM7.next_instruction, sizeof(u32)); - gzread(file, NDS_ARM7.R, sizeof(u32) * 16); - gzread(file, &NDS_ARM7.CPSR, sizeof(Status_Reg)); - gzread(file, &NDS_ARM7.SPSR, sizeof(Status_Reg)); - gzread(file, &NDS_ARM7.R13_usr, sizeof(u32)); - gzread(file, &NDS_ARM7.R14_usr, sizeof(u32)); - gzread(file, &NDS_ARM7.R13_svc, sizeof(u32)); - gzread(file, &NDS_ARM7.R14_svc, sizeof(u32)); - gzread(file, &NDS_ARM7.R13_abt, sizeof(u32)); - gzread(file, &NDS_ARM7.R14_abt, sizeof(u32)); - gzread(file, &NDS_ARM7.R13_und, sizeof(u32)); - gzread(file, &NDS_ARM7.R14_und, sizeof(u32)); - gzread(file, &NDS_ARM7.R13_irq, sizeof(u32)); - gzread(file, &NDS_ARM7.R14_irq, sizeof(u32)); - gzread(file, &NDS_ARM7.R8_fiq, sizeof(u32)); - gzread(file, &NDS_ARM7.R9_fiq, sizeof(u32)); - gzread(file, &NDS_ARM7.R10_fiq, sizeof(u32)); - gzread(file, &NDS_ARM7.R11_fiq, sizeof(u32)); - gzread(file, &NDS_ARM7.R12_fiq, sizeof(u32)); - gzread(file, &NDS_ARM7.R13_fiq, sizeof(u32)); - gzread(file, &NDS_ARM7.R14_fiq, sizeof(u32)); - gzread(file, &NDS_ARM7.SPSR_svc, sizeof(Status_Reg)); - gzread(file, &NDS_ARM7.SPSR_abt, sizeof(Status_Reg)); - gzread(file, &NDS_ARM7.SPSR_und, sizeof(Status_Reg)); - gzread(file, &NDS_ARM7.SPSR_irq, sizeof(Status_Reg)); - gzread(file, &NDS_ARM7.SPSR_fiq, sizeof(Status_Reg)); - gzread(file, &NDS_ARM7.intVector, sizeof(u32)); - gzread(file, &NDS_ARM7.LDTBit, sizeof(u8)); - gzread(file, &NDS_ARM7.waitIRQ, sizeof(BOOL)); - gzread(file, &NDS_ARM7.wIRQ, sizeof(BOOL)); - gzread(file, &NDS_ARM7.wirq, sizeof(BOOL)); +static bool ReadStateChunks(std::istream* is, s32 totalsize) +{ + bool ret = true; + while(totalsize > 0) + { + uint32 size; + u32 t; + if(!read32le(&t,is)) { ret=false; break; } + if(t == 0xFFFFFFFF) goto done; + if(!read32le(&size,is)) { ret=false; break; } + switch(t) + { + case 1: if(!ReadStateChunk(is,SF_ARM9,size)) ret=false; break; + case 2: if(!ReadStateChunk(is,SF_ARM7,size)) ret=false; break; + case 3: if(!ReadStateChunk(is,SF_MEM,size)) ret=false; break; + case 4: if(!ReadStateChunk(is,SF_NDS,size)) ret=false; break; + case 5: if(!gpu_loadstate(is)) ret=false; break; + case 60: if(!ReadStateChunk(is,SF_GFX3D,size)) ret=false; break; + case 61: if(!gfx3d_loadstate(is)) ret=false; break; + default: + ret=false; + break; + } + if(!ret) return false; + } +done: - // Read ARM9 cpu registers - gzread(file, &NDS_ARM9.proc_ID, sizeof(u32)); - gzread(file, &NDS_ARM9.instruction, sizeof(u32)); - gzread(file, &NDS_ARM9.instruct_adr, sizeof(u32)); - gzread(file, &NDS_ARM9.next_instruction, sizeof(u32)); - gzread(file, NDS_ARM9.R, sizeof(u32) * 16); - gzread(file, &NDS_ARM9.CPSR, sizeof(Status_Reg)); - gzread(file, &NDS_ARM9.SPSR, sizeof(Status_Reg)); - gzread(file, &NDS_ARM9.R13_usr, sizeof(u32)); - gzread(file, &NDS_ARM9.R14_usr, sizeof(u32)); - gzread(file, &NDS_ARM9.R13_svc, sizeof(u32)); - gzread(file, &NDS_ARM9.R14_svc, sizeof(u32)); - gzread(file, &NDS_ARM9.R13_abt, sizeof(u32)); - gzread(file, &NDS_ARM9.R14_abt, sizeof(u32)); - gzread(file, &NDS_ARM9.R13_und, sizeof(u32)); - gzread(file, &NDS_ARM9.R14_und, sizeof(u32)); - gzread(file, &NDS_ARM9.R13_irq, sizeof(u32)); - gzread(file, &NDS_ARM9.R14_irq, sizeof(u32)); - gzread(file, &NDS_ARM9.R8_fiq, sizeof(u32)); - gzread(file, &NDS_ARM9.R9_fiq, sizeof(u32)); - gzread(file, &NDS_ARM9.R10_fiq, sizeof(u32)); - gzread(file, &NDS_ARM9.R11_fiq, sizeof(u32)); - gzread(file, &NDS_ARM9.R12_fiq, sizeof(u32)); - gzread(file, &NDS_ARM9.R13_fiq, sizeof(u32)); - gzread(file, &NDS_ARM9.R14_fiq, sizeof(u32)); - gzread(file, &NDS_ARM9.SPSR_svc, sizeof(Status_Reg)); - gzread(file, &NDS_ARM9.SPSR_abt, sizeof(Status_Reg)); - gzread(file, &NDS_ARM9.SPSR_und, sizeof(Status_Reg)); - gzread(file, &NDS_ARM9.SPSR_irq, sizeof(Status_Reg)); - gzread(file, &NDS_ARM9.SPSR_fiq, sizeof(Status_Reg)); - gzread(file, &NDS_ARM9.intVector, sizeof(u32)); - gzread(file, &NDS_ARM9.LDTBit, sizeof(u8)); - gzread(file, &NDS_ARM9.waitIRQ, sizeof(BOOL)); - gzread(file, &NDS_ARM9.wIRQ, sizeof(BOOL)); - gzread(file, &NDS_ARM9.wirq, sizeof(BOOL)); + return ret; +} - // Read in other internal variables that are important - gzread (file, &nds, sizeof(NDSSystem)); +static void loadstate() +{ + // This should regenerate the vram banks + for (int i = 0; i < 0xA; i++) + MMU_write8(ARMCPU_ARM9, 0x04000240+i, MMU_read8(ARMCPU_ARM9, 0x04000240+i)); - // Read in memory/registers specific to the ARM9 - gzread (file, ARM9Mem.ARM9_ITCM, 0x8000); - gzread (file ,ARM9Mem.ARM9_DTCM, 0x4000); - gzread (file ,ARM9Mem.ARM9_WRAM, 0x1000000); - gzread (file, ARM9Mem.MAIN_MEM, 0x400000); - gzread (file, ARM9Mem.ARM9_REG, 0x10000); - gzread (file, ARM9Mem.ARM9_VMEM, 0x800); - gzread (file, ARM9Mem.ARM9_OAM, 0x800); - gzread (file, ARM9Mem.ARM9_ABG, 0x80000); - gzread (file, ARM9Mem.ARM9_BBG, 0x20000); - gzread (file, ARM9Mem.ARM9_AOBJ, 0x40000); - gzread (file, ARM9Mem.ARM9_BOBJ, 0x20000); - gzread (file, ARM9Mem.ARM9_LCD, 0xA4000); - - // Read in memory/registers specific to the ARM7 - gzread (file, MMU.ARM7_ERAM, 0x10000); - gzread (file, MMU.ARM7_REG, 0x10000); - gzread (file, MMU.ARM7_WIRAM, 0x10000); - - // Read in shared memory - gzread (file, MMU.SWIRAM, 0x8000); - - // Internal variable states should be regenerated - - // This should regenerate the vram banks - for (i = 0; i < 0xA; i++) - MMU_write8(ARMCPU_ARM9, 0x04000240+i, MMU_read8(ARMCPU_ARM9, 0x04000240+i)); - - // This should regenerate the graphics power control register - MMU_write16(ARMCPU_ARM9, 0x04000304, MMU_read16(ARMCPU_ARM9, 0x04000304)); + // This should regenerate the graphics power control register + MMU_write16(ARMCPU_ARM9, 0x04000304, MMU_read16(ARMCPU_ARM9, 0x04000304)); // This should regenerate the graphics configuration - for (i = REG_BASE_DISPA; i<=REG_BASE_DISPA + 0x7F; i+=2) - MMU_write16(ARMCPU_ARM9, i, MMU_read16(ARMCPU_ARM9, i)); - for (i = REG_BASE_DISPB; i<=REG_BASE_DISPB + 0x7F; i+=2) - MMU_write16(ARMCPU_ARM9, i, MMU_read16(ARMCPU_ARM9, i)); - - gzclose (file); - - return 1; -#else - return 0; -#endif + for (int i = REG_BASE_DISPA; i<=REG_BASE_DISPA + 0x7F; i+=2) + MMU_write16(ARMCPU_ARM9, i, MMU_read16(ARMCPU_ARM9, i)); + for (int i = REG_BASE_DISPB; i<=REG_BASE_DISPB + 0x7F; i+=2) + MMU_write16(ARMCPU_ARM9, i, MMU_read16(ARMCPU_ARM9, i)); } -int savestate_save (const char *file_name) { -#ifdef HAVE_LIBZ - gzFile file; +bool savestate_load(std::istream* is) +{ + char header[16]; + is->read(header,16); + if(is->fail() || memcmp(header,magic,16)) + return false; - file = gzopen( file_name, "wb" ); - if( file == NULL ) - return 0; + u32 ssversion,dversion,len,comprlen; + if(!read32le(&ssversion,is)) return false; + if(!read32le(&dversion,is)) return false; + if(!read32le(&len,is)) return false; + if(!read32le(&comprlen,is)) return false; - gzputs(file, "DeSmuME Savestate File"); - gzputc(file, SAVESTATE_VERSION); + if(ssversion != SAVESTATE_VERSION) return false; - // Save ARM7 cpu registers - gzwrite(file, &NDS_ARM7.proc_ID, sizeof(u32)); - gzwrite(file, &NDS_ARM7.instruction, sizeof(u32)); - gzwrite(file, &NDS_ARM7.instruct_adr, sizeof(u32)); - gzwrite(file, &NDS_ARM7.next_instruction, sizeof(u32)); - gzwrite(file, NDS_ARM7.R, sizeof(u32) * 16); - gzwrite(file, &NDS_ARM7.CPSR, sizeof(Status_Reg)); - gzwrite(file, &NDS_ARM7.SPSR, sizeof(Status_Reg)); - gzwrite(file, &NDS_ARM7.R13_usr, sizeof(u32)); - gzwrite(file, &NDS_ARM7.R14_usr, sizeof(u32)); - gzwrite(file, &NDS_ARM7.R13_svc, sizeof(u32)); - gzwrite(file, &NDS_ARM7.R14_svc, sizeof(u32)); - gzwrite(file, &NDS_ARM7.R13_abt, sizeof(u32)); - gzwrite(file, &NDS_ARM7.R14_abt, sizeof(u32)); - gzwrite(file, &NDS_ARM7.R13_und, sizeof(u32)); - gzwrite(file, &NDS_ARM7.R14_und, sizeof(u32)); - gzwrite(file, &NDS_ARM7.R13_irq, sizeof(u32)); - gzwrite(file, &NDS_ARM7.R14_irq, sizeof(u32)); - gzwrite(file, &NDS_ARM7.R8_fiq, sizeof(u32)); - gzwrite(file, &NDS_ARM7.R9_fiq, sizeof(u32)); - gzwrite(file, &NDS_ARM7.R10_fiq, sizeof(u32)); - gzwrite(file, &NDS_ARM7.R11_fiq, sizeof(u32)); - gzwrite(file, &NDS_ARM7.R12_fiq, sizeof(u32)); - gzwrite(file, &NDS_ARM7.R13_fiq, sizeof(u32)); - gzwrite(file, &NDS_ARM7.R14_fiq, sizeof(u32)); - gzwrite(file, &NDS_ARM7.SPSR_svc, sizeof(Status_Reg)); - gzwrite(file, &NDS_ARM7.SPSR_abt, sizeof(Status_Reg)); - gzwrite(file, &NDS_ARM7.SPSR_und, sizeof(Status_Reg)); - gzwrite(file, &NDS_ARM7.SPSR_irq, sizeof(Status_Reg)); - gzwrite(file, &NDS_ARM7.SPSR_fiq, sizeof(Status_Reg)); - gzwrite(file, &NDS_ARM7.intVector, sizeof(u32)); - gzwrite(file, &NDS_ARM7.LDTBit, sizeof(u8)); - gzwrite(file, &NDS_ARM7.waitIRQ, sizeof(BOOL)); - gzwrite(file, &NDS_ARM7.wIRQ, sizeof(BOOL)); - gzwrite(file, &NDS_ARM7.wirq, sizeof(BOOL)); + std::vector buf(len); - // Save ARM9 cpu registers - gzwrite(file, &NDS_ARM9.proc_ID, sizeof(u32)); - gzwrite(file, &NDS_ARM9.instruction, sizeof(u32)); - gzwrite(file, &NDS_ARM9.instruct_adr, sizeof(u32)); - gzwrite(file, &NDS_ARM9.next_instruction, sizeof(u32)); - gzwrite(file, NDS_ARM9.R, sizeof(u32) * 16); - gzwrite(file, &NDS_ARM9.CPSR, sizeof(Status_Reg)); - gzwrite(file, &NDS_ARM9.SPSR, sizeof(Status_Reg)); - gzwrite(file, &NDS_ARM9.R13_usr, sizeof(u32)); - gzwrite(file, &NDS_ARM9.R14_usr, sizeof(u32)); - gzwrite(file, &NDS_ARM9.R13_svc, sizeof(u32)); - gzwrite(file, &NDS_ARM9.R14_svc, sizeof(u32)); - gzwrite(file, &NDS_ARM9.R13_abt, sizeof(u32)); - gzwrite(file, &NDS_ARM9.R14_abt, sizeof(u32)); - gzwrite(file, &NDS_ARM9.R13_und, sizeof(u32)); - gzwrite(file, &NDS_ARM9.R14_und, sizeof(u32)); - gzwrite(file, &NDS_ARM9.R13_irq, sizeof(u32)); - gzwrite(file, &NDS_ARM9.R14_irq, sizeof(u32)); - gzwrite(file, &NDS_ARM9.R8_fiq, sizeof(u32)); - gzwrite(file, &NDS_ARM9.R9_fiq, sizeof(u32)); - gzwrite(file, &NDS_ARM9.R10_fiq, sizeof(u32)); - gzwrite(file, &NDS_ARM9.R11_fiq, sizeof(u32)); - gzwrite(file, &NDS_ARM9.R12_fiq, sizeof(u32)); - gzwrite(file, &NDS_ARM9.R13_fiq, sizeof(u32)); - gzwrite(file, &NDS_ARM9.R14_fiq, sizeof(u32)); - gzwrite(file, &NDS_ARM9.SPSR_svc, sizeof(Status_Reg)); - gzwrite(file, &NDS_ARM9.SPSR_abt, sizeof(Status_Reg)); - gzwrite(file, &NDS_ARM9.SPSR_und, sizeof(Status_Reg)); - gzwrite(file, &NDS_ARM9.SPSR_irq, sizeof(Status_Reg)); - gzwrite(file, &NDS_ARM9.SPSR_fiq, sizeof(Status_Reg)); - gzwrite(file, &NDS_ARM9.intVector, sizeof(u32)); - gzwrite(file, &NDS_ARM9.LDTBit, sizeof(u8)); - gzwrite(file, &NDS_ARM9.waitIRQ, sizeof(BOOL)); - gzwrite(file, &NDS_ARM9.wIRQ, sizeof(BOOL)); - gzwrite(file, &NDS_ARM9.wirq, sizeof(BOOL)); + if(comprlen != 0xFFFFFFFF) { + std::vector cbuf(comprlen); + is->read(&cbuf[0],comprlen); + if(is->fail()) return false; - // Save other internal variables that are important - gzwrite (file, &nds, sizeof(NDSSystem)); + uLongf uncomprlen = len; + int error = uncompress((uint8*)&buf[0],&uncomprlen,(uint8*)&cbuf[0],comprlen); + if(error != Z_OK || uncomprlen != len) + return false; + } else { + is->read((char*)&buf[0],len); + } - // Save memory/registers specific to the ARM9 - gzwrite (file, ARM9Mem.ARM9_ITCM, 0x8000); - gzwrite (file ,ARM9Mem.ARM9_DTCM, 0x4000); - gzwrite (file ,ARM9Mem.ARM9_WRAM, 0x1000000); - gzwrite (file, ARM9Mem.MAIN_MEM, 0x400000); - gzwrite (file, ARM9Mem.ARM9_REG, 0x10000); - gzwrite (file, ARM9Mem.ARM9_VMEM, 0x800); - gzwrite (file, ARM9Mem.ARM9_OAM, 0x800); - gzwrite (file, ARM9Mem.ARM9_ABG, 0x80000); - gzwrite (file, ARM9Mem.ARM9_BBG, 0x20000); - gzwrite (file, ARM9Mem.ARM9_AOBJ, 0x40000); - gzwrite (file, ARM9Mem.ARM9_BOBJ, 0x20000); - gzwrite (file, ARM9Mem.ARM9_LCD, 0xA4000); - - // Save memory/registers specific to the ARM7 - gzwrite (file, MMU.ARM7_ERAM, 0x10000); - gzwrite (file, MMU.ARM7_REG, 0x10000); - gzwrite (file, MMU.ARM7_WIRAM, 0x10000); + memorystream mstemp(&buf); + bool x = ReadStateChunks(&mstemp,(s32)len); - // Save shared memory - gzwrite (file, MMU.SWIRAM, 0x8000); + loadstate(); - gzclose (file); - - return 1; -#else - return 0; -#endif + return x; } +bool savestate_load(const char *file_name) +{ + std::ifstream f; + f.open(file_name,std::ios_base::binary|std::ios_base::in); + if(!f) return false; + + return savestate_load(&f); +} \ No newline at end of file diff --git a/desmume/src/saves.h b/desmume/src/saves.h index e97d27f8e..7dbbc71ea 100644 --- a/desmume/src/saves.h +++ b/desmume/src/saves.h @@ -33,6 +33,35 @@ typedef struct char date[40]; } savestates_t; + +struct SFORMAT +{ + //a void* to the data or a void** to the data + void *v; + + //size, plus flags + uint32 s; + + //a string description of the element + char *desc; +}; + +//X multiple multibyte elements +#define SS_MULT(X) (X<<24) + +//indicates that the value is a multibyte integer that needs to be put in the correct byte order +//this is the same as SS_MULT(1) +#define SS_RLSB SS_MULT(1) + + + +//all flags together so that we can mask them out and get the size +#define SS_FLAGS (SS_INDIRECT|SS_MULT(127)) + +//extract the multiplier +#define SS_UNMULT(X) ((X>>24)&0x7F) + + extern savestates_t savestates[NB_STATES]; void clear_savestates(); @@ -42,8 +71,8 @@ void sram_write (u32 address, u8 value); int sram_load (const char *file_name); int sram_save (const char *file_name); -int savestate_load (const char *file_name); -int savestate_save (const char *file_name); +bool savestate_load (const char *file_name); +bool savestate_save (const char *file_name); void savestate_slot(int num); void loadstate_slot(int num); diff --git a/desmume/src/types.h b/desmume/src/types.h index 0ae3bbdd3..762e7274f 100644 --- a/desmume/src/types.h +++ b/desmume/src/types.h @@ -20,6 +20,11 @@ #ifndef TYPES_HPP #define TYPES_HPP +#define DESMUME_NAME "DeSmuME" +#define DESMUME_VERSION_STRING "0.8.0b2-interim" +#define DESMUME_VERSION_NUMERIC 80002 +#define DESMUME_NAME_AND_VERSION DESMUME_NAME " " DESMUME_VERSION_STRING " " VERSION + #ifdef _WIN32 #define strcasecmp(x,y) stricmp(x,y) #else @@ -168,13 +173,17 @@ typedef int desmume_BOOL; #ifdef LOCAL_BE /* local arch is big endian */ # define LE_TO_LOCAL_16(x) ((((x)&0xff)<<8)|(((x)>>8)&0xff)) # define LE_TO_LOCAL_32(x) ((((x)&0xff)<<24)|(((x)&0xff00)<<8)|(((x)>>8)&0xff00)|(((x)>>24)&0xff)) +# define LE_TO_LOCAL_64(x) ((((x)&0xff)<<56)|(((x)&0xff00)<<40)|(((x)&0xff0000)<<24)|(((x)&0xff000000)<<8)|(((x)>>8)&0xff000000)|(((x)>>24)&0xff00))|(((x)>>40)&0xff00))|(((x)>>56)&0xff)) # define LOCAL_TO_LE_16(x) ((((x)&0xff)<<8)|(((x)>>8)&0xff)) # define LOCAL_TO_LE_32(x) ((((x)&0xff)<<24)|(((x)&0xff00)<<8)|(((x)>>8)&0xff00)|(((x)>>24)&0xff)) +# define LOCAL_TO_LE_64(x) ((((x)&0xff)<<56)|(((x)&0xff00)<<40)|(((x)&0xff0000)<<24)|(((x)&0xff000000)<<8)|(((x)>>8)&0xff000000)|(((x)>>24)&0xff00))|(((x)>>40)&0xff00))|(((x)>>56)&0xff)) #else /* local arch is little endian */ # define LE_TO_LOCAL_16(x) (x) # define LE_TO_LOCAL_32(x) (x) +# define LE_TO_LOCAL_64(x) (x) # define LOCAL_TO_LE_16(x) (x) # define LOCAL_TO_LE_32(x) (x) +# define LOCAL_TO_LE_64(x) (x) #endif /* kilobytes and megabytes macro */ @@ -194,4 +203,24 @@ typedef enum #define __PACKED #endif +///endian-flips count bytes. count should be even and nonzero. +inline void FlipByteOrder(u8 *src, u32 count) +{ + u8 *start=src; + u8 *end=src+count-1; + + if((count&1) || !count) return; /* This shouldn't happen. */ + + while(count--) + { + u8 tmp; + + tmp=*end; + *end=*start; + *start=tmp; + end--; + start++; + } +} + #endif diff --git a/desmume/src/windows/DeSmuME_2005.vcproj b/desmume/src/windows/DeSmuME_2005.vcproj index 6ebb86b96..649a9aa92 100644 --- a/desmume/src/windows/DeSmuME_2005.vcproj +++ b/desmume/src/windows/DeSmuME_2005.vcproj @@ -54,7 +54,7 @@ EnableFiberSafeOptimizations="false" WholeProgramOptimization="false" AdditionalIncludeDirectories="..;.\zlib123;.\zziplib" - PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;VERSION=\"0.8.0b2 DEBUG\";WIN32;BETA_VERSION;SPU_INTERPOLATE;HAVE_LIBZ" + PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;VERSION=\"DEBUG\";WIN32;BETA_VERSION;SPU_INTERPOLATE;HAVE_LIBZ;NOMINMAX" ExceptionHandling="1" BufferSecurityCheck="false" EnableEnhancedInstructionSet="0" @@ -140,7 +140,7 @@ EnableFiberSafeOptimizations="true" WholeProgramOptimization="true" AdditionalIncludeDirectories="..;.\zlib123;.\zziplib" - PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;VERSION=\"0.8.0b2\";WIN32;HAVE_LIBZ;HAVE_LIBZZIP;BETA_VERSION;SPU_INTERPOLATE" + PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;VERSION=\"Release\";WIN32;HAVE_LIBZ;HAVE_LIBZZIP;BETA_VERSION;SPU_INTERPOLATE" StringPooling="true" ExceptionHandling="1" BufferSecurityCheck="false" @@ -228,9 +228,9 @@ EnableFiberSafeOptimizations="true" WholeProgramOptimization="true" AdditionalIncludeDirectories="..;.\zlib123;.\zziplib" - PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;VERSION=\"0.8.0b2 SSE2\";WIN32;HAVE_LIBZ;HAVE_LIBZZIP;SSE2;BETA_VERSION;SPU_INTERPOLATE" + PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;VERSION=\"Release SSE2\";WIN32;HAVE_LIBZ;HAVE_LIBZZIP;SSE2;BETA_VERSION;SPU_INTERPOLATE;NOMINMAX" StringPooling="true" - ExceptionHandling="0" + ExceptionHandling="1" BufferSecurityCheck="false" EnableEnhancedInstructionSet="2" FloatingPointModel="2" @@ -820,6 +820,14 @@ RelativePath=".\palView.cpp" > + + + + diff --git a/desmume/src/windows/console.cpp b/desmume/src/windows/console.cpp index acc0a0e6a..08d5c3122 100644 --- a/desmume/src/windows/console.cpp +++ b/desmume/src/windows/console.cpp @@ -25,6 +25,7 @@ #include #include #include +#include "types.h" ///////////////////////////////////////////////////////////////// Console @@ -43,7 +44,7 @@ void OpenConsole() if (hConsole) return; AllocConsole(); memset(buf,0,256); - sprintf(buf,"DeSmuME v%s OUTPUT", VERSION); + sprintf(buf,"%s OUTPUT", DESMUME_NAME_AND_VERSION); SetConsoleTitle(TEXT(buf)); csize.X = 60; csize.Y = 800; @@ -56,7 +57,7 @@ void OpenConsole() hConsole = GetStdHandle(STD_OUTPUT_HANDLE); SetConsoleCP(GetACP()); SetConsoleOutputCP(GetACP()); - printlog("DeSmuME v%s BETA\n",VERSION); + printlog("%s\n",DESMUME_NAME_AND_VERSION); printlog("- compiled: %s %s\n\n",__DATE__,__TIME__); //redirect stdio diff --git a/desmume/src/windows/disView.cpp b/desmume/src/windows/disView.cpp index 2f9d465b4..9586ebd22 100644 --- a/desmume/src/windows/disView.cpp +++ b/desmume/src/windows/disView.cpp @@ -19,6 +19,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ +#include #include #include #include "../MMU.h" @@ -619,16 +620,16 @@ LRESULT CALLBACK DisViewBoxWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lP switch LOWORD(wParam) { case SB_LINEDOWN : - win->curr_ligne = min(0x3FFFFF7*(1+win->cpu->CPSR.bits.T), win->curr_ligne+1); + win->curr_ligne = std::min(0x3FFFFF7*(1+win->cpu->CPSR.bits.T), win->curr_ligne+1); break; case SB_LINEUP : - win->curr_ligne = (u32)max(0, (s32)win->curr_ligne-1); + win->curr_ligne = (u32)std::max(0, (s32)win->curr_ligne-1); break; case SB_PAGEDOWN : - win->curr_ligne = min(0x3FFFFF7*(1+win->cpu->CPSR.bits.T), win->curr_ligne+nbligne); + win->curr_ligne = std::min(0x3FFFFF7*(1+win->cpu->CPSR.bits.T), win->curr_ligne+nbligne); break; case SB_PAGEUP : - win->curr_ligne = (u32)max(0, (s32)win->curr_ligne-nbligne); + win->curr_ligne = (u32)std::max(0, (s32)win->curr_ligne-nbligne); break; } diff --git a/desmume/src/windows/main.cpp b/desmume/src/windows/main.cpp index 2c52e56d0..56424cb26 100644 --- a/desmume/src/windows/main.cpp +++ b/desmume/src/windows/main.cpp @@ -22,6 +22,7 @@ */ #define WIN32_LEAN_AND_MEAN +#include #include #include #include @@ -533,6 +534,107 @@ int CreateDDrawBuffers() return 1; } + +void Display() +{ + int res; + memset(&ddsd, 0, sizeof(ddsd)); + ddsd.dwSize = sizeof(ddsd); + ddsd.dwFlags=DDSD_ALL; + res=IDirectDrawSurface7_Lock(lpBackSurface,NULL,&ddsd,DDLOCK_WAIT, NULL); + + if (res == DD_OK) + { + char* buffer = (char*)ddsd.lpSurface; + + int i, j, sz=256*sizeof(u32); + if (ddsd.ddpfPixelFormat.dwRGBBitCount>16) + { + u16 *tmpGPU_Screen_src=(u16*)GPU_screen; + u32 tmpGPU_screen[98304]; + for(i=0; i<98304; i++) + tmpGPU_screen[i]= (((tmpGPU_Screen_src[i]>>10)&0x1F)<<3)| + (((tmpGPU_Screen_src[i]>>5)&0x1F)<<11)| + (((tmpGPU_Screen_src[i])&0x1F)<<19); + switch (GPU_rotation) + { + case 0: + { + for (i = 0; i < 98304; i+=256) //384*256 + { + memcpy(buffer,tmpGPU_screen+i,sz); + buffer += ddsd.lPitch; + } + break; + } + case 90: + { + u32 start; + memset(buffer,0,384*ddsd.lPitch); + for (j=0; j<256; j++) + { + start=98304+j; + for (i=0; i<384; i++) + { + start-=256; + ((u32*)buffer)[i]=((u32 *)tmpGPU_screen)[start]; + } + buffer += ddsd.lPitch; + } + break; + } + case 180: + { + u32 start=98300; + for (j=0; j<384; j++) + { + for (i=0; i<256; i++, --start) + ((u32*)buffer)[i]=((u32 *)tmpGPU_screen)[start]; + buffer += ddsd.lPitch; + } + break; + } + case 270: + { + u32 start; + memset(buffer,0,384*ddsd.lPitch); + for (j=0; j<256; j++) + { + start=256-j; + for (i=0; i<384; i++) + { + ((u32*)buffer)[i]=((u32 *)tmpGPU_screen)[start]; + start+=256; + } + buffer += ddsd.lPitch; + } + break; + } + } + } + else + printlog("16bit depth color not supported"); + IDirectDrawSurface7_Unlock(lpBackSurface,(LPRECT)ddsd.lpSurface); + + if (IDirectDrawSurface7_Blt(lpPrimarySurface,&MainWindowRect,lpBackSurface,0, DDBLT_WAIT,0)==DDERR_SURFACELOST) + { + printlog("DirectDraw buffers is lost\n"); + if (IDirectDrawSurface7_Restore(lpPrimarySurface)==DD_OK) + IDirectDrawSurface7_Restore(lpBackSurface); + } + } + else + { + if (res==DDERR_SURFACELOST) + { + printlog("DirectDraw buffers is lost\n"); + if (IDirectDrawSurface7_Restore(lpPrimarySurface)==DD_OK) + IDirectDrawSurface7_Restore(lpBackSurface); + } + } +} + + DWORD WINAPI run( LPVOID lpParameter) { char txt[80]; @@ -600,101 +702,7 @@ DWORD WINAPI run( LPVOID lpParameter) if (!skipnextframe) { - int res; - memset(&ddsd, 0, sizeof(ddsd)); - ddsd.dwSize = sizeof(ddsd); - ddsd.dwFlags=DDSD_ALL; - res=IDirectDrawSurface7_Lock(lpBackSurface,NULL,&ddsd,DDLOCK_WAIT, NULL); - - if (res == DD_OK) - { - char* buffer = (char*)ddsd.lpSurface; - - int i, j, sz=256*sizeof(u32); - if (ddsd.ddpfPixelFormat.dwRGBBitCount>16) - { - u16 *tmpGPU_Screen_src=(u16*)GPU_screen; - u32 tmpGPU_screen[98304]; - for(i=0; i<98304; i++) - tmpGPU_screen[i]= (((tmpGPU_Screen_src[i]>>10)&0x1F)<<3)| - (((tmpGPU_Screen_src[i]>>5)&0x1F)<<11)| - (((tmpGPU_Screen_src[i])&0x1F)<<19); - switch (GPU_rotation) - { - case 0: - { - for (i = 0; i < 98304; i+=256) //384*256 - { - memcpy(buffer,tmpGPU_screen+i,sz); - buffer += ddsd.lPitch; - } - break; - } - case 90: - { - u32 start; - memset(buffer,0,384*ddsd.lPitch); - for (j=0; j<256; j++) - { - start=98304+j; - for (i=0; i<384; i++) - { - start-=256; - ((u32*)buffer)[i]=((u32 *)tmpGPU_screen)[start]; - } - buffer += ddsd.lPitch; - } - break; - } - case 180: - { - u32 start=98300; - for (j=0; j<384; j++) - { - for (i=0; i<256; i++, --start) - ((u32*)buffer)[i]=((u32 *)tmpGPU_screen)[start]; - buffer += ddsd.lPitch; - } - break; - } - case 270: - { - u32 start; - memset(buffer,0,384*ddsd.lPitch); - for (j=0; j<256; j++) - { - start=256-j; - for (i=0; i<384; i++) - { - ((u32*)buffer)[i]=((u32 *)tmpGPU_screen)[start]; - start+=256; - } - buffer += ddsd.lPitch; - } - break; - } - } - } - else - printlog("16bit depth color not supported"); - IDirectDrawSurface7_Unlock(lpBackSurface,(LPRECT)ddsd.lpSurface); - - if (IDirectDrawSurface7_Blt(lpPrimarySurface,&MainWindowRect,lpBackSurface,0, DDBLT_WAIT,0)==DDERR_SURFACELOST) - { - printlog("DirectDraw buffers is lost\n"); - if (IDirectDrawSurface7_Restore(lpPrimarySurface)==DD_OK) - IDirectDrawSurface7_Restore(lpBackSurface); - } - } - else - { - if (res==DDERR_SURFACELOST) - { - printlog("DirectDraw buffers is lost\n"); - if (IDirectDrawSurface7_Restore(lpPrimarySurface)==DD_OK) - IDirectDrawSurface7_Restore(lpBackSurface); - } - } + Display(); fpsframecount++; QueryPerformanceCounter((LARGE_INTEGER *)&curticks); @@ -712,8 +720,8 @@ DWORD WINAPI run( LPVOID lpParameter) int load = 0; for(int i=0;i<16;i++) load = load/8 + nds.runCycleCollector[(i+nds.idleFrameCounter)&15]*7/8; - load = min(100,max(0,(int)(load*100/1120380))); - sprintf(txt,"(%02d%%) DeSmuME v%s", load, VERSION); + load = std::min(100,std::max(0,(int)(load*100/1120380))); + sprintf(txt,"(%02d%%) %s", load, DESMUME_NAME_AND_VERSION); SetWindowText(hwnd, txt); osd->addFixed(10, 10, "%02d Fps", fps); } @@ -810,9 +818,13 @@ void StateSaveSlot(int num) void StateLoadSlot(int num) { + BOOL wasPaused = paused; NDS_Pause(); loadstate_slot(num); - NDS_UnPause(); + if(!wasPaused) + NDS_UnPause(); + else + Display(); } BOOL LoadROM(char * filename, const char *cflash_disk_image) @@ -944,7 +956,7 @@ int WINAPI WinMain (HINSTANCE hThisInstance, GPU_rotation = GetPrivateProfileInt("Video","Window Rotate", 0, IniName); ForceRatio = GetPrivateProfileInt("Video","Window Force Ratio", 1, IniName); - sprintf(text, "DeSmuME v%s", VERSION); + sprintf(text, "%s", DESMUME_NAME_AND_VERSION); init_configured_features( &my_config); if ( !fill_configured_features( &my_config, lpszArgument)) { diff --git a/desmume/src/windows/memView.cpp b/desmume/src/windows/memView.cpp index cd159cf1e..1165fedba 100644 --- a/desmume/src/windows/memView.cpp +++ b/desmume/src/windows/memView.cpp @@ -19,6 +19,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ +#include #include #include #include @@ -436,16 +437,16 @@ LRESULT CALLBACK MemViewBoxWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lP switch LOWORD(wParam) { case SB_LINEDOWN : - win->curr_ligne = min(0X0FFFFFFFF, win->curr_ligne+1); + win->curr_ligne = std::min((s32)0x0FFFFFFFF, (s32)win->curr_ligne+1); break; case SB_LINEUP : - win->curr_ligne = (u32)max(0, (s32)win->curr_ligne-1); + win->curr_ligne = (u32)std::max(0l, (s32)win->curr_ligne-1); break; case SB_PAGEDOWN : - win->curr_ligne = min(0X0FFFFFFFF, win->curr_ligne+nbligne); + win->curr_ligne = std::min((s32)0x0FFFFFFFF, (s32)win->curr_ligne+nbligne); break; case SB_PAGEUP : - win->curr_ligne = (u32)max(0, (s32)win->curr_ligne-nbligne); + win->curr_ligne = (u32)std::max(0l, (s32)win->curr_ligne-nbligne); break; }