- 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
This commit is contained in:
parent
319adfc4e0
commit
b1e4934421
|
@ -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]
|
||||
|
|
|
@ -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
|
||||
=====================
|
||||
|
||||
|
|
|
@ -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];
|
||||
|
|
|
@ -40,9 +40,11 @@
|
|||
// GRAPHICS CORE
|
||||
// GPU_ligne
|
||||
|
||||
#include <algorithm>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <assert.h>
|
||||
#include <iostream>
|
||||
#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<u16>(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<u16>(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<u16>(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();
|
||||
}
|
|
@ -32,6 +32,10 @@
|
|||
#include "FIFO.h"
|
||||
#include "MMU.h"
|
||||
#include "GPU_osd.h"
|
||||
#include <iosfwd>
|
||||
|
||||
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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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 \
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -24,6 +24,7 @@
|
|||
//so, it doesnt composite to 2d correctly.
|
||||
//(re: new super mario brothers renders the stormclouds at the beginning)
|
||||
|
||||
#include <algorithm>
|
||||
#include <math.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
@ -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;j<type;j++) {
|
||||
VERT* vert = &gfx3d.vertlist->list[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];
|
||||
|
|
|
@ -22,6 +22,7 @@
|
|||
//This handles almost all of the work of 3d rendering, leaving the renderer
|
||||
// plugin responsible only for drawing primitives.
|
||||
|
||||
#include <algorithm>
|
||||
#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;
|
||||
}
|
|
@ -22,6 +22,7 @@
|
|||
#define _GFX3D_H_
|
||||
|
||||
#include "types.h"
|
||||
#include <iosfwd>
|
||||
|
||||
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
|
||||
|
|
|
@ -0,0 +1,303 @@
|
|||
#ifndef _memorystream_h_
|
||||
#define _memorystream_h_
|
||||
|
||||
#include <iostream>
|
||||
#include <string.h>
|
||||
#include <vector>
|
||||
#include <sstream>
|
||||
#include <stdexcept>
|
||||
#include <algorithm>
|
||||
|
||||
template<typename T>
|
||||
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<T>* 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<T>* _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<T>& 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<T> toVector()
|
||||
{
|
||||
return std::vector<T>(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<char, std::char_traits<char> >
|
||||
{
|
||||
public:
|
||||
memorystream()
|
||||
: std::basic_iostream<char, std::char_traits<char> >(&streambuf)
|
||||
{}
|
||||
|
||||
memorystream(int size)
|
||||
: std::basic_iostream<char, std::char_traits<char> >(&streambuf)
|
||||
, streambuf(size)
|
||||
{}
|
||||
|
||||
memorystream(char* usebuf, int buflength)
|
||||
: std::basic_iostream<char, std::char_traits<char> >(&streambuf)
|
||||
, streambuf(usebuf, buflength)
|
||||
{}
|
||||
|
||||
memorystream(std::vector<char>* usevec)
|
||||
: std::basic_iostream<char, std::char_traits<char> >(&streambuf)
|
||||
, streambuf(usevec)
|
||||
{}
|
||||
|
||||
//the underlying memory_streambuf
|
||||
memory_streambuf<char> 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
|
|
@ -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
|
||||
}
|
|
@ -0,0 +1,16 @@
|
|||
#ifndef _READWRITE_H_
|
||||
#define _READWRITE_H_
|
||||
|
||||
#include "types.h"
|
||||
#include <iostream>
|
||||
|
||||
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
|
|
@ -29,15 +29,137 @@
|
|||
#include "NDSSystem.h"
|
||||
#include <sys/stat.h>
|
||||
#include <time.h>
|
||||
#include <fstream>
|
||||
|
||||
#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()<temp+size)
|
||||
{
|
||||
u32 tsize;
|
||||
char toa[4];
|
||||
is->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;i<count;i++) {
|
||||
|
||||
if(tmp->s&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;i<count;i++) {
|
||||
|
||||
#ifndef LOCAL_LE
|
||||
if(rlsb)
|
||||
FlipByteOrder(sf->v,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<char> 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<char> 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);
|
||||
}
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\readwrite.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\readwrite.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\render3D.cpp"
|
||||
>
|
||||
|
|
|
@ -25,6 +25,7 @@
|
|||
#include <stdio.h>
|
||||
#include <fcntl.h>
|
||||
#include <io.h>
|
||||
#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
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include <algorithm>
|
||||
#include <tchar.h>
|
||||
#include <stdio.h>
|
||||
#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<s32>(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<s32>(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<s32>(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<s32>(0, (s32)win->curr_ligne-nbligne);
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
|
@ -22,6 +22,7 @@
|
|||
*/
|
||||
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#include <algorithm>
|
||||
#include <windows.h>
|
||||
#include <shellapi.h>
|
||||
#include <Winuser.h>
|
||||
|
@ -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)) {
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include <algorithm>
|
||||
#include <windows.h>
|
||||
#include <tchar.h>
|
||||
#include <stdio.h>
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue