integrate changes from rerecording branch
This commit is contained in:
parent
2c2484d77d
commit
76c0c2d245
1090
src/GPU.cpp
1090
src/GPU.cpp
File diff suppressed because it is too large
Load Diff
103
src/GPU.h
103
src/GPU.h
|
@ -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);}
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
||||
|
||||
|
|
|
@ -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
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
186
src/gfx3d.cpp
186
src/gfx3d.cpp
|
@ -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;
|
||||
}
|
||||
}
|
76
src/gfx3d.h
76
src/gfx3d.h
|
@ -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
|
||||
|
|
10
src/mc.cpp
10
src/mc.cpp
|
@ -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);
|
||||
|
|
408
src/movie.cpp
408
src/movie.cpp
|
@ -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
|
||||
}
|
||||
}
|
||||
|
||||
|
|
22
src/movie.h
22
src/movie.h
|
@ -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
|
||||
|
|
|
@ -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
|
||||
};
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
25
src/rtc.cpp
25
src/rtc.cpp
|
@ -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();
|
||||
|
||||
|
|
|
@ -30,4 +30,6 @@
|
|||
extern void rtcInit();
|
||||
extern u16 rtcRead();
|
||||
extern void rtcWrite(u16 val);
|
||||
|
||||
void InitMovieTime(void);
|
||||
#endif
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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);
|
|
@ -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];
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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"
|
||||
>
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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";
|
||||
|
|
|
@ -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--
|
||||
|
|
|
@ -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();
|
||||
}
|
|
@ -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
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -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
|
||||
|
File diff suppressed because it is too large
Load Diff
|
@ -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
|
|
@ -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);
|
||||
}
|
|
@ -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
|
@ -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
|
Loading…
Reference in New Issue