integrate changes from rerecording branch

This commit is contained in:
zeromus 2009-05-02 04:30:16 +00:00
parent 2c2484d77d
commit 76c0c2d245
40 changed files with 8329 additions and 3904 deletions

File diff suppressed because it is too large Load Diff

103
src/GPU.h
View File

@ -36,7 +36,7 @@
#include <iosfwd>
void gpu_savestate(std::ostream* os);
bool gpu_loadstate(std::istream* is);
bool gpu_loadstate(std::istream* is, int size);
/*******************************************************************************
this structure is for display control,
@ -402,7 +402,7 @@ void register_gl_fun(fun_gl_Begin beg,fun_gl_End end);
#define ADDRESS_STEP_8KB 0x02000
#define ADDRESS_STEP_16KB 0x04000
#define ADDRESS_STEP_32KB 0x08000
#define ADDRESS_STEP_64kB 0x10000
#define ADDRESS_STEP_64KB 0x10000
#define ADDRESS_STEP_128KB 0x20000
#define ADDRESS_STEP_256KB 0x40000
#define ADDRESS_STEP_512KB 0x80000
@ -598,12 +598,21 @@ typedef struct
extern CACHE_ALIGN u8 gpuBlendTable555[17][17][32][32];
enum BGType {
BGType_Invalid=0, BGType_Text=1, BGType_Affine=2, BGType_Large8bpp=3,
BGType_AffineExt=4, BGType_AffineExt_256x16=5, BGType_AffineExt_256x1=6, BGType_AffineExt_Direct=7
};
struct GPU
{
// some structs are becoming redundant
// some functions too (no need to recopy some vars as it is done by MMU)
REG_DISPx * dispx_st;
_BGxCNT & bgcnt(int num) { return (dispx_st)->dispx_BGxCNT[num].bits; }
_DISPCNT & dispCnt() { return dispx_st->dispx_DISPCNT.bits; }
void modeRender(int layer);
DISPCAPCNT dispCapCnt;
BOOL LayersEnable[5];
itemsForPriority_t itemsForPriority[NB_PRIORITIES];
@ -611,12 +620,14 @@ struct GPU
#define BGBmpBB BG_bmp_ram
#define BGChBB BG_tile_ram
u32 BG_bmp_large_ram[4];
u32 BG_bmp_ram[4];
u32 BG_tile_ram[4];
u32 BG_map_ram[4];
u8 BGExtPalSlot[4];
u32 BGSize[4][2];
BGType BGTypes[4];
struct MosaicColor {
u16 bg[4][256];
@ -695,6 +706,9 @@ struct GPU
bool blend1;
u8* currDst;
u16* _3dColorLine;
u8* _3dAlphaLine;
static struct MosaicLookup {
@ -721,11 +735,12 @@ struct GPU
u16 blend(u16 colA, u16 colB);
typedef void (*FinalOBJColFunct)(GPU *gpu, u32 passing, u8 *dst, u16 color, u8 alpha, u8 type, u16 x);
typedef void (*Final3DColFunct)(GPU *gpu, u32 passing, u8 *dst, u16 color, u8 alpha, u16 x);
typedef void (*Final3DColFunct)(GPU *gpu, int dstX, int srcX);
int setFinalColorBck_funcNum;
int setFinalColor3d_funcNum;
FinalOBJColFunct setFinalColorSpr;
Final3DColFunct setFinalColor3D;
//Final3DColFunct setFinalColor3D;
enum SpriteRenderMode {
SPRITE_1D, SPRITE_2D
} spriteRenderMode;
@ -735,6 +750,8 @@ struct GPU
void spriteRender(u8 * dst, u8 * dst_alpha, u8 * typeTab, u8 * prioTab);
void setFinalColorBG(u16 color, u8 x);
void setFinalColor3d(int dstX, int srcX);
FORCEINLINE void setFinalBGColorSpecialNone(u16 color, u8 x, bool blend1);
FORCEINLINE void setFinalBGColorSpecialBlend(u16 color, u8 x, bool blend1);
FORCEINLINE void setFinalBGColorSpecialIncrease(u16 color, u8 x, bool blend1);
@ -743,9 +760,22 @@ struct GPU
FORCEINLINE void setFinalBGColorSpecialBlendWnd(u16 color, u8 x, bool blend1);
FORCEINLINE void setFinalBGColorSpecialIncreaseWnd(u16 color, u8 x, bool blend1);
FORCEINLINE void setFinalBGColorSpecialDecreaseWnd(u16 color, u8 x, bool blend1);
FORCEINLINE void setFinal3DColorSpecialNone(int dstX, int srcX);
FORCEINLINE void setFinal3DColorSpecialBlend(int dstX, int srcX);
FORCEINLINE void setFinal3DColorSpecialIncrease(int dstX, int srcX);
FORCEINLINE void setFinal3DColorSpecialDecrease(int dstX, int srcX);
FORCEINLINE void setFinal3DColorSpecialNoneWnd(int dstX, int srcX);
FORCEINLINE void setFinal3DColorSpecialBlendWnd(int dstX, int srcX);
FORCEINLINE void setFinal3DColorSpecialIncreaseWnd(int dstX, int srcX);
FORCEINLINE void setFinal3DColorSpecialDecreaseWnd(int dstX, int srcX);
void __setFinalColorBck(u16 color, u8 x, bool opaque);
void setAffineStart(int layer, int xy, u32 val);
void setAffineStartWord(int layer, int xy, u16 val, int word);
u32 getAffineStart(int layer, int xy);
void refreshAffineStartRegs();
struct AffineInfo {
AffineInfo() : x(0), y(0) {}
@ -824,9 +854,7 @@ namespace GPU_EXT
void sprite1D(GPU * gpu, u16 l, u8 * dst, u8 * dst_alpha, u8 * typeTab, u8 * prioTab);
void sprite2D(GPU * gpu, u16 l, u8 * dst, u8 * dst_alpha, u8 * typeTab, u8 * prioTab);
extern const short sizeTab[4][4][2];
extern const size sprSizeTab[4][4];
extern const s8 mode2type[8][4];
typedef struct {
GPU * gpu;
@ -849,7 +877,7 @@ extern MMU_struct MMU;
#define GFXCORE_FULLSCREEN (1 << 0)
typedef struct
struct GraphicsInterface_struct
{
int id; // ID number for core(see above defines)
const char *Name; // Name of core
@ -858,7 +886,7 @@ typedef struct
void (*DeInit)(); // Deinitializes stuff related to core
void (*Resize)(int width, int height, BOOL fullscreen); // Resizes window or fullscreen
void (*OnScreenText)(char *string, ...); // For handling save state messages, etc.
} GraphicsInterface_struct;
} ;
extern GraphicsInterface_struct GFXDummy;
@ -879,43 +907,46 @@ void GPU_set_DISPCAPCNT(u32 val) ;
void GPU_ligne(NDS_Screen * screen, u16 l) ;
void GPU_setMasterBrightness (GPU *gpu, u16 val);
#define GPU_setWIN0_H(gpu, val) {gpu->WIN0H0 = val >> 8; gpu->WIN0H1 = val&0xFF; gpu->need_update_winh[0] = true; }
#define GPU_setWIN0_H0(gpu, val) { gpu->WIN0H0 = val; gpu->need_update_winh[0] = true; }
#define GPU_setWIN0_H1(gpu, val) { gpu->WIN0H1 = val; gpu->need_update_winh[0] = true; }
inline void GPU_setWIN0_H(GPU* gpu, u16 val) { gpu->WIN0H0 = val >> 8; gpu->WIN0H1 = val&0xFF; gpu->need_update_winh[0] = true; }
inline void GPU_setWIN0_H0(GPU* gpu, u8 val) { gpu->WIN0H0 = val; gpu->need_update_winh[0] = true; }
inline void GPU_setWIN0_H1(GPU* gpu, u8 val) { gpu->WIN0H1 = val; gpu->need_update_winh[0] = true; }
#define GPU_setWIN0_V(gpu, val) {gpu->WIN0V0 = val >> 8; gpu->WIN0V1 = val&0xFF;}
#define GPU_setWIN0_V0(gpu, val) gpu->WIN0V0 = val
#define GPU_setWIN0_V1(gpu, val) gpu->WIN0V1 = val
inline void GPU_setWIN0_V(GPU* gpu, u16 val) { gpu->WIN0V0 = val >> 8; gpu->WIN0V1 = val&0xFF;}
inline void GPU_setWIN0_V0(GPU* gpu, u8 val) { gpu->WIN0V0 = val; }
inline void GPU_setWIN0_V1(GPU* gpu, u8 val) { gpu->WIN0V1 = val; }
#define GPU_setWIN1_H(gpu, val) {gpu->WIN1H0 = val >> 8; gpu->WIN1H1 = val&0xFF; gpu->need_update_winh[1] = true; }
#define GPU_setWIN1_H0(gpu, val) { gpu->WIN1H0 = val; gpu->need_update_winh[1] = true; }
#define GPU_setWIN1_H1(gpu, val) { gpu->WIN1H1 = val; gpu->need_update_winh[1] = true; }
inline void GPU_setWIN1_H(GPU* gpu, u16 val) {gpu->WIN1H0 = val >> 8; gpu->WIN1H1 = val&0xFF; gpu->need_update_winh[1] = true; }
inline void GPU_setWIN1_H0(GPU* gpu, u8 val) { gpu->WIN1H0 = val; gpu->need_update_winh[1] = true; }
inline void GPU_setWIN1_H1(GPU* gpu, u8 val) { gpu->WIN1H1 = val; gpu->need_update_winh[1] = true; }
#define GPU_setWIN1_V(gpu, val) {gpu->WIN1V0 = val >> 8; gpu->WIN1V1 = val&0xFF;}
#define GPU_setWIN1_V0(gpu, val) gpu->WIN1V0 = val
#define GPU_setWIN1_V1(gpu, val) gpu->WIN1V1 = val
inline void GPU_setWIN1_V(GPU* gpu, u16 val) { gpu->WIN1V0 = val >> 8; gpu->WIN1V1 = val&0xFF; }
inline void GPU_setWIN1_V0(GPU* gpu, u8 val) { gpu->WIN1V0 = val; }
inline void GPU_setWIN1_V1(GPU* gpu, u8 val) { gpu->WIN1V1 = val; }
#define GPU_setWININ(gpu, val) {gpu->WININ0=val&0x1F;\
gpu->WININ0_SPECIAL=(val>>5)&1;\
gpu->WININ1=(val>>8)&0x1F;\
gpu->WININ1_SPECIAL=(val>>13)&1;\
}
#define GPU_setWININ0(gpu, val) {gpu->WININ0 = val&0x1F; gpu->WININ0_SPECIAL = (val>>5)&1;}
#define GPU_setWININ1(gpu, val) {gpu->WININ1 = val&0x1F; gpu->WININ1_SPECIAL = (val>>5)&1;}
inline void GPU_setWININ(GPU* gpu, u16 val) {
gpu->WININ0=val&0x1F;
gpu->WININ0_SPECIAL=(val>>5)&1;
gpu->WININ1=(val>>8)&0x1F;
gpu->WININ1_SPECIAL=(val>>13)&1;
}
#define GPU_setWINOUT16(gpu, val) { gpu->WINOUT=val&0x1F;\
gpu->WINOUT_SPECIAL=(val>>5)&1;\
gpu->WINOBJ=(val>>8)&0x1F;\
gpu->WINOBJ_SPECIAL=(val>>13)&1;\
}
#define GPU_setWINOUT(gpu, val) {gpu->WINOUT = val&0x1F; gpu->WINOUT_SPECIAL = (val>>5)&1;}
#define GPU_setWINOBJ(gpu, val) {gpu->WINOBJ = val&0x1F; gpu->WINOBJ_SPECIAL = (val>>5)&1;}
inline void GPU_setWININ0(GPU* gpu, u8 val) { gpu->WININ0 = val&0x1F; gpu->WININ0_SPECIAL = (val>>5)&1; }
inline void GPU_setWININ1(GPU* gpu, u8 val) { gpu->WININ1 = val&0x1F; gpu->WININ1_SPECIAL = (val>>5)&1; }
inline void GPU_setWINOUT16(GPU* gpu, u16 val) {
gpu->WINOUT=val&0x1F;
gpu->WINOUT_SPECIAL=(val>>5)&1;
gpu->WINOBJ=(val>>8)&0x1F;
gpu->WINOBJ_SPECIAL=(val>>13)&1;
}
inline void GPU_setWINOUT(GPU* gpu, u8 val) { gpu->WINOUT = val&0x1F; gpu->WINOUT_SPECIAL = (val>>5)&1; }
inline void GPU_setWINOBJ(GPU* gpu, u8 val) { gpu->WINOBJ = val&0x1F; gpu->WINOBJ_SPECIAL = (val>>5)&1; }
// Blending
void SetupFinalPixelBlitter (GPU *gpu);
#define GPU_setBLDCNT_LOW(gpu, val) {gpu->BLDCNT = (gpu->BLDCNT&0xFF00) | val; SetupFinalPixelBlitter (gpu);}
#define GPU_setBLDCNT_LOW(gpu, val) {gpu->BLDCNT = (gpu->BLDCNT&0xFF00) | (val); SetupFinalPixelBlitter (gpu);}
#define GPU_setBLDCNT_HIGH(gpu, val) {gpu->BLDCNT = (gpu->BLDCNT&0xFF) | (val<<8); SetupFinalPixelBlitter (gpu);}
#define GPU_setBLDCNT(gpu, val) {gpu->BLDCNT = val; SetupFinalPixelBlitter (gpu);}
#define GPU_setBLDCNT(gpu, val) {gpu->BLDCNT = (val); SetupFinalPixelBlitter (gpu);}

View File

@ -180,7 +180,11 @@ void OSDCLASS::addFixed(u16 x, u16 y, const char *fmt, ...)
if (strcmp(msg, old_msg) == 0) return;
render51.PrintString<DesmumeFont>(1,x,y,render51.MakeColor(128,0,0),msg,&screenshell);
render51.PrintString<DesmumeFont>(1,x-1,y-1,render51.MakeColor(0,0,0),msg,&screenshell);
render51.PrintString<DesmumeFont>(1,x+1,y-1,render51.MakeColor(0,0,0),msg,&screenshell);
render51.PrintString<DesmumeFont>(1,x-1,y+1,render51.MakeColor(0,0,0),msg,&screenshell);
render51.PrintString<DesmumeFont>(1,x+1,y+1,render51.MakeColor(0,0,0),msg,&screenshell);
render51.PrintString<DesmumeFont>(1,x,y,render51.MakeColor(255,255,255),msg,&screenshell);
needUpdate = true;
}

View File

@ -46,6 +46,7 @@
#include "mc.h"
#include "addons.h"
#include "mic.h"
#include "movie.h"
#ifdef DO_ASSERT_UNALIGNED
#define ASSERT_UNALIGNED(x) assert(x)

View File

@ -40,6 +40,7 @@
#include "bios.h"
#include "debug.h"
#include "cheatSystem.h"
#include "movie.h"
#ifdef _WIN32
#include "./windows/disView.h"
@ -844,6 +845,23 @@ int NDS_LoadROM( const char *filename, int bmtype, u32 bmsize,
return ret;
}
void MovieSRAM(int bmtype, u32 bmsize) {
char buf[MAX_PATH];
memset(buf, 0, MAX_PATH);
strcpy(buf, pathFilenameToROMwithoutExt);
strcat(buf, ".sav"); // DeSmuME memory card :)
if(movieMode != MOVIEMODE_INACTIVE) {
strcat(buf, "movie");
}
mc_realloc(&MMU.bupmem, bmtype, bmsize);
mc_load_file(&MMU.bupmem, buf);
}
void NDS_FreeROM(void)
{
if (MMU.CART_ROM != MMU.UNUSED_RAM)
@ -869,6 +887,8 @@ void NDS_Reset( void)
lastLag=0;
TotalLagFrames=0;
currFrameCounter=0;
MMU_clearMem();
//ARM7 BIOS IRQ HANDLER
@ -1564,10 +1584,9 @@ u32 NDS_exec(s32 nb)
{
int i, j;
//TODO - since NDS_exec is not necessarily called one frame at a time, this could be wrong.
LagFrameFlag=1;
nb = 560190<<1;
nb += nds.cycles;//(nds.cycles>>26)<<26;
LagFrameFlag=1;
//increase this to execute more instructions in each batch (reducing overhead)
//the value of 4 seems to optimize speed.. do lower values increase precision?
@ -2392,23 +2411,30 @@ static std::string MakeInputDisplayString(u16 pad, u16 padExt) {
return s;
}
void ClearAutoHold(void) {
for (int i=0; i < 10; i++) {
AutoHold.hold(i)=false;
}
}
void NDS_setPadFromMovie(u16 pad)
{
#define FIX(b,n) (((pad>>n)&1)!=0)
NDS_setPad(
FIX(pad,0),
FIX(pad,1),
FIX(pad,12), //R
FIX(pad,11), //L
FIX(pad,10), //D
FIX(pad,9), //U
FIX(pad,7), //Select
FIX(pad,8), //Start
FIX(pad,6), //B
FIX(pad,5), //A
FIX(pad,4), //Y
FIX(pad,3), //X
FIX(pad,2),
FIX(pad,3),
FIX(pad,4),
FIX(pad,5),
FIX(pad,6),
FIX(pad,7),
FIX(pad,8),
FIX(pad,9),
FIX(pad,10),
FIX(pad,11),
FIX(pad,12),
FIX(pad,1),
FIX(pad,0),
FIX(pad,13)
);
#undef FIX
@ -2417,12 +2443,12 @@ void NDS_setPadFromMovie(u16 pad)
turbo Turbo;
turbotime TurboTime;
static void SetTurbo(bool (&pad) [10]) {
static void SetTurbo(bool (&pad) [12]) {
bool turbo[4] = {true, false, true, false};
bool currentbutton;
for (int i=0; i < 10; i++) {
for (int i=0; i < 12; i++) {
currentbutton=Turbo.button(i);
if(currentbutton) {
@ -2434,7 +2460,7 @@ static void SetTurbo(bool (&pad) [10]) {
else
TurboTime.time(i)=0; //reset timer if the button isn't pressed
}
for (int i=0; i<10; i++)
for (int i=0; i<12; i++)
TurboTime.time(i)++;
}
@ -2443,7 +2469,7 @@ autohold AutoHold;
void NDS_setPad(bool R,bool L,bool D,bool U,bool T,bool S,bool B,bool A,bool Y,bool X,bool W,bool E,bool G, bool F)
{
bool padarray[10] = {R, L, D, U, T, S, B, A, Y, X};
bool padarray[12] = {R, L, D, U, T, S, B, A, Y, X, W, E};
SetTurbo(padarray);
@ -2457,6 +2483,8 @@ void NDS_setPad(bool R,bool L,bool D,bool U,bool T,bool S,bool B,bool A,bool Y,b
A=padarray[7];
Y=padarray[8];
X=padarray[9];
W=padarray[10];
E=padarray[11];
if(AutoHold.Right) R=!padarray[0];
if(AutoHold.Left) L=!padarray[1];
@ -2555,20 +2583,18 @@ void NDS_setPad(bool R,bool L,bool D,bool U,bool T,bool S,bool B,bool A,bool Y,b
nds.pad =
(FIX(r)<<0)|
(FIX(l)<<1)|
(FIX(d)<<2)|
(FIX(u)<<3)|
(FIX(t)<<4)|
(FIX(s)<<5)|
(FIX(r)<<12)|
(FIX(l)<<11)|
(FIX(d)<<10)|
(FIX(u)<<9)|
(FIX(s)<<8)|
(FIX(t)<<7)|
(FIX(b)<<6)|
(FIX(a)<<7)|
(FIX(y)<<8)|
(FIX(x)<<9)|
(FIX(w)<<10)|
(FIX(e)<<11)|
(FIX(g)<<12)|
(FIX(f)<<13);
(FIX(a)<<5)|
(FIX(y)<<4)|
(FIX(x)<<3)|
(FIX(w)<<2)|
(FIX(e)<<1);
// TODO: low power IRQ
}

View File

@ -45,6 +45,8 @@ struct turbo {
bool A;
bool Y;
bool X;
bool L;
bool R;
bool &button(int i) { return ((bool*)this)[i]; }
};
@ -62,6 +64,8 @@ struct turbotime {
int A;
int Y;
int X;
int L;
int R;
int &time(int i) { return ((int*)this)[i]; }
};
@ -380,6 +384,7 @@ class Driver {
public:
virtual BOOL WIFI_Host_InitSystem() { return FALSE; }
virtual void WIFI_Host_ShutdownSystem() {}
virtual BOOL AVI_IsRecording() { return FALSE; }
};
extern Driver* driver;
@ -387,6 +392,10 @@ extern std::string InputDisplayString;
extern int LagFrameFlag;
extern int lastLag, TotalLagFrames;
void MovieSRAM(int bmtype, u32 bmsize);
void ClearAutoHold(void);
#endif

View File

@ -75,19 +75,12 @@ static void ENDGL() {
#define CTASSERT(x) typedef char __assert ## y[(x) ? 1 : -1]
#endif
static ALIGN(16) u8 GPU_screen3D [256*192*4];
//static ALIGN(16) unsigned char GPU_screenStencil[256*256];
static ALIGN(16) u8 GPU_screen3D [256*192*4];
static const unsigned short map3d_cull[4] = {GL_FRONT_AND_BACK, GL_FRONT, GL_BACK, 0};
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;
float clearAlpha;
//derived values extracted from polyattr etc
static bool wireframe=false, alpha31=false;
@ -346,7 +339,6 @@ static void OGLReset()
// memset(GPU_screenStencil,0,sizeof(GPU_screenStencil));
memset(GPU_screen3D,0,sizeof(GPU_screen3D));
needRefreshFramebuffer = false;
}
@ -474,11 +466,6 @@ static char OGLInit(void)
glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_WRAP_S, GL_CLAMP); //clamp so that we dont run off the edges due to 1.0 -> [0,31] math
}
if(glBlendFuncSeparateEXT == NULL)
clearAlpha = 1;
else
clearAlpha = 0;
OGLReset();
ENDGL();
@ -536,7 +523,7 @@ static void setTexture(unsigned int format, unsigned int texpal)
}
TexCache_SetTexture(format, texpal);
TexCache_SetTexture<TexFormat_32bpp>(format, texpal);
}
@ -687,6 +674,49 @@ static void Control()
}
}
static void GL_ReadFramebuffer()
{
if(!BEGINGL()) return;
glFinish();
// glReadPixels(0,0,256,192,GL_STENCIL_INDEX, GL_UNSIGNED_BYTE, GPU_screenStencil);
glReadPixels(0,0,256,192,GL_BGRA_EXT, GL_UNSIGNED_BYTE, GPU_screen3D);
ENDGL();
//convert the pixels to a different format which is more convenient
//is it safe to modify the screen buffer? if not, we could make a temp copy
for(int i=0,y=191;y>=0;y--)
{
u16* dst = gfx3d_convertedScreen + (y<<8);
u8* dstAlpha = gfx3d_convertedAlpha + (y<<8);
#ifndef NOSSE2
//I dont know much about this kind of stuff, but this seems to help
//for some reason I couldnt make the intrinsics work
u8* wanx = (u8*)&((u32*)GPU_screen3D)[i];
#define ASS(X,Y) __asm { prefetchnta [wanx+32*0x##X##Y] }
#define PUNK(X) ASS(X,0) ASS(X,1) ASS(X,2) ASS(X,3) ASS(X,4) ASS(X,5) ASS(X,6) ASS(X,7) ASS(X,8) ASS(X,9) ASS(X,A) ASS(X,B) ASS(X,C) ASS(X,D) ASS(X,E) ASS(X,F)
PUNK(0); PUNK(1);
#endif
for(int x=0;x<256;x++,i++)
{
u32 &u32screen3D = ((u32*)GPU_screen3D)[i];
u32screen3D>>=3;
u32screen3D &= 0x1F1F1F1F;
const int t = i<<2;
const u8 a = GPU_screen3D[t+3];
const u8 r = GPU_screen3D[t+2];
const u8 g = GPU_screen3D[t+1];
const u8 b = GPU_screen3D[t+0];
dst[x] = R5G5B5TORGB15(r,g,b) | alpha_lookup[a];
dstAlpha[x] = alpha_5bit_to_4bit[a];
}
}
}
static void OGLRender()
{
if(!BEGINGL()) return;
@ -828,10 +858,9 @@ static void OGLRender()
}
}
//since we just redrew, we need to refresh the framebuffers
needRefreshFramebuffer = true;
ENDGL();
GL_ReadFramebuffer();
}
static void OGLVramReconfigureSignal()
@ -839,151 +868,6 @@ static void OGLVramReconfigureSignal()
TexCache_Invalidate();
}
static void GL_ReadFramebuffer()
{
if(!BEGINGL()) return;
glFinish();
// glReadPixels(0,0,256,192,GL_STENCIL_INDEX, GL_UNSIGNED_BYTE, GPU_screenStencil);
glReadPixels(0,0,256,192,GL_BGRA_EXT, GL_UNSIGNED_BYTE, GPU_screen3D);
ENDGL();
//convert the pixels to a different format which is more convenient
//is it safe to modify the screen buffer? if not, we could make a temp copy
for(int i=0;i<256*192;i++) {
u32 &u32screen3D = ((u32*)GPU_screen3D)[i];
u32screen3D>>=3;
u32screen3D &= 0x1F1F1F1F;
}
//debug: view depth buffer via color buffer for debugging
//int ctr=0;
//for(ctr=0;ctr<256*192;ctr++) {
// float zval = GPU_screen3Ddepth[ctr];
// u8* colorPtr = GPU_screen3D+ctr*3;
// if(zval<0) {
// colorPtr[0] = 255;
// colorPtr[1] = 0;
// colorPtr[2] = 0;
// } else if(zval>1) {
// colorPtr[0] = 0;
// colorPtr[1] = 0;
// colorPtr[2] = 255;
// } else {
// colorPtr[0] = colorPtr[1] = colorPtr[2] = zval*255;
// //INFO("%f %f %d\n",zval, zval*255,colorPtr[0]);
// }
//}
}
static void OGLGetLineCaptured(int line, u16* dst)
{
if(needRefreshFramebuffer) {
needRefreshFramebuffer = false;
GL_ReadFramebuffer();
}
u8 *screen3D = (u8*)GPU_screen3D+((191-line)<<10);
// u8 *screenStencil = (u8*)GPU_screenStencil+((191-line)<<8);
for(int i = 0; i < 256; i++)
{
/* u32 stencil = screenStencil[i];
if(!stencil)
{
dst[i] = 0x0000;
continue;
}*/
int t=i<<2;
/* u8 r = screen3D[t+2];
u8 g = screen3D[t+1];
u8 b = screen3D[t+0];*/
//if this math strikes you as wrong, be sure to look at GL_ReadFramebuffer() where the pixel format in screen3D is changed
//dst[i] = (b<<10) | (g<<5) | (r) | 0x8000;
dst[i] = (screen3D[t+2] | (screen3D[t+1] << 5) | (screen3D[t+0] << 10) | ((screen3D[t+3] > 0) ? 0x8000 : 0x0000));
}
}
static void OGLGetLine(int line, u16* dst, u8* dstAlpha)
{
assert(line<192 && line>=0);
if(needRefreshFramebuffer) {
needRefreshFramebuffer = false;
GL_ReadFramebuffer();
}
u8 *screen3D = (u8*)GPU_screen3D+((191-line)<<10);
//u8 *screenStencil = (u8*)GPU_screenStencil+((191-line)<<8);
//the renderer clears the stencil to 0
//then it sets it to 1 whenever it renders a pixel that passes the alpha test
//(it also sets it to 2 under some circumstances when rendering shadow volumes)
//so, we COULD use a zero stencil value to indicate that nothing should get composited.
//in fact, we are going to do that to fix some problems.
//but beware that it i figure it might could CAUSE some problems
//this alpha compositing blending logic isnt thought through very much
//someone needs to think about what bitdepth it should take place at and how to do it efficiently
for(int i=0;i<256;i++)
{
// u32 stencil = screenStencil[i];
//you would use this if you wanted to use the stencil buffer to make decisions here
// if(!stencil) continue;
// u16 oldcolor = dst[j];
int t=i<<2;
// u32 dstpixel;
dst[i] = (screen3D[t+2] | (screen3D[t+1] << 5) | (screen3D[t+0] << 10) | ((screen3D[t+3] > 0) ? 0x8000 : 0x0000));
dstAlpha[i] = alpha_5bit_to_4bit[screen3D[t+3]];
//old debug reminder: display alpha channel
//u32 r = screen3D[t+3];
//u32 g = screen3D[t+3];
//u32 b = screen3D[t+3];
//if this math strikes you as wrong, be sure to look at GL_ReadFramebuffer() where the pixel format in screen3D is changed
/* u32 a = screen3D[t+3];
typedef u8 mixtbl[32][32];
mixtbl & mix = mixTable555[a];
//r
u32 newpix = screen3D[t+2];
u32 oldpix = oldcolor&0x1F;
newpix = mix[newpix][oldpix];
dstpixel = newpix;
//g
newpix = screen3D[t+1];
oldpix = (oldcolor>>5)&0x1F;
newpix = mix[newpix][oldpix];
dstpixel |= (newpix<<5);
//b
newpix = screen3D[t+0];
oldpix = (oldcolor>>10)&0x1F;
newpix = mix[newpix][oldpix];
dstpixel |= (newpix<<10);
dst[j] = dstpixel;*/
}
}
GPU3DInterface gpu3Dgl = {
"OpenGL",
OGLInit,
@ -991,9 +875,4 @@ GPU3DInterface gpu3Dgl = {
OGLClose,
OGLRender,
OGLVramReconfigureSignal,
OGLGetLine,
OGLGetLineCaptured
};

View File

@ -32,6 +32,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#include "mem.h"
#include "readwrite.h"
#include "armcpu.h"
#include "NDSSystem.h"
SPU_struct *SPU_core = 0;
SPU_struct *SPU_user = 0;
@ -1034,7 +1035,10 @@ void SPU_Emulate_core()
spu_core_samples = (int)(samples);
samples -= spu_core_samples;
SPU_MixAudio<false>(SPU_core,spu_core_samples);
if(driver->AVI_IsRecording())
SPU_MixAudio<true>(SPU_core,spu_core_samples);
else
SPU_MixAudio<false>(SPU_core,spu_core_samples);
}
void SPU_Emulate_user()
@ -1300,7 +1304,7 @@ void spu_savestate(std::ostream* os)
}
}
bool spu_loadstate(std::istream* is)
bool spu_loadstate(std::istream* is, int size)
{
//read version
int version;

View File

@ -112,6 +112,6 @@ extern SPU_struct *SPU_core, *SPU_user;
extern int spu_core_samples;
void spu_savestate(std::ostream* os);
bool spu_loadstate(std::istream* is);
bool spu_loadstate(std::istream* is, int size);
#endif

View File

@ -41,6 +41,9 @@
#include "readwrite.h"
#include "FIFO.h"
using std::max;
using std::min;
GFX3D gfx3d;
//tables that are provided to anyone
@ -79,6 +82,11 @@ CACHE_ALIGN const u8 material_3bit_to_8bit[] = {
0x00, 0x24, 0x49, 0x6D, 0x92, 0xB6, 0xDB, 0xFF
};
//maybe not very precise
CACHE_ALIGN const u8 material_3bit_to_5bit[] = {
0, 4, 8, 13, 17, 22, 26, 31
};
CACHE_ALIGN const u8 alpha_5bit_to_4bit[] = {
0x00, 0x00,
0x01, 0x01,
@ -98,6 +106,13 @@ CACHE_ALIGN const u8 alpha_5bit_to_4bit[] = {
0x10, 0x10
};
CACHE_ALIGN const u16 alpha_lookup[] = {
0x0000,0x8000,0x8000,0x8000,0x8000,0x8000,0x8000,0x8000,
0x8000,0x8000,0x8000,0x8000,0x8000,0x8000,0x8000,0x8000,
0x8000,0x8000,0x8000,0x8000,0x8000,0x8000,0x8000,0x8000,
0x8000,0x8000,0x8000,0x8000,0x8000,0x8000,0x8000,0x8000};
//private acceleration tables
static float float16table[65536];
static float float10Table[1024];
@ -107,6 +122,9 @@ static float normalTable[1024];
#define fix2float(v) (((float)((s32)(v))) / (float)(1<<12))
#define fix10_2float(v) (((float)((s32)(v))) / (float)(1<<9))
CACHE_ALIGN u16 gfx3d_convertedScreen[256*192];
CACHE_ALIGN u8 gfx3d_convertedAlpha[256*192];
// Matrix stack handling
static CACHE_ALIGN MatrixStack mtxStack[4] = {
MatrixStack(1), // Projection stack
@ -165,7 +183,7 @@ static u32 lightColor[4] = {0,0,0,0};
static u32 lightDirection[4] = {0,0,0,0};
//material state:
static u16 dsDiffuse, dsAmbient, dsSpecular, dsEmission;
/* Shininess */
// Shininess
static float shininessTable[128] = {0};
static int shininessInd = 0;
@ -297,6 +315,9 @@ void gfx3d_reset()
last_t = 0;
last_s = 0;
viewport = 0xBFFF0000;
memset(gfx3d_convertedScreen,0,sizeof(gfx3d_convertedScreen));
memset(gfx3d_convertedAlpha,0,sizeof(gfx3d_convertedAlpha));
GFX_FIFOclear();
}
@ -396,6 +417,8 @@ void gfx3d_glStoreMatrix(u32 v)
if(mymode==0)
v = 0;
if(v==31) v=30; //? what should happen in this case?
MatrixStackLoadMatrix (&mtxStack[mymode], v&31, mtxCurrent[mymode]);
if(mymode==2)
MatrixStackLoadMatrix (&mtxStack[1], v&31, mtxCurrent[1]);
@ -410,6 +433,8 @@ void gfx3d_glRestoreMatrix(u32 v)
if(mymode==0)
v = 0;
if(v==31) v=30; //? what should happen in this case?
MatrixCopy (mtxCurrent[mymode], MatrixStackGetPos(&mtxStack[mymode], v&31));
if (mymode == 2)
MatrixCopy (mtxCurrent[1], MatrixStackGetPos(&mtxStack[1], v&31));
@ -1343,43 +1368,32 @@ static void gfx3d_FlushFIFO()
void gfx3d_glFlush(u32 v)
{
gfx3d.frameCtr++;
gfx3d_FlushFIFO();
//assert(!flushPending);
flushPending = TRUE;
gfx3d.sortmode = BIT0(v);
gfx3d.wbuffer = BIT1(v);
// reset
clInd = 0;
clCmd = 0;
//the renderer wil lget the lists we just built
gfx3d.polylist = polylist;
gfx3d.vertlist = vertlist;
//we need to sort the poly list with alpha polys last
//first, look for opaque polys
int polycount = polylist->count;
int ctr=0;
for(int i=0;i<polycount;i++) {
POLY &poly = polylist->list[i];
if(!poly.isTranslucent())
gfx3d.indexlist[ctr++] = i;
}
//then look for translucent polys
for(int i=0;i<polycount;i++) {
POLY &poly = polylist->list[i];
if(poly.isTranslucent())
gfx3d.indexlist[ctr++] = i;
}
//switch to the new lists
twiddleLists();
}
static int _CDECL_ gfx3d_ysort_compare(const void * elem1, const void * elem2)
{
int num1 = *(int*)elem1;
int num2 = *(int*)elem2;
POLY &poly1 = polylist->list[num1];
POLY &poly2 = polylist->list[num2];
if(poly1.maxy > poly2.maxy)
return 1;
else if(poly1.maxy < poly2.maxy)
return -1;
else if(poly1.miny < poly2.miny)
return 1;
else if(poly1.miny > poly2.miny)
return -1;
else
return 0;
}
void gfx3d_VBlankSignal()
{
//the 3d buffers are swapped when a vblank begins.
@ -1390,6 +1404,62 @@ void gfx3d_VBlankSignal()
return;
}
gfx3d.frameCtr++;
gfx3d_FlushFIFO();
// reset
clInd = 0;
clCmd = 0;
//the renderer wil lget the lists we just built
gfx3d.polylist = polylist;
gfx3d.vertlist = vertlist;
int polycount = polylist->count;
//find the min and max y values for each poly.
//TODO - this could be a small waste of time if we are manual sorting the translucent polys
for(int i=0;i<polycount;i++) {
POLY &poly = polylist->list[i];
for(int j=0;j<poly.type;j++) {
VERT &vert = vertlist->list[poly.vertIndexes[j]];
poly.miny = j==0?vert.y:min(poly.miny,vert.y);
poly.maxy = j==0?vert.y:max(poly.maxy,vert.y);
}
}
//we need to sort the poly list with alpha polys last
//first, look for opaque polys
int ctr=0;
for(int i=0;i<polycount;i++) {
POLY &poly = polylist->list[i];
if(!poly.isTranslucent())
gfx3d.indexlist[ctr++] = i;
}
int opaqueCount = ctr;
//then look for translucent polys
for(int i=0;i<polycount;i++) {
POLY &poly = polylist->list[i];
if(poly.isTranslucent())
gfx3d.indexlist[ctr++] = i;
}
//now we have to sort the opaque polys by y-value.
//should this be done after clipping??
//test case: harvest moon island of happiness character cretor UI
qsort(gfx3d.indexlist, opaqueCount, 4, gfx3d_ysort_compare);
if(!gfx3d.sortmode)
{
//if we are autosorting translucent polys, we need to do this also
//TODO - this is unverified behavior. need a test case
qsort(gfx3d.indexlist + opaqueCount, polycount - opaqueCount, 4, gfx3d_ysort_compare);
}
//switch to the new lists
twiddleLists();
flushPending = FALSE;
drawPending = TRUE;
}
@ -1403,6 +1473,13 @@ void gfx3d_VBlankEndSignal(bool skipFrame)
drawPending = FALSE;
gpu3D->NDS_3D_Render();
//if the null 3d core is chosen, then we need to clear out the 3d buffers to keep old data from being rendered
if(gpu3D == &gpu3DNull)
{
memset(gfx3d_convertedScreen,0,sizeof(gfx3d_convertedScreen));
memset(gfx3d_convertedScreen,0,sizeof(gfx3d_convertedAlpha));
}
}
#ifdef USE_GEOMETRY_FIFO_EMULATION
@ -2152,6 +2229,15 @@ void gfx3d_glGetLightColor(unsigned int index, unsigned int* dest)
*dest = lightColor[index];
}
void gfx3d_GetLineData(int line, u16** dst, u8** dstAlpha)
{
*dst = gfx3d_convertedScreen+((line)<<8);
if(dstAlpha != NULL)
{
*dstAlpha = gfx3d_convertedAlpha+((line)<<8);
}
}
//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.
@ -2209,11 +2295,6 @@ SFORMAT SF_GFX3D[]={
{ "GMAM", 2, 1, &dsAmbient},
{ "GMSP", 2, 1, &dsSpecular},
{ "GMEM", 2, 1, &dsEmission},
{ "GTST", 4, 1, &triStripToggle},
{ "GTVC", 4, 1, &tempVertInfo.count},
{ "GTVM", 4, 4, &tempVertInfo.map[0]},
{ "GTVF", 4, 1, &tempVertInfo.first},
{ "GLTW", 4, 1, &listTwiddle},
{ "GFLP", 4, 1, &flushPending},
{ "GDRP", 4, 1, &drawPending},
{ "GSET", 4, 1, &gfx3d.enableTexturing},
@ -2233,6 +2314,13 @@ SFORMAT SF_GFX3D[]={
{ "GSTT", 4, 32, gfx3d.rgbToonTable},
{ "GSST", 4, 128, shininessTable},
{ "GSSI", 4, 1, &shininessInd},
//------------------------
{ "GTST", 4, 1, &triStripToggle},
{ "GTVC", 4, 1, &tempVertInfo.count},
{ "GTVM", 4, 4, tempVertInfo.map},
{ "GTVF", 4, 1, &tempVertInfo.first},
{ "G3CS", 2, 256*192, gfx3d_convertedScreen},
{ "G3CA", 2, 256*192, gfx3d_convertedAlpha},
{ 0 }
};
@ -2240,10 +2328,15 @@ SFORMAT SF_GFX3D[]={
void gfx3d_savestate(std::ostream* os)
{
//dump the render lists
//TODO!!!!
OSWRITE(vertlist->count);
for(int i=0;i<vertlist->count;i++)
vertlist->list[i].save(os);
OSWRITE(polylist->count);
for(int i=0;i<polylist->count;i++)
polylist->list[i].save(os);
}
bool gfx3d_loadstate(std::istream* is)
bool gfx3d_loadstate(std::istream* is, int size)
{
gfx3d_glPolygonAttrib_cache();
gfx3d_glTexImage_cache();
@ -2254,14 +2347,21 @@ bool gfx3d_loadstate(std::istream* is)
gfx3d_glLightDirection_cache(3);
//jiggle the lists. and also wipe them. this is clearly not the best thing to be doing.
listTwiddle = 0;
polylist = &polylists[listTwiddle];
vertlist = &vertlists[listTwiddle];
polylist->count = 0;
vertlist->count = 0;
OSREAD(vertlist->count);
for(int i=0;i<vertlist->count;i++)
vertlist->list[i].load(is);
OSREAD(polylist->count);
for(int i=0;i<polylist->count;i++)
polylist->list[i].load(is);
gfx3d.polylist = &polylists[listTwiddle^1];
gfx3d.vertlist = &vertlists[listTwiddle^1];
gfx3d.polylist->count=0;
gfx3d.vertlist->count=0;
return true;
}
}

View File

@ -26,6 +26,8 @@
#include "types.h"
#include <iosfwd>
#include <ostream>
#include <istream>
//produce a 32bpp color from a DS RGB16
#define RGB16TO32(col,alpha) (((alpha)<<24) | ((((col) & 0x7C00)>>7)<<16) | ((((col) & 0x3E0)>>2)<<8) | (((col) & 0x1F)<<3))
@ -33,6 +35,9 @@
//produce a 32bpp color from a ds RGB15 plus an 8bit alpha, using a table
#define RGB15TO32(col,alpha8) ( ((alpha8)<<24) | color_15bit_to_24bit[col&0x7FFF] )
//produce a 5555 32bit color from a ds RGB15 plus an 5bit alpha
#define RGB15TO5555(col,alpha5) (((alpha5)<<24) | ((((col) & 0x7C00)>>10)<<16) | ((((col) & 0x3E0)>>5)<<8) | (((col) & 0x1F)))
//produce a 24bpp color from a ds RGB15, using a table
#define RGB15TO24_REVERSE(col) ( color_15bit_to_24bit_reverse[col&0x7FFF] )
@ -58,13 +63,15 @@
void gfx3d_init();
void gfx3d_reset();
#define OSWRITE(x) os->write((char*)&(x),sizeof((x)));
#define OSREAD(x) is->read((char*)&(x),sizeof((x)));
struct POLY {
int type; //tri or quad
u16 vertIndexes[4]; //up to four verts can be referenced by this poly
u32 polyAttr, texParam, texPalette; //the hardware rendering params
// int projIndex; //the index into the projlist that this poly uses
u32 pad;
u32 viewport;
float miny, maxy;
bool isTranslucent()
{
@ -81,6 +88,26 @@ struct POLY {
}
int getAlpha() { return (polyAttr>>16)&0x1F; }
void save(std::ostream* os)
{
OSWRITE(type);
OSWRITE(vertIndexes[0]); OSWRITE(vertIndexes[1]); OSWRITE(vertIndexes[2]); OSWRITE(vertIndexes[3]);
OSWRITE(polyAttr); OSWRITE(texParam); OSWRITE(texPalette);
OSWRITE(viewport);
OSWRITE(miny);
OSWRITE(maxy);
}
void load(std::istream* is)
{
OSREAD(type);
OSREAD(vertIndexes[0]); OSREAD(vertIndexes[1]); OSREAD(vertIndexes[2]); OSREAD(vertIndexes[3]);
OSREAD(polyAttr); OSREAD(texParam); OSREAD(texPalette);
OSREAD(viewport);
OSREAD(miny);
OSREAD(maxy);
}
};
#define POLYLIST_SIZE 100000
@ -110,6 +137,20 @@ struct VERT {
fcolor[1] = color[1];
fcolor[2] = color[2];
}
void save(std::ostream* os)
{
OSWRITE(x); OSWRITE(y); OSWRITE(z); OSWRITE(w);
OSWRITE(u); OSWRITE(v);
OSWRITE(color[0]); OSWRITE(color[1]); OSWRITE(color[2]);
OSWRITE(fcolor[0]); OSWRITE(fcolor[1]); OSWRITE(fcolor[2]);
}
void load(std::istream* is)
{
OSREAD(x); OSREAD(y); OSREAD(z); OSREAD(w);
OSREAD(u); OSREAD(v);
OSREAD(color[0]); OSREAD(color[1]); OSREAD(color[2]);
OSREAD(fcolor[0]); OSREAD(fcolor[1]); OSREAD(fcolor[2]);
}
};
#define VERTLIST_SIZE 400000
@ -177,15 +218,22 @@ extern GFX3D gfx3d;
//---------------------
extern CACHE_ALIGN const u16 alpha_lookup[32];
extern CACHE_ALIGN u32 color_15bit_to_24bit[32768];
extern CACHE_ALIGN u32 color_15bit_to_24bit_reverse[32768];
extern CACHE_ALIGN u16 color_15bit_to_16bit_reverse[32768];
extern CACHE_ALIGN u8 mixTable555[32][32][32];
extern CACHE_ALIGN const int material_5bit_to_31bit[32];
extern CACHE_ALIGN const u8 material_5bit_to_8bit[32];
extern CACHE_ALIGN const u8 material_3bit_to_5bit[8];
extern CACHE_ALIGN const u8 material_3bit_to_8bit[8];
extern CACHE_ALIGN const u8 alpha_5bit_to_4bit[32];
//these contain the 3d framebuffer converted into the most useful format
//they are stored here instead of in the renderers in order to consolidate the buffers
extern CACHE_ALIGN u16 gfx3d_convertedScreen[256*192];
extern CACHE_ALIGN u8 gfx3d_convertedAlpha[256*192];
//GE commands:
void gfx3d_glViewPort(u32 v);
void gfx3d_glClearColor(u32 v);
@ -208,11 +256,11 @@ BOOL gfx3d_glMultMatrix4x4(s32 v);
void gfx3d_glBegin(u32 v);
void gfx3d_glEnd(void);
void gfx3d_glColor3b(u32 v);
BOOL gfx3d_glVertex16b(unsigned int v);
BOOL gfx3d_glVertex16b(u32 v);
void gfx3d_glVertex10b(u32 v);
void gfx3d_glVertex3_cord(unsigned int one, unsigned int two, unsigned int v);
void gfx3d_glVertex3_cord(u32 one, u32 two, u32 v);
void gfx3d_glVertex_rel(u32 v);
void gfx3d_glSwapScreen(unsigned int screen);
void gfx3d_glSwapScreen(u32 screen);
int gfx3d_GetNumPolys();
int gfx3d_GetNumVertex();
void gfx3d_glPolygonAttrib (u32 val);
@ -225,16 +273,16 @@ void gfx3d_glTexImage(u32 val);
void gfx3d_glTexPalette(u32 val);
void gfx3d_glTexCoord(u32 val);
void gfx3d_glNormal(u32 v);
s32 gfx3d_GetClipMatrix (unsigned int index);
s32 gfx3d_GetDirectionalMatrix (unsigned int index);
s32 gfx3d_GetClipMatrix (u32 index);
s32 gfx3d_GetDirectionalMatrix (u32 index);
void gfx3d_glLightDirection (u32 v);
void gfx3d_glLightColor (u32 v);
void gfx3d_glAlphaFunc(u32 v);
BOOL gfx3d_glBoxTest(u32 v);
BOOL gfx3d_glPosTest(u32 v);
void gfx3d_glVecTest(u32 v);
unsigned int gfx3d_glGetPosRes(unsigned int index);
unsigned short gfx3d_glGetVecRes(unsigned int index);
u32 gfx3d_glGetPosRes(u32 index);
u16 gfx3d_glGetVecRes(u32 index);
void gfx3d_glFlush(u32 v);
void gfx3d_VBlankSignal();
void gfx3d_VBlankEndSignal(bool skipFrame);
@ -244,13 +292,15 @@ void gfx3d_sendCommandToFIFO(u32 val);
void gfx3d_sendCommand(u32 cmd, u32 param);
//other misc stuff
void gfx3d_glGetMatrix(unsigned int mode, int index, float* dest);
void gfx3d_glGetLightDirection(unsigned int index, unsigned int* dest);
void gfx3d_glGetLightColor(unsigned int index, unsigned int* dest);
void gfx3d_glGetMatrix(u32 mode, int index, float* dest);
void gfx3d_glGetLightDirection(u32 index, u32* dest);
void gfx3d_glGetLightColor(u32 index, u32* dest);
void gfx3d_GetLineData(int line, u16** dst, u8** dstAlpha);
struct SFORMAT;
extern SFORMAT SF_GFX3D[];
void gfx3d_savestate(std::ostream* os);
bool gfx3d_loadstate(std::istream* is);
bool gfx3d_loadstate(std::istream* is, int size);
#endif

View File

@ -23,6 +23,7 @@
#include "debug.h"
#include "types.h"
#include "mc.h"
#include "movie.h"
#define FW_CMD_READ 0x3
#define FW_CMD_WRITEDISABLE 0x4
@ -207,9 +208,16 @@ void mc_load_file(memory_chip_t *mc, const char* filename)
{
long size;
int type = -1;
FILE* file = fopen(filename, "rb+");
FILE* file;
size_t elems_read;
if(movieMode != MOVIEMODE_INACTIVE) {
mc->filename = strdup(filename);
return;
}
else
file = fopen(filename, "rb+");
if(file == NULL)
{
mc->filename = strdup(filename);

View File

@ -1,6 +1,6 @@
/* movie.cpp
*
* Copyright (C) 2006-2008 Zeromus
* Copyright (C) 2006-2009 DeSmuME team
*
* This file is part of DeSmuME
*
@ -22,14 +22,18 @@
#include <assert.h>
#include <limits.h>
#include <fstream>
#include "main.h"
#include "utils/guid.h"
#include "utils/xstring.h"
#include "movie.h"
#include "NDSSystem.h"
#include "readwrite.h"
#include "debug.h"
#include "rtc.h"
using namespace std;
bool freshMovie = false; //True when a movie loads, false when movie is altered. Used to determine if a movie has been altered since opening
bool autoMovieBackup = true;
#define FCEU_PrintError LOG
@ -189,6 +193,8 @@ void MovieData::installValue(std::string& key, std::string& val)
guid = Desmume_Guid::fromString(val);
else if(key == "comment")
comments.push_back(mbstowcs(val));
else if(key == "binary")
installBool(val,binaryFlag);
else if(key == "savestate")
{
int len = Base64StringToBytesLength(val);
@ -222,10 +228,10 @@ int MovieData::dump(std::ostream *os, bool binary)
*os << "savestate " << BytesToString(&savestate[0],savestate.size()) << endl;
if(binary)
{
////put one | to start the binary dump
//os->put('|');
//for(int i=0;i<(int)records.size();i++)
// records[i].dumpBinary(this,os,i);
//put one | to start the binary dump
os->put('|');
for(int i=0;i<(int)records.size();i++)
records[i].dumpBinary(this,os,i);
}
else
for(int i=0;i<(int)records.size();i++)
@ -268,8 +274,8 @@ static bool LoadFM2(MovieData& movieData, std::istream* fp, int size, bool stopA
isnewline = (c==10||c==13);
if(isrecchar && movieData.binaryFlag && !stopAfterHeader)
{
//LoadFM2_binarychunk(movieData, fp, size);
return false;
LoadFM2_binarychunk(movieData, fp, size);
return true;
}
switch(state)
{
@ -349,7 +355,7 @@ static void closeRecordingMovie()
/// Stop movie playback.
static void StopPlayback()
{
//FCEU_DispMessageOnMovie("Movie playback stopped.");
SetMessageToDisplay("Movie playback stopped.");
movieMode = MOVIEMODE_INACTIVE;
}
@ -357,8 +363,7 @@ static void StopPlayback()
/// Stop movie recording
static void StopRecording()
{
//FCEU_DispMessage("Movie recording stopped.");
SetMessageToDisplay("Movie recording stopped.");
movieMode = MOVIEMODE_INACTIVE;
closeRecordingMovie();
@ -366,7 +371,7 @@ static void StopRecording()
static void FCEUI_StopMovie()
void FCEUI_StopMovie()
{
//if(suppressMovieStop)
// return;
@ -377,11 +382,12 @@ static void FCEUI_StopMovie()
StopRecording();
curMovieFilename[0] = 0;
freshMovie = false;
}
//begin playing an existing movie
static void FCEUI_LoadMovie(const char *fname, bool _read_only, bool tasedit, int _pauseframe)
void FCEUI_LoadMovie(const char *fname, bool _read_only, bool tasedit, int _pauseframe)
{
//if(!tasedit && !FCEU_IsValidUI(FCEUI_PLAYMOVIE))
// return;
@ -416,6 +422,7 @@ static void FCEUI_LoadMovie(const char *fname, bool _read_only, bool tasedit, in
//fully reload the game to reinitialize everything before playing any movie
//poweron(true);
NDS_Reset();
////WE NEED TO LOAD A SAVESTATE
//if(currMovieData.savestate.size() != 0)
//{
@ -428,11 +435,15 @@ static void FCEUI_LoadMovie(const char *fname, bool _read_only, bool tasedit, in
movie_readonly = _read_only;
movieMode = MOVIEMODE_PLAY;
currRerecordCount = currMovieData.rerecordCount;
InitMovieTime();
MovieSRAM(backupmemorytype, backupmemorysize);
freshMovie = true;
ClearAutoHold();
//if(movie_readonly)
// FCEU_DispMessage("Replay started Read-Only.");
//else
// FCEU_DispMessage("Replay started Read+Write.");
if(movie_readonly)
SetMessageToDisplay("Replay started Read-Only.");
else
SetMessageToDisplay("Replay started Read+Write.");
}
static void openRecordingMovie(const char* fname)
@ -447,7 +458,7 @@ static void openRecordingMovie(const char* fname)
//begin recording a new movie
//TODO - BUG - the record-from-another-savestate doesnt work.
static void FCEUI_SaveMovie(const char *fname, std::wstring author)
void FCEUI_SaveMovie(const char *fname, std::wstring author)
{
//if(!FCEU_IsValidUI(FCEUI_RECORDMOVIE))
// return;
@ -468,6 +479,7 @@ static void FCEUI_SaveMovie(const char *fname, std::wstring author)
//currMovieData.romChecksum = GameInfo->MD5;
//currMovieData.romFilename = FileBase;
NDS_Reset();
//todo ?
//poweron(true);
//else
@ -479,81 +491,109 @@ static void FCEUI_SaveMovie(const char *fname, std::wstring author)
movieMode = MOVIEMODE_RECORD;
movie_readonly = false;
currRerecordCount = 0;
InitMovieTime();
MovieSRAM(backupmemorytype, backupmemorysize);
//FCEU_DispMessage("Movie recording started.");
SetMessageToDisplay("Movie recording started.");
}
void NDS_setTouchFromMovie(void) {
//the main interaction point between the emulator and the movie system.
//either dumps the current joystick state or loads one state from the movie
static void FCEUMOV_AddInputState()
{
//todo - for tasedit, either dump or load depending on whether input recording is enabled
//or something like that
//(input recording is just like standard read+write movie recording with input taken from gamepad)
//otherwise, it will come from the tasedit data.
if(movieMode == MOVIEMODE_PLAY)
{
if(movieMode == MOVIEMODE_PLAY)
{
//stop when we run out of frames
if(currFrameCounter == (int)currMovieData.records.size())
{
StopPlayback();
}
else
{
MovieRecord* mr = &currMovieData.records[currFrameCounter];
//reset if necessary
if(mr->command_reset())
{}
//ResetNES();
MovieRecord* mr = &currMovieData.records[currFrameCounter];
nds.touchX=mr->touch.x << 4;
nds.touchY=mr->touch.y << 4;
NDS_setPadFromMovie(mr->pad);
}
if(mr->touch.touch) {
nds.isTouch=mr->touch.touch;
MMU.ARM7_REG[0x136] &= 0xBF;
}
else {
nds.touchX=0;
nds.touchY=0;
nds.isTouch=0;
//if we are on the last frame, then pause the emulator if the player requested it
if(currFrameCounter == (int)currMovieData.records.size()-1)
{
/*if(FCEUD_PauseAfterPlayback())
{
FCEUI_ToggleEmulationPause();
}*/
}
MMU.ARM7_REG[0x136] |= 0x40;
}
osd->addFixed(mr->touch.x, mr->touch.y, "%s", "X");
}
}
//pause the movie at a specified frame
//if(FCEUMOV_ShouldPause() && FCEUI_EmulationPaused()==0)
//{
// FCEUI_ToggleEmulationPause();
// FCEU_DispMessage("Paused at specified movie frame");
//}
}
else if(movieMode == MOVIEMODE_RECORD)
{
MovieRecord mr;
//the main interaction point between the emulator and the movie system.
//either dumps the current joystick state or loads one state from the movie
void FCEUMOV_AddInputState()
{
//todo - for tasedit, either dump or load depending on whether input recording is enabled
//or something like that
//(input recording is just like standard read+write movie recording with input taken from gamepad)
//otherwise, it will come from the tasedit data.
mr.commands = 0;
mr.pad = nds.pad;
if(nds.isTouch) {
mr.touch.x = nds.touchX;
mr.touch.y = nds.touchY;
mr.touch.touch = 1;
} else {
mr.touch.x = 0;
mr.touch.y = 0;
mr.touch.touch = 0;
}
if(movieMode == MOVIEMODE_PLAY)
{
//stop when we run out of frames
if(currFrameCounter == (int)currMovieData.records.size())
{
StopPlayback();
}
else
{
MovieRecord* mr = &currMovieData.records[currFrameCounter];
mr.dump(&currMovieData, osRecordingMovie,currMovieData.records.size());
currMovieData.records.push_back(mr);
}
//reset if necessary
if(mr->command_reset())
{}
//ResetNES();
currFrameCounter++;
NDS_setPadFromMovie(mr->pad);
NDS_setTouchFromMovie();
}
/*extern uint8 joy[4];
memcpy(&cur_input_display,joy,4);*/
}
//if we are on the last frame, then pause the emulator if the player requested it
if(currFrameCounter == (int)currMovieData.records.size()-1)
{
/*if(FCEUD_PauseAfterPlayback())
{
FCEUI_ToggleEmulationPause();
}*/
}
//pause the movie at a specified frame
//if(FCEUMOV_ShouldPause() && FCEUI_EmulationPaused()==0)
//{
// FCEUI_ToggleEmulationPause();
// FCEU_DispMessage("Paused at specified movie frame");
//}
osd->addFixed(180, 176, "%s", "Playback");
}
else if(movieMode == MOVIEMODE_RECORD)
{
MovieRecord mr;
mr.commands = 0;
mr.pad = nds.pad;
if(nds.isTouch) {
mr.touch.x = nds.touchX >> 4;
mr.touch.y = nds.touchY >> 4;
mr.touch.touch = 1;
} else {
mr.touch.x = 0;
mr.touch.y = 0;
mr.touch.touch = 0;
}
mr.dump(&currMovieData, osRecordingMovie,currMovieData.records.size());
currMovieData.records.push_back(mr);
osd->addFixed(180, 176, "%s", "Recording");
}
currFrameCounter++;
/*extern uint8 joy[4];
memcpy(&cur_input_display,joy,4);*/
}
//TODO
@ -570,38 +610,60 @@ static void FCEUMOV_AddCommand(int cmd)
}
static int FCEUMOV_WriteState(std::ostream* os)
void mov_savestate(std::ostream* os)
{
//we are supposed to dump the movie data into the savestate
//if(movieMode == MOVIEMODE_RECORD || movieMode == MOVIEMODE_PLAY)
// return currMovieData.dump(os, true);
//else return 0;
if(movieMode == MOVIEMODE_RECORD || movieMode == MOVIEMODE_PLAY)
return currMovieData.dump(os, true);
else return 0;
{
write32le('MOVI',os);
currMovieData.dump(os, true);
}
else
{
write32le('NOMO',os);
}
}
//TODO EVERYTHING BELOW
static bool load_successful;
static bool FCEUMOV_ReadState(std::istream* is, uint32 size)
bool mov_loadstate(std::istream* is, int size)
{
load_successful = false;
int cookie;
if(read32le(&cookie,is) != 1) return false;
if(cookie == 'NOMO')
return true;
else if(cookie != 'MOVI')
return false;
size -= 4;
if (!movie_readonly && autoMovieBackup && freshMovie) //If auto-backup is on, movie has not been altered this session and the movie is in read+write mode
{
FCEUI_MakeBackupMovie(false); //Backup the movie before the contents get altered, but do not display messages
}
//a little rule: cant load states in read+write mode with a movie from an archive.
//so we are going to switch it to readonly mode in that case
if(!movie_readonly
//*&& FCEU_isFileInArchive(curMovieFilename)*/
) {
FCEU_PrintError("Cannot loadstate in Read+Write with movie from archive. Movie is now Read-Only.");
movie_readonly = true;
}
// if(!movie_readonly
// //*&& FCEU_isFileInArchive(curMovieFilename)*/
// ) {
// FCEU_PrintError("Cannot loadstate in Read+Write with movie from archive. Movie is now Read-Only.");
// movie_readonly = true;
// }
MovieData tempMovieData = MovieData();
std::ios::pos_type curr = is->tellg();
if(!LoadFM2(tempMovieData, is, size, false)) {
/*is->seekg((uint32)curr+size);
extern bool FCEU_state_loading_old_format;
// is->seekg((uint32)curr+size);
/* extern bool FCEU_state_loading_old_format;
if(FCEU_state_loading_old_format) {
if(movieMode == MOVIEMODE_PLAY || movieMode == MOVIEMODE_RECORD) {
FCEUI_StopMovie();
@ -652,12 +714,29 @@ static bool FCEUMOV_ReadState(std::istream* is, uint32 size)
if(movie_readonly)
{
//-------------------------------------------------------------
//this code would reload the movie from disk. allegedly it is helpful to hexers, but
//it is way too slow with dsm format. so it is only here as a reminder, and in case someone
//wants to play with it
//-------------------------------------------------------------
//{
// fstream fs (curMovieFilename);
// if(!LoadFM2(tempMovieData, &fs, INT_MAX, false))
// {
// FCEU_PrintError("Failed to reload DSM after loading savestate");
// }
// fs.close();
// currMovieData = tempMovieData;
//}
//-------------------------------------------------------------
//if the frame counter is longer than our current movie, then error
if(currFrameCounter > (int)currMovieData.records.size())
{
FCEU_PrintError("Savestate is from a frame (%d) after the final frame in the movie (%d). This is not permitted.", currFrameCounter, currMovieData.records.size()-1);
return false;
}
movieMode = MOVIEMODE_PLAY;
}
else
@ -666,10 +745,10 @@ static bool FCEUMOV_ReadState(std::istream* is, uint32 size)
tempMovieData.truncateAt(currFrameCounter);
currMovieData = tempMovieData;
#ifdef _S9XLUA_H
if(!FCEU_LuaRerecordCountSkip())
// #ifdef _S9XLUA_H
// if(!FCEU_LuaRerecordCountSkip())
currRerecordCount++;
#endif
// #endif
currMovieData.rerecordCount = currRerecordCount;
@ -680,6 +759,7 @@ static bool FCEUMOV_ReadState(std::istream* is, uint32 size)
}
load_successful = true;
freshMovie = false;
//// Maximus: Show the last input combination entered from the
//// movie within the state
@ -722,3 +802,137 @@ bool FCEUI_MovieGetInfo(std::istream* fp, MOVIE_INFO& info, bool skipFrameCount)
return true;
}
bool MovieRecord::parseBinary(MovieData* md, std::istream* is)
{
commands=is->get();
is->read((char *) &pad, sizeof pad);
is->read((char *) &touch.x, sizeof touch.x);
is->read((char *) &touch.y, sizeof touch.y);
is->read((char *) &touch.touch, sizeof touch.touch);
return true;
}
void MovieRecord::dumpBinary(MovieData* md, std::ostream* os, int index)
{
os->put(md->records[index].commands);
os->write((char *) &md->records[index].pad, sizeof md->records[index].pad);
os->write((char *) &md->records[index].touch.x, sizeof md->records[index].touch.x);
os->write((char *) &md->records[index].touch.y, sizeof md->records[index].touch.y);
os->write((char *) &md->records[index].touch.touch, sizeof md->records[index].touch.touch);
}
void LoadFM2_binarychunk(MovieData& movieData, std::istream* fp, int size)
{
int recordsize = 1; //1 for the command
recordsize = 6;
assert(size%6==0);
//find out how much remains in the file
int curr = fp->tellg();
fp->seekg(0,std::ios::end);
int end = fp->tellg();
int flen = end-curr;
fp->seekg(curr,std::ios::beg);
//the amount todo is the min of the limiting size we received and the remaining contents of the file
int todo = std::min(size, flen);
int numRecords = todo/recordsize;
movieData.records.resize(numRecords);
for(int i=0;i<numRecords;i++)
{
movieData.records[i].parseBinary(&movieData,fp);
}
}
#include <sstream>
bool CheckFileExists(const char* filename)
{
//This function simply checks to see if the given filename exists
string checkFilename;
if (filename)
checkFilename = filename;
//Check if this filename exists
fstream test;
test.open(checkFilename.c_str(),fstream::in);
if (test.fail())
{
test.close();
return false;
}
else
{
test.close();
return true;
}
}
void FCEUI_MakeBackupMovie(bool dispMessage)
{
//This function generates backup movie files
string currentFn; //Current movie fillename
string backupFn; //Target backup filename
string tempFn; //temp used in back filename creation
stringstream stream;
int x; //Temp variable for string manip
bool exist = false; //Used to test if filename exists
bool overflow = false; //Used for special situation when backup numbering exceeds limit
currentFn = curMovieFilename; //Get current moviefilename
backupFn = curMovieFilename; //Make backup filename the same as current moviefilename
x = backupFn.find_last_of("."); //Find file extension
backupFn = backupFn.substr(0,x); //Remove extension
tempFn = backupFn; //Store the filename at this point
for (unsigned int backNum=0;backNum<999;backNum++) //999 = arbituary limit to backup files
{
stream.str(""); //Clear stream
if (backNum > 99)
stream << "-" << backNum; //assign backNum to stream
else if (backNum <=99 && backNum >= 10)
stream << "-0"; //Make it 010, etc if two digits
else
stream << "-00" << backNum; //Make it 001, etc if single digit
backupFn.append(stream.str()); //add number to bak filename
backupFn.append(".bak"); //add extension
exist = CheckFileExists(backupFn.c_str()); //Check if file exists
if (!exist)
break; //Yeah yeah, I should use a do loop or something
else
{
backupFn = tempFn; //Before we loop again, reset the filename
if (backNum == 999) //If 999 exists, we have overflowed, let's handle that
{
backupFn.append("-001.bak"); //We are going to simply overwrite 001.bak
overflow = true; //Flag that we have exceeded limit
break; //Just in case
}
}
}
MovieData md = currMovieData; //Get current movie data
std::fstream* outf = new fstream(backupFn.c_str(),std::ios_base::out); //FCEUD_UTF8_fstream(backupFn, "wb"); //open/create file
md.dump(outf,false); //dump movie data
delete outf; //clean up, delete file object
//TODO, decide if fstream successfully opened the file and print error message if it doesn't
if (dispMessage) //If we should inform the user
{
// if (overflow)
// FCEUI_DispMessage("Backup overflow, overwriting %s",backupFn.c_str()); //Inform user of overflow
// else
// FCEUI_DispMessage("%s created",backupFn.c_str()); //Inform user of backup filename
}
}

View File

@ -21,6 +21,7 @@ typedef struct
std::string name_of_rom_used;
std::vector<std::wstring> comments;
std::vector<std::string> subtitles;
} MOVIE_INFO;
enum EMOVIEMODE
@ -88,12 +89,12 @@ public:
void clear();
//a waste of memory in lots of cases.. maybe make it a pointer later?
std::vector<char> savestate;
//std::vector<char> savestate;
void parse(MovieData* md, std::istream* is);
//bool parseBinary(MovieData* md, std::istream* is);
bool parseBinary(MovieData* md, std::istream* is);
void dump(MovieData* md, std::ostream* os, int index);
//void dumpBinary(MovieData* md, std::ostream* os, int index);
void dumpBinary(MovieData* md, std::ostream* os, int index);
void parsePad(std::istream* is, u16& pad);
void dumpPad(std::ostream* os, u16 pad);
@ -178,6 +179,19 @@ private:
}
};
bool FCEUI_MovieGetInfo(std::istream* fp, MOVIE_INFO& info, bool skipFrameCount);
extern int currFrameCounter;
extern EMOVIEMODE movieMode; //adelikat: main needs this for frame counter display
extern MovieData currMovieData; //adelikat: main needs this for frame counter display
bool FCEUI_MovieGetInfo(std::istream* fp, MOVIE_INFO& info, bool skipFrameCount);
void FCEUI_SaveMovie(const char *fname, std::wstring author);
void FCEUI_LoadMovie(const char *fname, bool _read_only, bool tasedit, int _pauseframe);
void FCEUI_StopMovie();
void FCEUMOV_AddInputState();
void NDS_setTouchFromMovie(void);
void mov_savestate(std::ostream* os);
bool mov_loadstate(std::istream* is, int size);
void LoadFM2_binarychunk(MovieData& movieData, std::istream* fp, int size);
extern bool movie_readonly;
void FCEUI_MakeBackupMovie(bool dispMessage);
#endif

View File

@ -202,16 +202,16 @@ struct PolyAttr
} polyAttr;
union FragmentColor {
u32 color;
struct {
//#ifdef WORDS_BIGENDIAN ?
u8 r,g,b,a;
};
};
struct Fragment
{
union Color {
u32 color;
struct {
//#ifdef WORDS_BIGENDIAN ?
u8 r,g,b,a;
} components;
} color;
u32 depth;
struct {
@ -220,7 +220,7 @@ struct Fragment
u8 stencil;
u8 pad[5];
u8 pad;
};
static VERT* verts[MAX_CLIPPED_VERTS];
@ -231,6 +231,8 @@ INLINE static void SubmitVertex(int vert_index, VERT& rawvert)
}
static Fragment screen[256*192];
static FragmentColor screenColor[256*192];
FORCEINLINE int iround(float f) {
return (int)f; //lol
@ -300,7 +302,7 @@ static struct Sampler
}
}
FORCEINLINE Fragment::Color sample(float u, float v)
FORCEINLINE FragmentColor sample(float u, float v)
{
//finally, we can use floor here. but, it is slower than we want.
//the best solution is probably to wait until the pipeline is full of fixed point
@ -308,13 +310,8 @@ static struct Sampler
int iv = floorf(v);
dowrap(iu,iv);
Fragment::Color color;
u32 col32 = ((u32*)textures.currentData)[(iv<<wshift)+iu];
//todo - teach texcache how to provide these already in 5555
col32 >>= 3;
col32 &= 0x1F1F1F1F;
color.color = col32;
FragmentColor color;
color.color = ((u32*)textures.currentData)[(iv<<wshift)+iu];
return color;
}
@ -332,11 +329,11 @@ struct Shader
}
float invu, invv, w;
Fragment::Color materialColor;
FragmentColor materialColor;
FORCEINLINE void shade(Fragment& dst)
FORCEINLINE void shade(FragmentColor& dst)
{
Fragment::Color texColor;
FragmentColor texColor;
float u,v;
switch(mode)
@ -345,19 +342,19 @@ struct Shader
u = invu*w;
v = invv*w;
texColor = sampler.sample(u,v);
dst.color.components.r = modulate_table[texColor.components.r][materialColor.components.r];
dst.color.components.g = modulate_table[texColor.components.g][materialColor.components.g];
dst.color.components.b = modulate_table[texColor.components.b][materialColor.components.b];
dst.color.components.a = modulate_table[texColor.components.a][materialColor.components.a];
dst.r = modulate_table[texColor.r][materialColor.r];
dst.g = modulate_table[texColor.g][materialColor.g];
dst.b = modulate_table[texColor.b][materialColor.b];
dst.a = modulate_table[texColor.a][materialColor.a];
//dst.color.components.a = 31;
//#ifdef _MSC_VER
//if(GetAsyncKeyState(VK_SHIFT)) {
// //debugging tricks
// dst.color = materialColor;
// dst = materialColor;
// if(GetAsyncKeyState(VK_TAB)) {
// u8 alpha = dst.color.components.a;
// dst.color.color = polynum*8+8;
// dst.color.components.a = alpha;
// u8 alpha = dst.a;
// dst.color = polynum*8+8;
// dst.a = alpha;
// }
//}
//#endif
@ -366,37 +363,37 @@ struct Shader
u = invu*w;
v = invv*w;
texColor = sampler.sample(u,v);
dst.color.components.r = decal_table[texColor.components.a][texColor.components.r][materialColor.components.r];
dst.color.components.g = decal_table[texColor.components.a][texColor.components.g][materialColor.components.g];
dst.color.components.b = decal_table[texColor.components.a][texColor.components.b][materialColor.components.b];
dst.color.components.a = materialColor.components.a;
dst.r = decal_table[texColor.a][texColor.r][materialColor.r];
dst.g = decal_table[texColor.a][texColor.g][materialColor.g];
dst.b = decal_table[texColor.a][texColor.b][materialColor.b];
dst.a = materialColor.a;
break;
case 2: //toon/highlight shading
u = invu*w;
v = invv*w;
texColor = sampler.sample(u,v);
u32 toonColorVal; toonColorVal = gfx3d.rgbToonTable[materialColor.components.r];
Fragment::Color toonColor;
toonColor.components.r = ((toonColorVal & 0x0000FF) >> 3);
toonColor.components.g = ((toonColorVal & 0x00FF00) >> 11);
toonColor.components.b = ((toonColorVal & 0xFF0000) >> 19);
dst.color.components.r = modulate_table[texColor.components.r][toonColor.components.r];
dst.color.components.g = modulate_table[texColor.components.g][toonColor.components.g];
dst.color.components.b = modulate_table[texColor.components.b][toonColor.components.b];
dst.color.components.a = modulate_table[texColor.components.a][materialColor.components.a];
u32 toonColorVal; toonColorVal = gfx3d.rgbToonTable[materialColor.r];
FragmentColor toonColor;
toonColor.r = ((toonColorVal & 0x0000FF) >> 3);
toonColor.g = ((toonColorVal & 0x00FF00) >> 11);
toonColor.b = ((toonColorVal & 0xFF0000) >> 19);
dst.r = modulate_table[texColor.r][toonColor.r];
dst.g = modulate_table[texColor.g][toonColor.g];
dst.b = modulate_table[texColor.b][toonColor.b];
dst.a = modulate_table[texColor.a][materialColor.a];
if(gfx3d.shading == GFX3D::HIGHLIGHT)
{
dst.color.components.r = min<u8>(31, (dst.color.components.r + toonColor.components.r));
dst.color.components.g = min<u8>(31, (dst.color.components.g + toonColor.components.g));
dst.color.components.b = min<u8>(31, (dst.color.components.b + toonColor.components.b));
dst.r = min<u8>(31, (dst.r + toonColor.r));
dst.g = min<u8>(31, (dst.g + toonColor.g));
dst.b = min<u8>(31, (dst.b + toonColor.b));
}
break;
case 3: //shadows
//is this right? only with the material color?
dst.color = materialColor;
dst = materialColor;
break;
case 4: //our own special mode which only uses the material color (for when texturing is disabled)
dst.color = materialColor;
dst = materialColor;
break;
}
@ -404,44 +401,45 @@ struct Shader
} shader;
static FORCEINLINE void alphaBlend(Fragment::Color & dst, const Fragment::Color & src)
static FORCEINLINE void alphaBlend(FragmentColor & dst, const FragmentColor & src)
{
if(gfx3d.enableAlphaBlending)
{
if(src.components.a == 0)
if(src.a == 0)
{
dst.components.a = max(src.components.a,dst.components.a);
dst.a = max(src.a,dst.a);
}
else if(src.components.a == 31 || dst.components.a == 0)
else if(src.a == 31 || dst.a == 0)
{
dst.color = src.color;
dst.components.a = max(src.components.a,dst.components.a);
dst = src;
dst.a = max(src.a,dst.a);
}
else
{
u8 alpha = src.components.a+1;
u8 alpha = src.a+1;
u8 invAlpha = 32 - alpha;
dst.components.r = (alpha*src.components.r + invAlpha*dst.components.r)>>5;
dst.components.g = (alpha*src.components.g + invAlpha*dst.components.g)>>5;
dst.components.b = (alpha*src.components.b + invAlpha*dst.components.b)>>5;
dst.components.a = max(src.components.a,dst.components.a);
dst.r = (alpha*src.r + invAlpha*dst.r)>>5;
dst.g = (alpha*src.g + invAlpha*dst.g)>>5;
dst.b = (alpha*src.b + invAlpha*dst.b)>>5;
dst.a = max(src.a,dst.a);
}
}
else
{
if(src.components.a == 0)
if(src.a == 0)
{
//do nothing; the fragment is totally transparent
}
else
{
dst.color = src.color;
dst = src;
}
}
}
static FORCEINLINE void pixel(int adr,float r, float g, float b, float invu, float invv, float w, float z) {
Fragment &destFragment = screen[adr];
FragmentColor &destFragmentColor = screenColor[adr];
//depth test
u32 depth;
@ -483,25 +481,25 @@ static FORCEINLINE void pixel(int adr,float r, float g, float b, float invu, flo
//this is a HACK:
//we are being very sloppy with our interpolation precision right now
//and rather than fix it, i just want to clamp it
shader.materialColor.components.r = max(0,min(31,(int)r));
shader.materialColor.components.g = max(0,min(31,(int)g));
shader.materialColor.components.b = max(0,min(31,(int)b));
shader.materialColor.r = max(0,min(31,(int)r));
shader.materialColor.g = max(0,min(31,(int)g));
shader.materialColor.b = max(0,min(31,(int)b));
shader.materialColor.components.a = polyAttr.alpha;
shader.materialColor.a = polyAttr.alpha;
//pixel shader
Fragment shaderOutput;
FragmentColor shaderOutput;
shader.shade(shaderOutput);
//alpha test
if(gfx3d.enableAlphaTest)
{
if(shaderOutput.color.components.a < gfx3d.alphaTestRef)
if(shaderOutput.a < gfx3d.alphaTestRef)
goto rejected_fragment;
}
//we shouldnt do any of this if we generated a totally transparent pixel
if(shaderOutput.color.components.a != 0)
if(shaderOutput.a != 0)
{
//handle shadow polys
if(shader.mode == 3)
@ -538,7 +536,7 @@ static FORCEINLINE void pixel(int adr,float r, float g, float b, float invu, flo
}
//handle polyids
bool isOpaquePixel = shaderOutput.color.components.a == 31;
bool isOpaquePixel = shaderOutput.a == 31;
if(isOpaquePixel)
{
destFragment.polyid.opaque = polyAttr.polyid;
@ -566,7 +564,7 @@ static FORCEINLINE void pixel(int adr,float r, float g, float b, float invu, flo
}
//alpha blending and write color
alphaBlend(destFragment.color, shaderOutput.color);
alphaBlend(destFragmentColor, shaderOutput);
//depth writing
if(isOpaquePixel || polyAttr.translucentDepthWrite)
@ -930,7 +928,8 @@ static char SoftRastInit(void)
return 1;
}
static void SoftRastReset() {}
static void SoftRastReset() {
}
static void SoftRastClose()
{
@ -940,45 +939,32 @@ static void SoftRastVramReconfigureSignal() {
TexCache_Invalidate();
}
static void SoftRastGetLine(int line, u16* dst, u8* dstAlpha)
static void SoftRastConvertFramebuffer()
{
Fragment* src = screen+((line)<<8);
for(int i=0;i<256;i++)
{
const bool testRenderAlpha = false;
u8 r = src->color.components.r;
u8 g = src->color.components.g;
u8 b = src->color.components.b;
*dst = R5G5B5TORGB15(r,g,b);
if(src->color.components.a > 0)
*dst |= 0x8000;
*dstAlpha = alpha_5bit_to_4bit[src->color.components.a];
FragmentColor* src = screenColor;
u16* dst = gfx3d_convertedScreen;
u8* dstAlpha = gfx3d_convertedAlpha;
if(testRenderAlpha)
//in an effort to speed this up, the misc pixel buffers and the color buffer were separated.
for(int i=0,y=0;y<192;y++)
{
#ifndef NOSSE2
u8* wanx = (u8*)&src[i];
#define ASS(X,Y) __asm { prefetchnta [wanx+32*0x##X##Y] }
#define PUNK(X) ASS(X,0) ASS(X,1) ASS(X,2) ASS(X,3) ASS(X,4) ASS(X,5) ASS(X,6) ASS(X,7) ASS(X,8) ASS(X,9) ASS(X,A) ASS(X,B) ASS(X,C) ASS(X,D) ASS(X,E) ASS(X,F)
PUNK(0); PUNK(1);
#endif
for(int x=0;x<256;x++,i++)
{
*dst = 0x8000 | R5G5B5TORGB15(src->color.components.a,src->color.components.a,src->color.components.a);
*dstAlpha = 16;
const u8 r = src[i].r;
const u8 g = src[i].g;
const u8 b = src[i].b;
const u8 a = src[i].a;
dst[i] = R5G5B5TORGB15(r,g,b) | alpha_lookup[a];
dstAlpha[i] = alpha_5bit_to_4bit[a];
}
src++;
dst++;
dstAlpha++;
}
}
static void SoftRastGetLineCaptured(int line, u16* dst) {
Fragment* src = screen+((line)<<8);
for(int i=0;i<256;i++)
{
u8 r = src->color.components.r;
u8 g = src->color.components.g;
u8 b = src->color.components.b;
*dst = R5G5B5TORGB15(r,g,b);
if(src->color.components.a > 0)
*dst |= 0x8000;
src++;
dst++;
}
}
@ -1158,10 +1144,11 @@ static void clipPoly(POLY* poly)
static void SoftRastRender()
{
Fragment clearFragment;
clearFragment.color.components.r = gfx3d.clearColor&0x1F;
clearFragment.color.components.g = (gfx3d.clearColor>>5)&0x1F;
clearFragment.color.components.b = (gfx3d.clearColor>>10)&0x1F;
clearFragment.color.components.a = (gfx3d.clearColor>>16)&0x1F;
FragmentColor clearFragmentColor;
clearFragmentColor.r = gfx3d.clearColor&0x1F;
clearFragmentColor.g = (gfx3d.clearColor>>5)&0x1F;
clearFragmentColor.b = (gfx3d.clearColor>>10)&0x1F;
clearFragmentColor.a = (gfx3d.clearColor>>16)&0x1F;
clearFragment.polyid.opaque = (gfx3d.clearColor>>24)&0x3F;
//special value for uninitialized translucent polyid. without this, fires in spiderman2 dont display
//I am not sure whether it is right, though. previously this was cleared to 0, as a guess,
@ -1171,6 +1158,8 @@ static void SoftRastRender()
clearFragment.stencil = 0;
for(int i=0;i<256*192;i++)
screen[i] = clearFragment;
for(int i=0;i<256*192;i++)
screenColor[i] = clearFragmentColor;
//convert colors to float to get more precision in case we need it
for(int i=0;i<gfx3d.vertlist->count;i++)
@ -1269,7 +1258,7 @@ static void SoftRastRender()
if(needInitTexture || lastTextureFormat != poly->texParam || lastTexturePalette != poly->texPalette)
{
TexCache_SetTexture(poly->texParam,poly->texPalette);
TexCache_SetTexture<TexFormat_15bpp>(poly->texParam,poly->texPalette);
sampler.setup(poly->texParam);
lastTextureFormat = poly->texParam;
lastTexturePalette = poly->texPalette;
@ -1294,6 +1283,7 @@ static void SoftRastRender()
// printf("rendered %d of %d polys after backface culling\n",gfx3d.polylist->count-culled,gfx3d.polylist->count);
SoftRastConvertFramebuffer();
}
GPU3DInterface gpu3DRasterize = {
@ -1303,6 +1293,4 @@ GPU3DInterface gpu3DRasterize = {
SoftRastClose,
SoftRastRender,
SoftRastVramReconfigureSignal,
SoftRastGetLine,
SoftRastGetLineCaptured
};

View File

@ -24,8 +24,6 @@ int cur3DCore = GPU3D_NULL;
static void NDS_nullFunc1 (void){}
static char NDS_nullFunc2 (void){ return 1; }
static void NDS_nullFunc3 (int,unsigned short*) {}
static void NDS_nullFunc4 (int,unsigned short*,unsigned char*) {}
GPU3DInterface gpu3DNull = {
"None",
@ -34,8 +32,6 @@ GPU3DInterface gpu3DNull = {
NDS_nullFunc1, //NDS_3D_Close
NDS_nullFunc1, //NDS_3D_Render
NDS_nullFunc1, //NDS_3D_VramReconfigureSignal
NDS_nullFunc4, //NDS_3D_GetLine
NDS_nullFunc3 //NDS_3D_GetLineCaptured
};
GPU3DInterface *gpu3D = &gpu3DNull;

View File

@ -21,6 +21,8 @@
#ifndef RENDER3D_H
#define RENDER3D_H
#include "types.h"
//not using this right now
#define CALL_CONVENTION
@ -44,13 +46,6 @@ typedef struct Render3DInterface
//called when the emulator reconfigures its vram. you may need to invalidate your texture cache.
void (CALL_CONVENTION* NDS_3D_VramReconfigureSignal) ();
//Retrieves a line of color buffer data
void (CALL_CONVENTION* NDS_3D_GetLine) (int line, unsigned short* dst, unsigned char* dstAlpha);
//Retrieves a line of color buffer data for capture
void (CALL_CONVENTION* NDS_3D_GetLineCaptured) (int line, unsigned short* dst);
} GPU3DInterface;
extern int cur3DCore;

View File

@ -33,6 +33,7 @@
#ifdef WIN32
#include "windows/main.h"
#endif
#include "movie.h"
typedef struct
{
@ -81,24 +82,26 @@ struct movietime movie;
int oldframeCounter;
u64 totalcycles=2904024960000ULL;//noon
int totalseconds;
bool init=false;
bool moviemode=false;
#ifdef WIN32
static void MovieTime(void) {
if(!init) {
void InitMovieTime(void) {
movie.year=9;
movie.month=1;
movie.monthday=1;
movie.weekday=4;
oldframeCounter=0;
init=true;
}
if(frameCounter > oldframeCounter) {
}
#ifdef WIN32
static void MovieTime(void) {
if(currFrameCounter > oldframeCounter) {
int difference;
difference=frameCounter-oldframeCounter;
oldframeCounter=frameCounter;
difference=currFrameCounter-oldframeCounter;
oldframeCounter=currFrameCounter;
totalcycles+=((560190<<1)*difference);
}
@ -143,7 +146,7 @@ static void rtcRecv()
tm_local->tm_year %= 100;
tm_local->tm_mon++;
if(moviemode) {
if(movieMode != MOVIEMODE_INACTIVE) {
MovieTime();
@ -177,7 +180,7 @@ static void rtcRecv()
time(&tm);
struct tm *tm_local= localtime(&tm);
if(moviemode) {
if(movieMode != MOVIEMODE_INACTIVE) {
MovieTime();

View File

@ -30,4 +30,6 @@
extern void rtcInit();
extern u16 rtcRead();
extern void rtcWrite(u16 val);
void InitMovieTime(void);
#endif

View File

@ -36,6 +36,8 @@
#include "memorystream.h"
#include "readwrite.h"
#include "gfx3d.h"
#include "movie.h"
#include "windows/main.h"
//void*v is actually a void** which will be indirected before reading
@ -129,8 +131,8 @@ SFORMAT SF_ARM9[]={
};
SFORMAT SF_MEM[]={
{ "ITCM", 1, 0x8000, ARM9Mem.ARM9_ITCM},
{ "DTCM", 1, 0x4000, ARM9Mem.ARM9_DTCM},
{ "ITCM", 1, sizeof(ARM9Mem.ARM9_ITCM), ARM9Mem.ARM9_ITCM},
{ "DTCM", 1, sizeof(ARM9Mem.ARM9_DTCM), ARM9Mem.ARM9_DTCM},
//for legacy purposes, WRAX is a separate variable. shouldnt be a problem.
{ "WRAM", 1, 0x400000, ARM9Mem.MAIN_MEM},
@ -141,9 +143,9 @@ SFORMAT SF_MEM[]={
//but there are actually no more registers than this
{ "9REG", 1, 0x2000, ARM9Mem.ARM9_REG},
{ "VMEM", 1, 0x800, ARM9Mem.ARM9_VMEM},
{ "OAMS", 1, 0x800, ARM9Mem.ARM9_OAM},
{ "LCDM", 1, 0xA4000, ARM9Mem.ARM9_LCD},
{ "VMEM", 1, sizeof(ARM9Mem.ARM9_VMEM), ARM9Mem.ARM9_VMEM},
{ "OAMS", 1, sizeof(ARM9Mem.ARM9_OAM), ARM9Mem.ARM9_OAM},
{ "LCDM", 1, sizeof(ARM9Mem.ARM9_LCD), ARM9Mem.ARM9_LCD},
{ 0 }
};
@ -169,15 +171,12 @@ extern u32 DMASrc[2][4];
extern u32 DMADst[2][4];
SFORMAT SF_MMU[]={
{ "M7BI", 1, 0x4000, MMU.ARM7_BIOS},
{ "M7ER", 1, 0x10000, MMU.ARM7_ERAM},
{ "M7RG", 1, 0x10000, MMU.ARM7_REG},
{ "M7WI", 1, 0x10000, MMU.ARM7_WIRAM},
{ "MVRM", 1, 4, MMU.VRAM_MAP},
{ "MVRM", 4, 9, MMU.LCD_VRAM_ADDR},
{ "MVRM", 1, 9, MMU.LCDCenable},
{ "MSWI", 1, 0x8000, MMU.SWIRAM},
{ "MCRA", 1, 0x10000, MMU.CART_RAM},
{ "M7BI", 1, sizeof(MMU.ARM7_BIOS), MMU.ARM7_BIOS},
{ "M7ER", 1, sizeof(MMU.ARM7_ERAM), MMU.ARM7_ERAM},
{ "M7RG", 1, sizeof(MMU.ARM7_REG), MMU.ARM7_REG},
{ "M7WI", 1, sizeof(MMU.ARM7_WIRAM), MMU.ARM7_WIRAM},
{ "MSWI", 1, sizeof(MMU.SWIRAM), MMU.SWIRAM},
{ "MCRA", 1, sizeof(MMU.CART_RAM), MMU.CART_RAM},
{ "M9RW", 1, 1, &MMU.ARM9_RW_MODE},
{ "MDTC", 4, 1, &MMU.DTCMRegion},
{ "MITC", 4, 1, &MMU.ITCMRegion},
@ -229,37 +228,46 @@ SFORMAT SF_MMU[]={
//fifos
{ "F0TL", 1, 1, &ipc_fifo[0].tail},
{ "F0BF", 4, 16, &ipc_fifo[0].buf[0]},
{ "F0BF", 4, 16, ipc_fifo[0].buf},
{ "F1TL", 1, 1, &ipc_fifo[1].tail},
{ "F1BF", 4, 16, &ipc_fifo[1].buf[0]},
{ "F1BF", 4, 16, ipc_fifo[1].buf},
{ "FDHD", 4, 1, &disp_fifo.head},
{ "FDTL", 4, 1, &disp_fifo.tail},
{ "FDBF", 4, 0x6000, &disp_fifo.buf[0]},
{ "FDBF", 4, 0x6000, disp_fifo.buf},
{ 0 }
};
SFORMAT SF_MOVIE[]={
{ "FRAC", 4, 1, &currFrameCounter},
{ "LAGC", 4, 1, &TotalLagFrames},
{ 0 }
};
static void mmu_savestate(std::ostream* os)
{
//version
write32le(0,os);
write32le(MMU.bupmem.type,os);
write32le(MMU.bupmem.size,os);
os->write((char*)MMU.bupmem.data,MMU.bupmem.size);
}
static bool mmu_loadstate(std::istream* is)
static bool mmu_loadstate(std::istream* is, int size)
{
//read version
int version;
if(read32le(&version,is) != 1) return false;
if(version != 0) return false;
int bupmem_type;
u32 bupmem_size;
if(read32le(&bupmem_type,is) != 1) return false;
if(read32le(&bupmem_size,is) != 1) return false;
if(bupmem_size != MMU.bupmem.size) return false; //mismatch between current initialized and saved size
mc_realloc(&MMU.bupmem,bupmem_type,bupmem_size);
is->read((char*)MMU.bupmem.data,bupmem_size);
if(is->fail()) return false;
@ -364,7 +372,7 @@ static bool cp15_loadone(armcp15_t *cp15, std::istream* is)
return true;
}
static bool cp15_loadstate(std::istream* is)
static bool cp15_loadstate(std::istream* is, int size)
{
//read version
int version;
@ -633,6 +641,9 @@ static int savestate_WriteChunk(std::ostream* os, int type, SFORMAT *sf)
return (bsize+8);
}
//TODO TODO TODO TODO TODO TODO TODO
// - this is retarded. why not write placeholders for size and then write directly to the stream
//and then go back and fill them in
static void savestate_WriteChunk(std::ostream* os, int type, void (*saveproc)(std::ostream* os))
{
//get the size
@ -657,6 +668,16 @@ static bool savestate_save(std::ostream* outstream, int compressionLevel)
writechunks(os);
ms.flush();
for(int i=0x2000;i<0x1000000;i++)
if(ARM9Mem.ARM9_REG[i] != 0) {
MessageBox(0,"Debug check fail: ARM9Mem.ARM9_REG",0,0);
}
for(int i=0;i<0x20000;i++)
if(ARM9Mem.blank_memory[i] != 0) {
MessageBox(0,"Debug check fail: ARM9Mem.blank_memory",0,0);
}
//save the length of the file
u32 len = ms.size();
@ -730,6 +751,8 @@ static void writechunks(std::ostream* os) {
savestate_WriteChunk(os,8,spu_savestate);
savestate_WriteChunk(os,90,SF_GFX3D);
savestate_WriteChunk(os,91,gfx3d_savestate);
savestate_WriteChunk(os,100,SF_MOVIE);
savestate_WriteChunk(os,101,mov_savestate);
savestate_WriteChunk(os,0xFFFFFFFF,(SFORMAT*)0);
}
@ -747,15 +770,17 @@ static bool ReadStateChunks(std::istream* is, s32 totalsize)
{
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(!cp15_loadstate(is)) ret=false; break;
case 3: if(!cp15_loadstate(is,size)) ret=false; break;
case 4: if(!ReadStateChunk(is,SF_MEM,size)) ret=false; break;
case 5: if(!ReadStateChunk(is,SF_NDS,size)) ret=false; break;
case 60: if(!ReadStateChunk(is,SF_MMU,size)) ret=false; break;
case 61: if(!mmu_loadstate(is)) ret=false; break;
case 7: if(!gpu_loadstate(is)) ret=false; break;
case 8: if(!spu_loadstate(is)) ret=false; break;
case 61: if(!mmu_loadstate(is,size)) ret=false; break;
case 7: if(!gpu_loadstate(is,size)) ret=false; break;
case 8: if(!spu_loadstate(is,size)) ret=false; break;
case 90: if(!ReadStateChunk(is,SF_GFX3D,size)) ret=false; break;
case 91: if(!gfx3d_loadstate(is)) ret=false; break;
case 91: if(!gfx3d_loadstate(is,size)) ret=false; break;
case 100: if(!ReadStateChunk(is,SF_MOVIE, size)) ret=false; break;
case 101: if(!mov_loadstate(is, size)) ret=false; break;
default:
ret=false;
break;
@ -842,13 +867,22 @@ static bool savestate_load(std::istream* is)
memorystream mstemp(&buf);
bool x = ReadStateChunks(&mstemp,(s32)len);
if(!x)
{
printf("Error loading savestate. It failed halfway through;\nSince there is no savestate backup system, your current game session is wrecked");
#ifdef _MSC_VER
MessageBox(0,"Error loading savestate. It failed halfway through;\nSince there is no savestate backup system, your current game session is wrecked",0,0);
#endif
return false;
}
loadstate();
if((nds.debugConsole!=0) != CommonSettings.DebugConsole) {
printf("WARNING: forcing console debug mode to: debugmode=%s\n",nds.debugConsole?"TRUE":"FALSE");
}
return x;
return true;
}
bool savestate_load(const char *file_name)

View File

@ -12,6 +12,7 @@
using std::min;
using std::max;
//only dump this from ogl renderer. for now, softrasterizer creates things in an incompatible pixel format
//#define DEBUG_DUMP_TEXTURE
//This class represents a number of regions of memory which should be viewed as contiguous
@ -150,7 +151,11 @@ static void DebugDumpTexture(int which)
static int lastTexture = -1;
void TexCache_SetTexture(unsigned int format, unsigned int texpal)
#define CONVERT(color,alpha) ((TEXFORMAT == TexFormat_32bpp)?(RGB15TO32(color,alpha)):RGB15TO5555(color,alpha))
template<TexCache_TexFormat TEXFORMAT>
void TexCache_SetTexture(u32 format, u32 texpal)
{
//for each texformat, number of palette entries
const int palSizes[] = {0, 32, 4, 16, 256, 0, 8, 0};
@ -309,7 +314,8 @@ REJECT:
//INFO("Texture %03i - format=%08X; pal=%04X (mode %X, width %04i, height %04i)\n",i, texcache[i].frm, texcache[i].pal, texcache[i].mode, sizeX, sizeY);
//============================================================================ Texture conversion
u32 palZeroTransparent = (1-((format>>29)&1))*255; // shash: CONVERT THIS TO A TABLE :)
const u32 opaqueColor = TEXFORMAT==TexFormat_32bpp?255:31;
u32 palZeroTransparent = (1-((format>>29)&1))*opaqueColor;
switch (texcache[tx].mode)
{
@ -321,7 +327,10 @@ REJECT:
{
u16 c = pal[*adr&31];
u8 alpha = *adr>>5;
*dwdst++ = RGB15TO32(c,material_3bit_to_8bit[alpha]);
if(TEXFORMAT == TexFormat_15bpp)
*dwdst++ = RGB15TO5555(c,material_3bit_to_5bit[alpha]);
else
*dwdst++ = RGB15TO32(c,material_3bit_to_8bit[alpha]);
adr++;
}
}
@ -339,19 +348,19 @@ REJECT:
bits = (*adr)&0x3;
c = pal[bits];
*dwdst++ = RGB15TO32(c,(bits == 0) ? palZeroTransparent : 255);
*dwdst++ = CONVERT(c,(bits == 0) ? palZeroTransparent : opaqueColor);
bits = ((*adr)>>2)&0x3;
c = pal[bits];
*dwdst++ = RGB15TO32(c,(bits == 0) ? palZeroTransparent : 255);
*dwdst++ = CONVERT(c,(bits == 0) ? palZeroTransparent : opaqueColor);
bits = ((*adr)>>4)&0x3;
c = pal[bits];
*dwdst++ = RGB15TO32(c,(bits == 0) ? palZeroTransparent : 255);
*dwdst++ = CONVERT(c,(bits == 0) ? palZeroTransparent : opaqueColor);
bits = ((*adr)>>6)&0x3;
c = pal[bits];
*dwdst++ = RGB15TO32(c,(bits == 0) ? palZeroTransparent : 255);
*dwdst++ = CONVERT(c,(bits == 0) ? palZeroTransparent : opaqueColor);
adr++;
}
@ -369,11 +378,11 @@ REJECT:
bits = (*adr)&0xF;
c = pal[bits];
*dwdst++ = RGB15TO32(c,(bits == 0) ? palZeroTransparent : 255);
*dwdst++ = CONVERT(c,(bits == 0) ? palZeroTransparent : opaqueColor);
bits = ((*adr)>>4);
c = pal[bits];
*dwdst++ = RGB15TO32(c,(bits == 0) ? palZeroTransparent : 255);
*dwdst++ = CONVERT(c,(bits == 0) ? palZeroTransparent : opaqueColor);
adr++;
}
}
@ -386,7 +395,7 @@ REJECT:
for(u32 x = 0; x < ms.items[j].len; ++x)
{
u16 c = pal[*adr];
*dwdst++ = RGB15TO32(c,(*adr == 0) ? palZeroTransparent : 255);
*dwdst++ = CONVERT(c,(*adr == 0) ? palZeroTransparent : opaqueColor);
adr++;
}
}
@ -444,7 +453,7 @@ REJECT:
u16 pal1offset = (pal1 & 0x3FFF)<<1;
u8 mode = pal1>>14;
u32 tmp_col[4];
tmp_col[0]=RGB16TO32(PAL4X4(pal1offset),255);
tmp_col[1]=RGB16TO32(PAL4X4(pal1offset+1),255);
@ -492,6 +501,17 @@ REJECT:
}
}
if(TEXFORMAT==TexFormat_15bpp)
{
for(int i=0;i<4;i++)
{
tmp_col[i] >>= 3;
tmp_col[i] &= 0x1F1F1F1F;
}
}
//TODO - this could be more precise for 32bpp mode (run it through the color separation table)
//set all 16 texels
for (int sy = 0; sy < 4; sy++)
{
@ -520,7 +540,10 @@ REJECT:
{
u16 c = pal[*adr&0x07];
u8 alpha = (*adr>>3);
*dwdst++ = RGB15TO32(c,material_5bit_to_8bit[alpha]);
if(TEXFORMAT == TexFormat_15bpp)
*dwdst++ = RGB15TO5555(c,alpha);
else
*dwdst++ = RGB15TO32(c,material_5bit_to_8bit[alpha]);
adr++;
}
}
@ -533,8 +556,8 @@ REJECT:
for(u32 x = 0; x < ms.items[j].len; ++x)
{
u16 c = map[x];
int alpha = ((c&0x8000)?255:0);
*dwdst++ = RGB15TO32(c&0x7FFF,alpha);
int alpha = ((c&0x8000)?opaqueColor:0);
*dwdst++ = CONVERT(c&0x7FFF,alpha);
}
}
break;
@ -585,3 +608,7 @@ void TexCache_Invalidate()
void (*TexCache_BindTexture)(u32 texnum) = NULL;
void (*TexCache_BindTextureData)(u32 texnum, u8* data);
//these templates needed to be instantiated manually
template void TexCache_SetTexture<TexFormat_32bpp>(u32 format, u32 texpal);
template void TexCache_SetTexture<TexFormat_15bpp>(u32 format, u32 texpal);

View File

@ -3,8 +3,14 @@
#include "common.h"
enum TexCache_TexFormat
{
TexFormat_32bpp,
TexFormat_15bpp
};
#define MAX_TEXTURE 500
#ifdef SSE2
#ifndef NOSSE2
struct ALIGN(16) TextureCache
#else
struct ALIGN(8) TextureCache
@ -36,7 +42,10 @@ extern void (*TexCache_BindTexture)(u32 texnum);
extern void (*TexCache_BindTextureData)(u32 texnum, u8* data);
void TexCache_Reset();
void TexCache_SetTexture(unsigned int format, unsigned int texpal);
template<TexCache_TexFormat format>
void TexCache_SetTexture(u32 format, u32 texpal);
void TexCache_Invalidate();
extern u8 TexCache_texMAP[1024*2048*4];

View File

@ -76,7 +76,7 @@
#endif
#define DESMUME_VERSION_NUMERIC 90300
#define DESMUME_VERSION_STRING " " "0.9.3 svn" DESMUME_FEATURE_STRING DESMUME_PLATFORM_STRING DESMUME_CPUEXT_STRING DESMUME_SUBVERSION_STRING DESMUME_COMPILER
#define DESMUME_VERSION_STRING " " "0.9.2-rr" DESMUME_FEATURE_STRING DESMUME_PLATFORM_STRING DESMUME_CPUEXT_STRING DESMUME_SUBVERSION_STRING DESMUME_COMPILER
#define DESMUME_NAME_AND_VERSION " " DESMUME_NAME DESMUME_VERSION_STRING
#ifdef _WIN32
@ -112,6 +112,13 @@
#endif
#endif
#ifdef _MSC_VER
#define _CDECL_ __cdecl
#else
#define _CDECL_
#endif
#ifndef INLINE
#if defined(_MSC_VER) || defined(__INTEL_COMPILER)
#define INLINE _inline

View File

@ -927,7 +927,7 @@ u16 WIFI_read16(wifimac_t *wifi,u32 address)
//printf("wifi: read reg 0x0214\n");
return 0x0009;
case 0x19C:
assert(false); //luigi, please pick something to return from here
//assert(false); //luigi, please pick something to return from here
return 0;
default:
// printf("wifi: read unhandled reg %03X\n", address);

View File

@ -647,6 +647,22 @@
RelativePath=".\palView.h"
>
</File>
<File
RelativePath=".\ram_search.cpp"
>
</File>
<File
RelativePath=".\ramwatch.cpp"
>
</File>
<File
RelativePath=".\ramwatch.h"
>
</File>
<File
RelativePath=".\replay.cpp"
>
</File>
<File
RelativePath=".\resource.h"
>

View File

@ -52,7 +52,7 @@
EnableFiberSafeOptimizations="false"
WholeProgramOptimization="false"
AdditionalIncludeDirectories=".;..;.\zlib123;.\zziplib;.\winpcap"
PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32;BETA_VERSION;SPU_INTERPOLATE;NOMINMAX;EXPERIMENTAL_WIFI"
PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;WIN32;BETA_VERSION;SPU_INTERPOLATE;NOMINMAX;EXPERIMENTAL_WIFI;HAVE_LIBZZIP;HAVE_LIBZ"
ExceptionHandling="1"
BufferSecurityCheck="false"
EnableEnhancedInstructionSet="0"
@ -550,6 +550,10 @@
RelativePath="..\MMU.cpp"
>
</File>
<File
RelativePath="..\movie.cpp"
>
</File>
<File
RelativePath="..\NDSSystem.cpp"
>
@ -964,6 +968,22 @@
RelativePath=".\palView.cpp"
>
</File>
<File
RelativePath=".\ram_search.cpp"
>
</File>
<File
RelativePath=".\ramwatch.cpp"
>
</File>
<File
RelativePath=".\replay.cpp"
>
</File>
<File
RelativePath=".\replay.h"
>
</File>
<File
RelativePath=".\snddx.cpp"
>
@ -1074,6 +1094,14 @@
RelativePath=".\palView.h"
>
</File>
<File
RelativePath=".\ram_search.h"
>
</File>
<File
RelativePath=".\ramwatch.h"
>
</File>
<File
RelativePath=".\resource.h"
>
@ -1202,6 +1230,10 @@
RelativePath="..\MMU.h"
>
</File>
<File
RelativePath="..\movie.h"
>
</File>
<File
RelativePath="..\NDSSystem.h"
>
@ -1277,6 +1309,10 @@
Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav"
UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}"
>
<File
RelativePath=".\bitmap1.bmp"
>
</File>
<File
RelativePath=".\DeSmuME.ico"
>
@ -1288,5 +1324,9 @@
</Filter>
</Files>
<Globals>
<Global
Name="RESOURCE_FILE"
Value="resources.rc"
/>
</Globals>
</VisualStudioProject>

View File

@ -414,11 +414,15 @@ void DRV_AviVideoUpdate(const u16* buffer)
AviNextSegment();
}
BOOL AVI_IsRecording()
{
return avi_file && avi_file->valid;
}
void DRV_AviSoundUpdate(void* soundData, int soundLen)
{
int nBytes;
if(!avi_file || !avi_file->valid || !avi_file->sound_added)
if(!AVI_IsRecording() || !avi_file->sound_added)
return;
nBytes = soundLen * avi_file->wave_format.nBlockAlign;

View File

@ -27,6 +27,7 @@
#include "render3d.h"
#include "throttle.h"
#include "../mic.h"
#include "../movie.h"
extern LRESULT OpenFile(); //adelikat: Made this an extern here instead of main.h Seemed icky not to limit the scope of this function
@ -154,9 +155,7 @@ void HK_MicrophoneKeyUp(int) {MicButtonPressed =0;}
void HK_AutoHoldClearKeyDown(int) {
for (int i=0; i < 10; i++) {
AutoHold.hold(i)=false;
}
ClearAutoHold();
}
void HK_Reset(int) {ResetGame();}
@ -168,6 +167,13 @@ void HK_ToggleFrame(int) {frameCounterDisplay ^= true;}
void HK_ToggleFPS(int) {FpsDisplay ^= true;}
void HK_ToggleInput(int) {ShowInputDisplay ^= true;}
void HK_ToggleLag(int) {ShowLagFrameCounter ^= true;}
void HK_ToggleReadOnly(int) {
movie_readonly ^= true;
if(movie_readonly)
SetMessageToDisplay("Read Only");
else
SetMessageToDisplay("Read+Write");
}
void HK_AutoHoldKeyDown(int) {AutoHoldPressed = true;}
void HK_AutoHoldKeyUp(int) {AutoHoldPressed = false;}
@ -178,6 +184,12 @@ void HK_TurboRightKeyUp(int) { Turbo.Right = false; }
void HK_TurboLeftKeyDown(int) { Turbo.Left = true; }
void HK_TurboLeftKeyUp(int) { Turbo.Left = false; }
void HK_TurboRKeyDown(int) { Turbo.R = true; }
void HK_TurboRKeyUp(int) { Turbo.R = false; }
void HK_TurboLKeyDown(int) { Turbo.L = true; }
void HK_TurboLKeyUp(int) { Turbo.L = false; }
void HK_TurboDownKeyDown(int) { Turbo.Down = true; }
void HK_TurboDownKeyUp(int) { Turbo.Down = false; }
@ -208,7 +220,9 @@ void HK_FastForwardKeyDown(int) { FastForward = 1; }
void HK_FastForwardKeyUp(int) { FastForward = 0; }
void HK_IncreaseSpeed(int) { IncreaseSpeed(); }
void HK_DecreaseSpeed(int) { DecreaseSpeed(); }
void HK_FrameAdvance(int) { FrameAdvance(); }
void HK_FrameAdvanceKeyDown(int) { FrameAdvance(true); }
void HK_FrameAdvanceKeyUp(int) { FrameAdvance(false); }
void HK_ToggleRasterizer(int) {
if(cur3DCore == GPU3D_OPENGL)
cur3DCore = GPU3D_SWRAST;
@ -261,7 +275,8 @@ void InitCustomKeys (SCustomKeys *keys)
keys->Pause.page = HOTKEY_PAGE_MAIN;
keys->Pause.key = VK_SPACE;
keys->FrameAdvance.handleKeyDown = HK_FrameAdvance;
keys->FrameAdvance.handleKeyDown = HK_FrameAdvanceKeyDown;
keys->FrameAdvance.handleKeyUp = HK_FrameAdvanceKeyUp;
keys->FrameAdvance.code = "FrameAdvance";
keys->FrameAdvance.name = L"Frame Advance";
keys->FrameAdvance.page = HOTKEY_PAGE_MAIN;
@ -348,6 +363,12 @@ void InitCustomKeys (SCustomKeys *keys)
keys->ToggleLag.page = HOTKEY_PAGE_MAIN;
keys->ToggleLag.key = NULL;
keys->ToggleReadOnly.handleKeyDown = HK_ToggleReadOnly;
keys->ToggleReadOnly.code = "ToggleReadOnly";
keys->ToggleReadOnly.name = L"Toggle Read Only";
keys->ToggleReadOnly.page = HOTKEY_PAGE_MAIN;
keys->ToggleReadOnly.key = NULL;
keys->RecordAVI.handleKeyDown = HK_RecordAVI;
keys->RecordAVI.code = "RecordAVI";
keys->RecordAVI.name = L"Record AVI";
@ -375,6 +396,20 @@ void InitCustomKeys (SCustomKeys *keys)
keys->TurboLeft.page = HOTKEY_PAGE_TURBO;
keys->TurboLeft.key = NULL;
keys->TurboR.handleKeyDown = HK_TurboRKeyDown;
keys->TurboR.handleKeyUp = HK_TurboRKeyUp;
keys->TurboR.code = "TurboR";
keys->TurboR.name = L"Turbo R";
keys->TurboR.page = HOTKEY_PAGE_TURBO;
keys->TurboR.key = NULL;
keys->TurboL.handleKeyDown = HK_TurboLKeyDown;
keys->TurboL.handleKeyUp = HK_TurboLKeyUp;
keys->TurboL.code = "TurboL";
keys->TurboL.name = L"Turbo L";
keys->TurboL.page = HOTKEY_PAGE_TURBO;
keys->TurboL.key = NULL;
keys->TurboDown.handleKeyDown = HK_TurboDownKeyDown;
keys->TurboDown.handleKeyUp = HK_TurboDownKeyUp;
keys->TurboDown.code = "TurboDown";

View File

@ -67,7 +67,7 @@ struct SCustomKeys
SCustomKey OpenROM, Reset, Pause, FrameAdvance, FastForward, FastForwardToggle, IncreaseSpeed, DecreaseSpeed, Microphone;
SCustomKey TurboRight, TurboLeft, TurboDown, TurboUp, TurboSelect, TurboStart, TurboB, TurboA, TurboY, TurboX;
SCustomKey TurboRight, TurboLeft, TurboDown, TurboUp, TurboSelect, TurboStart, TurboB, TurboA, TurboY, TurboX, TurboR, TurboL;
SCustomKey AutoHold, AutoHoldClear;
@ -80,6 +80,7 @@ struct SCustomKeys
SCustomKey ToggleFPS;
SCustomKey ToggleInput;
SCustomKey ToggleLag;
SCustomKey ToggleReadOnly;
SCustomKey LastItem; // dummy, must be last
//--methods--

View File

@ -69,13 +69,17 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#include "throttle.h"
#include "gbaslot_config.h"
#include "cheatsWin.h"
#include "Mmsystem.h"
#include "../mic.h"
#include "../common.h"
#include "main.h"
#include "hotkey.h"
#include "../movie.h"
#include "../replay.h"
#include "snddx.h"
#include "ramwatch.h"
#include "ram_search.h"
#include "directx/ddraw.h"
@ -91,8 +95,8 @@ using namespace std;
//----Recent ROMs menu globals----------
vector<string> RecentRoms; //The list of recent ROM filenames
const unsigned int MAX_RECENT_ROMS = 10; //To change the recent rom max, simply change this number
const unsigned int clearid = 600; // ID for the Clear recent ROMs item
const unsigned int baseid = 601; //Base identifier for the recent ROMs items
const unsigned int clearid = IDM_RECENT_RESERVED0; // ID for the Clear recent ROMs item
const unsigned int baseid = IDM_RECENT_RESERVED1; //Base identifier for the recent ROMs items
static HMENU recentromsmenu; //Handle to the recent ROMs submenu
//--------------------------------------
@ -107,6 +111,10 @@ void DRV_AviSoundUpdate(void* soundData, int soundLen);
bool DRV_AviIsRecording();
void DRV_AviVideoUpdate(const u16* buffer);
//------
DWORD hKeyInputTimer;
extern LRESULT CALLBACK RamSearchProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);
CRITICAL_SECTION win_sync;
volatile int win_sound_samplecounter = 0;
@ -157,6 +165,7 @@ int WndX = 0;
int WndY = 0;
int ScreenGap = 0;
extern HWND RamSearchHWnd;
static int FrameLimit = 1;
@ -215,9 +224,8 @@ GPU3DInterface *core3DList[] = {
int autoframeskipenab=0;
int frameskiprate=0;
int emu_paused = 0;
static int backupmemorytype=MC_TYPE_AUTODETECT;
static u32 backupmemorysize=1;
unsigned int frameCounter=0;
int backupmemorytype=MC_TYPE_AUTODETECT;
u32 backupmemorysize=1;
bool frameAdvance = false;
bool frameCounterDisplay = false;
bool FpsDisplay = false;
@ -343,10 +351,10 @@ void ResetHud(HudStruct *hudstruct) {
SetHudDummy(&hudstruct->Dummy);
}
unsigned int lastSaveState = 0; //Keeps track of last savestate used for quick save/load functions
stringstream MessageToDisplay; //temp variable to store message that will be displayed via DisplayMessage function
int displayMessageCounter = 0; //Counter to keep track with how long to display messages on screen
unsigned int lastSaveState = 0; //Keeps track of last savestate used for quick save/load functions
stringstream MessageToDisplay; //temp variable to store message that will be displayed via DisplayMessage function
int displayMessageCounter = 0; //Counter to keep track with how long to display messages on screen
bool NewMessageToDisplay = false; //Flag to indicate a new message is in queue
/* the firmware settings */
struct NDS_fw_config_data win_fw_config;
@ -382,6 +390,79 @@ struct configured_features {
const char *cflash_disk_image_file;
};
int KeyInDelayInCount=10;
static int lastTime = timeGetTime();
int repeattime;
VOID CALLBACK KeyInputTimer( UINT idEvent, UINT uMsg, DWORD_PTR dwUser, DWORD_PTR dw1, DWORD_PTR dw2)
{
//
// if(timeGetTime() - lastTime > 5)
// {
bool S9xGetState (WORD KeyIdent);
/* if(GUI.JoystickHotkeys)
{
static uint32 joyState [256];
for(int i = 0 ; i < 255 ; i++)
{
bool active = !S9xGetState(0x8000|i);
if(active)
{
if(joyState[i] < ULONG_MAX) // 0xffffffffUL
joyState[i]++;
if(joyState[i] == 1 || joyState[i] >= (unsigned) KeyInDelayInCount)
PostMessage(GUI.hWnd, WM_CUSTKEYDOWN, (WPARAM)(0x8000|i),(LPARAM)(NULL));
}
else
{
if(joyState[i])
{
joyState[i] = 0;
PostMessage(GUI.hWnd, WM_CUSTKEYUP, (WPARAM)(0x8000|i),(LPARAM)(NULL));
}
}
}
}*/
// if((!GUI.InactivePause || !Settings.ForcedPause)
// || (GUI.BackgroundInput || !(Settings.ForcedPause & (PAUSE_INACTIVE_WINDOW | PAUSE_WINDOW_ICONISED))))
// {
static uint32 joyState [256];
for(int i = 0 ; i < 255 ; i++)
{
bool active = !S9xGetState(i);
if(active)
{
if(joyState[i] < ULONG_MAX) // 0xffffffffUL
joyState[i]++;
if(joyState[i] == 1 || joyState[i] >= (unsigned) KeyInDelayInCount) {
//sort of fix the auto repeating
//TODO find something better
// repeattime++;
// if(repeattime % 10 == 0) {
PostMessage(MainWindow->getHWnd(), WM_CUSTKEYDOWN, (WPARAM)(i),(LPARAM)(NULL));
repeattime=0;
// }
}
}
else
{
if(joyState[i])
{
joyState[i] = 0;
PostMessage(MainWindow->getHWnd(), WM_CUSTKEYUP, (WPARAM)(i),(LPARAM)(NULL));
}
}
}
// }
// lastTime = timeGetTime();
// }
}
static void
init_configured_features( struct configured_features *config) {
config->arm9_gdb_port = 0;
@ -920,7 +1001,8 @@ void DisplayMessage()
{
//adelikat - By using stringstream, it leaves open the possibility to keep a series of message in queue
displayMessageCounter--;
osd->addFixed(0, 40, "%s",MessageToDisplay.str().c_str());
osd->addFixed(0, 120, "%s",MessageToDisplay.str().c_str());
NewMessageToDisplay = false;
}
}
@ -932,12 +1014,15 @@ void SaveStateMessages(int slotnum, int whichMessage)
{
case 0: //State saved
MessageToDisplay << "State " << slotnum << " saved.";
NewMessageToDisplay = true; //adelikat: TODO: make these call SetMessageToDisplay instead
break;
case 1: //State loaded
MessageToDisplay << "State " << slotnum << " loaded.";
NewMessageToDisplay = true;
break;
case 2: //Save slot selected
MessageToDisplay << "State " << slotnum << " selected.";
NewMessageToDisplay = true;
default:
break;
}
@ -999,12 +1084,13 @@ DWORD WINAPI run()
while(execute)
{
input_process();
FCEUMOV_AddInputState();
if (ShowInputDisplay) osd->addFixed(Hud.InputDisplay.x, Hud.InputDisplay.y, "%s",InputDisplayString.c_str());
{
Lock lock;
cycles = NDS_exec((560190<<1)-cycles);
NDS_exec(0);
win_sound_samplecounter = 735;
}
@ -1025,7 +1111,17 @@ DWORD WINAPI run()
static int fps3d = 0;
if (FpsDisplay) osd->addFixed(Hud.FpsDisplay.x, Hud.FpsDisplay.y, "%02d Fps / %02d 3d", fps, fps3d);
osd->update();
if (frameCounterDisplay)
{
if (movieMode == MOVIEMODE_PLAY)
osd->addFixed(Hud.FrameCounter.x, Hud.FrameCounter.y, "%d/%d",currFrameCounter,currMovieData.records.size());
else if(movieMode == MOVIEMODE_RECORD)
osd->addFixed(Hud.FrameCounter.x, Hud.FrameCounter.y, "%d",currFrameCounter);
else
osd->addFixed(Hud.FrameCounter.x, Hud.FrameCounter.y, "%d (no movie)",currFrameCounter);
}
if(!DRV_AviIsRecording()) osd->update();
Display();
osd->clear();
@ -1047,6 +1143,8 @@ DWORD WINAPI run()
}
Update_RAM_Watch();
Update_RAM_Search();
fpsframecount++;
QueryPerformanceCounter((LARGE_INTEGER *)&curticks);
@ -1141,14 +1239,19 @@ DWORD WINAPI run()
emu_halt();
SPU_Pause(1);
}
frameCounter++;
if (frameCounterDisplay) osd->addFixed(Hud.FrameCounter.x, Hud.FrameCounter.y, "%d",frameCounter);
if (ShowLagFrameCounter) osd->addFixed(Hud.LagFrameCounter.x, Hud.LagFrameCounter.y, "%d",TotalLagFrames);
if (ShowMicrophone) osd->addFixed(Hud.Microphone.x, Hud.Microphone.y, "%d",MicDisplay);
DisplayMessage();
// DisplayMessage();
CheckMessages();
}
if (NewMessageToDisplay)
{
DisplayMessage();
osd->update();
Display();
osd->clear();
}
paused = TRUE;
CheckMessages();
Sleep(100);
@ -1203,7 +1306,6 @@ BOOL LoadROM(char * filename, const char *cflash_disk_image)
#endif
{
INFO("Loading %s was successful\n",filename);
frameCounter=0;
lagframecounter=0;
UpdateRecentRoms(filename);
osd->setRotate(GPU_rotation);
@ -1327,6 +1429,7 @@ static void ExitRunLoop()
emu_halt();
}
BOOL AVI_IsRecording();
class WinDriver : public Driver
{
virtual BOOL WIFI_Host_InitSystem() {
@ -1356,6 +1459,11 @@ class WinDriver : public Driver
WSACleanup() ;
#endif
}
virtual BOOL AVI_IsRecording()
{
return ::AVI_IsRecording();
}
};
int WINAPI WinMain (HINSTANCE hThisInstance,
@ -1594,6 +1702,10 @@ int WINAPI WinMain (HINSTANCE hThisInstance,
MainWindow->checkMenu(frameskiprate + IDC_FRAMESKIP0, MF_BYCOMMAND | MF_CHECKED);
}
int KeyInRepeatMSec=20;
hKeyInputTimer = timeSetEvent (KeyInRepeatMSec, 0, KeyInputTimer, 0, TIME_PERIODIC);
cur3DCore = GetPrivateProfileInt("3D", "Renderer", GPU3D_OPENGL, IniName);
CommonSettings.HighResolutionInterpolateColor = GetPrivateProfileInt("3D", "HighResolutionInterpolateColor", 1, IniName);
NDS_3D_ChangeCore(cur3DCore);
@ -2183,11 +2295,24 @@ void Pause()
emu_paused ^= 1;
}
void FrameAdvance()
bool first;
void FrameAdvance(bool state)
{
frameAdvance = true;
execute = TRUE;
emu_paused = 1;
if(state) {
if(first) {
frameAdvance=true;
}
else {
execute = TRUE;
first=false;
}
}
else {
emu_halt();
SPU_Pause(1);
emu_paused = 1;
}
}
enum CONFIGSCREEN
@ -2282,6 +2407,10 @@ LRESULT CALLBACK WindowProcedure (HWND hwnd, UINT message, WPARAM wParam, LPARAM
EnableMenuItem(mainMenu, IDM_CHEATS_SEARCH, MF_BYCOMMAND | (romloaded) ? MF_ENABLED : MF_GRAYED);
EnableMenuItem(mainMenu, IDM_WIFISETTINGS, MF_BYCOMMAND | (romloaded) ? MF_ENABLED : MF_GRAYED);
EnableMenuItem(mainMenu, IDM_RECORD_MOVIE, MF_BYCOMMAND | (romloaded && movieMode == MOVIEMODE_INACTIVE) ? MF_ENABLED : MF_GRAYED);
EnableMenuItem(mainMenu, IDM_PLAY_MOVIE, MF_BYCOMMAND | (romloaded && movieMode == MOVIEMODE_INACTIVE) ? MF_ENABLED : MF_GRAYED);
EnableMenuItem(mainMenu, IDM_STOPMOVIE, MF_BYCOMMAND | (romloaded && movieMode != MOVIEMODE_INACTIVE) ? MF_ENABLED : MF_GRAYED);
//Update savestate slot items based on ROM loaded
for (int x = 0; x < 10; x++)
{
@ -2413,6 +2542,7 @@ LRESULT CALLBACK WindowProcedure (HWND hwnd, UINT message, WPARAM wParam, LPARAM
//break;
case WM_KEYDOWN:
break;
case WM_SYSKEYDOWN:
case WM_CUSTKEYDOWN:
{
@ -2906,7 +3036,15 @@ LRESULT CALLBACK WindowProcedure (HWND hwnd, UINT message, WPARAM wParam, LPARAM
case IDM_CHEATS_SEARCH:
CheatsSearchDialog(hwnd);
return 0;
case IDM_RECORD_MOVIE:
MovieRecordTo();
return 0;
case IDM_PLAY_MOVIE:
Replay_LoadMovie();
return 0;
case IDM_STOPMOVIE:
FCEUI_StopMovie();
return 0;
case ID_VIEW_FRAMECOUNTER:
frameCounterDisplay ^= 1;
MainWindow->checkMenu(ID_VIEW_FRAMECOUNTER, frameCounterDisplay ? MF_CHECKED : MF_UNCHECKED);
@ -2946,6 +3084,25 @@ LRESULT CALLBACK WindowProcedure (HWND hwnd, UINT message, WPARAM wParam, LPARAM
osd->clear();
return 0;
case ID_RAM_SEARCH:
if(!RamSearchHWnd)
{
RamSearchHWnd = CreateDialog(hAppInst, MAKEINTRESOURCE(IDD_RAMSEARCH), hwnd, (DLGPROC) RamSearchProc);
}
else
SetForegroundWindow(RamSearchHWnd);
break;
case ID_RAM_WATCH:
if(!RamWatchHWnd)
{
RamWatchHWnd = CreateDialog(hAppInst, MAKEINTRESOURCE(IDD_RAMWATCH), hwnd, (DLGPROC) RamWatchProc);
// DialogsOpen++;
}
else
SetForegroundWindow(RamWatchHWnd);
return 0;
#define clearsaver() \
MainWindow->checkMenu(IDC_SAVETYPE1, MF_BYCOMMAND | MF_UNCHECKED); \
MainWindow->checkMenu(IDC_SAVETYPE2, MF_BYCOMMAND | MF_UNCHECKED); \
@ -3185,7 +3342,6 @@ LRESULT CALLBACK WindowProcedure (HWND hwnd, UINT message, WPARAM wParam, LPARAM
}
}
return DefWindowProc (hwnd, message, wParam, lParam);
}
@ -3327,7 +3483,6 @@ LRESULT CALLBACK EmulationSettingsDlgProc(HWND hDlg, UINT uMsg, WPARAM wParam, L
{
CheatsSearchReset();
NDS_Reset();
frameCounter = 0;
}
}
}
@ -3561,7 +3716,6 @@ LRESULT CALLBACK WifiSettingsDlgProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM
{
CheatsSearchReset();
NDS_Reset();
frameCounter = 0;
}
}
}
@ -3683,7 +3837,6 @@ void ResetGame()
{
CheatsSearchReset();
NDS_Reset();
frameCounter=0;
}
//adelikat: This function allows another file to add a message to the screen
@ -3693,6 +3846,7 @@ void SetMessageToDisplay(const char *message)
//adelikat: TODO: set up a function that does the clearing and setting of the counter, so this code doesn't have to be done all over the place
// make the function receive an int for the counter, but overload so that if no int, 120 is used
MessageToDisplay << message;
NewMessageToDisplay = true;
displayMessageCounter = 120;//
}
@ -3729,4 +3883,9 @@ void UpdateHotkeyAssignments()
text = text.substr(0,truncate);
text.append("\tCtrl+O"); //TODO: Append actual hotkey assignment
ChangeMenuItemText(IDM_OPEN, text); //Set Menu item text
}
HWND GetMainHWND()
{
return MainWindow->getHWnd();
}

View File

@ -11,14 +11,13 @@ extern unsigned int lastSaveState;
void SaveStateMessages(int slotnum, int whichMessage);
void Display();
void Pause();
void FrameAdvance();
void FrameAdvance(bool state);
void ResetGame(); //Resets game (for the menu item & hotkey
void AviRecordTo();
void AviEnd();
void SetMessageToDisplay(const char *message); //For sending output to the main screen
extern bool ShowInputDisplay;
extern unsigned int frameCounter;
extern bool frameCounterDisplay;
extern bool FpsDisplay;
extern bool ShowInputDisplay;
@ -28,5 +27,9 @@ extern bool ShowLagFrameCounter;
#define GPU3D_OPENGL 1
#define GPU3D_SWRAST 2
extern int backupmemorytype;
extern u32 backupmemorysize;
HWND GetMainHWND(); //adelikat: returns the main window handle
#endif

1932
src/windows/ram_search.cpp Normal file

File diff suppressed because it is too large Load Diff

49
src/windows/ram_search.h Normal file
View File

@ -0,0 +1,49 @@
#ifndef RAM_SEARCH_H
#define RAM_SEARCH_H
//64k in Ram_68k[], 8k in Ram_Z80[]
//#define _68K_RAM_SIZE 64*1024
//#define Z80_RAM_SIZE 8*1024
/*#define SRAM_SIZE (((SRAM_End - SRAM_Start) > 2) ? SRAM_End - SRAM_Start : 0)
#define BRAM_SIZE ((8 << BRAM_Ex_Size) * 1024)*/
//#define GENESIS_RAM_SIZE (_68K_RAM_SIZE + Z80_RAM_SIZE)
//_32X_Ram[]
//#define _32X_RAM_SIZE 256*1024
//512k in Ram_Prg, 256k in Ram_Word_1M and Ram_Word_2M
//(docs say 6Mbit of ram, but I'm not sure what's used when)
//#define SEGACD_RAM_PRG_SIZE 512*1024
//#define SEGACD_1M_RAM_SIZE 256*1024
//#define SEGACD_2M_RAM_SIZE 256*1024
//#define SEGACD_RAM_SIZE (SEGACD_RAM_PRG_SIZE + SEGACD_2M_RAM_SIZE)
//#define MAX_RAM_SIZE (0x112000)
//#define MAX_RAM_SIZE (0xD2000)
#define MAX_RAM_SIZE (0x400000)
extern char rs_type_size;
extern int ResultCount;
unsigned int sizeConv(unsigned int index,char size, char *prevSize = &rs_type_size, bool usePrev = false);
unsigned int GetRamValue(unsigned int Addr,char Size);
void prune(char Search, char Operater, char Type, int Value, int OperatorParameter);
void CompactAddrs();
void reset_address_info();
void signal_new_frame();
void signal_new_size();
void UpdateRamSearchTitleBar(int percent = 0);
void Update_RAM_Search();
void SetRamSearchUndoType(HWND hDlg, int type);
unsigned int ReadValueAtHardwareAddress(unsigned int address, unsigned int size);
bool WriteValueAtHardwareRAMAddress(unsigned int address, unsigned int value, unsigned int size, bool hookless=false);
bool IsHardwareRAMAddressValid(unsigned int address);
extern int curr_ram_size;
extern bool noMisalign;
extern bool littleEndian;
#endif

1171
src/windows/ramwatch.cpp Normal file

File diff suppressed because it is too large Load Diff

39
src/windows/ramwatch.h Normal file
View File

@ -0,0 +1,39 @@
#ifndef RAMWATCH_H
#define RAMWATCH_H
#include "windows.h"
bool ResetWatches();
void OpenRWRecentFile(int memwRFileNumber);
extern bool AutoRWLoad;
extern bool RWSaveWindowPos;
#define MAX_RECENT_WATCHES 5
extern char rw_recent_files[MAX_RECENT_WATCHES][1024];
extern bool AskSave();
extern int ramw_x;
extern int ramw_y;
extern bool RWfileChanged;
// AddressWatcher is self-contained now
struct AddressWatcher
{
unsigned int Address; // hardware address
char Size;
char Type;
char* comment; // NULL means no comment, non-NULL means allocated comment
bool WrongEndian;
unsigned int CurValue;
};
#define MAX_WATCH_COUNT 256
extern AddressWatcher rswatches[MAX_WATCH_COUNT];
extern int WatchCount; // number of valid items in rswatches
extern char Watch_Dir[1024];
bool InsertWatch(const AddressWatcher& Watch, char *Comment);
bool InsertWatch(const AddressWatcher& Watch, HWND parent=NULL); // asks user for comment
void Update_RAM_Watch();
bool Load_Watches(bool clear, const char* filename);
LRESULT CALLBACK RamWatchProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);
extern HWND RamWatchHWnd;
#endif

157
src/windows/replay.cpp Normal file
View File

@ -0,0 +1,157 @@
#include <io.h>
#include "resource.h"
#include "replay.h"
#include "common.h"
#include "main.h"
#include "movie.h"
#include "utils/xstring.h"
bool replayreadonly=1;
//adelikat: TODO: put this in one of the header files
template<int BUFSIZE>
inline std::wstring GetDlgItemTextW(HWND hDlg, int nIDDlgItem) {
wchar_t buf[BUFSIZE];
GetDlgItemTextW(hDlg, nIDDlgItem, buf, BUFSIZE);
return buf;
}
template<int BUFSIZE>
inline std::string GetDlgItemText(HWND hDlg, int nIDDlgItem) {
char buf[BUFSIZE];
GetDlgItemText(hDlg, nIDDlgItem, buf, BUFSIZE);
return buf;
}
char playfilename[MAX_PATH] = "";
//Replay movie dialog
BOOL CALLBACK ReplayDialogProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
OPENFILENAME ofn;
char szChoice[MAX_PATH]={0};
char filename[MAX_PATH] = "";
switch(uMsg)
{
case WM_INITDIALOG:
SendDlgItemMessage(hwndDlg, IDC_CHECK_READONLY, BM_SETCHECK, replayreadonly?BST_CHECKED:BST_UNCHECKED, 0);
return FALSE;
case WM_COMMAND:
int wID = LOWORD(wParam);
switch(wID)
{
case ID_BROWSE:
ZeroMemory(&ofn, sizeof(ofn));
ofn.lStructSize = sizeof(ofn);
ofn.hwndOwner = MainWindow->getHWnd();
ofn.lpstrFilter = "Desmume Movie File (*.dsm)\0*.dsm\0All files(*.*)\0*.*\0\0";
ofn.nFilterIndex = 1;
ofn.lpstrFile = filename;
ofn.lpstrTitle = "Replay Movie from File";
ofn.nMaxFile = MAX_PATH;
ofn.lpstrDefExt = "dsm";
GetOpenFileName(&ofn);
strcpy(playfilename, filename);
SetDlgItemText(hwndDlg, PM_FILENAME, playfilename);
return true;
case IDC_CHECK_READONLY:
replayreadonly ^= 1;
return true;
case IDOK:
FCEUI_LoadMovie(playfilename, replayreadonly, false, 80000);
ZeroMemory(&playfilename, sizeof(playfilename));
EndDialog(hwndDlg, 0);
return true;
case IDCANCEL:
ZeroMemory(&playfilename, sizeof(playfilename));
EndDialog(hwndDlg, 0);
return true;
}
}
return false;
}
//Record movie dialog
static BOOL CALLBACK RecordDialogProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
static struct CreateMovieParameters* p = NULL;
std::wstring author = L"";
switch(uMsg)
{
case WM_INITDIALOG:
return false;
case WM_COMMAND:
switch(LOWORD(wParam))
{
case IDOK: {
author = GetDlgItemTextW<500>(hwndDlg,IDC_EDIT_AUTHOR);
std::string fname = GetDlgItemText<MAX_PATH>(hwndDlg,IDC_EDIT_FILENAME);
FCEUI_SaveMovie(fname.c_str(), author);
EndDialog(hwndDlg, 0);
return true;
}
case IDCANCEL:
EndDialog(hwndDlg, 0);
return true;
case IDC_BUTTON_BROWSEFILE:
{
OPENFILENAME ofn;
char szChoice[MAX_PATH]={0};
char recordfilename[MAX_PATH];
// browse button
ZeroMemory(&ofn, sizeof(ofn));
ofn.lStructSize = sizeof(ofn);
ofn.hwndOwner = MainWindow->getHWnd();
ofn.lpstrFilter = "Desmume Movie File (*.dsm)\0*.dsm\0All files(*.*)\0*.*\0\0";
ofn.lpstrFile = szChoice;
ofn.lpstrTitle = "Record a new movie";
ofn.lpstrDefExt = "dsm";
ofn.nMaxFile = MAX_PATH;
ofn.Flags = OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT;
GetSaveFileName(&ofn);
strcpy(recordfilename, szChoice);
SetDlgItemText(hwndDlg, IDC_EDIT_FILENAME, recordfilename);
//if(GetSaveFileName(&ofn))
// UpdateRecordDialogPath(hwndDlg,szChoice);
return true;
}
}
}
return false;
}
//Show the play movie dialog and play a movie
void Replay_LoadMovie()
{
char* fn = (char*)DialogBoxParam(hAppInst, "IDD_REPLAYINP", GetMainHWND(), ReplayDialogProc, false);
if(fn)
{
FCEUI_LoadMovie(fn, movie_readonly, false, 100000);
free(fn);
}
}
//Show the record movie dialog and record a movie.
void MovieRecordTo()
{
DialogBoxParam(hAppInst, MAKEINTRESOURCE(IDD_RECORDMOVIE), GetMainHWND(), RecordDialogProc, (LPARAM)0);
}

2
src/windows/replay.h Normal file
View File

@ -0,0 +1,2 @@
void Replay_LoadMovie();
void MovieRecordTo();

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

24
src/windows/targetver.h Normal file
View File

@ -0,0 +1,24 @@
#pragma once
// The following macros define the minimum required platform. The minimum required platform
// is the earliest version of Windows, Internet Explorer etc. that has the necessary features to run
// your application. The macros work by enabling all features available on platform versions up to and
// including the version specified.
// Modify the following defines if you have to target a platform prior to the ones specified below.
// Refer to MSDN for the latest info on corresponding values for different platforms.
#ifndef WINVER // Specifies that the minimum required platform is Windows Vista.
#define WINVER 0x0600 // Change this to the appropriate value to target other versions of Windows.
#endif
#ifndef _WIN32_WINNT // Specifies that the minimum required platform is Windows Vista.
#define _WIN32_WINNT 0x0600 // Change this to the appropriate value to target other versions of Windows.
#endif
#ifndef _WIN32_WINDOWS // Specifies that the minimum required platform is Windows 98.
#define _WIN32_WINDOWS 0x0410 // Change this to the appropriate value to target Windows Me or later.
#endif
#ifndef _WIN32_IE // Specifies that the minimum required platform is Internet Explorer 7.0.
#define _WIN32_IE 0x0700 // Change this to the appropriate value to target other versions of IE.
#endif