/************************************************************************** * DSemu: GameBoy Advance interface and encapsulation (gba.c) * * Released under the terms of the BSD Public Licence * * Imran Nazar (tf@oopsilon.com), 2004 * **************************************************************************/ #include #include #include "arm7.h" #include "mmu.h" #include "gpu.h" #include "defs.h" #include "vtbl.h" #include "win.h" #include "err.h" #include "emu.h" #include "gba.h" #include "res.h" #include "key.h" #include "ioreg.h" LOGVTBL *logvt=NULL; IOREG GBAio[512]; u16 ioregflags[]={ 3,3,3,1,3,3,3,3,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, 2,2,2,2,3,3,2,0,3,2,2,0,0,0,0,0,3,3,3,0,3,0,3,0,3,3,3,0,3,0,3,0, 3,3,3,0,0,0,0,0,3,3,3,3,3,3,3,3,3,3,3,3,0,0,0,0,2,2,2,2,2,3,2,2, 2,2,2,3,2,2,2,2,2,3,2,2,2,2,2,3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 3,3,3,3,3,3,3,3,0,0,0,0,0,0,0,0,3,3,3,3,3,3,0,0,1,3,3,0,0,0,0,0, 3,0,0,0,0,0,0,0,3,3,3,3,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 3,3,3,0,3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, }; u32 *screenbuf=NULL, *dbgbuf=NULL, *palbuf=NULL, *membuf=NULL; HDC hDCMain, hDCPal, hDCDbg, hDCMem; BITMAPV4HEADER BmpInfo; HWND hWnd, hWndPal, hWndDbg, hWndMem; int stepclk, dbgmode, memmode; u32 dumpaddr; u16 KeyMap[256]={0}; void ResizeWin(HWND wnd, int x, int y) { RECT rWnd, rCli, rDiff, rStat; HWND hStatus; int neww, newh; char str[80]; GetWindowRect(wnd, &rWnd); GetClientRect(wnd, &rCli); SetRect(&rDiff, 0, 0, (rWnd.right - rWnd.left) - rCli.right, (rWnd.bottom - rWnd.top) - rCli.bottom); hStatus = GetDlgItem(wnd, ID_STATUS); if(hStatus) { SendMessage(hStatus, WM_SIZE, 0, 0); GetWindowRect(hStatus, &rStat); } else SetRect(&rStat,0,0,0,0); neww = x + rDiff.right; newh = y + rDiff.bottom + (rStat.bottom - rStat.top); SetWindowPos(wnd, HWND_TOP, 0, 0, neww, newh, SWP_NOMOVE|SWP_NOZORDER); } EMUVTBL *getVt() { return &vtbl; } int emuInit(char *file, LOGVTBL *lvtbl, HWND wnd, HWND pwnd, HWND dwnd, HWND mwnd) { char str[40], inifile[MAX_PATH*2]; int a; vtbl.running=0; vtbl.animate=0; logvt=lvtbl; stepclk=0; hWnd=wnd; hWndPal=pwnd; hWndDbg=dwnd; hWndMem=mwnd; dbgbuf = (u32*)malloc(468*144*2); if(!dbgbuf) RETFAIL("FAIL: Main: Buffer init."); memset(dbgbuf, 0, 468*144*2); if(ARM7init(file,dbgbuf)) RETFAIL("FAIL: Main: ARM7 init."); if(GPUinit()) RETFAIL("FAIL: Main: GPU init."); ResizeWin(hWnd, 240, 160); ResizeWin(hWndPal, 144, 160); ResizeWin(hWndDbg, 480, 160); ResizeWin(hWndMem, 360, 160); screenbuf = (u32*)malloc(240*160*2); if(!screenbuf) RETFAIL("FAIL: Main: Buffer init."); memset(screenbuf, 0, 240*160*2); palbuf = (u32*)malloc(128*144*2); if(!screenbuf) RETFAIL("FAIL: Main: Buffer init."); memset(screenbuf, 0, 128*144*2); membuf = (u32*)malloc(360*160*2); if(!membuf) RETFAIL("FAIL: Main: Buffer init."); memset(membuf, 0, 360*160*2); hDCMain = GetDC(hWnd); hDCPal = GetDC(hWndPal); hDCDbg = GetDC(hWndDbg); hDCMem = GetDC(hWndMem); memset(&BmpInfo, 0, sizeof(BmpInfo)); BmpInfo.bV4Size = sizeof(BmpInfo); BmpInfo.bV4Planes = 1; // Must be one, apparently BmpInfo.bV4BitCount = 16; BmpInfo.bV4V4Compression = BI_RGB|BI_BITFIELDS; BmpInfo.bV4RedMask = 0x001F; BmpInfo.bV4GreenMask = 0x03E0; BmpInfo.bV4BlueMask = 0x7C00; GetCurrentDirectory(MAX_PATH, inifile); sprintf(inifile, "%s\\dsemu.ini", inifile); GetPrivateProfileString("Keys","UP","26",str,4,inifile); KeyMap[strtol(str,NULL,16)&255]=GBAKEY_UP; GetPrivateProfileString("Keys","DOWN","28",str,4,inifile); KeyMap[strtol(str,NULL,16)&255]=GBAKEY_DOWN; GetPrivateProfileString("Keys","LEFT","25",str,4,inifile); KeyMap[strtol(str,NULL,16)&255]=GBAKEY_LEFT; GetPrivateProfileString("Keys","RIGHT","27",str,4,inifile); KeyMap[strtol(str,NULL,16)&255]=GBAKEY_RIGHT; GetPrivateProfileString("Keys","A","5A",str,4,inifile); KeyMap[strtol(str,NULL,16)&255]=GBAKEY_A; GetPrivateProfileString("Keys","B","58",str,4,inifile); KeyMap[strtol(str,NULL,16)&255]=GBAKEY_B; GetPrivateProfileString("Keys","L","41",str,4,inifile); KeyMap[strtol(str,NULL,16)&255]=GBAKEY_L; GetPrivateProfileString("Keys","R","53",str,4,inifile); KeyMap[strtol(str,NULL,16)&255]=GBAKEY_R; GetPrivateProfileString("Keys","START","0D",str,4,inifile); KeyMap[strtol(str,NULL,16)&255]=GBAKEY_START; GetPrivateProfileString("Keys","SELECT","08",str,4,inifile); KeyMap[strtol(str,NULL,16)&255]=GBAKEY_SELECT; GetPrivateProfileString("General","FixFPS","1",str,4,inifile); vtbl.fixfps=strtol(str,NULL,10)&1; dbgmode=3; memmode=1; dumpaddr=0x04000000; for(a=0;a<512;a++) GBAio[a].flags=ioregflags[a]; if(emuReset()) RETFAIL("FAIL: Main: Initialisation."); RETPASS("Main: Emulator initialised."); } void emuFini() { logvt->append("Main: Emulator shutting down."); ARM7status(); GPUfini(); ARM7fini(); memset(screenbuf, 0, 240*160*2); memset(dbgbuf, 0, 468*144*2); memset(palbuf, 0, 128*144*2); memset(membuf, 0, 360*160*2); BmpInfo.bV4Width = 240; BmpInfo.bV4Height = -160; SetDIBitsToDevice(hDCMain, 0, 0, 240, 160, 0, 0, 0, 160, screenbuf, (BITMAPINFO*)&BmpInfo, DIB_RGB_COLORS); BmpInfo.bV4Width = 468; BmpInfo.bV4Height = -144; SetDIBitsToDevice(hDCDbg, 6, 8, 468, 144, 0, 0, 0, 144, dbgbuf, (BITMAPINFO*)&BmpInfo, DIB_RGB_COLORS); BmpInfo.bV4Width = 128; BmpInfo.bV4Height = -144; SetDIBitsToDevice(hDCPal, 8, 8, 128, 144, 0, 0, 0, 144, palbuf, (BITMAPINFO*)&BmpInfo, DIB_RGB_COLORS); BmpInfo.bV4Width = 360; BmpInfo.bV4Height = -160; SetDIBitsToDevice(hDCMem, 0, 0, 360, 160, 0, 0, 0, 160, membuf, (BITMAPINFO*)&BmpInfo, DIB_RGB_COLORS); ReleaseDC(hWnd, hDCMain); ReleaseDC(hWndPal, hDCPal); ReleaseDC(hWndDbg, hDCDbg); ReleaseDC(hWndMem, hDCMem); hWnd=NULL; hWndPal=NULL; hWndDbg=NULL; hWndMem=NULL; hDCMain=NULL; hDCPal=NULL; hDCDbg=NULL; hDCMem=NULL; if(membuf) free(membuf); if(dbgbuf) free(dbgbuf); if(palbuf) free(palbuf); if(screenbuf) free(screenbuf); membuf=NULL; dbgbuf=NULL; palbuf=NULL; screenbuf=NULL; } void emuRefresh() { // logvt->append("Main: If we fail, we shouldn't be here."); GPUpal(palbuf); BmpInfo.bV4Width = 240; BmpInfo.bV4Height = -160; SetDIBitsToDevice(hDCMain, 0, 0, 240, 160, 0, 0, 0, 160, screenbuf, (BITMAPINFO*)&BmpInfo, DIB_RGB_COLORS); BmpInfo.bV4Width = 468; BmpInfo.bV4Height = -144; SetDIBitsToDevice(hDCDbg, 6, 8, 468, 144, 0, 0, 0, 144, dbgbuf, (BITMAPINFO*)&BmpInfo, DIB_RGB_COLORS); BmpInfo.bV4Width = 128; BmpInfo.bV4Height = -144; SetDIBitsToDevice(hDCPal, 8, 8, 128, 144, 0, 0, 0, 144, palbuf, (BITMAPINFO*)&BmpInfo, DIB_RGB_COLORS); BmpInfo.bV4Width = 360; BmpInfo.bV4Height = -160; SetDIBitsToDevice(hDCMem, 0, 0, 360, 160, 0, 0, 0, 160, membuf, (BITMAPINFO*)&BmpInfo, DIB_RGB_COLORS); } void emuStep() { static int stepwhere=1; stepclk+=ARM7exec(); ARM7status(0,dbgmode); emuMMUDump(dumpaddr,memmode); SendMessage(hWndDbg, WM_OFFRESET, 0, 0); if(stepclk>=960 && stepwhere==1) { stepclk=0; stepwhere=2; // logvt->append("Line!"); if(vtbl.gpuon) GPUscanline(screenbuf); } if(stepclk>=272 && stepwhere==2) { stepclk=0; stepwhere=1; if(vtbl.gpuon) GPUclearHBL(); } emuRefresh(); } int emuReset() { int a; for(a=0;a<512;a++) GBAio[a].data=0; GBAio[REG_KEYINPUT].data=0x03FF; if(ARM7reset()) RETFAIL("FAIL: ARM7: Reset."); GPUreset(); memset(screenbuf, 0, 240*160*2); memset(dbgbuf, 0, 468*144*2); memset(palbuf, 0, 128*144*2); memset(membuf, 0, 360*160*2); SendMessage(hWndDbg, WM_OFFRESET, 0, 0); ARM7status(0,dbgmode); emuMMUDump(dumpaddr,memmode); BmpInfo.bV4Width = 240; BmpInfo.bV4Height = -160; SetDIBitsToDevice(hDCMain, 0, 0, 240, 160, 0, 0, 0, 160, screenbuf, (BITMAPINFO*)&BmpInfo, DIB_RGB_COLORS); BmpInfo.bV4Width = 468; BmpInfo.bV4Height = -144; SetDIBitsToDevice(hDCDbg, 6, 8, 468, 144, 0, 0, 0, 144, dbgbuf, (BITMAPINFO*)&BmpInfo, DIB_RGB_COLORS); BmpInfo.bV4Width = 128; BmpInfo.bV4Height = -144; SetDIBitsToDevice(hDCPal, 8, 8, 128, 144, 0, 0, 0, 144, palbuf, (BITMAPINFO*)&BmpInfo, DIB_RGB_COLORS); BmpInfo.bV4Width = 360; BmpInfo.bV4Height = -160; SetDIBitsToDevice(hDCMem, 0, 0, 360, 160, 0, 0, 0, 160, membuf, (BITMAPINFO*)&BmpInfo, DIB_RGB_COLORS); return 0; } void emuFrame() { int a; for(a=0;a<228;a++) { if(ARM7execfor(960)) break; if(vtbl.gpuon) GPUscanline(screenbuf); if(ARM7execfor(272)) break; if(vtbl.gpuon) GPUclearHBL(); } BmpInfo.bV4Width = 240; BmpInfo.bV4Height = -160; SetDIBitsToDevice(hDCMain, 0, 0, 240, 160, 0, 0, 0, 160, screenbuf, (BITMAPINFO*)&BmpInfo, DIB_RGB_COLORS); } void emuLine() { ARM7execfor(960); if(vtbl.gpuon) GPUscanline(screenbuf); ARM7execfor(272); if(vtbl.gpuon) GPUclearHBL(); BmpInfo.bV4Width = 240; BmpInfo.bV4Height = -160; SetDIBitsToDevice(hDCMain, 0, 0, 240, 160, 0, 0, 0, 160, screenbuf, (BITMAPINFO*)&BmpInfo, DIB_RGB_COLORS); } void emuLineDbg() { int a; ARM7execfor(960); if(vtbl.gpuon) GPUscanline(screenbuf); ARM7execfor(272); if(vtbl.gpuon) GPUclearHBL(); ARM7status(0,dbgmode); emuMMUDump(dumpaddr,memmode); SendMessage(hWndDbg, WM_OFFRESET, 0, 0); emuRefresh(); } void emuPause() { SendMessage(hWnd, WM_COMMAND, ID_MENU_DBG_PAUSE, 0); SendMessage(hWndDbg, WM_PAINT, 0, 0); } void emuResize(int lParam) { } void emuDebugCPU(int off,int mode) { dbgmode=mode; ARM7status(off,dbgmode); } #define dump16b(p) \ for(a=0;a<16;a++) \ { \ sprintf(str, \ "%08X: %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X\n", \ (p)+a*16, \ MMUrdB(1,(p)+a*16+0x0),MMUrdB(1,(p)+a*16+0x1), \ MMUrdB(1,(p)+a*16+0x2),MMUrdB(1,(p)+a*16+0x3), \ MMUrdB(1,(p)+a*16+0x4),MMUrdB(1,(p)+a*16+0x5), \ MMUrdB(1,(p)+a*16+0x6),MMUrdB(1,(p)+a*16+0x7), \ MMUrdB(1,(p)+a*16+0x8),MMUrdB(1,(p)+a*16+0x9), \ MMUrdB(1,(p)+a*16+0xA),MMUrdB(1,(p)+a*16+0xB), \ MMUrdB(1,(p)+a*16+0xC),MMUrdB(1,(p)+a*16+0xD), \ MMUrdB(1,(p)+a*16+0xE),MMUrdB(1,(p)+a*16+0xF)); \ dbgOut(membuf,360,160,str,0,24+a*8,0x7FFF); \ } #define dump16h(p) \ (p)&=0xFFFFFFF0; \ for(a=0;a<16;a++) \ { \ sprintf(str, \ "%08X: %04X %04X %04X %04X %04X %04X %04X %04X\n", \ (p)+a*16, \ MMUrdH(1,(p)+a*16+0x0),MMUrdH(1,(p)+a*16+0x2), \ MMUrdH(1,(p)+a*16+0x4),MMUrdH(1,(p)+a*16+0x6), \ MMUrdH(1,(p)+a*16+0x8),MMUrdH(1,(p)+a*16+0xA), \ MMUrdH(1,(p)+a*16+0xC),MMUrdH(1,(p)+a*16+0xE)); \ dbgOut(membuf,360,160,str,0,24+a*8,0x7FFF); \ } #define dump16w(p) \ for(a=0;a<16;a++) \ { \ sprintf(str, \ "%08X: %08X %08X %08X %08X\n", \ (p)+a*16, \ MMUrdW(1,(p)+a*16+0x0), \ MMUrdW(1,(p)+a*16+0x4), \ MMUrdW(1,(p)+a*16+0x8), \ MMUrdW(1,(p)+a*16+0xC)); \ dbgOut(membuf,360,160,str,0,24+a*8,0x7FFF); \ } void emuMMUDump(u32 addr, int mode) { int a; char str[512]; dumpaddr=addr; dbgOutClear(membuf,360,160); memmode=mode; switch(mode) { case 1: dump16b(addr); break; case 2: dump16h(addr); break; case 3: dump16w(addr); break; } } void emuGPUCol(int idx) { GPUpalcol(palbuf,idx); BmpInfo.bV4Width = 128; BmpInfo.bV4Height = -144; SetDIBitsToDevice(hDCPal, 8, 8, 128, 144, 0, 0, 0, 144, palbuf, (BITMAPINFO*)&BmpInfo, DIB_RGB_COLORS); } void emuKeySet(u32 vk, int updown) { if(updown==1) GBAio[REG_KEYINPUT].data&=(0xFFFF-KeyMap[vk&255]); else if(updown==0) GBAio[REG_KEYINPUT].data|=(KeyMap[vk&255]); } /*** EOF:gba.c ***********************************************************/