diff --git a/branches/voxel/src/boards/12in1.cpp b/branches/voxel/src/boards/12in1.cpp index 15f6c079..add67cc4 100644 --- a/branches/voxel/src/boards/12in1.cpp +++ b/branches/voxel/src/boards/12in1.cpp @@ -17,43 +17,45 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * - * 7-in-1 Darkwing Duck, Snake, MagicBlock (PCB marked as "12 in 1") + * 7-in-1 Darkwing Duck, Snake, MagicBlock (PCB marked as "12 in 1") + * 12-in-1 1991 New Star Co. Ltd. + * */ #include "mapinc.h" -static uint8 reg[4]; +static uint8 prgchr[2], ctrl; static SFORMAT StateRegs[] = { - { reg, 4, "REGS" }, + { prgchr, 2, "REGS" }, + { &ctrl, 1, "CTRL" }, { 0 } }; static void Sync(void) { - uint8 bank = (reg[3] & 3) << 3; - setchr4(0x0000, (reg[1] >> 3) | (bank << 2)); - setchr4(0x1000, (reg[2] >> 3) | (bank << 2)); - if (reg[3] & 8) { - setprg32(0x8000, ((reg[2] & 7) >> 1) | bank); + uint8 bank = (ctrl & 3) << 3; + setchr4(0x0000, (prgchr[0] >> 3) | (bank << 2)); + setchr4(0x1000, (prgchr[1] >> 3) | (bank << 2)); + if (ctrl & 8) { + setprg16(0x8000, bank | (prgchr[0] & 6) | 0); // actually, both 0 and 1 registers used, but they will switch each PA12 transition + setprg16(0xc000, bank | (prgchr[0] & 6) | 1); // if bits are different for both registers, so they must be programmed strongly the same! } else { - setprg16(0x8000, (reg[1] & 7) | bank); - setprg16(0xc000, 7 | bank); + setprg16(0x8000, bank | (prgchr[0] & 7)); + setprg16(0xc000, bank | 7 ); } - setmirror(((reg[3] & 4) >> 2) ^ 1); + setmirror(((ctrl & 4) >> 2) ^ 1); } static DECLFW(BMC12IN1Write) { - switch (A) { - case 0xafff: reg[0] = V; break; - case 0xbfff: reg[1] = V; break; - case 0xdfff: reg[2] = V; break; - case 0xefff: reg[3] = V; break; + switch (A & 0xE000) { + case 0xA000: prgchr[0] = V; Sync(); break; + case 0xC000: prgchr[1] = V; Sync(); break; + case 0xE000: ctrl = V & 0x0F; Sync(); break; } - Sync(); } static void BMC12IN1Power(void) { - reg[0] = reg[1] = reg[2] = reg[3] = 0; + prgchr[0] = prgchr[1] = ctrl = 0; Sync(); SetReadHandler(0x8000, 0xFFFF, CartBR); SetWriteHandler(0x8000, 0xFFFF, BMC12IN1Write); @@ -68,3 +70,4 @@ void BMC12IN1_Init(CartInfo *info) { GameStateRestore = StateRestore; AddExState(&StateRegs, ~0, 0, 0); } + diff --git a/branches/voxel/src/boards/225.cpp b/branches/voxel/src/boards/225.cpp index 9df7d518..fd008ea2 100644 --- a/branches/voxel/src/boards/225.cpp +++ b/branches/voxel/src/boards/225.cpp @@ -39,7 +39,7 @@ static void Sync(void) { } else setprg32(0x8000, prg >> 1); setchr8(chr); - setmirror(mirr); + setmirror(mirr ^ 1); } static DECLFW(M225Write) { diff --git a/branches/voxel/src/boards/datalatch.cpp b/branches/voxel/src/boards/datalatch.cpp index 716e101e..0665eeb6 100644 --- a/branches/voxel/src/boards/datalatch.cpp +++ b/branches/voxel/src/boards/datalatch.cpp @@ -201,6 +201,20 @@ void CPROM_Init(CartInfo *info) { Latch_Init(info, CPROMSync, 0, 0x8000, 0xFFFF, 0, 0); } +//------------------ Map 29 --------------------------- //Used by Glider, http://www.retrousb.com/product_info.php?cPath=30&products_id=58 + +static void M29Sync() { + setprg16(0x8000, (latche & 0x1C) >> 2); + setprg16(0xc000, ~0); + setchr8r(0, latche & 3); + setprg8r(0x10, 0x6000, 0); +} + +void Mapper29_Init(CartInfo *info) { + Latch_Init(info, M29Sync, 0, 0x8000, 0xFFFF, 1, 0); +} + + //------------------ Map 38 --------------------------- static void M38Sync(void) { diff --git a/branches/voxel/src/debug.cpp b/branches/voxel/src/debug.cpp index c71274c4..2f85dbb7 100644 --- a/branches/voxel/src/debug.cpp +++ b/branches/voxel/src/debug.cpp @@ -14,7 +14,7 @@ #include #include - +unsigned int debuggerPageSize = 14; int vblankScanLines = 0; //Used to calculate scanlines 240-261 (vblank) int vblankPixel = 0; //Used to calculate the pixels in vblank @@ -232,7 +232,7 @@ int getBank(int offs) if (GameInfo && GameInfo->type==GIT_NSF) return addr != -1 ? addr / 0x1000 : -1; - return addr != -1 ? addr / 0x4000 : -1; + return addr != -1 ? addr / (1<convert_buffer, 0, VIDEO_WIDTH*(avi_file->end_scanline-avi_file->start_scanline)*3); buffer += avi_file->start_scanline * VIDEO_WIDTH; + PALETTEENTRY* color_palette = GetPalette(); for(int y=avi_file->start_scanline; yend_scanline; ++y) { diff --git a/branches/voxel/src/drivers/win/cdlogger.cpp b/branches/voxel/src/drivers/win/cdlogger.cpp index 7c64ed9a..cff4a75e 100644 --- a/branches/voxel/src/drivers/win/cdlogger.cpp +++ b/branches/voxel/src/drivers/win/cdlogger.cpp @@ -414,6 +414,11 @@ void SaveStrippedROM(int invert) if(!GetSaveFileName(&ofn))return; fp = fopen(sromfilename,"wb"); + if(!fp) + { + FCEUD_PrintError("Error opening target stripped rom file!"); + return; + } if(GameInfo->type==GIT_NSF) { diff --git a/branches/voxel/src/drivers/win/config.cpp b/branches/voxel/src/drivers/win/config.cpp index ea23aee4..17198463 100644 --- a/branches/voxel/src/drivers/win/config.cpp +++ b/branches/voxel/src/drivers/win/config.cpp @@ -185,8 +185,8 @@ static CFGSTRUCT fceuconfig[] = NAC("palyo",pal_emulation), NAC("genie",genie), - NAC("fs",fullscreen), - NAC("vgamode",vmod), + NAC("fs",_FIXME_getFullscreenVar()), + NAC("vgamode",_FIXME_getVModeIdxVar()), NAC("sound",soundo), NAC("sicon",status_icon), @@ -206,8 +206,8 @@ static CFGSTRUCT fceuconfig[] = NACS("odavi",directory_names[12]), NACS("odbase",directory_names[13]), - AC(winspecial), - AC(NTSCwinspecial), + NAC("winspecial", _FIXME_getFilterModeWindowedIdxVar()), + NAC("NTSCwinspecial", _FIXME_getFilterOptionVar()), AC(winsizemulx), AC(winsizemuly), AC(tvAspectX), @@ -231,23 +231,23 @@ static CFGSTRUCT fceuconfig[] = NACA("InputType",InputType), - NAC("vmcx",vmodes[0].x), - NAC("vmcy",vmodes[0].y), - NAC("vmcb",vmodes[0].bpp), - NAC("vmcf",vmodes[0].flags), - NAC("vmcxs",vmodes[0].xscale), - NAC("vmcys",vmodes[0].yscale), - NAC("vmspecial",vmodes[0].special), + NAC("vmcx",_FIXME_getCustomVideoModeVar().width), + NAC("vmcy",_FIXME_getCustomVideoModeVar().height), + NAC("vmcb",_FIXME_getCustomVideoModeVar().bpp), + NAC("vmcf",_FIXME_getCustomVideoModeVar().flags), + NAC("vmcxs",_FIXME_getCustomVideoModeVar().xscale), + NAC("vmcys",_FIXME_getCustomVideoModeVar().yscale), + NAC("vmspecial",_FIXME_getCustomVideoModeVar().filter), NAC("srendline",srendlinen), NAC("erendline",erendlinen), NAC("srendlinep",srendlinep), NAC("erendlinep",erendlinep), - AC(directDrawModeWindowed), - AC(directDrawModeFullscreen), - AC(winsync), - NAC("988fssync",fssync), + NAC("directDrawModeWindowed", _FIXME_getDDrawModeWindowedVar()), + NAC("directDrawModeFullscreen", _FIXME_getDDrawModeFullscreenVar()), + NAC("winsync", _FIXME_getWindowedSyncModeIdxVar()), + NAC("988fssync",_FIXME_getFullscreenSyncModeIdxVar()), AC(ismaximized), AC(maxconbskip), @@ -279,7 +279,10 @@ static CFGSTRUCT fceuconfig[] = AC(debuggerSaveLoadDEBFiles), AC(debuggerDisplayROMoffsets), AC(debuggerFontSize), - AC(hexeditorFontSize), + AC(debuggerPageSize), + AC(hexeditorFontWidth), + AC(hexeditorFontHeight), + ACS(hexeditorFontName), AC(fullSaveStateLoads), AC(frameSkipAmt), AC(fps_scale_frameadvance), diff --git a/branches/voxel/src/drivers/win/config.h b/branches/voxel/src/drivers/win/config.h index 1b163101..6606f695 100644 --- a/branches/voxel/src/drivers/win/config.h +++ b/branches/voxel/src/drivers/win/config.h @@ -1,3 +1,7 @@ +// FIXME for Windows, make use of Config class the way linux version does +// old config registers variables by placing their addresses into static array, which makes +// many modules expose their internal vars and pollute globals; there is also no way to know when a +// setting was changed by it, which spawns auxillary functions intended to push new values through void SaveConfig(const char *filename); void LoadConfig(const char *filename); diff --git a/branches/voxel/src/drivers/win/debugger.cpp b/branches/voxel/src/drivers/win/debugger.cpp index e7c97822..980ca65d 100644 --- a/branches/voxel/src/drivers/win/debugger.cpp +++ b/branches/voxel/src/drivers/win/debugger.cpp @@ -41,12 +41,10 @@ #include "debuggersp.h" -extern Name* lastBankNames; -extern Name* loadedBankNames; +extern Name* pageNames[32]; extern Name* ramBankNames; extern bool ramBankNamesLoaded; -extern int lastBank; -extern int loadedBank; +extern int pageNumbersLoaded[32]; extern int myNumWPs; // ################################## End of SP CODE ########################### @@ -525,8 +523,9 @@ void Disassemble(HWND hWnd, int id, int scrollid, unsigned int addr) if (symbDebugEnabled) { replaceNames(ramBankNames, a, &disassembly_operands[i]); - replaceNames(loadedBankNames, a, &disassembly_operands[i]); - replaceNames(lastBankNames, a, &disassembly_operands[i]); + for(int p=0;p>(debuggerPageSize); } + +//old +//Name* lastBankNames = 0; +//Name* loadedBankNames = 0; + +//new +Name* pageNames[32] = {0}; //the maximum number of pages we could have is 32, based on 1KB debuggerPageSize + +//old +//int lastBank = -1; +//int loadedBank = -1; + +//new +int pageNumbersLoaded[32]; //TODO - need to initialize these to -1 somehow + Name* ramBankNames = 0; bool ramBankNamesLoaded = false; -int lastBank = -1; -int loadedBank = -1; + extern char LoadedRomFName[2048]; char NLfilename[2048]; bool symbDebugEnabled = true; @@ -547,29 +560,24 @@ char* generateNLFilenameForAddress(uint16 address) } Name* getNamesPointerForAddress(uint16 address) { - // this function is called very often (when using "Symbolic trace"), so this is sorted by frequency - if (address >= 0xC000) + if(address >= 0x8000) { - return lastBankNames; - } else if (address >= 0x8000) - { - return loadedBankNames; - } else + return pageNames[RomPageIndexForAddress(address)]; + } + else { return ramBankNames; } } void setNamesPointerForAddress(uint16 address, Name* newNode) { - if (address < 0x8000) + if (address >= 0x8000) + { + pageNames[RomPageIndexForAddress(address)] = newNode; + } + else { ramBankNames = newNode; - } else if (address < 0xC000) - { - loadedBankNames = newNode; - } else - { - lastBankNames = newNode; } } @@ -592,44 +600,32 @@ void loadNameFiles() ramBankNames = parseNameFile(generateNLFilenameForAddress(0x0000)); } - // Find out which bank is loaded at 0xC000 - cb = getBank(0xC000); - if (cb == -1) // No bank was loaded at that offset - { - free(lastBankNames); - lastBankNames = 0; - } else if (cb != lastBank) - { - // If the bank changed since loading the NL files the last time it's necessary - // to load the address descriptions of the new bank. - lastBank = cb; + int nPages = 1<<(15-debuggerPageSize); - if (lastBankNames) - freeList(lastBankNames); + for(int i=0;i #include +#include "video.h" #include "input.h" #include "keyboard.h" #include "joystick.h" @@ -42,9 +43,8 @@ LPDIRECTINPUT7 lpDI=0; void InitInputPorts(bool fourscore); -int tempwinsync = 0; //Temp variable used by turbo to turn of sync settings +VSYNCMODE tempwinsync = SYNCMODE_NONE; //Temp variable used by turbo to turn of sync settings int tempsoundquality = 0; //Temp variable used by turbo to turn of sound quality settings -extern int winsync; extern int soundquality; extern bool replaceP2StartWithMicrophone; //UsrInputType[] is user-specified. InputType[] is current @@ -376,7 +376,7 @@ static uint32 UpdatePPadData(int w) static uint8 fkbkeys[0x48]; -static uint8 suborkbkeys[0x60]; +static uint8 suborkbkeys[0x65]; void KeyboardUpdateState(void); //mbg merge 7/17/06 yech had to add this @@ -421,6 +421,7 @@ void FCEUD_UpdateInput() if(cidisabled) UpdateFKB(); break; + case SIFC_PEC586KB: case SIFC_SUBORKB: if(cidisabled) UpdateSuborKB(); @@ -510,6 +511,7 @@ void InitInputPorts(bool fourscore) case SIFC_FKB: InputDPtr=fkbkeys; break; + case SIFC_PEC586KB: case SIFC_SUBORKB: InputDPtr=suborkbkeys; break; @@ -554,7 +556,7 @@ ButtConfig fkbmap[0x48]= MK(BL_CURSORUP),MK(BL_CURSORLEFT),MK(BL_CURSORRIGHT),MK(BL_CURSORDOWN) }; -ButtConfig suborkbmap[0x60]= +ButtConfig suborkbmap[0x65]= { MC(0x01),MC(0x3b),MC(0x3c),MC(0x3d),MC(0x3e),MC(0x3f),MC(0x40),MC(0x41),MC(0x42),MC(0x43), MC(0x44),MC(0x57),MC(0x58),MC(0x45),MC(0x29),MC(0x02),MC(0x03),MC(0x04),MC(0x05),MC(0x06), @@ -565,7 +567,8 @@ ButtConfig suborkbmap[0x60]= MC(0x21),MC(0x22),MC(0x23),MC(0x24),MC(0x25),MC(0x26),MC(0x27),MC(0x28),MC(0x4b),MC(0x4c), MC(0x4d),MC(0x2a),MC(0x2c),MC(0x2d),MC(0x2e),MC(0x2f),MC(0x30),MC(0x31),MC(0x32),MC(0x33), MC(0x34),MC(0x35),MC(0x2b),MC(0xc8),MC(0x4f),MC(0x50),MC(0x51),MC(0x1d),MC(0x38),MC(0x39), - MC(0xcb),MC(0xd0),MC(0xcd),MC(0x52),MC(0x53) + MC(0xcb),MC(0xd0),MC(0xcd),MC(0x52),MC(0x53),MC(0x00),MC(0x00),MC(0x00),MC(0x00),MC(0x00), + MC(0x00), }; @@ -573,7 +576,7 @@ static void UpdateFKB(void) { int x; - for(x=0;x<0x48;x++) + for(x=0;xbmiColors[i].rgbRed = color_palette[i].peRed; diff --git a/branches/voxel/src/drivers/win/texthook.cpp b/branches/voxel/src/drivers/win/texthook.cpp index 934e946c..748aa9f1 100644 --- a/branches/voxel/src/drivers/win/texthook.cpp +++ b/branches/voxel/src/drivers/win/texthook.cpp @@ -46,7 +46,6 @@ char *textToTrans; // buffer to hold the text that needs translating char *transText; //holds the translated text -extern void FCEUD_BlitScreen(uint8 *XBuf); //needed for pause, not sure where this is defined... //adelikat merge 7/1/08 - had to add these extern variables //------------------------------ extern uint8 PALRAM[0x20]; diff --git a/branches/voxel/src/drivers/win/tracer.cpp b/branches/voxel/src/drivers/win/tracer.cpp index e14e7e2f..4f806e73 100644 --- a/branches/voxel/src/drivers/win/tracer.cpp +++ b/branches/voxel/src/drivers/win/tracer.cpp @@ -48,8 +48,8 @@ using namespace std; #include "debuggersp.h" -extern Name* lastBankNames; -extern Name* loadedBankNames; +extern Name* pageNames[32]; +extern int pageNumbersLoaded[32]; extern Name* ramBankNames; // ################################## End of SP CODE ########################### @@ -840,8 +840,8 @@ void FCEUD_TraceInstruction(uint8 *opcode, int size) } replaceNames(ramBankNames, a, &tempAddressesLog); - replaceNames(loadedBankNames, a, &tempAddressesLog); - replaceNames(lastBankNames, a, &tempAddressesLog); + for(int i=0;i +#include "utils/bitflags.h" -extern bool fullscreenByDoubleclick; -static int RecalcCustom(void); -void InputScreenChanged(int fs); -void UpdateRendBounds(); +static bool dispModeWasChanged = false; // tells if driver should reset display mode on shutdown; set on fullscreen +static DWORD colorsBitMask[3]; // masks to extract components from color data with different bpp -static DDCAPS caps; -static int mustrestore=0; -static DWORD CBM[3]; +static int bpp; // bits per pixel +static bool wipeSurface = true; // tells mode/resolution was changed and we should wipe surface -static int bpp; -static int vflags; -static int veflags; +// Surface modes selected for windowed and fullscreen +static DIRECTDRAW_MODE directDrawModeWindowed = DIRECTDRAW_MODE_SOFTWARE; +static DIRECTDRAW_MODE directDrawModeFullscreen = DIRECTDRAW_MODE_FULL; -int directDrawModeWindowed = DIRECTDRAW_MODE_SOFTWARE; -int directDrawModeFullscreen = DIRECTDRAW_MODE_FULL; +// vertical sync modes for windowed and fullscreen +static VSYNCMODE idxFullscreenSyncMode = SYNCMODE_NONE; +static VSYNCMODE idxWindowedSyncMode = SYNCMODE_NONE; + // apparently sync settings are ignored during netplay -int fssync=0; -int winsync=0; +static VFILTER idxFilterModeWindowed = FILTER_NONE; // filter selected for windowed mode + // fullscreen mode filter index is taken from active VideoMode struct +static int ntscFilterOption = 0; // special NTSC filter effect + // never changed in code; might be loaded from config I guess +static int vmodeIdx; // current video mode index + // never changed in code, can be loaded from config -int winspecial = 0; -int NTSCwinspecial = 0; -int vmod = 0; - -vmdef vmodes[11] = +static VideoMode videoModes[11] = { - {0,0,0,VMDF_DXBLT|VMDF_STRFS,1,1,0}, // Custom - set to current resolution at the first launch + {0,0,0,VIDEOMODEFLAG_DXBLT|VIDEOMODEFLAG_STRFS,1,1,0}, // Custom - set to current resolution at the first launch {320,240,8,0,1,1,0}, //1 {512,384,8,0,1,1,0}, //2 {640,480,32,0,1,1,0}, //3 {640,480,32,0,1,1,0}, //4 {640,480,32,0,1,1,0}, //5 - {640,480,32,VMDF_DXBLT,2,2,0}, //6 - {1024,768,32,VMDF_DXBLT,4,3,0}, //7 - {1280,1024,32,VMDF_DXBLT,5,4,0}, //8 - {1600,1200,32,VMDF_DXBLT,6,5,0}, //9 - {800,600,32,VMDF_DXBLT|VMDF_STRFS,0,0} //10 + {640,480,32,VIDEOMODEFLAG_DXBLT,2,2,0}, //6 + {1024,768,32,VIDEOMODEFLAG_DXBLT,4,3,0}, //7 + {1280,1024,32,VIDEOMODEFLAG_DXBLT,5,4,0}, //8 + {1600,1200,32,VIDEOMODEFLAG_DXBLT,6,5,0}, //9 + {800,600,32,VIDEOMODEFLAG_DXBLT|VIDEOMODEFLAG_STRFS,0,0} //10 }; -extern uint8 PALRAM[0x20]; +extern uint8 PALRAM[0x20]; // NES palette ram -PALETTEENTRY *color_palette; +static PALETTEENTRY color_palette[256]; // driver palette -static int PaletteChanged=0; +static bool updateDDPalette = true; // flag to update DirectDraw palette -LPDIRECTDRAWCLIPPER lpClipper=0; -LPDIRECTDRAW lpDD=0; -LPDIRECTDRAW7 lpDD7=0; -LPDIRECTDRAWPALETTE lpddpal = 0; +static LPDIRECTDRAW7 ddraw7Handle = 0; // our working DirectDraw +static LPDIRECTDRAWCLIPPER ddClipperHandle = 0; // DD clipper to keep image within window boundaries +static LPDIRECTDRAWPALETTE ddPaletteHandle = 0; // DD palette -DDSURFACEDESC2 ddsd; -DDSURFACEDESC2 ddsdback; +// surface descriptions +static DDSURFACEDESC2 surfaceDescScreen; +static DDSURFACEDESC2 surfaceDescOffscreen; -LPDIRECTDRAWSURFACE7 lpDDSPrimary=0; -LPDIRECTDRAWSURFACE7 lpDDSDBack=0; -LPDIRECTDRAWSURFACE7 lpDDSBack=0; +// surfaces +static LPDIRECTDRAWSURFACE7 lpScreenSurface=0; // screen surface +static LPDIRECTDRAWSURFACE7 lpBackBuffer=0; // back buffer of screen surface + // in doublebuffer mode image ends up here, then surface is flipped +static LPDIRECTDRAWSURFACE7 lpOffscreenSurface=0; // offscreen surface -DDBLTFX blitfx = { sizeof(DDBLTFX) }; +static RECT activeRect = {0}; // active area of the screen where image is displayed and mouse input is processed -RECT bestfitRect = {0}; +static bool fullscreenDesired = false; // 'Desired' fullscreen status +static bool fullscreenActual = false; // Internal 'actual' fullscreen status -#define RELEASE(x) if(x) { x->Release(); x = 0; } +static int filterScaleMultiplier[6] = {1,2,2,2,3,3}; // scale multipliers for defined filters -static void ShowDDErr(char *s) + +static void RestoreLostScreenSurface() { - char tempo[512]; - sprintf(tempo,"DirectDraw: %s",s); - FCEUD_PrintError(tempo); -} - -int RestoreDD(int w) -{ - if (w == 1) // lpDDSBack - { - if(!lpDDSBack) return 0; - if(IDirectDrawSurface7_Restore(lpDDSBack)!=DD_OK) return 0; - } else // 0 means lpDDSPrimary - { - if(!lpDDSPrimary) return 0; - if(IDirectDrawSurface7_Restore(lpDDSPrimary)!=DD_OK) return 0; + if(lpScreenSurface) { + IDirectDrawSurface7_Restore(lpScreenSurface); + wipeSurface = true; } - veflags|=1; - return 1; } -void FCEUD_SetPalette(unsigned char index, unsigned char r, unsigned char g, unsigned char b) +static void RestoreLostOffscreenSurface() { - if (force_grayscale) - { - // convert the palette entry to grayscale - int gray = ((float)r * 0.299 + (float)g * 0.587 + (float)b * 0.114); - color_palette[index].peRed = gray; - color_palette[index].peGreen = gray; - color_palette[index].peBlue = gray; - } else - { - color_palette[index].peRed = r; - color_palette[index].peGreen = g; - color_palette[index].peBlue = b; + if(lpOffscreenSurface) { + IDirectDrawSurface7_Restore(lpOffscreenSurface); + wipeSurface = true; } - PaletteChanged=1; } -void FCEUD_GetPalette(unsigned char i, unsigned char *r, unsigned char *g, unsigned char *b) +static bool CreateDDraw() { - *r=color_palette[i].peRed; - *g=color_palette[i].peGreen; - *b=color_palette[i].peBlue; -} + ShutdownVideoDriver(); -static bool firstInitialize = true; -static int InitializeDDraw(int fs) -{ - //only init the palette the first time through - if (firstInitialize) + HRESULT status; { - firstInitialize = false; - color_palette = (PALETTEENTRY*)malloc(256 * sizeof(PALETTEENTRY)); - } - - if ((fs && directDrawModeFullscreen == DIRECTDRAW_MODE_SOFTWARE) || (!fs && directDrawModeWindowed == DIRECTDRAW_MODE_SOFTWARE)) - ddrval = DirectDrawCreate((GUID FAR *)DDCREATE_EMULATIONONLY, &lpDD, NULL); + GUID FAR *guid; + if ((GetIsFullscreen() && directDrawModeFullscreen == DIRECTDRAW_MODE_SOFTWARE) || (!GetIsFullscreen() && directDrawModeWindowed == DIRECTDRAW_MODE_SOFTWARE)) + guid = (GUID FAR *)DDCREATE_EMULATIONONLY; else - ddrval = DirectDrawCreate(NULL, &lpDD, NULL); + guid = NULL; - if (ddrval != DD_OK) + LPDIRECTDRAW ddrawHandle; + status = DirectDrawCreate(guid, &ddrawHandle, NULL); + if (status != DD_OK) { - //ShowDDErr("Error creating DirectDraw object."); FCEU_printf("Error creating DirectDraw object.\n"); - return 0; + return false; } - //mbg merge 7/17/06 changed: - ddrval = IDirectDraw_QueryInterface(lpDD,IID_IDirectDraw7,(LPVOID *)&lpDD7); - //ddrval = IDirectDraw_QueryInterface(lpDD,&IID_IDirectDraw7,(LPVOID *)&lpDD7); - IDirectDraw_Release(lpDD); - - if (ddrval != DD_OK) + status = IDirectDraw_QueryInterface(ddrawHandle,IID_IDirectDraw7,(LPVOID *)&ddraw7Handle); + IDirectDraw_Release(ddrawHandle); + if (status != DD_OK) { - //ShowDDErr("Error querying interface."); FCEU_printf("Error querying interface.\n"); - return 0; + return false; + } } + DDCAPS caps; + memset(&caps,0,sizeof(caps)); caps.dwSize=sizeof(caps); - if(IDirectDraw7_GetCaps(lpDD7,&caps,0)!=DD_OK) + if(IDirectDraw7_GetCaps(ddraw7Handle,&caps,0)!=DD_OK) { - //ShowDDErr("Error getting capabilities."); FCEU_printf("Error getting capabilities.\n"); - return 0; + return false; } - return 1; + + return true; } -static int GetBPP(void) +static bool InitBPPStuff(bool fullscreen) { DDPIXELFORMAT ddpix; - memset(&ddpix,0,sizeof(ddpix)); ddpix.dwSize=sizeof(ddpix); - ddrval=IDirectDrawSurface7_GetPixelFormat(lpDDSPrimary,&ddpix); - if (ddrval != DD_OK) - { - //ShowDDErr("Error getting primary surface pixel format."); - FCEU_printf("Error getting primary surface pixel format.\n"); - return 0; - } - - if(ddpix.dwFlags&DDPF_RGB) - { - //mbg merge 7/17/06 removed silly dummy union stuff now that we have c++ + HRESULT status = IDirectDrawSurface7_GetPixelFormat(lpScreenSurface,&ddpix); + if (status == DD_OK) { + if (FL_TEST(ddpix.dwFlags, DDPF_RGB)) { bpp=ddpix.dwRGBBitCount; - CBM[0]=ddpix.dwRBitMask; - CBM[1]=ddpix.dwGBitMask; - CBM[2]=ddpix.dwBBitMask; - } - else - { - //ShowDDErr("RGB data not valid."); - FCEU_printf("RGB data not valid.\n"); - return 0; - } - if(bpp==15) bpp=16; + colorsBitMask[0]=ddpix.dwRBitMask; + colorsBitMask[1]=ddpix.dwGBitMask; + colorsBitMask[2]=ddpix.dwBBitMask; + + if (bpp==15) bpp=16; - return 1; -} + if (!fullscreen || (bpp==16 || bpp==24 || bpp==32)) { // in fullscreen check for supported bitcount + if (bpp >= 16) + { + int filterIdx = (fullscreen)? videoModes[vmodeIdx].filter:idxFilterModeWindowed; + int ntscFiltOpt = 0; + if (filterIdx == FILTER_NTSC2X) { + ntscFiltOpt = ntscFilterOption; + } -static int InitBPPStuff(int fs) -{ + InitBlitToHigh(bpp/8, + colorsBitMask[0], + colorsBitMask[1], + colorsBitMask[2], + 0, + filterIdx, + ntscFiltOpt); - int specfilteropt = 0; - switch (winspecial) - { - case 3: - specfilteropt = NTSCwinspecial; - break; + return true; + } + else if (bpp==8) + { + HRESULT status = IDirectDraw7_CreatePalette( ddraw7Handle, + DDPCAPS_8BIT|DDPCAPS_ALLOW256|DDPCAPS_INITIALIZE, + color_palette, + &ddPaletteHandle, + NULL); + if (status == DD_OK) { + status = IDirectDrawSurface7_SetPalette(lpScreenSurface, ddPaletteHandle); + if (status == DD_OK) { + return true; } - - if(bpp >= 16) - { - InitBlitToHigh(bpp >> 3, CBM[0], CBM[1], CBM[2], 0, fs?vmodes[vmod].special:winspecial,specfilteropt); + else { + FCEU_printf("Error setting palette object.\n"); } - else if(bpp==8) - { - ddrval=IDirectDraw7_CreatePalette( lpDD7, DDPCAPS_8BIT|DDPCAPS_ALLOW256|DDPCAPS_INITIALIZE,color_palette,&lpddpal,NULL); - if (ddrval != DD_OK) - { - //ShowDDErr("Error creating palette object."); + } + else { FCEU_printf("Error creating palette object.\n"); - return 0; } - ddrval=IDirectDrawSurface7_SetPalette(lpDDSPrimary, lpddpal); - if (ddrval != DD_OK) - { - //ShowDDErr("Error setting palette object."); - FCEU_printf("Error setting palette object.\n"); - return 0; + } + } // if(supported bpp) + } + else { + FCEU_printf("RGB data not valid.\n"); } } - return 1; + else { + FCEU_printf("Error getting primary surface pixel format.\n"); + } + + return false; } -void recalculateBestFitRect(int width, int height) +void OnWindowSizeChange(int wndWidth, int wndHeight) { - if (!lpDD7) + if (!ddraw7Handle) return; // DirectDraw isn't initialized yet - double screen_width = VNSWID; - double screen_height = FSettings.TotalScanlines(); - if (eoptions & EO_TVASPECT) - screen_width = ceil(screen_height * (screen_width / 256) * (tvAspectX / tvAspectY)); + double srcHeight = FSettings.TotalScanlines(); + double srcWidth = VNSWID; + if (FL_TEST(eoptions, EO_TVASPECT)) + srcWidth = ceil(srcHeight * (srcWidth / 256) * (tvAspectX / tvAspectY)); - int center_x = width / 2; - int center_y = height / 2; + double current_aspectratio = (double)wndWidth / (double)wndHeight; + double needed_aspectratio = srcWidth / srcHeight; - // calculate bestfitRect - double current_aspectratio = (double)width / (double)height; - double needed_aspectratio = screen_width / screen_height; - if (current_aspectratio >= needed_aspectratio) - { - // the window is wider than emulated screen - double new_height = height; - if (eoptions & EO_SQUAREPIXELS) - { - new_height = int((double)height / screen_height) * screen_height; + double new_width; + double new_height; + if (current_aspectratio >= needed_aspectratio) { + // the window is wider or match emulated screen + new_height = wndHeight; + if (FL_TEST(eoptions, EO_SQUAREPIXELS)) { + new_height = srcHeight * int((double)wndHeight / srcHeight); // integer scale of src if (new_height == 0) - new_height = height; + new_height = wndHeight; // window is smaller than src (or srcHeight is zero, which I hope never the case) } - bestfitRect.top = center_y - (int)(new_height / 2); - bestfitRect.bottom = bestfitRect.top + new_height; - double new_width = (new_height * needed_aspectratio); - if (eoptions & EO_SQUAREPIXELS && !(eoptions & EO_TVASPECT)) - { - int new_width_integer = int((double)new_width / screen_width) * screen_width; + + new_width = (new_height * needed_aspectratio); + if (FL_TEST(eoptions, EO_SQUAREPIXELS) && !FL_TEST(eoptions, EO_TVASPECT)) { + int new_width_integer = int((double)new_width / srcWidth) * srcWidth; if (new_width_integer > 0) new_width = new_width_integer; } - bestfitRect.left = center_x - (int)(new_width / 2); - bestfitRect.right = bestfitRect.left + new_width; - } else - { + } + else { // the window is taller than emulated screen - double new_width = width; - if (eoptions & EO_SQUAREPIXELS) + new_width = wndWidth; + if (FL_TEST(eoptions, EO_SQUAREPIXELS)) { - new_width = int((double)width / screen_width) * screen_width; + new_width = int((double)wndWidth / srcWidth) * srcWidth; if (new_width == 0) - new_width = width; + new_width = wndWidth; } - bestfitRect.left = center_x - (int)(new_width / 2); - bestfitRect.right = bestfitRect.left + new_width; - double new_height = (new_width / needed_aspectratio); - if (eoptions & EO_SQUAREPIXELS && !(eoptions & EO_TVASPECT)) + + new_height = (new_width / needed_aspectratio); + if (FL_TEST(eoptions, EO_SQUAREPIXELS) && !FL_TEST(eoptions, EO_TVASPECT)) { - int new_height_integer = int((double)new_height / screen_height) * screen_height; + int new_height_integer = int((double)new_height / srcHeight) * srcHeight; if (new_height_integer > 0) new_height = new_height_integer; } - bestfitRect.top = center_y - (int)(new_height / 2); - bestfitRect.bottom = bestfitRect.top + new_height; + } + + activeRect.left = (int)((wndWidth - new_width) / 2); + activeRect.right = activeRect.left + new_width; + activeRect.top = (int)((wndHeight - new_height) / 2); + activeRect.bottom = activeRect.top + new_height; +} + +static void ResetVideoModeParams() +{ + // use current display settings + if (!ddraw7Handle) + return; + + DDSURFACEDESC2 surfaceDescription; + memset(&surfaceDescription,0,sizeof(surfaceDescription)); + surfaceDescription.dwSize = sizeof(DDSURFACEDESC2); + HRESULT status = IDirectDraw7_GetDisplayMode(ddraw7Handle, &surfaceDescription); + if (SUCCEEDED(status)) { + videoModes[vmodeIdx].width = surfaceDescription.dwWidth; + videoModes[vmodeIdx].height = surfaceDescription.dwHeight; + videoModes[vmodeIdx].bpp = surfaceDescription.ddpfPixelFormat.dwRGBBitCount; + videoModes[vmodeIdx].xscale = videoModes[vmodeIdx].yscale = 1; + videoModes[vmodeIdx].flags = VIDEOMODEFLAG_DXBLT|VIDEOMODEFLAG_STRFS; } } -int SetVideoMode(int fs) +static bool RecalcVideoModeParams() { - int specmul = 1; // Special scaler size multiplier + VideoMode& vmode = videoModes[0]; + if ((vmode.width <= 0) || (vmode.height <= 0)) + ResetVideoModeParams(); - if(fs) - if(!vmod) - if(!RecalcCustom()) - return(0); + if(FL_TEST(vmode.flags, VIDEOMODEFLAG_STRFS)) { + FL_SET(vmode.flags, VIDEOMODEFLAG_DXBLT); + } + else if(vmode.xscale!=1 || vmode.yscale!=1 || vmode.filter!=FILTER_NONE) { + // if scaled or have filter (which may have scale) + FL_SET(vmode.flags, VIDEOMODEFLAG_DXBLT); - vflags=0; - veflags=1; - PaletteChanged=1; + if(vmode.filter != FILTER_NONE) { + // adjust vmode scale to be no less than filter scale + int mult = filterScaleMultiplier[vmode.filter]; - ResetVideo(); - fullscreen=fs; + if(vmode.xscale < mult) + vmode.xscale = mult; + if(vmode.yscale < mult) + vmode.yscale = mult; - if(!InitializeDDraw(fs)) return(1); // DirectDraw not initialized - - - if(!fs) - { - // -Video Modes Tag- - if(winspecial <= 3 && winspecial >= 1) - specmul = 2; - else if(winspecial >= 4 && winspecial <= 5) - specmul = 3; - else - specmul = 1; - - ShowCursorAbs(1); - windowedfailed=1; - HideFWindow(0); - - ddrval = IDirectDraw7_SetCooperativeLevel ( lpDD7, hAppWnd, DDSCL_NORMAL); - if (ddrval != DD_OK) - { - //ShowDDErr("Error setting cooperative level."); - FCEU_printf("Error setting cooperative level.\n"); - return 1; + if(vmode.xscale == mult && vmode.yscale == mult) + FL_CLEAR(vmode.flags, VIDEOMODEFLAG_DXBLT); // exact match, no need for "region blit"? } - //Beginning - memset(&ddsd,0,sizeof(ddsd)); - ddsd.dwSize = sizeof(ddsd); - ddsd.dwFlags = DDSD_CAPS; - ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE; - - ddrval = IDirectDraw7_CreateSurface ( lpDD7, &ddsd, &lpDDSPrimary,(IUnknown FAR*)NULL); - if (ddrval != DD_OK) - { - //ShowDDErr("Error creating primary surface."); - FCEU_printf("Error creating primary surface.\n"); - return 1; - } - - memset(&ddsdback,0,sizeof(ddsdback)); - ddsdback.dwSize=sizeof(ddsdback); - ddsdback.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH; - ddsdback.ddsCaps.dwCaps= DDSCAPS_OFFSCREENPLAIN; - - ddsdback.dwWidth=256 * specmul; - ddsdback.dwHeight=FSettings.TotalScanlines() * specmul; - - if (directDrawModeWindowed == DIRECTDRAW_MODE_SURFACE_IN_RAM) - // create the buffer in system memory - ddsdback.ddsCaps.dwCaps |= DDSCAPS_SYSTEMMEMORY; - - ddrval = IDirectDraw7_CreateSurface(lpDD7, &ddsdback, &lpDDSBack, (IUnknown FAR*)NULL); - if (ddrval != DD_OK) - { - //ShowDDErr("Error creating secondary surface."); - FCEU_printf("Error creating secondary surface.\n"); - return 0; - } - - if(!GetBPP()) - return 0; - - if(bpp!=16 && bpp!=24 && bpp!=32) - { - //ShowDDErr("Current bit depth not supported!"); - FCEU_printf("Current bit depth not supported!\n"); - return 0; - } - - if(!InitBPPStuff(fs)) - return 0; - - ddrval=IDirectDraw7_CreateClipper(lpDD7,0,&lpClipper,0); - if (ddrval != DD_OK) - { - //ShowDDErr("Error creating clipper."); - FCEU_printf("Error creating clipper.\n"); - return 0; - } - - ddrval=IDirectDrawClipper_SetHWnd(lpClipper,0,hAppWnd); - if (ddrval != DD_OK) - { - //ShowDDErr("Error setting clipper window."); - FCEU_printf("Error setting clipper window.\n"); - return 0; - } - ddrval=IDirectDrawSurface7_SetClipper(lpDDSPrimary,lpClipper); - if (ddrval != DD_OK) - { - //ShowDDErr("Error attaching clipper to primary surface."); - FCEU_printf("Error attaching clipper to primary surface.\n"); - return 0; - } - - windowedfailed=0; - SetMainWindowStuff(); - } else - { - //Following is full-screen - if(vmod == 0) // Custom mode - { - // -Video Modes Tag- - if(vmodes[0].special <= 3 && vmodes[0].special >= 1) - specmul = 2; - else if(vmodes[0].special >= 4 && vmodes[0].special <= 5) - specmul = 3; - else - specmul = 1; - } - HideFWindow(1); - - ddrval = IDirectDraw7_SetCooperativeLevel ( lpDD7, hAppWnd,DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN | DDSCL_ALLOWREBOOT); - if (ddrval != DD_OK) - { - //ShowDDErr("Error setting cooperative level."); - FCEU_printf("Error setting cooperative level.\n"); - return 0; - } - - ddrval = IDirectDraw7_SetDisplayMode(lpDD7, vmodes[vmod].x, vmodes[vmod].y,vmodes[vmod].bpp,0,0); - if (ddrval != DD_OK) - { - //ShowDDErr("Error setting display mode."); - FCEU_printf("Error setting display mode.\n"); - return 0; - } - if(vmodes[vmod].flags&VMDF_DXBLT) - { - memset(&ddsdback,0,sizeof(ddsdback)); - ddsdback.dwSize=sizeof(ddsdback); - ddsdback.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH; - ddsdback.ddsCaps.dwCaps= DDSCAPS_OFFSCREENPLAIN; - - ddsdback.dwWidth=256 * specmul; //vmodes[vmod].srect.right; - ddsdback.dwHeight=FSettings.TotalScanlines() * specmul; //vmodes[vmod].srect.bottom; - - if (directDrawModeFullscreen == DIRECTDRAW_MODE_SURFACE_IN_RAM) - // create the buffer in system memory - ddsdback.ddsCaps.dwCaps |= DDSCAPS_SYSTEMMEMORY; - - ddrval = IDirectDraw7_CreateSurface ( lpDD7, &ddsdback, &lpDDSBack, (IUnknown FAR*)NULL); - if(ddrval!=DD_OK) - { - //ShowDDErr("Error creating secondary surface."); - FCEU_printf("Error creating secondary surface.\n"); - return 0; + if(VNSWID*vmode.xscale > vmode.width) { + // videomode scale makes image too wide for it + if(vmode.filter == FILTER_NONE) { + FCEUD_PrintError("Scaled width is out of range. Reverting to no horizontal scaling."); + vmode.xscale=1; + } + else { + FCEUD_PrintError("Scaled width is out of range."); + return false; } } - if (eoptions & EO_BESTFIT) - recalculateBestFitRect(vmodes[vmod].x, vmodes[vmod].y); + if(FSettings.TotalScanlines()*vmode.yscale > vmode.height) { + // videomode scale makes image too tall for it + if(vmode.filter == FILTER_NONE) { + FCEUD_PrintError("Scaled height is out of range. Reverting to no vertical scaling."); + vmode.yscale=1; + } + else { + FCEUD_PrintError("Scaled height is out of range."); + return false; + } + } + + vmode.srcRect.left = VNSCLIP; + vmode.srcRect.top = FSettings.FirstSLine; + vmode.srcRect.right = 256-VNSCLIP; + vmode.srcRect.bottom = FSettings.LastSLine+1; + + vmode.dstRect.top = (vmode.height-(FSettings.TotalScanlines()*vmode.yscale)) / 2; + vmode.dstRect.bottom = vmode.dstRect.top+FSettings.TotalScanlines()*vmode.yscale; + vmode.dstRect.left = (vmode.width-(VNSWID*vmode.xscale)) / 2; + vmode.dstRect.right = vmode.dstRect.left+VNSWID*vmode.xscale; + } + + // -Video Modes Tag- + if((vmode.filter == FILTER_HQ2X || vmode.filter == FILTER_HQ3X) && vmode.bpp == 8) + { + // HQ2x/HQ3x requires 16bpp or 32bpp(best) + vmode.bpp = 32; + } + + if(vmode.width= 1) - specialmul = 2; - else if(winspecial >= 4 && winspecial <= 5) - specialmul = 3; - else specialmul = 1; + int scale = filterScaleMultiplier[idxFilterModeWindowed]; - srect.top=srect.left=0; - srect.right=VNSWID * specialmul; - srect.bottom=FSettings.TotalScanlines() * specialmul; - - if(PaletteChanged==1) - { - FixPaletteHi(); - PaletteChanged=0; + if(updateDDPalette) { + SetPaletteBlitToHigh((uint8*)color_palette); + updateDDPalette = false; } - if(!GetClientAbsRect(&wrect)) return; - - ddrval=IDirectDrawSurface7_Lock(lpDDSBack,NULL,&ddsdback, 0, NULL); - if (ddrval != DD_OK) + // Render XBuf into offscreen surface { - if (ddrval == DDERR_SURFACELOST) - RestoreDD(1); - return; + HRESULT status = IDirectDrawSurface7_Lock(lpOffscreenSurface, + NULL, + &surfaceDescOffscreen, + 0, + NULL); + + if (status != DD_OK) { + if (status == DDERR_SURFACELOST) + RestoreLostOffscreenSurface(); + return; } - //mbg merge 7/17/06 removing dummyunion stuff - pitch=ddsdback.lPitch; - ScreenLoc=(unsigned char*)ddsdback.lpSurface; //mbg merge 7/17/06 added cst - if(veflags&1) - { - memset(ScreenLoc,0,pitch*ddsdback.dwHeight); - veflags&=~1; + int pitch = surfaceDescOffscreen.lPitch; + unsigned char *dstOffscreenBuf = (unsigned char*)surfaceDescOffscreen.lpSurface; + + if(wipeSurface) { + memset(dstOffscreenBuf, 0, pitch * surfaceDescOffscreen.dwHeight); + wipeSurface = false; } - Blit8ToHigh(XBuf+FSettings.FirstSLine*256+VNSCLIP,ScreenLoc, VNSWID, FSettings.TotalScanlines(), pitch,specialmul,specialmul); + Blit8ToHigh(XBuf + FSettings.FirstSLine * 256 + VNSCLIP, + dstOffscreenBuf, + VNSWID, + FSettings.TotalScanlines(), + pitch, + scale, + scale); - IDirectDrawSurface7_Unlock(lpDDSBack, NULL); + IDirectDrawSurface7_Unlock(lpOffscreenSurface, NULL); + } - FCEUD_VerticalSync(); // aquanull 2011-11-28 fix tearing - if (eoptions & EO_BESTFIT && (bestfitRect.top || bestfitRect.left)) + VerticalSync(); + + // Blit offscreen to screen surface { - // blit with resizing - blitRect.top = wrect.top + bestfitRect.top; - blitRect.bottom = blitRect.top + bestfitRect.bottom - bestfitRect.top; - blitRect.left = wrect.left + bestfitRect.left; - blitRect.right = blitRect.left + bestfitRect.right - bestfitRect.left; - if (IDirectDrawSurface7_Blt(lpDDSPrimary, &blitRect, lpDDSBack, &srect, DDBLT_ASYNC, 0) != DD_OK) - { - ddrval = IDirectDrawSurface7_Blt(lpDDSPrimary, &blitRect, lpDDSBack, &srect, DDBLT_WAIT, 0); - if(ddrval != DD_OK) - { - if(ddrval == DDERR_SURFACELOST) + RECT rectSrc; // size of bitmap in offscreen surface + rectSrc.left = 0; + rectSrc.top = 0; + rectSrc.right = VNSWID * scale; + rectSrc.bottom = FSettings.TotalScanlines() * scale; + + RECT rectDst; + bool fillBorder = false; + if (FL_TEST(eoptions, EO_BESTFIT) && (activeRect.top || activeRect.left)) { - RestoreDD(1); - RestoreDD(0); + // blit into activeRect + rectDst.top = rectWindow.top + activeRect.top; + rectDst.bottom = rectDst.top + activeRect.bottom - activeRect.top; + rectDst.left = rectWindow.left + activeRect.left; + rectDst.right = rectDst.left + activeRect.right - activeRect.left; + + fillBorder = true; + } + else { + // blit into window rect + rectDst = rectWindow; + } + + if(IDirectDrawSurface7_Blt(lpScreenSurface, &rectDst, lpOffscreenSurface, &rectSrc, DDBLT_ASYNC, 0) != DD_OK) { + HRESULT status = IDirectDrawSurface7_Blt(lpScreenSurface, &rectDst, lpOffscreenSurface, &rectSrc, DDBLT_WAIT, 0); + if(status != DD_OK) { + if(status == DDERR_SURFACELOST) { + RestoreLostOffscreenSurface(); + RestoreLostScreenSurface(); } return; } } - // clear borders - if (eoptions & EO_BGCOLOR) - { + + if (fillBorder) { + DDBLTFX blitfx = { sizeof(DDBLTFX) }; + if (FL_TEST(eoptions, EO_BGCOLOR)) { // fill the surface using BG color from PPU unsigned char r, g, b; FCEUD_GetPalette(0x80 | PALRAM[0], &r, &g, &b); blitfx.dwFillColor = (r << 16) + (g << 8) + b; - } else - { + } + else { blitfx.dwFillColor = 0; } - if (bestfitRect.top) - { + + if (activeRect.top) { // upper border - blitRect.top = wrect.top; - blitRect.bottom = wrect.top + bestfitRect.top; - blitRect.left = wrect.left; - blitRect.right = wrect.right; - IDirectDrawSurface7_Blt(lpDDSPrimary, &blitRect, NULL, NULL, DDBLT_COLORFILL | DDBLT_ASYNC, &blitfx); + rectDst = rectWindow; + rectDst.bottom = rectWindow.top + activeRect.top; + IDirectDrawSurface7_Blt(lpScreenSurface, &rectDst, NULL, NULL, DDBLT_COLORFILL | DDBLT_ASYNC, &blitfx); // lower border - blitRect.top += bestfitRect.bottom; - blitRect.bottom = wrect.bottom; - IDirectDrawSurface7_Blt(lpDDSPrimary, &blitRect, NULL, NULL, DDBLT_COLORFILL | DDBLT_ASYNC, &blitfx); + rectDst.top += activeRect.bottom; + rectDst.bottom = rectWindow.bottom; + IDirectDrawSurface7_Blt(lpScreenSurface, &rectDst, NULL, NULL, DDBLT_COLORFILL | DDBLT_ASYNC, &blitfx); } - if (bestfitRect.left) - { + + if (activeRect.left) { // left border - blitRect.top = wrect.top; - blitRect.bottom = wrect.bottom; - blitRect.left = wrect.left; - blitRect.right = wrect.left + bestfitRect.left; - IDirectDrawSurface7_Blt(lpDDSPrimary, &blitRect, NULL, NULL, DDBLT_COLORFILL | DDBLT_ASYNC, &blitfx); + rectDst = rectWindow; + rectDst.right = rectWindow.left + activeRect.left; + IDirectDrawSurface7_Blt(lpScreenSurface, &rectDst, NULL, NULL, DDBLT_COLORFILL | DDBLT_ASYNC, &blitfx); // right border - blitRect.left += bestfitRect.right; - blitRect.right = wrect.right; - IDirectDrawSurface7_Blt(lpDDSPrimary, &blitRect, NULL, NULL, DDBLT_COLORFILL | DDBLT_ASYNC, &blitfx); + rectDst.left += activeRect.right; + rectDst.right = rectWindow.right; + IDirectDrawSurface7_Blt(lpScreenSurface, &rectDst, NULL, NULL, DDBLT_COLORFILL | DDBLT_ASYNC, &blitfx); } - } else - { - // blit without resizing - if(IDirectDrawSurface7_Blt(lpDDSPrimary, &wrect, lpDDSBack, &srect, DDBLT_ASYNC, 0) != DD_OK) - { - ddrval = IDirectDrawSurface7_Blt(lpDDSPrimary, &wrect, lpDDSBack, &srect, DDBLT_WAIT, 0); - if(ddrval != DD_OK) - { - if(ddrval == DDERR_SURFACELOST) - { - RestoreDD(1); - RestoreDD(0); - } - return; } } - } } -static void DD_FillRect(LPDIRECTDRAWSURFACE7 surf, int left, int top, int right, int bottom, DWORD color) -{ - RECT r; - SetRect(&r,left,top,right,bottom); - DDBLTFX fx; - memset(&fx,0,sizeof(DDBLTFX)); - fx.dwSize = sizeof(DDBLTFX); - //fx.dwFillColor = color; - fx.dwFillColor = 0; //color is just for debug - surf->Blt(&r,NULL,NULL,DDBLT_COLORFILL | DDBLT_WAIT,&fx); -} - - +// Renders XBuf into one of three buffers depending on current settings +// If rendered into offscreen will blit into one of screen surface buffers with either stretch or integer scale +// If doublebuffering enabled, when transferring image to screen surface its back buffer is selected, then +// surface is flipped static void BlitScreenFull(uint8 *XBuf) { - static int pitch; - char *ScreenLoc; - //unsigned long x; //mbg merge 7/17/06 removed - //uint8 y; //mbg merge 7/17/06 removed - RECT srect, drect; - LPDIRECTDRAWSURFACE7 lpDDSVPrimary; - int specmul; // Special scaler size multiplier - // -Video Modes Tag- - if(vmodes[0].special <= 3 && vmodes[0].special >= 1) - specmul = 2; - else if(vmodes[0].special >= 4 && vmodes[0].special <= 5) - specmul = 3; - else - specmul = 1; + // in doublebuffer mode image should end up in screen surface back buffer + LPDIRECTDRAWSURFACE7 targetScreenSurface = (idxFullscreenSyncMode == SYNCMODE_DOUBLEBUF)? lpBackBuffer:lpScreenSurface; + if (!targetScreenSurface) return; - if(fssync==3) - lpDDSVPrimary=lpDDSDBack; - else - lpDDSVPrimary=lpDDSPrimary; - - if (!lpDDSVPrimary) return; - - if(PaletteChanged==1) - { - if(bpp>=16) - FixPaletteHi(); - else - { - ddrval=IDirectDrawPalette_SetEntries(lpddpal,0,0,256,color_palette); - if(ddrval!=DD_OK) - { - if(ddrval==DDERR_SURFACELOST) RestoreDD(0); + if(updateDDPalette) { + if(bpp>=16) SetPaletteBlitToHigh((uint8*)color_palette); + else { + HRESULT status = IDirectDrawPalette_SetEntries(ddPaletteHandle,0,0,256,color_palette); + if(status != DD_OK) { + if(status == DDERR_SURFACELOST) RestoreLostScreenSurface(); return; } } - PaletteChanged=0; + updateDDPalette = false; } - if(vmodes[vmod].flags&VMDF_DXBLT) - { - // start rendering into backbuffer - ddrval=IDirectDrawSurface7_Lock(lpDDSBack,NULL,&ddsdback, 0, NULL); - if(ddrval!=DD_OK) - { - if(ddrval==DDERR_SURFACELOST) RestoreDD(1); - return; - } - ScreenLoc=(char *)ddsdback.lpSurface; //mbg merge 7/17/06 added cast - pitch=ddsdback.lPitch; //mbg merge 7/17/06 removed dummyunion stuff - - srect.top=0; - srect.left=0; - srect.right=VNSWID * specmul; - srect.bottom=FSettings.TotalScanlines() * specmul; - - //if(vmodes[vmod].flags&VMDF_STRFS) - //{ - drect.top=0; - drect.left=0; - drect.right=vmodes[vmod].x; - drect.bottom=vmodes[vmod].y; - /* - } - else - { - drect.top=(vmodes[vmod].y-(FSettings.TotalScanlines()*vmodes[vmod].yscale))>>1; - drect.bottom=drect.top+(FSettings.TotalScanlines()*vmodes[vmod].yscale); - drect.left=(vmodes[vmod].x-VNSWID*vmodes[vmod].xscale)>>1; - drect.right=drect.left+VNSWID*vmodes[vmod].xscale; - RECT fullScreen; - fullScreen.left = fullScreen.top = 0; - fullScreen.right = vmodes[vmod].x; - fullScreen.bottom = vmodes[vmod].y; - RECT r; - r = drect; - int left = r.left; - int top = r.top; - int right = r.right; - int bottom = r.bottom; - DD_FillRect(lpDDSVPrimary,0,0,left,top,RGB(255,0,0)); //topleft - DD_FillRect(lpDDSVPrimary,left,0,right,top,RGB(128,0,0)); //topcenter - DD_FillRect(lpDDSVPrimary,right,0,fullScreen.right,top,RGB(0,255,0)); //topright - DD_FillRect(lpDDSVPrimary,0,top,left,bottom,RGB(0,128,0)); //left - DD_FillRect(lpDDSVPrimary,right,top,fullScreen.right,bottom,RGB(0,0,255)); //right - DD_FillRect(lpDDSVPrimary,0,bottom,left,fullScreen.bottom,RGB(0,0,128)); //bottomleft - DD_FillRect(lpDDSVPrimary,left,bottom,right,fullScreen.bottom,RGB(255,0,255)); //bottomcenter - DD_FillRect(lpDDSVPrimary,right,bottom,fullScreen.right,fullScreen.bottom,RGB(0,255,255)); //bottomright - } - */ - } else - { - // start rendering directly to screen - FCEUD_VerticalSync(); - ddrval=IDirectDrawSurface7_Lock(lpDDSVPrimary,NULL,&ddsd, 0, NULL); - if(ddrval!=DD_OK) - { - if(ddrval==DDERR_SURFACELOST) RestoreDD(0); + char* targetBuf; + int pitch; + RECT srcRect; + RECT displayRect; + int scale = filterScaleMultiplier[videoModes[vmodeIdx].filter]; + if(FL_TEST(videoModes[vmodeIdx].flags, VIDEOMODEFLAG_DXBLT)) { + // will render to offscreen surface + DDSURFACEDESC2 offscreenDesc; + memset(&offscreenDesc,0,sizeof(offscreenDesc)); + offscreenDesc.dwSize = sizeof(DDSURFACEDESC2); + HRESULT status = IDirectDrawSurface7_Lock(lpOffscreenSurface,NULL,&offscreenDesc, 0, NULL); + if(status != DD_OK) { + if(status==DDERR_SURFACELOST) RestoreLostOffscreenSurface(); return; } - ScreenLoc=(char*)ddsd.lpSurface; //mbg merge 7/17/06 added cast - pitch=ddsd.lPitch; //mbg merge 7/17/06 removing dummyunion stuff + targetBuf = (char *)offscreenDesc.lpSurface; + pitch = offscreenDesc.lPitch; + + srcRect.top = 0; + srcRect.left = 0; + srcRect.right = VNSWID * scale; + srcRect.bottom = FSettings.TotalScanlines() * scale; + + displayRect.top = 0; + displayRect.left = 0; + displayRect.right = videoModes[vmodeIdx].width; + displayRect.bottom = videoModes[vmodeIdx].height; + } + else { + // will render to selected screen buffer + VerticalSync(); + + DDSURFACEDESC2 screenDesc; + memset(&screenDesc,0,sizeof(screenDesc)); + screenDesc.dwSize = sizeof(DDSURFACEDESC2); + HRESULT status = IDirectDrawSurface7_Lock(targetScreenSurface,NULL,&screenDesc, 0, NULL); + if(status != DD_OK) { + if(status == DDERR_SURFACELOST) RestoreLostScreenSurface(); + return; } - if(veflags&1) - { - if(vmodes[vmod].flags&VMDF_DXBLT) - { - veflags|=2; - memset((char *)ScreenLoc,0,pitch*srect.bottom); - } - else - { - memset((char *)ScreenLoc,0,pitch*vmodes[vmod].y); - } - PaletteChanged=1; - veflags&=~1; + targetBuf = (char*)screenDesc.lpSurface; + pitch = screenDesc.lPitch; } - //mbg 6/29/06 merge -#ifndef MSVC - if(vmod==5) - { - if(eoptions&EO_CLIPSIDES) - { - asm volatile( - "xorl %%edx, %%edx\n\t" - "akoop1:\n\t" - "movb $120,%%al \n\t" - "akoop2:\n\t" - "movb 1(%%esi),%%dl\n\t" - "shl $16,%%edx\n\t" - "movb (%%esi),%%dl\n\t" - "movl %%edx,(%%edi)\n\t" - "addl $2,%%esi\n\t" - "addl $4,%%edi\n\t" - "decb %%al\n\t" - "jne akoop2\n\t" - "addl $16,%%esi\n\t" - "addl %%ecx,%%edi\n\t" - "decb %%bl\n\t" - "jne akoop1\n\t" - : - : "S" (XBuf+FSettings.FirstSLine*256+VNSCLIP), "D" (ScreenLoc+((240-FSettings.TotalScanlines())/2)*pitch+(640-(VNSWID<<1))/2),"b" (FSettings.TotalScanlines()), "c" ((pitch-VNSWID)<<1) - : "%al", "%edx", "%cc" ); + if(wipeSurface) { + int lineCount = (FL_TEST(videoModes[vmodeIdx].flags, VIDEOMODEFLAG_DXBLT))? srcRect.bottom:videoModes[vmodeIdx].height; + memset(targetBuf, 0, pitch * lineCount); + updateDDPalette = true; + wipeSurface = false; } - else - { - asm volatile( - "xorl %%edx, %%edx\n\t" - "koop1:\n\t" - "movb $128,%%al \n\t" - "koop2:\n\t" - "movb 1(%%esi),%%dl\n\t" - "shl $16,%%edx\n\t" - "movb (%%esi),%%dl\n\t" - "movl %%edx,(%%edi)\n\t" - "addl $2,%%esi\n\t" - "addl $4,%%edi\n\t" - "decb %%al\n\t" - "jne koop2\n\t" - "addl %%ecx,%%edi\n\t" - "decb %%bl\n\t" - "jne koop1\n\t" - : - : "S" (XBuf+FSettings.FirstSLine*256), "D" (ScreenLoc+((240-FSettings.TotalScanlines())/2)*pitch+(640-512)/2),"b" (FSettings.TotalScanlines()), "c" (pitch-512+pitch) - : "%al", "%edx", "%cc" ); - } - } - else if(vmod==4) - { - if(eoptions&EO_CLIPSIDES) - { - asm volatile( - "ayoop1:\n\t" - "movb $120,%%al \n\t" - "ayoop2:\n\t" - "movb 1(%%esi),%%dh\n\t" - "movb %%dh,%%dl\n\t" - "shl $16,%%edx\n\t" - "movb (%%esi),%%dl\n\t" - "movb %%dl,%%dh\n\t" // Ugh - "movl %%edx,(%%edi)\n\t" - "addl $2,%%esi\n\t" - "addl $4,%%edi\n\t" - "decb %%al\n\t" - "jne ayoop2\n\t" - "addl $16,%%esi\n\t" - "addl %%ecx,%%edi\n\t" - "decb %%bl\n\t" - "jne ayoop1\n\t" - : - : "S" (XBuf+FSettings.FirstSLine*256+VNSCLIP), "D" (ScreenLoc+((240-FSettings.TotalScanlines())/2)*pitch+(640-(VNSWID<<1))/2),"b" (FSettings.TotalScanlines()), "c" ((pitch-VNSWID)<<1) - : "%al", "%edx", "%cc" ); - } - else - { - asm volatile( - "yoop1:\n\t" - "movb $128,%%al \n\t" - "yoop2:\n\t" - "movb 1(%%esi),%%dh\n\t" - "movb %%dh,%%dl\n\t" - "shl $16,%%edx\n\t" - "movb (%%esi),%%dl\n\t" - "movb %%dl,%%dh\n\t" // Ugh - "movl %%edx,(%%edi)\n\t" - "addl $2,%%esi\n\t" - "addl $4,%%edi\n\t" - "decb %%al\n\t" - "jne yoop2\n\t" - "addl %%ecx,%%edi\n\t" - "decb %%bl\n\t" - "jne yoop1\n\t" - : - : "S" (XBuf+FSettings.FirstSLine*256), "D" (ScreenLoc+((240-FSettings.TotalScanlines())/2)*pitch+(640-512)/2),"b" (FSettings.TotalScanlines()), "c" (pitch-512+pitch) - : "%al", "%edx", "%cc" ); - } - } - else -#endif - //mbg 6/29/06 merge - { - if(!(vmodes[vmod].flags&VMDF_DXBLT)) - { + + if(!FL_TEST(videoModes[vmodeIdx].flags, VIDEOMODEFLAG_DXBLT)) { // -Video Modes Tag- - if(vmodes[vmod].special) - ScreenLoc += (vmodes[vmod].drect.left*(bpp>>3)) + ((vmodes[vmod].drect.top)*pitch); + if(videoModes[vmodeIdx].filter != FILTER_NONE) + targetBuf += (videoModes[vmodeIdx].dstRect.left * (bpp/8)) + (videoModes[vmodeIdx].dstRect.top * pitch); else - ScreenLoc+=((vmodes[vmod].x-VNSWID)>>1)*(bpp>>3)+(((vmodes[vmod].y-FSettings.TotalScanlines())>>1))*pitch; - } - - if(bpp>=16) - { - Blit8ToHigh(XBuf+FSettings.FirstSLine*256+VNSCLIP,(uint8*)ScreenLoc, VNSWID, FSettings.TotalScanlines(), pitch,specmul,specmul); //mbg merge 7/17/06 added cast - } - else - { - XBuf+=FSettings.FirstSLine*256+VNSCLIP; - // -Video Modes Tag- - if(vmodes[vmod].special) - Blit8To8(XBuf,(uint8*)ScreenLoc, VNSWID, FSettings.TotalScanlines(), pitch,vmodes[vmod].xscale,vmodes[vmod].yscale,0,vmodes[vmod].special); //mbg merge 7/17/06 added cast - else - Blit8To8(XBuf,(uint8*)ScreenLoc, VNSWID, FSettings.TotalScanlines(), pitch,1,1,0,0); //mbg merge 7/17/06 added cast - } + targetBuf += ((videoModes[vmodeIdx].width-VNSWID)/2)*(bpp/8)+(((videoModes[vmodeIdx].height-FSettings.TotalScanlines())/2))*pitch; } - if(vmodes[vmod].flags&VMDF_DXBLT) - { - IDirectDrawSurface7_Unlock(lpDDSBack, NULL); - FCEUD_VerticalSync(); - if (eoptions & EO_BESTFIT && (bestfitRect.top || bestfitRect.left) && !vmod) - { - // blit with resizing - if (IDirectDrawSurface7_Blt(lpDDSVPrimary, &bestfitRect, lpDDSBack, &srect, DDBLT_ASYNC, 0) != DD_OK) + // Render XBuf into selected target buf + if(bpp >= 16) { + Blit8ToHigh(XBuf+FSettings.FirstSLine*256+VNSCLIP, + (uint8*)targetBuf, + VNSWID, + FSettings.TotalScanlines(), + pitch, + scale, + scale); + } + else { + // 8 bpp + Blit8To8(XBuf+FSettings.FirstSLine*256+VNSCLIP, + (uint8*)targetBuf, + VNSWID, + FSettings.TotalScanlines(), + pitch, + (videoModes[vmodeIdx].filter != FILTER_NONE)? videoModes[vmodeIdx].xscale:1, + (videoModes[vmodeIdx].filter != FILTER_NONE)? videoModes[vmodeIdx].yscale:1, + 0, + videoModes[vmodeIdx].filter); + } + + if(FL_TEST(videoModes[vmodeIdx].flags, VIDEOMODEFLAG_DXBLT)) { + IDirectDrawSurface7_Unlock(lpOffscreenSurface, NULL); + + VerticalSync(); + + bool fillBorder = false; + RECT* pDstRect; + if (FL_TEST(eoptions, EO_BESTFIT) && (activeRect.top || activeRect.left) && vmodeIdx==0) { + pDstRect = &activeRect; // blit offscreen to activeRect + fillBorder = true; + } + else { + pDstRect = NULL; // blit offscreen to entire surface + } + + if (IDirectDrawSurface7_Blt(targetScreenSurface, pDstRect, lpOffscreenSurface, &srcRect, DDBLT_ASYNC, 0) != DD_OK) { + HRESULT status = IDirectDrawSurface7_Blt(targetScreenSurface, pDstRect, lpOffscreenSurface, &srcRect, DDBLT_WAIT, 0); + if(status != DD_OK) { - ddrval = IDirectDrawSurface7_Blt(lpDDSVPrimary, &bestfitRect, lpDDSBack, &srect, DDBLT_WAIT, 0); - if(ddrval != DD_OK) + if(status == DDERR_SURFACELOST) { - if(ddrval == DDERR_SURFACELOST) - { - RestoreDD(1); - RestoreDD(0); + RestoreLostOffscreenSurface(); + RestoreLostScreenSurface(); } return; } } - // clear borders - if (eoptions & EO_BGCOLOR) - { + + if(fillBorder) { + DDBLTFX blitfx = { sizeof(DDBLTFX) }; + if (FL_TEST(eoptions, EO_BGCOLOR)) { // fill the surface using BG color from PPU unsigned char r, g, b; FCEUD_GetPalette(0x80 | PALRAM[0], &r, &g, &b); blitfx.dwFillColor = (r << 16) + (g << 8) + b; - } else - { + } + else { blitfx.dwFillColor = 0; } - static RECT borderRect; - if (bestfitRect.top) - { + + RECT borderRect; + if (pDstRect->top) { // upper border - borderRect.top = drect.top; - borderRect.bottom = drect.top + bestfitRect.top; - borderRect.left = drect.left; - borderRect.right = drect.right; - IDirectDrawSurface7_Blt(lpDDSPrimary, &borderRect, NULL, NULL, DDBLT_COLORFILL | DDBLT_ASYNC, &blitfx); + borderRect = displayRect; + borderRect.bottom = displayRect.top + pDstRect->top; + IDirectDrawSurface7_Blt(lpScreenSurface, &borderRect, NULL, NULL, DDBLT_COLORFILL | DDBLT_ASYNC, &blitfx); // lower border - borderRect.top += bestfitRect.bottom; - borderRect.bottom = drect.bottom; - IDirectDrawSurface7_Blt(lpDDSPrimary, &borderRect, NULL, NULL, DDBLT_COLORFILL | DDBLT_ASYNC, &blitfx); + borderRect.top += pDstRect->bottom; + borderRect.bottom = displayRect.bottom; + IDirectDrawSurface7_Blt(lpScreenSurface, &borderRect, NULL, NULL, DDBLT_COLORFILL | DDBLT_ASYNC, &blitfx); } - if (bestfitRect.left) + if (activeRect.left) { // left border - borderRect.top = drect.top; - borderRect.bottom = drect.bottom; - borderRect.left = drect.left; - borderRect.right = drect.left + bestfitRect.left; - IDirectDrawSurface7_Blt(lpDDSPrimary, &borderRect, NULL, NULL, DDBLT_COLORFILL | DDBLT_ASYNC, &blitfx); + borderRect = displayRect; + borderRect.right = displayRect.left + pDstRect->left; + IDirectDrawSurface7_Blt(lpScreenSurface, &borderRect, NULL, NULL, DDBLT_COLORFILL | DDBLT_ASYNC, &blitfx); // right border - borderRect.left += bestfitRect.right; - borderRect.right = drect.right; - IDirectDrawSurface7_Blt(lpDDSPrimary, &borderRect, NULL, NULL, DDBLT_COLORFILL | DDBLT_ASYNC, &blitfx); - } - } else - { - /* - if(veflags&2) - { - // clear screen surface (is that really necessary?) - if(IDirectDrawSurface7_Lock(lpDDSVPrimary, NULL, &ddsd, 0, NULL)==DD_OK) - { - memset(ddsd.lpSurface,0,ddsd.lPitch*vmodes[vmod].y); //mbg merge 7/17/06 removing dummyunion stuff - IDirectDrawSurface7_Unlock(lpDDSVPrimary, NULL); - veflags&=~2; - } - } - */ - // blit without resizing - if(IDirectDrawSurface7_Blt(lpDDSVPrimary, NULL, lpDDSBack, &srect, DDBLT_ASYNC,0)!=DD_OK) - { - ddrval=IDirectDrawSurface7_Blt(lpDDSVPrimary, NULL, lpDDSBack, &srect, DDBLT_WAIT,0); - if(ddrval!=DD_OK) - { - if(ddrval==DDERR_SURFACELOST) - { - RestoreDD(1); - RestoreDD(0); - } - return; + borderRect.left += activeRect.right; + borderRect.right = displayRect.right; + IDirectDrawSurface7_Blt(lpScreenSurface, &borderRect, NULL, NULL, DDBLT_COLORFILL | DDBLT_ASYNC, &blitfx); } } } - } else - { - IDirectDrawSurface7_Unlock(lpDDSVPrimary, NULL); + else { + IDirectDrawSurface7_Unlock(targetScreenSurface, NULL); } - if(fssync==3) - { - IDirectDrawSurface7_Flip(lpDDSPrimary,0,0); + if(idxFullscreenSyncMode == SYNCMODE_DOUBLEBUF) { + IDirectDrawSurface7_Flip(lpScreenSurface,0,0); } } -void ResetVideo(void) +void InitVideoDriver() { + SetVideoMode(); +} + +void ShutdownVideoDriver(void) { ShowCursorAbs(1); KillBlitToHigh(); - if(lpDD7) - if(mustrestore) + if(ddraw7Handle) { + if(dispModeWasChanged) { - IDirectDraw7_RestoreDisplayMode(lpDD7); - mustrestore=0; + IDirectDraw7_RestoreDisplayMode(ddraw7Handle); + dispModeWasChanged = false; + } } - RELEASE(lpddpal); - RELEASE(lpDDSBack); - RELEASE(lpDDSPrimary); - RELEASE(lpClipper); - RELEASE(lpDD7); -} - -int specialmlut[5] = {1,2,2,3,3}; - -void ResetCustomMode() -{ - // use current display settings - if (!lpDD7) - return; - - vmdef *cmode = &vmodes[0]; - - DDSURFACEDESC2 temp_ddsd; - temp_ddsd.dwSize = sizeof(DDSURFACEDESC2); - IDirectDraw7_GetDisplayMode(lpDD7, &temp_ddsd); - if (FAILED(ddrval)) - return; - cmode->x = temp_ddsd.dwWidth; - cmode->y = temp_ddsd.dwHeight; - cmode->bpp = temp_ddsd.ddpfPixelFormat.dwRGBBitCount; - cmode->xscale = cmode->yscale = 1; - cmode->flags = VMDF_DXBLT|VMDF_STRFS; -} - -static int RecalcCustom(void) -{ - vmdef *cmode = &vmodes[0]; - - if ((cmode->x <= 0) || (cmode->y <= 0)) - ResetCustomMode(); - - if(cmode->flags&VMDF_STRFS) - { - cmode->flags |= VMDF_DXBLT; - } else if(cmode->xscale!=1 || cmode->yscale!=1 || cmode->special) - { - cmode->flags &= ~VMDF_DXBLT; - if(cmode->special) - { - int mult = specialmlut[cmode->special]; - - if(cmode->xscale < mult) - cmode->xscale = mult; - if(cmode->yscale < mult) - cmode->yscale = mult; - - if(cmode->xscale != mult || cmode->yscale != mult) - cmode->flags|=VMDF_DXBLT; - } - else - cmode->flags|=VMDF_DXBLT; - - - if(VNSWID*cmode->xscale>cmode->x) - { - if(cmode->special) - { - FCEUD_PrintError("Scaled width is out of range."); - return(0); - } - else - { - FCEUD_PrintError("Scaled width is out of range. Reverting to no horizontal scaling."); - cmode->xscale=1; - } - } - if(FSettings.TotalScanlines()*cmode->yscale>cmode->y) - { - if(cmode->special) - { - FCEUD_PrintError("Scaled height is out of range."); - return(0); - } - else - { - FCEUD_PrintError("Scaled height is out of range. Reverting to no vertical scaling."); - cmode->yscale=1; - } - } - - cmode->srect.left=VNSCLIP; - cmode->srect.top=FSettings.FirstSLine; - cmode->srect.right=256-VNSCLIP; - cmode->srect.bottom=FSettings.LastSLine+1; - - cmode->drect.top=(cmode->y-(FSettings.TotalScanlines()*cmode->yscale))>>1; - cmode->drect.bottom=cmode->drect.top+FSettings.TotalScanlines()*cmode->yscale; - - cmode->drect.left=(cmode->x-(VNSWID*cmode->xscale))>>1; - cmode->drect.right=cmode->drect.left+VNSWID*cmode->xscale; - } - - // -Video Modes Tag- - if((cmode->special == 1 || cmode->special == 4) && cmode->bpp == 8) - { - cmode->bpp = 32; - //FCEUD_PrintError("HQ2x/HQ3x requires 16bpp or 32bpp(best)."); - //return(0); - } - - if(cmode->xyflags&VMDF_STRFS)) - { - FCEUD_PrintError("Vertical resolution must not be less than the total number of drawn scanlines."); - return(0); - } - - return(1); + if(ddPaletteHandle) { + ddPaletteHandle->Release(); + ddPaletteHandle = NULL; + } + if(lpOffscreenSurface) { + lpOffscreenSurface->Release(); + lpOffscreenSurface = NULL; + } + if(lpScreenSurface) { + lpScreenSurface->Release(); + lpScreenSurface = NULL; + } + if(ddClipperHandle) { + ddClipperHandle->Release(); + ddClipperHandle = NULL; + } + if(ddraw7Handle) { + ddraw7Handle->Release(); + ddraw7Handle = NULL; + } } +//====================== +// Settings dialog +//====================== +// TODO: here's couple of things that should reside in now-empy gui.cpp BOOL SetDlgItemDouble(HWND hDlg, int item, double value) { char buf[16]; @@ -1216,7 +933,7 @@ double GetDlgItemDouble(HWND hDlg, int item) return(ret); } -BOOL CALLBACK VideoConCallB(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) +static BOOL CALLBACK VideoConCallB(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) { static char *vmstr[11]={ "Custom", @@ -1237,24 +954,18 @@ BOOL CALLBACK VideoConCallB(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lPara { case WM_INITDIALOG: { - /* - for(x=0;x<11;x++) - SendDlgItemMessage(hwndDlg,IDC_VIDEOCONFIG_MODE,CB_ADDSTRING,0,(LPARAM)(LPSTR)vmstr[x]); - SendDlgItemMessage(hwndDlg,IDC_VIDEOCONFIG_MODE,CB_SETCURSEL,vmod,(LPARAM)(LPSTR)0); - */ - SendDlgItemMessage(hwndDlg,IDC_VIDEOCONFIG_BPP,CB_ADDSTRING,0,(LPARAM)(LPSTR)"8"); SendDlgItemMessage(hwndDlg,IDC_VIDEOCONFIG_BPP,CB_ADDSTRING,0,(LPARAM)(LPSTR)"16"); SendDlgItemMessage(hwndDlg,IDC_VIDEOCONFIG_BPP,CB_ADDSTRING,0,(LPARAM)(LPSTR)"24"); SendDlgItemMessage(hwndDlg,IDC_VIDEOCONFIG_BPP,CB_ADDSTRING,0,(LPARAM)(LPSTR)"32"); - SendDlgItemMessage(hwndDlg,IDC_VIDEOCONFIG_BPP,CB_SETCURSEL,(vmodes[0].bpp>>3)-1,(LPARAM)(LPSTR)0); + SendDlgItemMessage(hwndDlg,IDC_VIDEOCONFIG_BPP,CB_SETCURSEL,(videoModes[vmodeIdx].bpp/8)-1,(LPARAM)(LPSTR)0); - SetDlgItemInt(hwndDlg,IDC_VIDEOCONFIG_XRES,vmodes[0].x,0); - SetDlgItemInt(hwndDlg,IDC_VIDEOCONFIG_YRES,vmodes[0].y,0); + SetDlgItemInt(hwndDlg,IDC_VIDEOCONFIG_XRES,videoModes[vmodeIdx].width,0); + SetDlgItemInt(hwndDlg,IDC_VIDEOCONFIG_YRES,videoModes[vmodeIdx].height,0); - //SetDlgItemInt(hwndDlg,IDC_VIDEOCONFIG_XSCALE,vmodes[0].xscale,0); - //SetDlgItemInt(hwndDlg,IDC_VIDEOCONFIG_YSCALE,vmodes[0].yscale,0); - //CheckRadioButton(hwndDlg,IDC_RADIO_SCALE,IDC_RADIO_STRETCH,(vmodes[0].flags&VMDF_STRFS)?IDC_RADIO_STRETCH:IDC_RADIO_SCALE); + //SetDlgItemInt(hwndDlg,IDC_VIDEOCONFIG_XSCALE,videoModes[vmodeIdx].xscale,0); + //SetDlgItemInt(hwndDlg,IDC_VIDEOCONFIG_YSCALE,videoModes[vmodeIdx].yscale,0); + //CheckRadioButton(hwndDlg,IDC_RADIO_SCALE,IDC_RADIO_STRETCH,FL_TEST(videoModes[vmodeIdx].flags, VIDEOMODEFLAG_STRFS)?IDC_RADIO_STRETCH:IDC_RADIO_SCALE); // -Video Modes Tag- char *str[]={"","hq2x","Scale2x","NTSC 2x","hq3x","Scale3x"}; @@ -1265,8 +976,8 @@ BOOL CALLBACK VideoConCallB(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lPara SendDlgItemMessage(hwndDlg,IDC_VIDEOCONFIG_SCALER_WIN,CB_ADDSTRING,0,(LPARAM)(LPSTR)str[x]); } - SendDlgItemMessage(hwndDlg, IDC_VIDEOCONFIG_SCALER_FS, CB_SETCURSEL, vmodes[0].special, (LPARAM)(LPSTR)0); - SendDlgItemMessage(hwndDlg, IDC_VIDEOCONFIG_SCALER_WIN, CB_SETCURSEL, winspecial, (LPARAM)(LPSTR)0); + SendDlgItemMessage(hwndDlg, IDC_VIDEOCONFIG_SCALER_FS, CB_SETCURSEL, videoModes[vmodeIdx].filter, (LPARAM)(LPSTR)0); + SendDlgItemMessage(hwndDlg, IDC_VIDEOCONFIG_SCALER_WIN, CB_SETCURSEL, idxFilterModeWindowed, (LPARAM)(LPSTR)0); // Direct Draw modes SendDlgItemMessage(hwndDlg, IDC_VIDEOCONFIG_DIRECTDRAW_WIN, CB_ADDSTRING, 0, (LPARAM)(LPSTR)"No hardware acceleration"); @@ -1281,31 +992,31 @@ BOOL CALLBACK VideoConCallB(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lPara SendDlgItemMessage(hwndDlg, IDC_VIDEOCONFIG_DIRECTDRAW_FS, CB_SETCURSEL, directDrawModeFullscreen, (LPARAM)(LPSTR)0); - if(eoptions&EO_FSAFTERLOAD) + if(FL_TEST(eoptions, EO_FSAFTERLOAD)) CheckDlgButton(hwndDlg,IDC_VIDEOCONFIG_AUTO_FS,BST_CHECKED); - if(eoptions&EO_HIDEMOUSE) + if(FL_TEST(eoptions, EO_HIDEMOUSE)) CheckDlgButton(hwndDlg,IDC_VIDEOCONFIG_HIDEMOUSE,BST_CHECKED); - if(eoptions&EO_CLIPSIDES) + if(FL_TEST(eoptions, EO_CLIPSIDES)) CheckDlgButton(hwndDlg,IDC_VIDEOCONFIG_CLIPSIDES,BST_CHECKED); - if(eoptions&EO_BESTFIT) + if(FL_TEST(eoptions, EO_BESTFIT)) CheckDlgButton(hwndDlg, IDC_VIDEOCONFIG_BESTFIT, BST_CHECKED); - if(eoptions&EO_BGCOLOR) + if(FL_TEST(eoptions, EO_BGCOLOR)) CheckDlgButton(hwndDlg,IDC_VIDEOCONFIG_CONSOLE_BGCOLOR,BST_CHECKED); - if(eoptions&EO_SQUAREPIXELS) + if(FL_TEST(eoptions, EO_SQUAREPIXELS)) CheckDlgButton(hwndDlg, IDC_VIDEOCONFIG_SQUARE_PIXELS, BST_CHECKED); - if(eoptions&EO_TVASPECT) + if(FL_TEST(eoptions, EO_TVASPECT)) CheckDlgButton(hwndDlg, IDC_VIDEOCONFIG_TVASPECT, BST_CHECKED); - if(eoptions&EO_FORCEISCALE) + if(FL_TEST(eoptions, EO_FORCEISCALE)) CheckDlgButton(hwndDlg,IDC_FORCE_INT_VIDEO_SCALARS,BST_CHECKED); - if(eoptions&EO_FORCEASPECT) + if(FL_TEST(eoptions, EO_FORCEASPECT)) CheckDlgButton(hwndDlg,IDC_FORCE_ASPECT_CORRECTION,BST_CHECKED); SetDlgItemInt(hwndDlg,IDC_SCANLINE_FIRST_NTSC,srendlinen,0); @@ -1330,10 +1041,10 @@ BOOL CALLBACK VideoConCallB(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lPara SendDlgItemMessage(hwndDlg,IDC_VIDEOCONFIG_SYNC_METHOD_FS,CB_ADDSTRING,0,(LPARAM)(LPSTR)"Lazy wait for VBlank"); SendDlgItemMessage(hwndDlg,IDC_VIDEOCONFIG_SYNC_METHOD_FS,CB_ADDSTRING,0,(LPARAM)(LPSTR)"Double Buffering"); - SendDlgItemMessage(hwndDlg,IDC_VIDEOCONFIG_SYNC_METHOD_WIN,CB_SETCURSEL,winsync,(LPARAM)(LPSTR)0); - SendDlgItemMessage(hwndDlg,IDC_VIDEOCONFIG_SYNC_METHOD_FS,CB_SETCURSEL,fssync,(LPARAM)(LPSTR)0); + SendDlgItemMessage(hwndDlg,IDC_VIDEOCONFIG_SYNC_METHOD_WIN,CB_SETCURSEL,idxWindowedSyncMode,(LPARAM)(LPSTR)0); + SendDlgItemMessage(hwndDlg,IDC_VIDEOCONFIG_SYNC_METHOD_FS,CB_SETCURSEL,idxFullscreenSyncMode,(LPARAM)(LPSTR)0); - if(eoptions&EO_NOSPRLIM) + if(FL_TEST(eoptions, EO_NOSPRLIM)) CheckDlgButton(hwndDlg,IDC_VIDEOCONFIG_NO8LIM,BST_CHECKED); char buf[1024] = "Full Screen"; @@ -1342,11 +1053,11 @@ BOOL CALLBACK VideoConCallB(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lPara { strcat(buf, " ("); strcat(buf, GetKeyComboName(c)); - if (fullscreenByDoubleclick) + if (GetIsFullscreenOnDoubleclick()) strcat(buf, " or double-click)"); else strcat(buf, ")"); - } else if (fullscreenByDoubleclick) + } else if (GetIsFullscreenOnDoubleclick()) { strcat(buf, " (double-click anywhere)"); } @@ -1364,39 +1075,20 @@ gornk: if(IsDlgButtonChecked(hwndDlg,IDC_VIDEOCONFIG_CLIPSIDES)==BST_CHECKED) { - eoptions|=EO_CLIPSIDES; + FL_SET(eoptions, EO_CLIPSIDES); ClipSidesOffset = 8; } else { - eoptions&=~EO_CLIPSIDES; + FL_CLEAR(eoptions, EO_CLIPSIDES); ClipSidesOffset = 0; } - if (IsDlgButtonChecked(hwndDlg, IDC_VIDEOCONFIG_BESTFIT) == BST_CHECKED) - eoptions |= EO_BESTFIT; - else - eoptions &= ~EO_BESTFIT; - - if (IsDlgButtonChecked(hwndDlg, IDC_VIDEOCONFIG_CONSOLE_BGCOLOR) == BST_CHECKED) - eoptions |= EO_BGCOLOR; - else - eoptions &= ~EO_BGCOLOR; - - if (IsDlgButtonChecked(hwndDlg, IDC_VIDEOCONFIG_SQUARE_PIXELS) == BST_CHECKED) - eoptions |= EO_SQUAREPIXELS; - else - eoptions &= ~EO_SQUAREPIXELS; - - if (IsDlgButtonChecked(hwndDlg, IDC_VIDEOCONFIG_TVASPECT) == BST_CHECKED) - eoptions |= EO_TVASPECT; - else - eoptions &= ~EO_TVASPECT; - - if(IsDlgButtonChecked(hwndDlg,IDC_VIDEOCONFIG_NO8LIM)==BST_CHECKED) - eoptions|=EO_NOSPRLIM; - else - eoptions&=~EO_NOSPRLIM; + FL_FROMBOOL(eoptions, EO_BESTFIT, IsDlgButtonChecked(hwndDlg, IDC_VIDEOCONFIG_BESTFIT) == BST_CHECKED); + FL_FROMBOOL(eoptions, EO_BGCOLOR, IsDlgButtonChecked(hwndDlg, IDC_VIDEOCONFIG_CONSOLE_BGCOLOR) == BST_CHECKED); + FL_FROMBOOL(eoptions, EO_SQUAREPIXELS, IsDlgButtonChecked(hwndDlg, IDC_VIDEOCONFIG_SQUARE_PIXELS) == BST_CHECKED); + FL_FROMBOOL(eoptions, EO_TVASPECT, IsDlgButtonChecked(hwndDlg, IDC_VIDEOCONFIG_TVASPECT) == BST_CHECKED); + FL_FROMBOOL(eoptions, EO_NOSPRLIM, IsDlgButtonChecked(hwndDlg,IDC_VIDEOCONFIG_NO8LIM) == BST_CHECKED); srendlinen=GetDlgItemInt(hwndDlg,IDC_SCANLINE_FIRST_NTSC,0,0); erendlinen=GetDlgItemInt(hwndDlg,IDC_SCANLINE_LAST_NTSC,0,0); @@ -1412,45 +1104,33 @@ gornk: UpdateRendBounds(); - /* - if(IsDlgButtonChecked(hwndDlg,IDC_RADIO_STRETCH)==BST_CHECKED) - vmodes[0].flags |= VMDF_STRFS|VMDF_DXBLT; - else - vmodes[0].flags &= ~(VMDF_STRFS|VMDF_DXBLT); - vmod=SendDlgItemMessage(hwndDlg,IDC_VIDEOCONFIG_MODE,CB_GETCURSEL,0,(LPARAM)(LPSTR)0); - */ - vmodes[0].x=GetDlgItemInt(hwndDlg,IDC_VIDEOCONFIG_XRES,0,0); - vmodes[0].y=GetDlgItemInt(hwndDlg,IDC_VIDEOCONFIG_YRES,0,0); - vmodes[0].bpp=(SendDlgItemMessage(hwndDlg,IDC_VIDEOCONFIG_BPP,CB_GETCURSEL,0,(LPARAM)(LPSTR)0)+1)<<3; + videoModes[0].width=GetDlgItemInt(hwndDlg,IDC_VIDEOCONFIG_XRES,0,0); + videoModes[0].height=GetDlgItemInt(hwndDlg,IDC_VIDEOCONFIG_YRES,0,0); + videoModes[0].bpp=(SendDlgItemMessage(hwndDlg,IDC_VIDEOCONFIG_BPP,CB_GETCURSEL,0,(LPARAM)(LPSTR)0)+1)<<3; - //vmodes[0].xscale=GetDlgItemInt(hwndDlg,IDC_VIDEOCONFIG_XSCALE,0,0); - //vmodes[0].yscale=GetDlgItemInt(hwndDlg,IDC_VIDEOCONFIG_YSCALE,0,0); - vmodes[0].special=SendDlgItemMessage(hwndDlg,IDC_VIDEOCONFIG_SCALER_FS,CB_GETCURSEL,0,(LPARAM)(LPSTR)0); + videoModes[0].filter = static_cast(SendDlgItemMessage(hwndDlg,IDC_VIDEOCONFIG_SCALER_FS,CB_GETCURSEL,0,(LPARAM)(LPSTR)0)); - winspecial = SendDlgItemMessage(hwndDlg, IDC_VIDEOCONFIG_SCALER_WIN, CB_GETCURSEL, 0, (LPARAM)(LPSTR)0); - directDrawModeWindowed = SendDlgItemMessage(hwndDlg, IDC_VIDEOCONFIG_DIRECTDRAW_WIN, CB_GETCURSEL, 0, (LPARAM)(LPSTR)0) % DIRECTDRAW_MODES_TOTAL; - directDrawModeFullscreen = SendDlgItemMessage(hwndDlg, IDC_VIDEOCONFIG_DIRECTDRAW_FS, CB_GETCURSEL, 0, (LPARAM)(LPSTR)0) % DIRECTDRAW_MODES_TOTAL; + idxFilterModeWindowed = static_cast(SendDlgItemMessage(hwndDlg, IDC_VIDEOCONFIG_SCALER_WIN, CB_GETCURSEL, 0, (LPARAM)(LPSTR)0)); - if(IsDlgButtonChecked(hwndDlg,IDC_VIDEOCONFIG_FS)==BST_CHECKED) - fullscreen=1; - else - fullscreen=0; + directDrawModeWindowed = static_cast(SendDlgItemMessage(hwndDlg, IDC_VIDEOCONFIG_DIRECTDRAW_WIN, CB_GETCURSEL, 0, (LPARAM)(LPSTR)0)); + if(directDrawModeWindowed >= DIRECTDRAW_MODES_TOTAL) { + FCEU_printf("DirectDraw windowed mode index out of bounds.\n"); + directDrawModeWindowed = DIRECTDRAW_MODE_SOFTWARE; + } - if(IsDlgButtonChecked(hwndDlg,IDC_VIDEOCONFIG_AUTO_FS)==BST_CHECKED) - eoptions|=EO_FSAFTERLOAD; - else - eoptions&=~EO_FSAFTERLOAD; + directDrawModeFullscreen = static_cast(SendDlgItemMessage(hwndDlg, IDC_VIDEOCONFIG_DIRECTDRAW_FS, CB_GETCURSEL, 0, (LPARAM)(LPSTR)0)); + if(directDrawModeFullscreen >= DIRECTDRAW_MODES_TOTAL) { + FCEU_printf("DirectDraw fullscreen mode index out of bounds.\n"); + directDrawModeFullscreen = DIRECTDRAW_MODE_SOFTWARE; + } - if(IsDlgButtonChecked(hwndDlg,IDC_VIDEOCONFIG_HIDEMOUSE)==BST_CHECKED) - eoptions|=EO_HIDEMOUSE; - else - eoptions&=~EO_HIDEMOUSE; + SetIsFullscreen( IsDlgButtonChecked(hwndDlg,IDC_VIDEOCONFIG_FS)==BST_CHECKED ); - eoptions &= ~(EO_FORCEISCALE | EO_FORCEASPECT); - if(IsDlgButtonChecked(hwndDlg,IDC_FORCE_INT_VIDEO_SCALARS)==BST_CHECKED) - eoptions|=EO_FORCEISCALE; - if(IsDlgButtonChecked(hwndDlg,IDC_FORCE_ASPECT_CORRECTION)==BST_CHECKED) - eoptions|=EO_FORCEASPECT; + FL_FROMBOOL(eoptions, EO_FSAFTERLOAD, IsDlgButtonChecked(hwndDlg,IDC_VIDEOCONFIG_AUTO_FS)==BST_CHECKED); + FL_FROMBOOL(eoptions, EO_HIDEMOUSE, IsDlgButtonChecked(hwndDlg,IDC_VIDEOCONFIG_HIDEMOUSE)==BST_CHECKED); + + FL_FROMBOOL(eoptions, EO_FORCEISCALE, IsDlgButtonChecked(hwndDlg,IDC_FORCE_INT_VIDEO_SCALARS)==BST_CHECKED); + FL_FROMBOOL(eoptions, EO_FORCEASPECT, IsDlgButtonChecked(hwndDlg,IDC_FORCE_ASPECT_CORRECTION)==BST_CHECKED); winsizemulx = GetDlgItemDouble(hwndDlg, IDC_WINSIZE_MUL_X); winsizemuly = GetDlgItemDouble(hwndDlg, IDC_WINSIZE_MUL_Y); @@ -1462,8 +1142,8 @@ gornk: if (tvAspectY < 0.1) tvAspectY = 0.1; - winsync=SendDlgItemMessage(hwndDlg,IDC_VIDEOCONFIG_SYNC_METHOD_WIN,CB_GETCURSEL,0,(LPARAM)(LPSTR)0); - fssync=SendDlgItemMessage(hwndDlg,IDC_VIDEOCONFIG_SYNC_METHOD_FS,CB_GETCURSEL,0,(LPARAM)(LPSTR)0); + idxWindowedSyncMode = static_cast(SendDlgItemMessage(hwndDlg,IDC_VIDEOCONFIG_SYNC_METHOD_WIN,CB_GETCURSEL,0,(LPARAM)(LPSTR)0)); + idxFullscreenSyncMode = static_cast(SendDlgItemMessage(hwndDlg,IDC_VIDEOCONFIG_SYNC_METHOD_FS,CB_GETCURSEL,0,(LPARAM)(LPSTR)0)); EndDialog(hwndDlg,0); break; } @@ -1471,47 +1151,143 @@ gornk: return 0; } -void SetFSVideoMode() +void DoVideoConfigFix() { - changerecursive=1; - if(!SetVideoMode(1)) - SetVideoMode(0); - changerecursive=0; -} - - -void DoVideoConfigFix(void) -{ - FCEUI_DisableSpriteLimitation(eoptions&EO_NOSPRLIM); + FCEUI_DisableSpriteLimitation(FL_TEST(eoptions, EO_NOSPRLIM)); UpdateRendBounds(); } -void PushCurrentVideoSettings() +//Shows the Video configuration dialog. +void ShowConfigVideoDialog(void) { - if(fullscreen) + if ((videoModes[0].width <= 0) || (videoModes[0].height <= 0)) + ResetVideoModeParams(); + DialogBox(fceu_hInstance, "VIDEOCONFIG", hAppWnd, VideoConCallB); + DoVideoConfigFix(); + FCEUD_VideoChanged(); +} + + +//====================== +// Get/Set +//====================== + +RECT GetActiveRect() { + return activeRect; +} + +PALETTEENTRY* GetPalette() { + return color_palette; +} + +bool GetIsFullscreen() { + return (fullscreenActual != 0); +} + +void SetIsFullscreen(bool f) { + fullscreenDesired = f; +} + +VSYNCMODE GetWindowedSyncModeIdx() { + return idxWindowedSyncMode; +} + +void SetWindowedSyncModeIdx(VSYNCMODE idx) { + idxWindowedSyncMode = idx; +} + + +//====================== +// FCEUD +//====================== +//draw input aids if we are fullscreen +bool FCEUD_ShouldDrawInputAids() +{ + return GetIsFullscreen(); +} + +//static uint8 *XBSave; +void FCEUD_BlitScreen(uint8 *XBuf) +{ + if(fullscreenActual) { - SetFSVideoMode(); + BlitScreenFull(XBuf); } else { - changerecursive = 1; - SetVideoMode(0); - changerecursive = 0; - //SetMainWindowStuff(); // it's already called inside SetVideoMode() + if(!windowedfailed) + BlitScreenWindow(XBuf); } } -//Shows the Video configuration dialog. -void ConfigVideo(void) -{ - if ((vmodes[0].x <= 0) || (vmodes[0].y <= 0)) - ResetCustomMode(); - DialogBox(fceu_hInstance, "VIDEOCONFIG", hAppWnd, VideoConCallB); - DoVideoConfigFix(); - PushCurrentVideoSettings(); -} - void FCEUD_VideoChanged() { - PushCurrentVideoSettings(); -} \ No newline at end of file + changerecursive = 1; + if(!SetVideoMode()) { + SetIsFullscreen(false); + SetVideoMode(); + } + changerecursive = 0; +} + +void FCEUD_SetPalette(unsigned char index, unsigned char r, unsigned char g, unsigned char b) +{ + if (force_grayscale) + { + // convert the palette entry to grayscale + int gray = ((float)r * 0.299 + (float)g * 0.587 + (float)b * 0.114); + color_palette[index].peRed = gray; + color_palette[index].peGreen = gray; + color_palette[index].peBlue = gray; + } else + { + color_palette[index].peRed = r; + color_palette[index].peGreen = g; + color_palette[index].peBlue = b; + } + updateDDPalette = true; +} + +void FCEUD_GetPalette(unsigned char i, unsigned char *r, unsigned char *g, unsigned char *b) +{ + *r=color_palette[i].peRed; + *g=color_palette[i].peGreen; + *b=color_palette[i].peBlue; +} + + +bool& _FIXME_getFullscreenVar() { + return fullscreenActual; // provide config with actual fullscreen state, not desired +} + +int& _FIXME_getVModeIdxVar() { + return vmodeIdx; +} + +VSYNCMODE& _FIXME_getFullscreenSyncModeIdxVar() { + return idxFullscreenSyncMode; +} + +VSYNCMODE& _FIXME_getWindowedSyncModeIdxVar() { + return idxWindowedSyncMode; +} + +VFILTER& _FIXME_getFilterModeWindowedIdxVar() { + return idxFilterModeWindowed; +} + +int& _FIXME_getFilterOptionVar() { + return ntscFilterOption; +} + +DIRECTDRAW_MODE& _FIXME_getDDrawModeWindowedVar() { + return directDrawModeWindowed; +} + +DIRECTDRAW_MODE& _FIXME_getDDrawModeFullscreenVar() { + return directDrawModeFullscreen; +} + +VideoMode& _FIXME_getCustomVideoModeVar() { + return videoModes[0]; +} diff --git a/branches/voxel/src/drivers/win/video.h b/branches/voxel/src/drivers/win/video.h index 201e5f44..367bd35e 100644 --- a/branches/voxel/src/drivers/win/video.h +++ b/branches/voxel/src/drivers/win/video.h @@ -1,71 +1,96 @@ #ifndef WIN_VIDEO_H #define WIN_VIDEO_H -#include "common.h" +#include +#include "types.h" -// I like hacks. -#define uint8 __UNO492032 -#include -#include "ddraw.h" -#undef LPCWAVEFORMATEX -#include "dsound.h" -#include "dinput.h" -#include -#include // For directories configuration dialog. -#undef uint8 - -#include "main.h" -#include "window.h" - -enum DIRECTDRAW_MODES +typedef enum { - DIRECTDRAW_MODE_SOFTWARE, - DIRECTDRAW_MODE_SURFACE_IN_RAM, - DIRECTDRAW_MODE_FULL, + DIRECTDRAW_MODE_SOFTWARE = 0, // all features are emulated in software + DIRECTDRAW_MODE_SURFACE_IN_RAM, // place offscreen surface in RAM rather than in VRAM; may or may not use hardware acceleration + DIRECTDRAW_MODE_FULL, // use available hardware features, emulate the rest // ... DIRECTDRAW_MODES_TOTAL -}; +} DIRECTDRAW_MODE; -#define VF_DDSTRETCHED 1 +#define VIDEOMODEFLAG_DXBLT 1 +#define VIDEOMODEFLAG_STRFS 2 -#define VEF_LOSTSURFACE 1 -#define VEF____INTERNAL 2 - -#define VMDF_DXBLT 1 -#define VMDF_STRFS 2 +typedef enum +{ + FILTER_NONE = 0, + FILTER_HQ2X, + FILTER_SCALE2X, + FILTER_NTSC2X, + FILTER_HQ3X, + FILTER_SCALE3X +} VFILTER; typedef struct { - int x; - int y; + int width; + int height; int bpp; int flags; int xscale; int yscale; - RECT srect; - RECT drect; - int special; -} vmdef; + RECT srcRect; + RECT dstRect; + VFILTER filter; +} VideoMode; -// left, top, right, bottom -extern vmdef vmodes[11]; -extern int winspecial; -extern int NTSCwinspecial; +typedef enum { + SYNCMODE_NONE = 0, + SYNCMODE_WAIT, + SYNCMODE_LAZYWAIT, + SYNCMODE_DOUBLEBUF +} VSYNCMODE; -extern int directDrawModeWindowed; -extern int directDrawModeFullscreen; +void InitVideoDriver(void); +void ShutdownVideoDriver(); -extern int fssync; -extern int winsync; +// Recalculate blit rectangle within window of given size +void OnWindowSizeChange(int width, int height); -void SetFSVideoMode(); -void FCEUD_BlitScreen(uint8 *XBuf); -void ConfigVideo(); -void recalculateBestFitRect(int width, int height); -int SetVideoMode(int fs); +// Get current blit rectangle +RECT GetActiveRect(void); + +// Get driver palette +PALETTEENTRY* GetPalette(void); + +// Returns true when in fullscreen mode, false when in windowed +bool GetIsFullscreen(void); + +// Set fullscreen mode flag +// FCEUD_VideoChanged() must be called in order to make value take effect +void SetIsFullscreen(bool f); + +VSYNCMODE GetWindowedSyncModeIdx(void); +void SetWindowedSyncModeIdx(VSYNCMODE idx); + + +// Bring up the Video configuration dialog +void ShowConfigVideoDialog(); + +// (Re)apply render lines and sprite limitation to FCE void DoVideoConfigFix(); + + +// Implements FCEUD requirements +bool FCEUD_ShouldDrawInputAids(void); void FCEUD_BlitScreen(uint8 *XBuf); -void ResetVideo(); -void SetFSVideoMode(); -void PushCurrentVideoSettings(); -void ResetCustomMode(); +void FCEUD_VideoChanged(void); // this one should be declared here +void FCEUD_SetPalette(unsigned char index, unsigned char r, unsigned char g, unsigned char b); +void FCEUD_GetPalette(unsigned char i, unsigned char *r, unsigned char *g, unsigned char *b); + + +// see win/config.h +bool& _FIXME_getFullscreenVar(void); +int& _FIXME_getVModeIdxVar(void); +VSYNCMODE& _FIXME_getFullscreenSyncModeIdxVar(void); +VSYNCMODE& _FIXME_getWindowedSyncModeIdxVar(void); +VFILTER& _FIXME_getFilterModeWindowedIdxVar(void); +int& _FIXME_getFilterOptionVar(void); +DIRECTDRAW_MODE& _FIXME_getDDrawModeWindowedVar(void); +DIRECTDRAW_MODE& _FIXME_getDDrawModeFullscreenVar(void); +VideoMode& _FIXME_getCustomVideoModeVar(void); #endif diff --git a/branches/voxel/src/drivers/win/window.cpp b/branches/voxel/src/drivers/win/window.cpp index 9c41d173..536add32 100644 --- a/branches/voxel/src/drivers/win/window.cpp +++ b/branches/voxel/src/drivers/win/window.cpp @@ -83,8 +83,6 @@ extern PLAYBACK playback; #include "Win32InputBox.h" extern int32 fps_scale_unpaused; -//extern void ToggleFullscreen(); - using namespace std; //----Context Menu - Some dynamically added menu items @@ -995,7 +993,7 @@ void HideFWindow(int h) //Toggles the display status of the main menu. void ToggleHideMenu(void) { - if(!fullscreen && !nofocus && (GameInfo || tog)) + if(!GetIsFullscreen() && !nofocus && (GameInfo || tog)) { tog ^= 1; HideMenu(tog); @@ -1034,7 +1032,7 @@ bool ALoad(const char *nameo, char* innerFilename, bool silent) UpdateCheckedMenuItems(); - PushCurrentVideoSettings(); + FCEUD_VideoChanged(); std::string recentFileName = nameo; if(GameInfo->archiveFilename && GameInfo->archiveCount>1) @@ -1053,7 +1051,10 @@ bool ALoad(const char *nameo, char* innerFilename, bool silent) if(eoptions & EO_FSAFTERLOAD) { - SetFSVideoMode(); + changerecursive=1; + SetIsFullscreen(true); + FCEUD_VideoChanged(); + changerecursive=0; } @@ -1119,7 +1120,7 @@ void LoadNewGamey(HWND hParent, const char *initialdir) void GetMouseData(uint32 (&md)[3]) { - extern RECT bestfitRect; + RECT bestfitRect = GetActiveRect(); double screen_width = VNSWID; double screen_height = FSettings.TotalScanlines(); @@ -1271,8 +1272,10 @@ LRESULT FAR PASCAL AppWndProc(HWND hWnd,UINT msg,WPARAM wParam,LPARAM lParam) { if (fullscreenByDoubleclick) { - extern void ToggleFullscreen(); - ToggleFullscreen(); + changerecursive=1; + SetIsFullscreen(!GetIsFullscreen()); + FCEUD_VideoChanged(); + changerecursive=0; return 0; } else { @@ -1379,7 +1382,7 @@ LRESULT FAR PASCAL AppWndProc(HWND hWnd,UINT msg,WPARAM wParam,LPARAM lParam) goto proco; case WM_SIZE: - if (!fullscreen && !changerecursive && !windowedfailed) + if (!GetIsFullscreen() && !changerecursive && !windowedfailed) { switch(wParam) { @@ -1439,7 +1442,7 @@ LRESULT FAR PASCAL AppWndProc(HWND hWnd,UINT msg,WPARAM wParam,LPARAM lParam) //break; goto proco; case WM_DISPLAYCHANGE: - if(!fullscreen && !changerecursive) + if(!GetIsFullscreen() && !changerecursive) vchanged=1; goto proco; case WM_DROPFILES: @@ -1970,7 +1973,7 @@ LRESULT FAR PASCAL AppWndProc(HWND hWnd,UINT msg,WPARAM wParam,LPARAM lParam) FCEUI_SetVidSystem(pal_emulation); RefreshThrottleFPS(); UpdateCheckedMenuItems(); - PushCurrentVideoSettings(); + FCEUD_VideoChanged(); break; case MENU_DIRECTORIES: ConfigDirectories(); @@ -1994,7 +1997,7 @@ LRESULT FAR PASCAL AppWndProc(HWND hWnd,UINT msg,WPARAM wParam,LPARAM lParam) ConfigTiming(); break; case MENU_VIDEO: - ConfigVideo(); + ShowConfigVideoDialog(); break; case MENU_HOTKEYS: MapInput(); @@ -2290,16 +2293,16 @@ LRESULT FAR PASCAL AppWndProc(HWND hWnd,UINT msg,WPARAM wParam,LPARAM lParam) if(wParam==SC_KEYMENU) { - if(GameInfo && ((InputType[2]==SIFC_FKB) || (InputType[2]==SIFC_SUBORKB)) && cidisabled) + if(GameInfo && ((InputType[2]==SIFC_FKB) || (InputType[2]==SIFC_SUBORKB) || (InputType[2]==SIFC_PEC586KB)) && cidisabled) break; - if(lParam == VK_RETURN || fullscreen || tog) break; + if(lParam == VK_RETURN || GetIsFullscreen() || tog) break; } goto proco; case WM_SYSKEYDOWN: - if(GameInfo && ((InputType[2]==SIFC_FKB) || (InputType[2]==SIFC_SUBORKB)) && cidisabled) + if(GameInfo && ((InputType[2]==SIFC_FKB) || (InputType[2]==SIFC_SUBORKB) || (InputType[2]==SIFC_PEC586KB)) && cidisabled) break; // Hopefully this won't break DInput... - if(fullscreen || tog) + if(GetIsFullscreen() || tog) { if(wParam==VK_MENU) break; @@ -2328,26 +2331,16 @@ adelikat: Outsourced this to a remappable hotkey if(GameInfo) { //Only disable command keys if a game is loaded(and the other conditions are right, of course). - if(InputType[2]==SIFC_FKB) + if((InputType[2]==SIFC_FKB) || (InputType[2]==SIFC_SUBORKB) || (InputType[2]==SIFC_PEC586KB)) { if(wParam==VK_SCROLL) { cidisabled^=1; - FCEUI_DispMessage("Family Keyboard %sabled.",0,cidisabled?"en":"dis"); + FCEUI_DispMessage("%s Keyboard %sabled.",0,InputType[2]==SIFC_FKB?"Family":(InputType[2]==SIFC_SUBORKB?"Subor":"PEC586"),cidisabled?"en":"dis"); } if(cidisabled) break; // Hopefully this won't break DInput... } - if(InputType[2]==SIFC_SUBORKB) - { - if(wParam==VK_SCROLL) - { - cidisabled^=1; - FCEUI_DispMessage("Subor Keyboard %sabled.",0,cidisabled?"en":"dis"); - } - if(cidisabled) - break; - } } goto proco; @@ -2472,9 +2465,10 @@ void FixWXY(int pref, bool shift_held) void UpdateFCEUWindow(void) { - if(vchanged && !fullscreen && !changerecursive && !nofocus) + if(vchanged && !GetIsFullscreen() && !changerecursive && !nofocus) { - SetVideoMode(0); + SetIsFullscreen(false); + FCEUD_VideoChanged(); vchanged = 0; } @@ -2615,11 +2609,13 @@ void SetMainWindowStuff() ShowWindow(hAppWnd, SW_SHOWNORMAL); } - if (eoptions & EO_BESTFIT && !windowedfailed) + // removed check for EO_BESTFIT flag + // OnWindowSizeChange() now is a general purpose window resize handler on video driver side + if (!windowedfailed) { RECT client_recr; GetClientRect(hAppWnd, &client_recr); - recalculateBestFitRect(client_recr.right - client_recr.left, client_recr.bottom - client_recr.top); + OnWindowSizeChange(client_recr.right - client_recr.left, client_recr.bottom - client_recr.top); } } @@ -2987,6 +2983,10 @@ void UpdateMenuHotkeys() ChangeMenuItemText(MENU_CDLOGGER, combined); } +bool GetIsFullscreenOnDoubleclick() { + return fullscreenByDoubleclick; +} + //This function is for the context menu item Save Movie As... //It gets a filename from the user then calls CreateMovie() void SaveMovieAs() diff --git a/branches/voxel/src/drivers/win/window.h b/branches/voxel/src/drivers/win/window.h index b600c317..ddc49f3c 100644 --- a/branches/voxel/src/drivers/win/window.h +++ b/branches/voxel/src/drivers/win/window.h @@ -40,6 +40,10 @@ void GetMouseData(uint32 (&md)[3]); //void ChangeMenuItemText(int menuitem, string text); void UpdateMenuHotkeys(); +// Returns true if fullscreen via double click is enabled +// TODO: replace fullscreenByDoubleclick references with a call to this +bool GetIsFullscreenOnDoubleclick(void); + template inline std::string GetDlgItemText(HWND hDlg, int nIDDlgItem) { char buf[BUFSIZE]; diff --git a/branches/voxel/src/git.h b/branches/voxel/src/git.h index b785be9c..d541cf1a 100644 --- a/branches/voxel/src/git.h +++ b/branches/voxel/src/git.h @@ -69,14 +69,15 @@ enum ESIFC SIFC_4PLAYER = 3, SIFC_FKB = 4, SIFC_SUBORKB = 5, - SIFC_HYPERSHOT = 6, - SIFC_MAHJONG = 7, - SIFC_QUIZKING = 8, - SIFC_FTRAINERA = 9, - SIFC_FTRAINERB = 10, - SIFC_OEKAKIDS = 11, - SIFC_BWORLD = 12, - SIFC_TOPRIDER = 13, + SIFC_PEC586KB = 6, + SIFC_HYPERSHOT = 7, + SIFC_MAHJONG = 8, + SIFC_QUIZKING = 9, + SIFC_FTRAINERA = 10, + SIFC_FTRAINERB = 11, + SIFC_OEKAKIDS = 12, + SIFC_BWORLD = 13, + SIFC_TOPRIDER = 14, SIFC_COUNT = SIFC_TOPRIDER }; @@ -92,6 +93,7 @@ inline const char* ESIFC_Name(ESIFC esifc) "4-Player Adapter", "Family Keyboard", "Subor Keyboard", + "PEC586 Keyboard", "HyperShot Pads", "Mahjong", "Quiz King Buzzers", diff --git a/branches/voxel/src/ines.cpp b/branches/voxel/src/ines.cpp index 61a51913..8b7629c4 100644 --- a/branches/voxel/src/ines.cpp +++ b/branches/voxel/src/ines.cpp @@ -473,7 +473,7 @@ static BMAPPINGLocal bmap[] = { {"Konami VRC6 Rev. B", 26, Mapper26_Init}, {"CC-21 MI HUN CHE", 27, UNLCC21_Init}, // Former dupe for VRC2/VRC4 mapper, redefined with crc to mihunche boards {"", 28, Mapper28_Init}, -// {"", 29, Mapper29_Init}, + {"", 29, Mapper29_Init}, // {"", 30, Mapper30_Init}, // {"", 31, Mapper31_Init}, {"IREM G-101", 32, Mapper32_Init}, @@ -972,6 +972,7 @@ static int iNES_Init(int num) { switch (num) { // FIXME, mapper or game data base with the board parameters and ROM/RAM sizes case 13: CHRRAMSize = 16 * 1024; break; case 6: + case 29: case 96: CHRRAMSize = 32 * 1024; break; case 176: CHRRAMSize = 128 * 1024; break; default: CHRRAMSize = 8 * 1024; break; diff --git a/branches/voxel/src/ines.h b/branches/voxel/src/ines.h index 2913b00b..ec27df87 100644 --- a/branches/voxel/src/ines.h +++ b/branches/voxel/src/ines.h @@ -108,6 +108,7 @@ void Mapper24_Init(CartInfo *); void Mapper25_Init(CartInfo *); void Mapper26_Init(CartInfo *); void Mapper28_Init(CartInfo *); +void Mapper29_Init(CartInfo *); void Mapper32_Init(CartInfo *); void Mapper33_Init(CartInfo *); void Mapper34_Init(CartInfo *); diff --git a/branches/voxel/src/input.cpp b/branches/voxel/src/input.cpp index 864e35e8..58765e75 100644 --- a/branches/voxel/src/input.cpp +++ b/branches/voxel/src/input.cpp @@ -38,6 +38,7 @@ #ifdef WIN32 #include "drivers/win/main.h" +#include "drivers/win/video.h" #include "drivers/win/memwatch.h" #include "drivers/win/cheat.h" #include "drivers/win/debugger.h" @@ -67,6 +68,7 @@ extern INPUTCFC *FCEU_InitArkanoidFC(void); extern INPUTCFC *FCEU_InitSpaceShadow(void); extern INPUTCFC *FCEU_InitFKB(void); extern INPUTCFC *FCEU_InitSuborKB(void); +extern INPUTCFC *FCEU_InitPEC586KB(void); extern INPUTCFC *FCEU_InitHS(void); extern INPUTCFC *FCEU_InitMahjong(void); extern INPUTCFC *FCEU_InitQuizKing(void); @@ -431,6 +433,9 @@ static void SetInputStuffFC() case SIFC_SUBORKB: portFC.driver=FCEU_InitSuborKB(); break; + case SIFC_PEC586KB: + portFC.driver=FCEU_InitPEC586KB(); + break; case SIFC_HYPERSHOT: portFC.driver=FCEU_InitHS(); break; @@ -1175,15 +1180,13 @@ static void FCEUI_DoExit(void) void ToggleFullscreen() { #ifdef WIN32 - extern int SetVideoMode(int fs); //adelikat: Yeah, I know, hacky extern void UpdateCheckedMenuItems(); UpdateCheckedMenuItems(); - changerecursive=1; - int oldmode = fullscreen; - if(!SetVideoMode(oldmode ^ 1)) - SetVideoMode(oldmode); + changerecursive=1; + SetIsFullscreen(!GetIsFullscreen()); + FCEUD_VideoChanged(); changerecursive=0; #endif } diff --git a/branches/voxel/src/input/fkb.cpp b/branches/voxel/src/input/fkb.cpp index 0cb7f118..c6f55bc9 100644 --- a/branches/voxel/src/input/fkb.cpp +++ b/branches/voxel/src/input/fkb.cpp @@ -21,82 +21,69 @@ #include #include "share.h" #include "fkb.h" -#define AK2(x,y) ( (FKB_##x) | (FKB_##y <<8) ) -#define AK(x) FKB_##x +#define AK(x) FKB_ ## x static uint8 bufit[0x49]; static uint8 ksmode; static uint8 ksindex; - -static uint16 matrix[9][2][4]= +static uint16 matrix[9][2][4] = { -{{AK(F8),AK(RETURN),AK(BRACKETLEFT),AK(BRACKETRIGHT)}, - {AK(KANA),AK(RIGHTSHIFT),AK(BACKSLASH),AK(STOP)}}, -{{AK(F7),AK(AT),AK(COLON),AK(SEMICOLON)}, - {AK(UNDERSCORE),AK(SLASH),AK(MINUS),AK(CARET)}}, -{{AK(F6),AK(O),AK(L),AK(K)}, - {AK(PERIOD),AK(COMMA),AK(P),AK(0)}}, -{{AK(F5),AK(I),AK(U),AK(J)}, - {AK(M),AK(N),AK(9),AK(8)}}, -{{AK(F4),AK(Y),AK(G),AK(H)}, - {AK(B),AK(V),AK(7),AK(6)}}, -{{AK(F3),AK(T),AK(R),AK(D)}, - {AK(F),AK(C),AK(5),AK(4)}}, -{{AK(F2),AK(W),AK(S),AK(A)}, - {AK(X),AK(Z),AK(E),AK(3)}}, -{{AK(F1),AK(ESCAPE),AK(Q),AK(CONTROL)}, - {AK(LEFTSHIFT),AK(GRAPH),AK(1),AK(2)}}, -{{AK(CLEAR),AK(UP),AK(RIGHT),AK(LEFT)}, - {AK(DOWN),AK(SPACE),AK(DELETE),AK(INSERT)}}, + { { AK(F8), AK(RETURN), AK(BRACKETLEFT), AK(BRACKETRIGHT) }, + { AK(KANA), AK(RIGHTSHIFT), AK(BACKSLASH), AK(STOP) } }, + { { AK(F7), AK(AT), AK(COLON), AK(SEMICOLON) }, + { AK(UNDERSCORE), AK(SLASH), AK(MINUS), AK(CARET) } }, + { { AK(F6), AK(O), AK(L), AK(K) }, + { AK(PERIOD), AK(COMMA), AK(P), AK(0) } }, + { { AK(F5), AK(I), AK(U), AK(J) }, + { AK(M), AK(N), AK(9), AK(8) } }, + { { AK(F4), AK(Y), AK(G), AK(H) }, + { AK(B), AK(V), AK(7), AK(6) } }, + { { AK(F3), AK(T), AK(R), AK(D) }, + { AK(F), AK(C), AK(5), AK(4) } }, + { { AK(F2), AK(W), AK(S), AK(A) }, + { AK(X), AK(Z), AK(E), AK(3) } }, + { { AK(F1), AK(ESCAPE), AK(Q), AK(CONTROL) }, + { AK(LEFTSHIFT), AK(GRAPH), AK(1), AK(2) } }, + { { AK(CLEAR), AK(UP), AK(RIGHT), AK(LEFT) }, + { AK(DOWN), AK(SPACE), AK(DELETE), AK(INSERT) } }, }; -static void FKB_Write(uint8 v) -{ - v>>=1; - if(v&2) - { - if((ksmode&1) && !(v&1)) - ksindex=(ksindex+1)%9; - } - ksmode=v; +static void FKB_Write(uint8 v) { + v >>= 1; + if (v & 2) { + if ((ksmode & 1) && !(v & 1)) + ksindex = (ksindex + 1) % 9; + } + ksmode = v; } -static uint8 FKB_Read(int w, uint8 ret) -{ - //printf("$%04x, %d, %d\n",w+0x4016,ksindex,ksmode&1); - if(w) - { - int x; +static uint8 FKB_Read(int w, uint8 ret) { + if (w) { + int x; - ret&=~0x1E; - for(x=0;x<4;x++) - if(bufit[ matrix[ksindex][ksmode&1][x]&0xFF ] || bufit[ matrix[ksindex][ksmode&1][x]>>8]) - { - ret|=1<<(x+1); - } - ret^=0x1E; - } - return(ret); + ret &= ~0x1E; + for (x = 0; x < 4; x++) + if (bufit[ matrix[ksindex][ksmode & 1][x] & 0xFF ] || bufit[ matrix[ksindex][ksmode & 1][x] >> 8]) + ret |= 1 << (x + 1); + ret ^= 0x1E; + } + return(ret); } -static void FKB_Strobe(void) -{ - ksmode=0; - ksindex=0; - //printf("strobe\n"); +static void FKB_Strobe(void) { + ksmode = 0; + ksindex = 0; } -static void FKB_Update(void *data, int arg) -{ - memcpy(bufit+1,data,0x48); +static void FKB_Update(void *data, int arg) { + memcpy(bufit + 1, data, sizeof(bufit) - 1); } -static INPUTCFC FKB={FKB_Read,FKB_Write,FKB_Strobe,FKB_Update,0,0}; +static INPUTCFC FKB = { FKB_Read, FKB_Write, FKB_Strobe, FKB_Update, 0, 0 }; -INPUTCFC *FCEU_InitFKB(void) -{ - memset(bufit,0,sizeof(bufit)); - ksmode=ksindex=0; - return(&FKB); +INPUTCFC *FCEU_InitFKB(void) { + memset(bufit, 0, sizeof(bufit)); + ksmode = ksindex = 0; + return(&FKB); } diff --git a/branches/voxel/src/input/fkb.h b/branches/voxel/src/input/fkb.h index b5dcadd4..d635d9d3 100644 --- a/branches/voxel/src/input/fkb.h +++ b/branches/voxel/src/input/fkb.h @@ -1,72 +1,72 @@ -#define FKB_F1 0x01 -#define FKB_F2 0x02 -#define FKB_F3 0x03 -#define FKB_F4 0x04 -#define FKB_F5 0x05 -#define FKB_F6 0x06 -#define FKB_F7 0x07 -#define FKB_F8 0x08 -#define FKB_1 0x09 -#define FKB_2 0x0A -#define FKB_3 0x0B -#define FKB_4 0x0C -#define FKB_5 0x0D -#define FKB_6 0x0E -#define FKB_7 0x0F -#define FKB_8 0x10 -#define FKB_9 0x11 -#define FKB_0 0x12 -#define FKB_MINUS 0x13 -#define FKB_CARET 0x14 -#define FKB_BACKSLASH 0x15 -#define FKB_STOP 0x16 -#define FKB_ESCAPE 0x17 -#define FKB_Q 0x18 -#define FKB_W 0x19 -#define FKB_E 0x1A -#define FKB_R 0x1B -#define FKB_T 0x1C -#define FKB_Y 0x1D -#define FKB_U 0x1E -#define FKB_I 0x1F -#define FKB_O 0x20 -#define FKB_P 0x21 -#define FKB_AT 0x22 -#define FKB_BRACKETLEFT 0x23 -#define FKB_RETURN 0x24 -#define FKB_CONTROL 0x25 -#define FKB_A 0x26 -#define FKB_S 0x27 -#define FKB_D 0x28 -#define FKB_F 0x29 -#define FKB_G 0x2A -#define FKB_H 0x2B -#define FKB_J 0x2C -#define FKB_K 0x2D -#define FKB_L 0x2E -#define FKB_SEMICOLON 0x2F -#define FKB_COLON 0x30 -#define FKB_BRACKETRIGHT 0x31 -#define FKB_KANA 0x32 -#define FKB_LEFTSHIFT 0x33 -#define FKB_Z 0x34 -#define FKB_X 0x35 -#define FKB_C 0x36 -#define FKB_V 0x37 -#define FKB_B 0x38 -#define FKB_N 0x39 -#define FKB_M 0x3A -#define FKB_COMMA 0x3B -#define FKB_PERIOD 0x3C -#define FKB_SLASH 0x3D -#define FKB_UNDERSCORE 0x3E -#define FKB_RIGHTSHIFT 0x3F -#define FKB_GRAPH 0x40 -#define FKB_SPACE 0x41 -#define FKB_CLEAR 0x42 -#define FKB_INSERT 0x43 -#define FKB_DELETE 0x44 -#define FKB_UP 0x45 -#define FKB_LEFT 0x46 -#define FKB_RIGHT 0x47 -#define FKB_DOWN 0x48 +#define FKB_F1 0x01 +#define FKB_F2 0x02 +#define FKB_F3 0x03 +#define FKB_F4 0x04 +#define FKB_F5 0x05 +#define FKB_F6 0x06 +#define FKB_F7 0x07 +#define FKB_F8 0x08 +#define FKB_1 0x09 +#define FKB_2 0x0A +#define FKB_3 0x0B +#define FKB_4 0x0C +#define FKB_5 0x0D +#define FKB_6 0x0E +#define FKB_7 0x0F +#define FKB_8 0x10 +#define FKB_9 0x11 +#define FKB_0 0x12 +#define FKB_MINUS 0x13 +#define FKB_CARET 0x14 +#define FKB_BACKSLASH 0x15 +#define FKB_STOP 0x16 +#define FKB_ESCAPE 0x17 +#define FKB_Q 0x18 +#define FKB_W 0x19 +#define FKB_E 0x1A +#define FKB_R 0x1B +#define FKB_T 0x1C +#define FKB_Y 0x1D +#define FKB_U 0x1E +#define FKB_I 0x1F +#define FKB_O 0x20 +#define FKB_P 0x21 +#define FKB_AT 0x22 +#define FKB_BRACKETLEFT 0x23 +#define FKB_RETURN 0x24 +#define FKB_CONTROL 0x25 +#define FKB_A 0x26 +#define FKB_S 0x27 +#define FKB_D 0x28 +#define FKB_F 0x29 +#define FKB_G 0x2A +#define FKB_H 0x2B +#define FKB_J 0x2C +#define FKB_K 0x2D +#define FKB_L 0x2E +#define FKB_SEMICOLON 0x2F +#define FKB_COLON 0x30 +#define FKB_BRACKETRIGHT 0x31 +#define FKB_KANA 0x32 +#define FKB_LEFTSHIFT 0x33 +#define FKB_Z 0x34 +#define FKB_X 0x35 +#define FKB_C 0x36 +#define FKB_V 0x37 +#define FKB_B 0x38 +#define FKB_N 0x39 +#define FKB_M 0x3A +#define FKB_COMMA 0x3B +#define FKB_PERIOD 0x3C +#define FKB_SLASH 0x3D +#define FKB_UNDERSCORE 0x3E +#define FKB_RIGHTSHIFT 0x3F +#define FKB_GRAPH 0x40 +#define FKB_SPACE 0x41 +#define FKB_CLEAR 0x42 +#define FKB_INSERT 0x43 +#define FKB_DELETE 0x44 +#define FKB_UP 0x45 +#define FKB_LEFT 0x46 +#define FKB_RIGHT 0x47 +#define FKB_DOWN 0x48 diff --git a/branches/voxel/src/input/pec586kb.cpp b/branches/voxel/src/input/pec586kb.cpp new file mode 100644 index 00000000..5288760e --- /dev/null +++ b/branches/voxel/src/input/pec586kb.cpp @@ -0,0 +1,96 @@ +/* FCE Ultra - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2002 Xodnizel + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include "share.h" +#include "suborkb.h" + +#define AK(x) FKB_ ## x + +static uint8 bufit[0x66]; +static uint8 kspos, kstrobe; +static uint8 ksindex; + +//TODO: check all keys, some of the are wrong + +static uint16 matrix[13][8] = +{ + { AK(ESCAPE),AK(SPACE),AK(LMENU),AK(LCONTROL),AK(LSHIFT),AK(GRAVE),AK(TAB),AK(CAPITAL) }, + { AK(F6),AK(F7),AK(F5),AK(F4),AK(F8),AK(F2),AK(F1),AK(F3) }, + { AK(EQUALS), AK(NUMPAD0),AK(PERIOD),AK(A),AK(RETURN),AK(1),AK(Q),AK(Z) }, + { 0, AK(NUMPAD3),AK(NUMPAD6),AK(S),AK(NUMPAD9),AK(2),AK(W),AK(X) }, + { AK(SLASH), AK(NUMPAD2),AK(NUMPAD5),AK(D),AK(NUMPAD8),AK(3),AK(E),AK(C) }, + { AK(BREAK), AK(NUMPAD1),AK(NUMPAD4),AK(F),AK(NUMPAD7),AK(4),AK(R),AK(V) }, + { AK(BACK),AK(BACKSLASH),AK(GRETURN),AK(G),AK(RBRACKET),AK(5),AK(T),AK(B) }, + { AK(9),AK(PERIOD),AK(L),AK(K),AK(O),AK(8),AK(I),AK(COMMA) }, + { AK(0),AK(SLASH),AK(SEMICOLON),AK(J),AK(P),AK(7),AK(U),AK(M) }, + { AK(MINUS),AK(MINUS),AK(APOSTROPHE),AK(H),AK(LBRACKET),AK(6),AK(Y),AK(N) }, + { AK(F11),AK(F12),AK(F10),0,AK(MINUS),AK(F9),0,0 }, + { AK(UP),AK(RIGHT),AK(DOWN),AK(DIVIDE),AK(LEFT),AK(MULTIPLY),AK(SUBTRACT),AK(ADD) }, + { AK(INSERT),AK(NUMPAD1),AK(HOME),AK(PRIOR),AK(DELETE),AK(END),AK(NEXT),AK(NUMLOCK) }, +}; + +static void PEC586KB_Write(uint8 v) { + if (!(kstrobe & 2) && (v & 2)) { + kspos = 0; + } + if ((kstrobe & 1) && !(v & 1)) { + ksindex = 0; + } + if ((kstrobe & 4) && !(v & 4)) { + kspos++; + kspos %= 13; + } + kstrobe = v; +} + +static uint8 PEC586KB_Read(int w, uint8 ret) { +#ifdef FCEUDEF_DEBUGGER + if (!fceuindbg) { +#endif + if (w) { + ret &= ~2; + if(bufit[matrix[kspos][7-ksindex]]) + ret |= 2; + ksindex++; + ksindex&=7; + } +#ifdef FCEUDEF_DEBUGGER + } +#endif + return(ret); +} + +static void PEC586KB_Strobe(void) { +// kstrobe = 0; +// ksindex = 0; +} + +static void PEC586KB_Update(void *data, int arg) { + memcpy(bufit + 1, data, sizeof(bufit) - 1); +} + +static INPUTCFC PEC586KB = { PEC586KB_Read, PEC586KB_Write, PEC586KB_Strobe, PEC586KB_Update, 0, 0 }; + +INPUTCFC *FCEU_InitPEC586KB(void) { + memset(bufit, 0, sizeof(bufit)); + kspos = ksindex = kstrobe = 0; + return(&PEC586KB); +} diff --git a/branches/voxel/src/input/suborkb.cpp b/branches/voxel/src/input/suborkb.cpp index 41595c23..5e54a374 100644 --- a/branches/voxel/src/input/suborkb.cpp +++ b/branches/voxel/src/input/suborkb.cpp @@ -1,94 +1,84 @@ +/* FCE Ultra - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2002 Xodnizel + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + #include #include "share.h" #include "suborkb.h" -#define AK2(x,y) ( (FKB_##x) | (FKB_##y <<8) ) -#define AK(x) FKB_##x +#define AK(x) FKB_ ## x -static uint8 bufit[0x61]; +static uint8 bufit[0x66]; static uint8 ksmode; static uint8 ksindex; - -static uint16 matrix[13][2][4]= +static uint16 matrix[13][2][4] = { -{{AK(4),AK(G),AK(F),AK(C)}, - {AK(F2),AK(E),AK(5),AK(V)}}, -{{AK(2),AK(D),AK(S),AK(END)}, - {AK(F1),AK(W),AK(3),AK(X)}}, -{{AK(INSERT),AK(BACK),AK(NEXT),AK(RIGHT)}, - {AK(F8),AK(PRIOR),AK(DELETE),AK(HOME)}}, -{{AK(9),AK(I),AK(L),AK(COMMA)}, - {AK(F5),AK(O),AK(0),AK(PERIOD)}}, -{{AK(RBRACKET),AK(RETURN),AK(UP),AK(LEFT)}, - {AK(F7),AK(LBRACKET),AK(BACKSLASH),AK(DOWN)}}, -{{AK(Q),AK(CAPITAL),AK(Z),AK(TAB)}, - {AK(ESCAPE),AK(A),AK(1),AK(LCONTROL)}}, -{{AK(7),AK(Y),AK(K),AK(M)}, - {AK(F4),AK(U),AK(8),AK(J)}}, -{{AK(MINUS),AK(SEMICOLON),AK(APOSTROPHE),AK(SLASH)}, - {AK(F6),AK(P),AK(EQUALS),AK(LSHIFT)}}, -{{AK(T),AK(H),AK(N),AK(SPACE)}, - {AK(F3),AK(R),AK(6),AK(B)}}, -{{0,0,0,0}, - {0,0,0,0}}, -{{AK(LMENU),AK(NUMPAD4),AK(NUMPAD7),AK(F11)}, - {AK(F12),AK(NUMPAD1),AK(NUMPAD2),AK(NUMPAD8)}}, -{{AK(SUBTRACT),AK(ADD),AK(MULTIPLY),AK(NUMPAD9)}, - {AK(F10),AK(NUMPAD5),AK(DIVIDE),AK(NUMLOCK)}}, -{{AK(GRAVE),AK(NUMPAD6),AK(PAUSE),AK(SPACE)}, - {AK(F9),AK(NUMPAD3),AK(DECIMAL),AK(NUMPAD0)}}, + { { AK(4), AK(G), AK(F), AK(C) }, { AK(F2), AK(E), AK(5), AK(V) } }, + { { AK(2), AK(D), AK(S), AK(END) }, { AK(F1), AK(W), AK(3), AK(X) } }, + { { AK(INSERT), AK(BACK), AK(NEXT), AK(RIGHT) }, { AK(F8), AK(PRIOR), AK(DELETE), AK(HOME) } }, + { { AK(9), AK(I), AK(L), AK(COMMA) }, { AK(F5), AK(O), AK(0), AK(PERIOD) } }, + { { AK(RBRACKET), AK(RETURN), AK(UP), AK(LEFT) }, { AK(F7), AK(LBRACKET), AK(BACKSLASH), AK(DOWN) } }, + { { AK(Q), AK(CAPITAL), AK(Z), AK(TAB) }, { AK(ESCAPE), AK(A), AK(1), AK(LCONTROL) } }, + { { AK(7), AK(Y), AK(K), AK(M) }, { AK(F4), AK(U), AK(8), AK(J) } }, + { { AK(MINUS), AK(SEMICOLON), AK(APOSTROPHE), AK(SLASH) }, { AK(F6), AK(P), AK(EQUALS), AK(LSHIFT) } }, + { { AK(T), AK(H), AK(N), AK(SPACE) }, { AK(F3), AK(R), AK(6), AK(B) } }, + { { AK(NUMPAD6), AK(GRETURN), AK(NUMPAD4), AK(NUMPAD8) }, { AK(NUMPAD2), 0, 0, 0 } }, // baibaidino actually uses diferent layot + { { AK(LMENU), AK(NUMPAD4), AK(NUMPAD7), AK(F11) }, { AK(F12), AK(NUMPAD1), AK(NUMPAD2), AK(NUMPAD8) } }, + { { AK(SUBTRACT), AK(ADD), AK(MULTIPLY), AK(NUMPAD9) }, { AK(F10), AK(NUMPAD5), AK(DIVIDE), AK(NUMLOCK) } }, + { { AK(GRAVE), AK(NUMPAD6), AK(PAUSE), AK(SPACE) }, { AK(F9), AK(NUMPAD3), AK(DECIMAL), AK(NUMPAD0) } }, }; -static void SuborKB_Write(uint8 v) -{ - v>>=1; - if(v&2) - { - if((ksmode&1) && !(v&1)) - ksindex=(ksindex+1)%13; - } - ksmode=v; +static void SuborKB_Write(uint8 v) { + v >>= 1; + if (v & 2) { + if ((ksmode & 1) && !(v & 1)) + ksindex = (ksindex + 1) % 13; + } + ksmode = v; } -static uint8 SuborKB_Read(int w, uint8 ret) -{ - if(w) - { - int x; +static uint8 SuborKB_Read(int w, uint8 ret) { + if (w) { + int x; - ret&=~0x1E; -// if(ksindex==9) -// { -// if(ksmode&1) -// ret|=2; -// } -// else -// { - for(x=0;x<4;x++) - if(bufit[matrix[ksindex][ksmode&1][x]&0xFF]||bufit[matrix[ksindex][ksmode&1][x]>>8]) - ret|=1<<(x+1); -// } - ret^=0x1E; - } - return(ret); + ret &= ~0x1E; + for (x = 0; x < 4; x++) + if (bufit[matrix[ksindex][ksmode & 1][x]]) + ret |= 1 << (x + 1); + ret ^= 0x1E; + } + return(ret); } -static void SuborKB_Strobe(void) -{ - ksmode=0; - ksindex=0; +static void SuborKB_Strobe(void) { + ksmode = 0; + ksindex = 0; } -static void SuborKB_Update(void *data, int arg) -{ - memcpy(bufit+1,data,0x60); +static void SuborKB_Update(void *data, int arg) { + memcpy(bufit + 1, data, sizeof(bufit) - 1); } -static INPUTCFC SuborKB={SuborKB_Read,SuborKB_Write,SuborKB_Strobe,SuborKB_Update,0,0}; +static INPUTCFC SuborKB = { SuborKB_Read, SuborKB_Write, SuborKB_Strobe, SuborKB_Update, 0, 0 }; -INPUTCFC *FCEU_InitSuborKB(void) -{ - memset(bufit,0,sizeof(bufit)); - ksmode=ksindex=0; - return(&SuborKB); +INPUTCFC *FCEU_InitSuborKB(void) { + memset(bufit, 0, sizeof(bufit)); + ksmode = ksindex = 0; + return(&SuborKB); } diff --git a/branches/voxel/src/input/suborkb.h b/branches/voxel/src/input/suborkb.h index 735f8204..db01bd4e 100644 --- a/branches/voxel/src/input/suborkb.h +++ b/branches/voxel/src/input/suborkb.h @@ -1,96 +1,102 @@ -#define FKB_ESCAPE 0x01 -#define FKB_F1 0x02 -#define FKB_F2 0x03 -#define FKB_F3 0x04 -#define FKB_F4 0x05 -#define FKB_F5 0x06 -#define FKB_F6 0x07 -#define FKB_F7 0x08 -#define FKB_F8 0x09 -#define FKB_F9 0x0A -#define FKB_F10 0x0B -#define FKB_F11 0x0C -#define FKB_F12 0x0D -#define FKB_PAUSE 0x0E -#define FKB_GRAVE 0x0F -#define FKB_1 0x10 -#define FKB_2 0x11 -#define FKB_3 0x12 -#define FKB_4 0x13 -#define FKB_5 0x14 -#define FKB_6 0x15 -#define FKB_7 0x16 -#define FKB_8 0x17 -#define FKB_9 0x18 -#define FKB_0 0x19 -#define FKB_MINUS 0x1A -#define FKB_EQUALS 0x1B -#define FKB_BACK 0x1C -#define FKB_INSERT 0x1D -#define FKB_HOME 0x1E -#define FKB_PRIOR 0x1F -#define FKB_NUMLOCK 0x20 -#define FKB_DIVIDE 0x21 -#define FKB_MULTIPLY 0x22 -#define FKB_SUBTRACT 0x23 -#define FKB_TAB 0x24 -#define FKB_Q 0x25 -#define FKB_W 0x26 -#define FKB_E 0x27 -#define FKB_R 0x28 -#define FKB_T 0x29 -#define FKB_Y 0x2A -#define FKB_U 0x2B -#define FKB_I 0x2C -#define FKB_O 0x2D -#define FKB_P 0x2E -#define FKB_LBRACKET 0x2F -#define FKB_RBRACKET 0x30 -#define FKB_RETURN 0x31 -#define FKB_DELETE 0x32 -#define FKB_END 0x33 -#define FKB_NEXT 0x34 -#define FKB_NUMPAD7 0x35 -#define FKB_NUMPAD8 0x36 -#define FKB_NUMPAD9 0x37 -#define FKB_ADD 0x38 -#define FKB_CAPITAL 0x39 -#define FKB_A 0x3A -#define FKB_S 0x3B -#define FKB_D 0x3C -#define FKB_F 0x3D -#define FKB_G 0x3E -#define FKB_H 0x3F -#define FKB_J 0x40 -#define FKB_K 0x41 -#define FKB_L 0x42 -#define FKB_SEMICOLON 0x43 -#define FKB_APOSTROPHE 0x44 -#define FKB_NUMPAD4 0x45 -#define FKB_NUMPAD5 0x46 -#define FKB_NUMPAD6 0x47 -#define FKB_LSHIFT 0x48 -#define FKB_Z 0x49 -#define FKB_X 0x4A -#define FKB_C 0x4B -#define FKB_V 0x4C -#define FKB_B 0x4D -#define FKB_N 0x4E -#define FKB_M 0x4F -#define FKB_COMMA 0x50 -#define FKB_PERIOD 0x51 -#define FKB_SLASH 0x52 -#define FKB_BACKSLASH 0x53 -#define FKB_UP 0x54 -#define FKB_NUMPAD1 0x55 -#define FKB_NUMPAD2 0x56 -#define FKB_NUMPAD3 0x57 -#define FKB_LCONTROL 0x58 -#define FKB_LMENU 0x59 -#define FKB_SPACE 0x5A -#define FKB_LEFT 0x5B -#define FKB_DOWN 0x5C -#define FKB_RIGHT 0x5D -#define FKB_NUMPAD0 0x5E -#define FKB_DECIMAL 0x5F +#define FKB_ESCAPE 0x01 +#define FKB_F1 0x02 +#define FKB_F2 0x03 +#define FKB_F3 0x04 +#define FKB_F4 0x05 +#define FKB_F5 0x06 +#define FKB_F6 0x07 +#define FKB_F7 0x08 +#define FKB_F8 0x09 +#define FKB_F9 0x0A +#define FKB_F10 0x0B +#define FKB_F11 0x0C +#define FKB_F12 0x0D +#define FKB_PAUSE 0x0E +#define FKB_GRAVE 0x0F +#define FKB_1 0x10 +#define FKB_2 0x11 +#define FKB_3 0x12 +#define FKB_4 0x13 +#define FKB_5 0x14 +#define FKB_6 0x15 +#define FKB_7 0x16 +#define FKB_8 0x17 +#define FKB_9 0x18 +#define FKB_0 0x19 +#define FKB_MINUS 0x1A +#define FKB_EQUALS 0x1B +#define FKB_BACK 0x1C +#define FKB_INSERT 0x1D +#define FKB_HOME 0x1E +#define FKB_PRIOR 0x1F +#define FKB_NUMLOCK 0x20 +#define FKB_DIVIDE 0x21 +#define FKB_MULTIPLY 0x22 +#define FKB_SUBTRACT 0x23 +#define FKB_TAB 0x24 +#define FKB_Q 0x25 +#define FKB_W 0x26 +#define FKB_E 0x27 +#define FKB_R 0x28 +#define FKB_T 0x29 +#define FKB_Y 0x2A +#define FKB_U 0x2B +#define FKB_I 0x2C +#define FKB_O 0x2D +#define FKB_P 0x2E +#define FKB_LBRACKET 0x2F +#define FKB_RBRACKET 0x30 +#define FKB_RETURN 0x31 +#define FKB_DELETE 0x32 +#define FKB_END 0x33 +#define FKB_NEXT 0x34 +#define FKB_NUMPAD7 0x35 +#define FKB_NUMPAD8 0x36 +#define FKB_NUMPAD9 0x37 +#define FKB_ADD 0x38 +#define FKB_CAPITAL 0x39 +#define FKB_A 0x3A +#define FKB_S 0x3B +#define FKB_D 0x3C +#define FKB_F 0x3D +#define FKB_G 0x3E +#define FKB_H 0x3F +#define FKB_J 0x40 +#define FKB_K 0x41 +#define FKB_L 0x42 +#define FKB_SEMICOLON 0x43 +#define FKB_APOSTROPHE 0x44 +#define FKB_NUMPAD4 0x45 +#define FKB_NUMPAD5 0x46 +#define FKB_NUMPAD6 0x47 +#define FKB_LSHIFT 0x48 +#define FKB_Z 0x49 +#define FKB_X 0x4A +#define FKB_C 0x4B +#define FKB_V 0x4C +#define FKB_B 0x4D +#define FKB_N 0x4E +#define FKB_M 0x4F +#define FKB_COMMA 0x50 +#define FKB_PERIOD 0x51 +#define FKB_SLASH 0x52 +#define FKB_BACKSLASH 0x53 +#define FKB_UP 0x54 +#define FKB_NUMPAD1 0x55 +#define FKB_NUMPAD2 0x56 +#define FKB_NUMPAD3 0x57 +#define FKB_LCONTROL 0x58 +#define FKB_LMENU 0x59 +#define FKB_SPACE 0x5A +#define FKB_LEFT 0x5B +#define FKB_DOWN 0x5C +#define FKB_RIGHT 0x5D +#define FKB_NUMPAD0 0x5E +#define FKB_DECIMAL 0x5F +#define FKB_RSHIFT 0x60 +#define FKB_RMENU 0x61 +#define FKB_RCONTROL 0x62 +#define FKB_BREAK 0x63 +#define FKB_RESET 0x64 +#define FKB_GRETURN 0x65 diff --git a/branches/voxel/src/state.cpp b/branches/voxel/src/state.cpp index 30593544..f4da8e0c 100644 --- a/branches/voxel/src/state.cpp +++ b/branches/voxel/src/state.cpp @@ -47,6 +47,7 @@ #include "drivers/win/main.h" #include "drivers/win/ram_search.h" #include "drivers/win/ramwatch.h" +#include "drivers/win/video.h" #endif #include @@ -243,7 +244,11 @@ static bool ReadStateChunk(EMUFILE* is, SFORMAT *sf, int size) static int read_sfcpuc=0, read_snd=0; +#ifndef WIN32 +// included corresponding header on Windows, no longer needed +// TODO do the same for SDL and remove declaration completely void FCEUD_BlitScreen(uint8 *XBuf); //mbg merge 7/17/06 YUCKY had to add +#endif void UpdateFCEUWindow(void); //mbg merge 7/17/06 YUCKY had to add static bool ReadStateChunks(EMUFILE* is, int32 totalsize) { diff --git a/branches/voxel/src/unif.cpp b/branches/voxel/src/unif.cpp index 0238d441..28ea0471 100644 --- a/branches/voxel/src/unif.cpp +++ b/branches/voxel/src/unif.cpp @@ -390,6 +390,7 @@ static BMAPPING bmap[] = { { "NovelDiamond9999999in1", Novel_Init, 0 }, { "OneBus", UNLOneBus_Init, 0 }, { "PEC-586", UNLPEC586Init, 0 }, + { "RET-CUFROM", Mapper29_Init, BMCFLAG_32KCHRR }, { "RROM", NROM_Init, 0 }, { "RROM-128", NROM_Init, 0 }, { "SA-002", TCU02_Init, 0 }, diff --git a/branches/voxel/src/utils/bitflags.h b/branches/voxel/src/utils/bitflags.h new file mode 100644 index 00000000..c198766a --- /dev/null +++ b/branches/voxel/src/utils/bitflags.h @@ -0,0 +1,10 @@ +#ifndef BITFLAGS_H +#define BITFLAGS_H + +// Flag test / set / clear macros for convenience and clarity +#define FL_TEST(var, mask) (var & mask) +#define FL_SET(var, mask) (var |= mask) +#define FL_CLEAR(var, mask) (var &= ~mask) +#define FL_FROMBOOL(var, mask, b) (var = (b)? var|mask:var&(~mask)) + +#endif // BITFLAGS_H diff --git a/branches/voxel/vc/vc10_fceux.vcxproj b/branches/voxel/vc/vc10_fceux.vcxproj index 3808a52f..35180975 100644 --- a/branches/voxel/vc/vc10_fceux.vcxproj +++ b/branches/voxel/vc/vc10_fceux.vcxproj @@ -596,6 +596,7 @@ + @@ -963,6 +964,7 @@ + diff --git a/branches/voxel/vc/vc10_fceux.vcxproj.filters b/branches/voxel/vc/vc10_fceux.vcxproj.filters index df76bafe..920dff8a 100644 --- a/branches/voxel/vc/vc10_fceux.vcxproj.filters +++ b/branches/voxel/vc/vc10_fceux.vcxproj.filters @@ -958,6 +958,9 @@ boards + + input + @@ -1464,6 +1467,9 @@ utils + + input + diff --git a/branches/voxel/vc/vc8_fceux.vcproj b/branches/voxel/vc/vc8_fceux.vcproj index 1e22cf4a..84976518 100644 --- a/branches/voxel/vc/vc8_fceux.vcproj +++ b/branches/voxel/vc/vc8_fceux.vcproj @@ -1,4861 +1,4834 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + ProjectType="Visual C++" + Version="8.00" + Name="fceux" + ProjectGUID="{6893EF44-FEA3-46DF-B236-C4C200F54294}" + RootNamespace="fceux" + Keyword="Win32Proj" + > + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/branches/voxel/vc/vc9_fceux.vcproj b/branches/voxel/vc/vc9_fceux.vcproj index d5bad547..056e8c27 100644 --- a/branches/voxel/vc/vc9_fceux.vcproj +++ b/branches/voxel/vc/vc9_fceux.vcproj @@ -1,4723 +1,4727 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + ProjectType="Visual C++" + Version="9.00" + Name="fceux" + ProjectGUID="{6893EF44-FEA3-46DF-B236-C4C200F54294}" + RootNamespace="fceux" + Keyword="Win32Proj" + TargetFrameworkVersion="131072" + > + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +