/* 正式にv0.6にするかは定かでない版 開発者予備軍のための学習資料として Pseudoの部分を公開 */ // Title: Dr.Hell's GDI GPU // Version: 0.6 // Copyright: (C)Dr.Hell, 2002-2003 // Web: http://members.tripod.co.jp/DrHell/ //----------------------------------------------------------------------------- // ヘッダ //----------------------------------------------------------------------------- #include //----------------------------------------------------------------------------- // コンパイル条件 //----------------------------------------------------------------------------- //#define NOTPSEUDO //----------------------------------------------------------------------------- // バージョン //----------------------------------------------------------------------------- #define GPU_VERSION 1 #define GPU_REVISION 0 #define GPU_BUILD 6 //----------------------------------------------------------------------------- // フリーズ情報構造体 //----------------------------------------------------------------------------- typedef struct { DWORD Version; DWORD GP1; DWORD Control[256]; BYTE FrameBuffer[0x100000]; } GPUFREEZE; //----------------------------------------------------------------------------- // グローバル変数 //----------------------------------------------------------------------------- #ifdef NOTPSEUDO char LIBNAME[] = "Dr.Hell's GDI Driver"; #else char LIBNAME[] = "Dr.Hell's GDI Pseudo Driver"; #endif HINSTANCE Application; // インスタンス HWND MainWindow; // ウィンドウハンドル HDC MainDC; // デバイスコンテキスト int MainFrame[2]; // フレームサイズ // レジスタ int GP0; // データレジスタ int GP1 = 0x14802000; // コントロールレジスタ // パケット int Packet[16], PacketIndex; // パケットバッファ int ShortOfPacket = 0; // 不足パケット数 // 描画基礎 WORD FrameBuffer[524288]; // フレームバッファ 1024*512 WORD *CLUT = (void *)FrameBuffer; // CLUT WORD *TexturePage = (void *)FrameBuffer; // テクスチャページ WORD *DrawingPoint = (void *)FrameBuffer; // 描画点 WORD DrawingColour[2]; // 描画色, マスクビット int LightColour[3]; // 光源色 int SemiTransparencyRate; // 半透明率 int TextureWindow[4] = {0, 0, 255, 255}; // テクスチャウィンドウ int Pixel[2]; // テクスチャ座標(を2^N倍したもの) // 描画環境 int DrawingArea[4] = { // 描画領域 0, 0, 256, 240 }; int DrawingOffset[2] = {0, 0}; // 描画オフセット int DrawingEnvironment[16]; // その他描画環境(今後のために設定だけは保存) int DisplayArea[8] = { // 表示領域 0, 0, 256, 240, // フレームバッファ内 0, 0, 256, 240 // 出力スクリーン上 }; // フレームスキップ int DrawingCount = 0; int DrawingRate = 0; int DrawingSkip = 0; int DisplayCount = 0; int DisplayRate = 0; int DisplaySkip = 0; int TickCount = 0; int TickRate[2] = {256000 / 60, 0}; int Stretch = 0; // 定数 BYTE PacketCount[256] = { 0, 0, 2, 0, 0, 0, 0, 0, 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, 3, 6, 6, 6, 6, 4, 4, 4, 4, 8, 8, 8, 8, 5, 5, 5, 5, 8, 8, 8, 8, 7, 7, 7, 7,11,11,11,11, 2, 2, 2, 2, 0, 0, 0, 0, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 0, 0, 0, 0, 4, 4, 4, 4, 4, 4, 4, 4, 2, 2, 2, 2, 3, 3, 3, 3, 1, 1, 1, 1, 2, 2, 2, 2, 1, 1, 1, 1, 2, 2, 2, 2, 1, 1, 1, 1, 2, 2, 2, 2, 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, 2, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 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 }; int HorizontalResolution[8] = { // 水平解像度 256, 368, 320, 384, 512, 512, 640, 640 }; int VerticalResolution[4] = { // 垂直解像度 240, 480, 256, 480 }; //----------------------------------------------------------------------------- // プロトタイプ宣言 //----------------------------------------------------------------------------- DWORD CALLBACK PSEgetLibType(void); char * CALLBACK PSEgetLibName(void); DWORD CALLBACK PSEgetLibVersion(void); int CALLBACK GPUinit(void); int CALLBACK GPUshutdown(void); int CALLBACK GPUopen(HWND); int CALLBACK GPUclose(void); int CALLBACK GPUconfigure(void); void CALLBACK GPUabout(void); int CALLBACK GPUtest(void); void CALLBACK GPUwriteData(DWORD); void CALLBACK GPUwriteStatus(DWORD); DWORD CALLBACK GPUreadData(void); DWORD CALLBACK GPUreadStatus(void); int CALLBACK GPUdmaChain(DWORD *, DWORD); int CALLBACK GPUgetMode(void); void CALLBACK GPUsetMode(DWORD); void CALLBACK GPUupdateLace(void); void CALLBACK GPUmakeSnapshot(void); void CALLBACK GPUwriteDataMem(DWORD *, int); void CALLBACK GPUreadDataMem(DWORD *, int); void CALLBACK GPUdisplayText(char *); void CALLBACK GPUdisplayFlags(DWORD); int CALLBACK GPUfreeze(DWORD, GPUFREEZE *); void CALLBACK GPUshowScreenPic(BYTE *); void CALLBACK GPUgetScreenPic(BYTE *); void GPUreadConfig(void); void GPUwriteConfig(void); void ExecuteDrawingCommand(void); void ExecuteDrawingCommandP(void); //----------------------------------------------------------------------------- // GP1 レジスタの意味 //----------------------------------------------------------------------------- /* 0x14802000 // 標準状態 0x80000000 // 31 描画ライン 0:偶数ライン, 1:奇数ライン 0x60000000 // 29-30 DMAモード 0:I/O, 2:DMA-IN, 3:DMA-OUT 0x14000000 // 28 スタンバイ 0x08000000 // 27 フレームバッファ、メインメモリ間転送 0:NG 1:OK 0x03000000 // 24-25 不明 0x00800000 // 23 表示 0:ON 1:OFF 0x00400000 // 22 インターレースモードフラグ 0:ノンインターレース 1:インターレース 0x00200000 // 21 フレームバッファのビットモード 0:16bit 1:24bit 0x00100000 // 20 ビデオ信号方式 0:NTSC 1:PAL 0x00080000 // 19 垂直解像度 0:240 1:480 0x00070000 // 16-18 水平解像度 256,384,320,320,512,512,640,640 0x0000E000 // 13-15 0x00001000 // 12 マスク処理フラグ 0:OFF 1:ON 0x00000800 // 11 描画色の最上位ビット 0x00000400 // 10 表示領域への描画フラグ 0:NG 1:OK 0x00000200 // 09 ディザ処理フラグ 0:OFF 1:ON 0x00000180 // 07-08 テクスチャのビットモード 0x00000060 // 05-06 半透明率 0x00000010 // 04 テクスチャページのY座標 0x0000000F // 00-03 〃 のX座標 */ //----------------------------------------------------------------------------- // エントリーポイント //----------------------------------------------------------------------------- BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) { Application = hinstDLL; return(TRUE); } //----------------------------------------------------------------------------- // 文字列コピー //----------------------------------------------------------------------------- char *StrCpy(char *lpString1, const char *lpString2) { for (; *lpString2; *lpString1++ = *lpString2++); *lpString1 = 0; return(lpString1); } //----------------------------------------------------------------------------- // 10進数変換 //----------------------------------------------------------------------------- char *IntToDec(char *lpString, int iValue) { char *r, szNumber[] = "0123456789"; int iDigits, iValue2; if (iValue < 0) { *lpString++ = '-'; iValue = -iValue; } for (iValue2 = iValue, iDigits = 0; iValue2; iValue2 /= 10, iDigits++); if (!iDigits) iDigits++; r = lpString = &lpString[iDigits]; *lpString = 0; for (; iDigits; iDigits--) { *(--lpString) = szNumber[iValue % 10]; iValue /= 10; } return(r); } //----------------------------------------------------------------------------- // 10進数逆変換 //----------------------------------------------------------------------------- BOOL DecToInt(const char *lpString, int *ipValue) { int iSign = 1; *ipValue = 0; if (!*lpString) return(FALSE); if (*lpString == '-') { lpString++; iSign = -1; } else if (*lpString == '+') lpString++; do { (*ipValue) *= 10; if ((*lpString >= '0') && (*lpString <= '9')) (*ipValue) += (*lpString - '0'); else return(FALSE); } while (*(++lpString)); (*ipValue) *= iSign; return(TRUE); } //----------------------------------------------------------------------------- // PSEgetLibType 02 //----------------------------------------------------------------------------- DWORD CALLBACK PSEgetLibType(void) { return(2); // GPU } //----------------------------------------------------------------------------- // PSEgetLibName 03 //----------------------------------------------------------------------------- char * CALLBACK PSEgetLibName(void) { return(LIBNAME); } //----------------------------------------------------------------------------- // PSEgetLibVersion 04 //----------------------------------------------------------------------------- DWORD CALLBACK PSEgetLibVersion(void) { return((GPU_VERSION << 16) | (GPU_REVISION << 8) | GPU_BUILD); } //----------------------------------------------------------------------------- // GPUinit 05 //----------------------------------------------------------------------------- int CALLBACK GPUinit(void) { return(0); } //----------------------------------------------------------------------------- // GPUshutdown 06 //----------------------------------------------------------------------------- int CALLBACK GPUshutdown(void) { return(0); } //----------------------------------------------------------------------------- // GPUopen 07 //----------------------------------------------------------------------------- int CALLBACK GPUopen(HWND p1) { int w, h; RECT r1, r2; MainWindow = p1; MainDC = GetDC(MainWindow); GetWindowRect(MainWindow, &r1); GetClientRect(MainWindow, &r2); MainFrame[0] = (r1.right - r1.left) - (r2.right - r2.left); MainFrame[1] = (r1.bottom - r1.top) - (r2.bottom - r2.top); GPUconfigure(); if (Stretch) { w = 640; h = 480; } else { w = DisplayArea[2]; h = DisplayArea[3]; } SetWindowPos(MainWindow, HWND_TOPMOST, 2, 2, w + MainFrame[0], h + MainFrame[1], 0); return(0); } //----------------------------------------------------------------------------- // GPUclose 08 //----------------------------------------------------------------------------- int CALLBACK GPUclose(void) { ReleaseDC(MainWindow, MainDC); return(0); } //----------------------------------------------------------------------------- // GPUconfigure 09 //----------------------------------------------------------------------------- #define CONFIGURE_BUTTON_OK 128 #define CONFIGURE_EDIT_DRAWINGRATE 130 #define CONFIGURE_EDIT_DISPLAYRATE 132 #define CONFIGURE_EDIT_FPSLIMIT 134 #define CONFIGURE_CHECKBOX_STRETCH 135 LRESULT CALLBACK ConfigureProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { int temp; char s[256]; switch (message) { case WM_COMMAND: switch (LOWORD(wParam)) { case CONFIGURE_BUTTON_OK: GetDlgItemText(hWnd, CONFIGURE_EDIT_DRAWINGRATE, s, sizeof(s)); if (DecToInt(s, &temp)) DrawingRate = temp; GetDlgItemText(hWnd, CONFIGURE_EDIT_DISPLAYRATE, s, sizeof(s)); if (DecToInt(s, &temp)) DisplayRate = temp; GetDlgItemText(hWnd, CONFIGURE_EDIT_FPSLIMIT, s, sizeof(s)); if (DecToInt(s, &temp)) if (temp) TickRate[0] = 256000 / temp; Stretch = (IsDlgButtonChecked(hWnd, CONFIGURE_CHECKBOX_STRETCH) == BST_CHECKED); GPUwriteConfig(); SendMessage(hWnd, WM_CLOSE, 0, 0); break; default: return FALSE; } break; case WM_INITDIALOG: GPUreadConfig(); IntToDec(s, DrawingRate); SetDlgItemText(hWnd, CONFIGURE_EDIT_DRAWINGRATE, s); IntToDec(s, DisplayRate); SetDlgItemText(hWnd, CONFIGURE_EDIT_DISPLAYRATE, s); if (TickRate[0]) IntToDec(s, 256000 / TickRate[0]); SetDlgItemText(hWnd, CONFIGURE_EDIT_FPSLIMIT, s); if (Stretch) temp = BST_CHECKED; else temp = BST_UNCHECKED; CheckDlgButton(hWnd, CONFIGURE_CHECKBOX_STRETCH, temp); break; case WM_CLOSE: EndDialog(hWnd, NULL); break; default: return FALSE; } return TRUE; } int CALLBACK GPUconfigure(void) { DialogBox(Application, "CONFIGURE", GetActiveWindow(), (DLGPROC)ConfigureProc); return(0); } //----------------------------------------------------------------------------- // GPUabout 10 //----------------------------------------------------------------------------- #define ABOUT_BUTTON_OK 128 LRESULT CALLBACK AboutProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { switch (message) { case WM_COMMAND: switch (LOWORD(wParam)) { case ABOUT_BUTTON_OK: SendMessage(hWnd, WM_CLOSE, 0, 0); break; default: return FALSE; } break; case WM_CLOSE: EndDialog(hWnd, NULL); break; default: return FALSE; } return TRUE; } void CALLBACK GPUabout(void) { DialogBox(Application, "ABOUT", GetActiveWindow(), (DLGPROC)AboutProc); } //----------------------------------------------------------------------------- // GPUtest 11 //----------------------------------------------------------------------------- int CALLBACK GPUtest(void) { return(0); } //----------------------------------------------------------------------------- // GPUwriteData 12 //----------------------------------------------------------------------------- void CALLBACK GPUwriteData(DWORD data) { GP1 &= ~0x14000000; if (ShortOfPacket) { ShortOfPacket--; Packet[PacketIndex++] = data; } else { Packet[0] = data; ShortOfPacket = PacketCount[((BYTE *)Packet)[3]]; PacketIndex = 1; } #ifdef NOTPSEUDO if (!ShortOfPacket) ExecuteDrawingCommand(); #else if (!ShortOfPacket) ExecuteDrawingCommandP(); #endif GP1 |= 0x14000000; } //----------------------------------------------------------------------------- // GPUwriteStatus 13 //----------------------------------------------------------------------------- void CALLBACK GPUwriteStatus(DWORD data) { int temp; switch(data >> 24) { case 0x00: GP1 = 0x14802000; // 初期値 ShortOfPacket = 0; break; case 0x01: ShortOfPacket = 0; break; case 0x02: ShortOfPacket = 0; break; case 0x03: GP1 = (GP1 & ~0x00800000) | ((data & 1) << 23); break; case 0x04: if (data == 0x04000000) ShortOfPacket = 0; GP1 = (GP1 & ~0x60000000) | ((data & 3) << 29); break; case 0x05: DisplayArea[0] = data & 0x000003FF; DisplayArea[1] = (data & 0x000FFC00) >> 10; break; case 0x06: DisplayArea[4] = data & 0x00000FFF; DisplayArea[6] = (data & 0x00FFF000) >> 12; break; case 0x07: DisplayArea[5] = data & 0x000003FF; DisplayArea[7] = (data & 0x000FFC00) >> 10; break; case 0x08: DrawingEnvironment[0x08] = (data >> 7) & 1; // リバース(?) temp = GP1; GP1 = (GP1 & ~0x007F0000) | ((data & 0x3F) << 17) | ((data & 0x40) << 10); DisplayArea[2] = HorizontalResolution[(GP1 >> 16) & 7]; DisplayArea[3] = VerticalResolution [(GP1 >> 19) & 3]; if (!Stretch) if ((GP1 ^ temp) & 0x001F0000) SetWindowPos(MainWindow, HWND_TOPMOST, 0, 0, DisplayArea[2] + MainFrame[0], DisplayArea[3] + MainFrame[1], SWP_NOMOVE); break; case 0x09: DrawingEnvironment[0x09] = data & 1; // GPUB(?) break; case 0x10: Packet[0] = data; ShortOfPacket = 1; PacketIndex = 1; break; } } //----------------------------------------------------------------------------- // GPUreadData 14 //----------------------------------------------------------------------------- DWORD CALLBACK GPUreadData(void) { GP1 &= ~0x14000000; #ifdef NOTPSEUDO if (ShortOfPacket) ExecuteDrawingCommand(); #else if (ShortOfPacket) ExecuteDrawingCommandP(); #endif GP1 |= 0x14000000; return(GP0); } //----------------------------------------------------------------------------- // GPUreadStatus 15 //----------------------------------------------------------------------------- DWORD CALLBACK GPUreadStatus(void) { return(GP1); } //----------------------------------------------------------------------------- // GPUdmaChain 16 //----------------------------------------------------------------------------- int CALLBACK GPUdmaChain(DWORD *baseAddr, DWORD dmaVAddr) { DWORD *dmaAddr, dmaCount, dmaVAddr2; GP1 &= ~0x14000000; // スタンバイ解除 dmaVAddr &= 0x00FFFFFF; while (dmaVAddr != 0xFFFFFF) { dmaAddr = (baseAddr + (dmaVAddr >> 2)); dmaCount = (*dmaAddr >> 24); dmaVAddr2 = *dmaAddr & 0x00FFFFFF; dmaAddr++; if (dmaVAddr != dmaVAddr2) dmaVAddr = dmaVAddr2; else dmaVAddr = 0xFFFFFF; while (dmaCount) { dmaCount--; if (ShortOfPacket) { ShortOfPacket--; Packet[PacketIndex++] = *dmaAddr++; } else { Packet[0] = *dmaAddr++; ShortOfPacket = PacketCount[((BYTE *)Packet)[3]]; PacketIndex = 1; } if (!ShortOfPacket) { #ifdef NOTPSEUDO ExecuteDrawingCommand(); #else ExecuteDrawingCommandP(); #endif } } } GP1 = (GP1 | 0x14000000) & ~0x60000000; // スタンバイ、DMA終了 return(0); } //----------------------------------------------------------------------------- // GPUgetMode 17 //----------------------------------------------------------------------------- int CALLBACK GPUgetMode(void) { return(0); } //----------------------------------------------------------------------------- // GPUsetMode 18 //----------------------------------------------------------------------------- void CALLBACK GPUsetMode(DWORD p1) { } //----------------------------------------------------------------------------- // GPUupdateLace 19 //----------------------------------------------------------------------------- BYTE OutputScreen[614400]; void CALLBACK GPUupdateLace(void) { static BYTE BitmapInfo[40] = { 0x28,0x00,0x00,0x00,0x80,0x02,0x00,0x00, 0xE0,0x01,0x00,0x00,0x01,0x00,0x10,0x00, 0x00,0x00,0x00,0x00,0x00,0x60,0x09,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }; int x0, x1, x2, xx, yy; DWORD *DisplayPoint, *DrawingPoint2; // 表示ポイント、32bit描画ポイント GP1 ^= 0x80000000; // 描画ラインのトグル TickRate[1] += TickRate[0]; TickCount += (TickRate[1] >> 8); TickRate[1] &= 0xFF; DrawingSkip++; DisplaySkip++; if ((GP1 & 0x00080000) || (DrawingRate < 1)) DrawingCount = -1; if (!DrawingCount) { DrawingSkip = 0; return; } if (DrawingCount > 0) if (DisplayArea[1] >= DisplayArea[3]) return; if (DrawingSkip > DrawingRate) DrawingSkip = 0; if (DisplaySkip > DisplayRate) DisplaySkip = 0; if (DisplaySkip) return; if (GP1 & 0x00800000) return; // No Display の場合 if (DrawingCount > 0) DrawingCount = 0; x0 = DisplayArea[2] >> 1; if (GP1 & 0x00200000) { // 24 bit mode DisplayPoint = (void *)&OutputScreen[1280 * (DisplayArea[3] - 1)]; DrawingPoint = &FrameBuffer[(DisplayArea[1] << 10) + DisplayArea[0]]; x1 = -320 - x0; x2 = 1024 - x0 - x0 - x0; for (yy = 0; yy < DisplayArea[3]; yy++) { for (xx = 0; xx < x0; xx++) { *DisplayPoint++ = ((DrawingPoint[0] & 0x00F8) << 7) | ((DrawingPoint[0] & 0xF800) >> 6) | ((DrawingPoint[1] & 0x00F8) >> 3) | ((DrawingPoint[1] & 0xF800) << 15) | ((DrawingPoint[2] & 0x00F8) << 18) | ((DrawingPoint[2] & 0xF800) << 5); DrawingPoint += 3; } DisplayPoint += x1; DrawingPoint += x2; } } else { // 16 bit mode DisplayPoint = (void *)&OutputScreen[1280 * (DisplayArea[3] - 1)]; DrawingPoint2 = (void *)&FrameBuffer[(DisplayArea[1] << 10) + DisplayArea[0]]; x1 = -320 - x0; x2 = 512 - x0; for (yy = 0; yy < DisplayArea[3]; yy++) { for (xx = 0; xx < x0; xx++) { *DisplayPoint++ = (*DrawingPoint2 & 0x83E083E0) | ((*DrawingPoint2 & 0x7C007C00) >> 10) | ((*DrawingPoint2 & 0x001F001F) << 10); DrawingPoint2++; } DisplayPoint += x1; DrawingPoint2 += x2; } } if (Stretch) StretchDIBits(MainDC, 0, 0, 640, 480, 0, 0, DisplayArea[2], DisplayArea[3], (void *)OutputScreen, (void *)BitmapInfo, DIB_RGB_COLORS, SRCCOPY); else SetDIBitsToDevice(MainDC, 0, 0, DisplayArea[2], DisplayArea[3], 0, 0, 0, DisplayArea[3], (void *)OutputScreen, (void *)BitmapInfo, DIB_RGB_COLORS); for (; (int)GetTickCount() < TickCount; ); DisplayCount++; if (!(DisplayCount & 0x3F)) TickCount = GetTickCount(); } //----------------------------------------------------------------------------- // GPUmakeSnapshot 20 //----------------------------------------------------------------------------- void CALLBACK GPUmakeSnapshot(void) { HANDLE hFile; int temp = 0; char *r, s[256]; BYTE bmfh[14] = { 'B','M',0x36,0x60,0x09,0x00,0x00,0x00,0x00,0x00,0x36,0x00,0x00,0x00 }; BYTE bmih[40] = { 0x28,0x00,0x00,0x00,0x80,0x02,0x00,0x00, 0xE0,0x01,0x00,0x00,0x01,0x00,0x10,0x00, 0x00,0x00,0x00,0x00,0x00,0x60,0x09,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }; do { r = StrCpy(s, "Snapshot"); r = IntToDec(r, temp++); StrCpy(r, ".bmp"); hFile = CreateFile(s, GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_NEW, FILE_ATTRIBUTE_NORMAL, 0); } while (hFile == INVALID_HANDLE_VALUE); WriteFile(hFile, (void *)bmfh, sizeof(bmfh), (void *)&temp, NULL); WriteFile(hFile, (void *)bmih, sizeof(bmih), (void *)&temp, NULL); WriteFile(hFile, (void *)OutputScreen, sizeof(OutputScreen), (void *)&temp, NULL); CloseHandle(hFile); } //----------------------------------------------------------------------------- // GPUwriteDataMem 21 //----------------------------------------------------------------------------- void CALLBACK GPUwriteDataMem(DWORD *dmaAddr, int dmaCount) { GP1 &= ~0x14000000; // スタンバイ解除 while (dmaCount--) { if (ShortOfPacket) { ShortOfPacket--; Packet[PacketIndex++] = *dmaAddr++; } else { Packet[0] = *dmaAddr++; ShortOfPacket = PacketCount[((BYTE *)Packet)[3]]; PacketIndex = 1; } #ifdef NOTPSEUDO if (!ShortOfPacket) ExecuteDrawingCommand(); #else if (!ShortOfPacket) ExecuteDrawingCommandP(); #endif } GP1 = (GP1 | 0x14000000) & ~0x60000000; // スタンバイ、DMA終了 } //----------------------------------------------------------------------------- // GPUreadDataMem 22 //----------------------------------------------------------------------------- void CALLBACK GPUreadDataMem(DWORD *dmaAddr, int dmaCount) { GP1 &= ~0x14000000; // スタンバイ解除 while (dmaCount--) { #ifdef NOTPSEUDO if (ShortOfPacket) ExecuteDrawingCommand(); #else if (ShortOfPacket) ExecuteDrawingCommandP(); #endif *dmaAddr++ = GP0; } GP1 = (GP1 | 0x14000000) & ~0x60000000; // スタンバイ、DMA終了 } //----------------------------------------------------------------------------- // GPUdisplayText 23 //----------------------------------------------------------------------------- void CALLBACK GPUdisplayText(char *p1) { } //----------------------------------------------------------------------------- // GPUdisplayFlags 24 //----------------------------------------------------------------------------- void CALLBACK GPUdisplayFlags(DWORD p1) { } //----------------------------------------------------------------------------- // GPUfreeze 25 //----------------------------------------------------------------------------- int CALLBACK GPUfreeze(DWORD p1, GPUFREEZE *p2) { DWORD temp; if (p1 == 2) { temp = *(DWORD *)p2; if ((temp < 0) || (temp > 8)) return(0); return(1); } if (p2 == NULL) return(0); if (p2->Version != 1) return(0); if (p1 == 1) { p2->GP1 = GP1; for (temp = 0; temp < 16; temp++) p2->Control[temp] = Packet[temp]; p2->Control[16] = PacketIndex; p2->Control[17] = ShortOfPacket; p2->Control[18] = GP0; p2->Control[19] = (int)CLUT - (int)FrameBuffer; p2->Control[20] = (int)TexturePage - (int)FrameBuffer; p2->Control[21] = (int)DrawingPoint - (int)FrameBuffer; p2->Control[22] = DrawingColour[0]; p2->Control[23] = DrawingColour[1]; p2->Control[24] = LightColour[0]; p2->Control[25] = LightColour[1]; p2->Control[26] = LightColour[2]; p2->Control[27] = SemiTransparencyRate; p2->Control[28] = TextureWindow[0]; p2->Control[29] = TextureWindow[1]; p2->Control[30] = TextureWindow[2]; p2->Control[31] = TextureWindow[3]; p2->Control[32] = Pixel[0]; p2->Control[33] = Pixel[1]; p2->Control[34] = DrawingArea[0]; p2->Control[35] = DrawingArea[1]; p2->Control[36] = DrawingArea[2]; p2->Control[37] = DrawingArea[3]; p2->Control[38] = DrawingOffset[0]; p2->Control[39] = DrawingOffset[1]; p2->Control[40] = DisplayArea[0]; p2->Control[41] = DisplayArea[1]; p2->Control[42] = DisplayArea[2]; p2->Control[43] = DisplayArea[3]; p2->Control[44] = DisplayArea[4]; p2->Control[45] = DisplayArea[5]; p2->Control[46] = DisplayArea[6]; p2->Control[47] = DisplayArea[7]; p2->Control[48] = DrawingCount; p2->Control[49] = DrawingRate; p2->Control[50] = DrawingSkip; p2->Control[51] = DisplayCount; p2->Control[52] = DisplayRate; p2->Control[53] = DisplaySkip; p2->Control[54] = TickCount; p2->Control[55] = TickRate[0]; p2->Control[56] = TickRate[1]; p2->Control[57] = Stretch; CopyMemory(p2->FrameBuffer, FrameBuffer, sizeof(FrameBuffer)); return(1); } if (p1 == 0) { GP1 = p2->GP1; for (temp = 0; temp < 16; temp++) Packet[temp] = p2->Control[temp]; PacketIndex = p2->Control[16]; ShortOfPacket = p2->Control[17]; GP0 = p2->Control[18]; CLUT = (void *)((int)FrameBuffer + p2->Control[19]); TexturePage = (void *)((int)FrameBuffer + p2->Control[20]); DrawingPoint = (void *)((int)FrameBuffer + p2->Control[21]); DrawingColour[0] = p2->Control[22]; DrawingColour[1] = p2->Control[23]; LightColour[0] = p2->Control[24]; LightColour[1] = p2->Control[25]; LightColour[2] = p2->Control[26]; SemiTransparencyRate = p2->Control[27]; TextureWindow[0] = p2->Control[28]; TextureWindow[1] = p2->Control[29]; TextureWindow[2] = p2->Control[30]; TextureWindow[3] = p2->Control[31]; Pixel[0] = p2->Control[32]; Pixel[1] = p2->Control[33]; DrawingArea[0] = p2->Control[34]; DrawingArea[1] = p2->Control[35]; DrawingArea[2] = p2->Control[36]; DrawingArea[3] = p2->Control[37]; DrawingOffset[0] = p2->Control[38]; DrawingOffset[1] = p2->Control[39]; DisplayArea[0] = p2->Control[40]; DisplayArea[1] = p2->Control[41]; DisplayArea[2] = p2->Control[42]; DisplayArea[3] = p2->Control[43]; DisplayArea[4] = p2->Control[44]; DisplayArea[5] = p2->Control[45]; DisplayArea[6] = p2->Control[46]; DisplayArea[7] = p2->Control[47]; DrawingCount = p2->Control[48]; DrawingRate = p2->Control[49]; DrawingSkip = p2->Control[50]; DisplayCount = p2->Control[51]; DisplayRate = p2->Control[52]; DisplaySkip = p2->Control[53]; TickCount = p2->Control[54]; TickRate[0] = p2->Control[55]; TickRate[1] = p2->Control[56]; Stretch = p2->Control[57]; CopyMemory(FrameBuffer, p2->FrameBuffer, sizeof(FrameBuffer)); return(1); } return(0); } //----------------------------------------------------------------------------- // GPUshowScreenPic 26 //----------------------------------------------------------------------------- void CALLBACK GPUshowScreenPic(BYTE *p1) { } //----------------------------------------------------------------------------- // GPUgetScreenPic 27 //----------------------------------------------------------------------------- void CALLBACK GPUgetScreenPic(BYTE *p1) { int temp = 0; HANDLE hFile; char s[256], *r; BYTE bmfh[14] = { 'B','M',0x36,0x00,0x10,0x00,0x00,0x00,0x00,0x00,0x36,0x00,0x00,0x00 }; BYTE bmih[40] = { 0x28,0x00,0x00,0x00,0x00,0x04,0x00,0x00, 0x00,0x02,0x00,0x00,0x01,0x00,0x10,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x10,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }; do { r = StrCpy(s, "ScreenPic"); r = IntToDec(r, temp++); StrCpy(r, ".bmp"); hFile = CreateFile(s, GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_NEW, FILE_ATTRIBUTE_NORMAL, 0); } while (hFile == INVALID_HANDLE_VALUE); WriteFile(hFile, (void *)bmfh, sizeof(bmfh), (void *)&temp, NULL); WriteFile(hFile, (void *)bmih, sizeof(bmih), (void *)&temp, NULL); WriteFile(hFile, FrameBuffer, sizeof(FrameBuffer), (void *)&temp, NULL); CloseHandle(hFile); } //----------------------------------------------------------------------------- // 設定をレジストリから読み込む //----------------------------------------------------------------------------- void GPUreadConfig(void) { DWORD cbData, dwType; HKEY hKey; if (ERROR_SUCCESS != RegOpenKeyEx(HKEY_CURRENT_USER, "Software\\Vision Thing\\PSEmu Pro\\GPU\\HellGDI", NULL, KEY_ALL_ACCESS, &hKey)) return; cbData = 4; RegQueryValueEx(hKey, "DrawingRate", NULL, &dwType, (void *)&DrawingRate, &cbData); cbData = 4; RegQueryValueEx(hKey, "DisplayRate", NULL, &dwType, (void *)&DisplayRate, &cbData); cbData = 4; RegQueryValueEx(hKey, "FPSLimit", NULL, &dwType, (void *)&TickRate[0], &cbData); cbData = 4; RegQueryValueEx(hKey, "Stretch", NULL, &dwType, (void *)&Stretch, &cbData); RegCloseKey(hKey); } //----------------------------------------------------------------------------- // 設定をレジストリに書き込む //----------------------------------------------------------------------------- void GPUwriteConfig(void) { DWORD dwDisposition; HKEY hKey; RegCreateKeyEx(HKEY_CURRENT_USER, "Software\\Vision Thing\\PSEmu Pro\\GPU\\HellGDI", 0, NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hKey, &dwDisposition); RegSetValueEx(hKey, "DrawingRate", 0, REG_DWORD, (void *)&DrawingRate, 4); RegSetValueEx(hKey, "DisplayRate", 0, REG_DWORD, (void *)&DisplayRate, 4); RegSetValueEx(hKey, "FPSLimit", 0, REG_DWORD, (void *)&TickRate[0], 4); RegSetValueEx(hKey, "Stretch", 0, REG_DWORD, (void *)&Stretch, 4); RegCloseKey(hKey); } //----------------------------------------------------------------------------- // スワップ //----------------------------------------------------------------------------- void SwapInt(int *value0, int *value1) { int temp; temp = *value0; *value0 = *value1; *value1 = temp; } //----------------------------------------------------------------------------- // DrawingColour //----------------------------------------------------------------------------- void SetColour(int colour) { DrawingColour[0] = ((colour & 0xF80000) >> 9) | ((colour & 0x00F800) >> 6) | ((colour & 0x0000F8) >> 3); } //----------------------------------------------------------------------------- // CLUT //----------------------------------------------------------------------------- void SetCLUT(int clut) { CLUT = &FrameBuffer[(clut >> 12) & 0x7FFF0]; } //----------------------------------------------------------------------------- // TexturePage //----------------------------------------------------------------------------- void SetTPage(int tpage) { GP1 = (GP1 & ~0x7FF) | ((tpage >> 16) & 0x7FF); SemiTransparencyRate = (GP1 & 0x00000060) >> 5; TexturePage = &FrameBuffer[((GP1 & 0x10) << 14) + ((GP1 & 0x0F) << 6)]; } //----------------------------------------------------------------------------- // 疑似ポリゴン //----------------------------------------------------------------------------- void PolygonDrawingP(void) { int x0, x1, x2, x3, x4, x5, x6, x7, x8, xx; int y0, y1, y2, y3, y4, yy; int p, temp; if (DrawingSkip) return; if (!DrawingCount) if (DrawingArea[1] >= DisplayArea[3]) return; DrawingCount = 1; x0 = ((short *)Packet)[2] + DrawingOffset[0]; y0 = ((short *)Packet)[3] + DrawingOffset[1]; x1 = ((short *)Packet)[4] + DrawingOffset[0]; y1 = ((short *)Packet)[5] + DrawingOffset[1]; x2 = ((short *)Packet)[6] + DrawingOffset[0]; y2 = ((short *)Packet)[7] + DrawingOffset[1]; if ((DWORD)(x0 + 1024) > (DWORD)2048) return; if ((DWORD)(x1 + 1024) > (DWORD)2048) return; if ((DWORD)(x2 + 1024) > (DWORD)2048) return; if (y0 > y1) { SwapInt(&x0, &x1); SwapInt(&y0, &y1); } if (y1 > y2) { SwapInt(&x1, &x2); SwapInt(&y1, &y2); } if (y0 > y1) { SwapInt(&x0, &x1); SwapInt(&y0, &y1); } if ((y0 > DrawingArea[3]) || (y2 < DrawingArea[1])) return; SetColour(Packet[0]); DrawingColour[0] |= DrawingColour[1]; for (temp = 0; temp < 2; temp++) { y3 = 1; y4 = 0; if (temp) { if (y1 - y2) { x5 = ((x2 - x1) << 10) / (y2 - y1); x6 = ((x2 - x0) << 10) / (y2 - y0); x3 = (x1 << 10) + (x5 >> 1); x4 = (x2 << 10) + ((x0 - x2) << 10) * (((y2 - y1) << 1) - 1) / ((y2 - y0) << 1); y3 = y1; y4 = y2 - 1; } } else { if (y0 - y1) { x5 = ((x1 - x0) << 10) / (y1 - y0); x6 = ((x2 - x0) << 10) / (y2 - y0); x3 = (x0 << 10) + (x5 >> 1); x4 = (x0 << 10) + (x6 >> 1); y3 = y0; y4 = y1 - 1; } } if (x3 > x4) { SwapInt(&x3, &x4); SwapInt(&x5, &x6); } if (y3 < DrawingArea[1]) { xx = DrawingArea[1] - y3; x3 += (x5 * xx); x4 += (x6 * xx); y3 = DrawingArea[1]; } if (y4 > DrawingArea[3]) y4 = DrawingArea[3]; p = ((GP1 >> 11) & 2) | ((Packet[0] >> 25) & 1); for (yy = y3; yy <= y4; yy++) { x7 = x3 >> 10; x8 = (x4 >> 10) - 1; if (x7 < DrawingArea[0]) x7 = DrawingArea[0]; if (x8 > DrawingArea[2]) x8 = DrawingArea[2]; DrawingPoint = &FrameBuffer[(yy << 10) + x7]; switch (p) { case 0: for (xx = x7; xx <= x8; xx++, DrawingPoint++) *DrawingPoint = DrawingColour[0]; break; case 1: for (xx = x7; xx <= x8; xx++, DrawingPoint++) if (!((yy + xx) & 1)) *DrawingPoint = DrawingColour[0]; break; case 2: for (xx = x7; xx <= x8; xx++, DrawingPoint++) if (!(*DrawingPoint & 0x8000)) *DrawingPoint = DrawingColour[0]; break; case 3: for (xx = x7; xx <= x8; xx++, DrawingPoint++) if (!(*DrawingPoint & 0x8000)) if (!((yy + xx) & 1)) *DrawingPoint = DrawingColour[0]; break; } x3 += x5; x4 += x6; } } } //----------------------------------------------------------------------------- // 擬似直線 //----------------------------------------------------------------------------- void StraightLineDrawingP(void) { int x0, x1, xx; int y0, y1, yy; int temp; if (DrawingSkip) return; if (!DrawingCount) if (DrawingArea[1] >= DisplayArea[3]) return; DrawingCount = 1; x0 = ((short *)Packet)[2] + DrawingOffset[0]; y0 = ((short *)Packet)[3] + DrawingOffset[1]; x1 = ((short *)Packet)[4] + DrawingOffset[0]; y1 = ((short *)Packet)[5] + DrawingOffset[1]; if ((DWORD)(x0 + 1024) > (DWORD)2048) return; if ((DWORD)(x1 + 1024) > (DWORD)2048) return; SetColour(Packet[0]); DrawingColour[0] |= DrawingColour[1]; // 差分の計算 if (x0 > x1) xx = x0 - x1; else xx = x1 - x0; if (y0 > y1) yy = y0 - y1; else yy = y1 - y0; // y 方向に長い場合 if (yy > xx) { if (y0 > y1) { SwapInt(&x0, &x1); SwapInt(&y0, &y1); } if (y0 > DrawingArea[3]) return; x0 <<= 10; x1 = ((x1 << 10) - x0) / yy; if (y0 < DrawingArea[1]) { x0 += (x1 * (DrawingArea[1] - y0)); y0 = DrawingArea[1]; } if (y1 > DrawingArea[3]) y1 = DrawingArea[3]; temp = DrawingArea[2] - DrawingArea[0]; for (yy = y0; yy <= y1; yy++) { xx = x0 >> 10; x0 += x1; if ((DWORD)(xx - DrawingArea[0]) < (DWORD)temp) FrameBuffer[(yy << 10) + xx] = DrawingColour[0]; } // x 方向に長い場合 } else if (xx) { if (x0 > x1) { SwapInt(&x0, &x1); SwapInt(&y0, &y1); } if (x0 > DrawingArea[2]) return; y0 <<= 10; y1 = ((y1 << 10) - y0) / xx; if (x0 < DrawingArea[0]) { y0 += (y1 * (DrawingArea[0] - x0)); x0 = DrawingArea[0]; } if (x1 > DrawingArea[2]) x1 = DrawingArea[2]; temp = DrawingArea[3] - DrawingArea[1]; for (xx = x0; xx <= x1; xx++) { yy = y0 >> 10; y0 += y1; if ((DWORD)(yy - DrawingArea[1]) < (DWORD)temp) FrameBuffer[(yy << 10) + xx] = DrawingColour[0]; } // 点の場合 } else { if ((DWORD)(x0 - DrawingArea[0]) > (DWORD)(DrawingArea[2] - DrawingArea[0])) return; if ((DWORD)(y0 - DrawingArea[1]) > (DWORD)(DrawingArea[3] - DrawingArea[1])) return; FrameBuffer[(y0 << 10) + x0] = DrawingColour[0]; } } //----------------------------------------------------------------------------- // 擬似矩形 //----------------------------------------------------------------------------- void RectangleDrawingP(void) { int x0, x1, xx; int y0, y1, yy; int temp; if (DrawingSkip) return; if (!DrawingCount) if (DrawingArea[1] >= DisplayArea[3]) return; DrawingCount = 1; x0 = ((short *)Packet)[2] + DrawingOffset[0]; y0 = ((short *)Packet)[3] + DrawingOffset[1]; x1 = ((short *)Packet)[4] + x0 - 1; y1 = ((short *)Packet)[5] + y0 - 1; if (x0 < DrawingArea[0]) x0 = DrawingArea[0]; if (x1 > DrawingArea[2]) x1 = DrawingArea[2]; if (y0 < DrawingArea[1]) y0 = DrawingArea[1]; if (y1 > DrawingArea[3]) y1 = DrawingArea[3]; SetColour(Packet[0]); DrawingColour[0] |= DrawingColour[1]; temp = ((GP1 >> 11) & 2) | ((Packet[0] >> 25) & 1); for (yy = y0; yy <= y1; yy++) { DrawingPoint = &FrameBuffer[(yy << 10) + x0]; switch (temp) { case 0: for (xx = x0; xx <= x1; xx++, DrawingPoint++) *DrawingPoint = DrawingColour[0]; break; case 1: for (xx = x0; xx <= x1; xx++, DrawingPoint++) if (!((yy + xx) & 1)) *DrawingPoint = DrawingColour[0]; break; case 2: for (xx = x0; xx <= x1; xx++, DrawingPoint++) if (!(*DrawingPoint & 0x8000)) *DrawingPoint = DrawingColour[0]; break; case 3: for (xx = x0; xx <= x1; xx++, DrawingPoint++) if (!(*DrawingPoint & 0x8000)) if (!((yy + xx) & 1)) *DrawingPoint = DrawingColour[0]; break; } } } //----------------------------------------------------------------------------- // 描画コマンド実行 //----------------------------------------------------------------------------- #ifdef NOTPSEUDO #include "GPU2.C" #else void ExecuteDrawingCommandP(void) { int x0, x1, xx; int y0, y1, yy; switch(((BYTE *)Packet)[3]) { // 01 キャッシュフラッシュ case 0x01: ShortOfPacket = 0; return; // 02 矩形 RectangleDrawingとは異なり描画環境に影響されない case 0x02: if (DrawingSkip) return; x0 = ((short *)Packet)[2]; y0 = ((short *)Packet)[3]; x1 = ((short *)Packet)[4] + x0 - 1; y1 = ((short *)Packet)[5] + y0 - 1; if (x0 < 0 ) x0 = 0; if (x1 > 1023) x1 = 1023; if (y0 < 0 ) y0 = 0; if (y1 > 511 ) y1 = 511; SetColour(Packet[0]); for (yy = y0; yy <= y1; yy++) { DrawingPoint = &FrameBuffer[(yy << 10) + x0]; for (xx = x0; xx <= x1; xx++, DrawingPoint++) *DrawingPoint = DrawingColour[0]; } return; // 10 GPU Info case 0x10: switch (Packet[0] & 0xFF) { case 3: GP0 = (DrawingArea[1] << 10) | DrawingArea[0]; return; case 4: GP0 = ((DrawingArea[3] - DrawingArea[1] + 1) << 10) | (DrawingArea[2] - DrawingArea[0] + 1); return; case 5: GP0 = (DrawingOffset[1] << 11) | DrawingOffset[0]; return; case 7: GP0 = 2; return; default: GP0 = 0; } ShortOfPacket = 0; return; // 20 ポリゴン フラット case 0x20:case 0x21:case 0x22:case 0x23: PolygonDrawingP(); return; // 24 ポリゴン フラット+テクスチャ case 0x24:case 0x25:case 0x26:case 0x27: Packet[2] = Packet[3]; Packet[3] = Packet[5]; PolygonDrawingP(); return; // 28 クワッド フラット case 0x28:case 0x29:case 0x2A:case 0x2B: PolygonDrawingP(); Packet[1] = Packet[4]; PolygonDrawingP(); return; // 2C クワッド フラット+テクスチャ case 0x2C:case 0x2D:case 0x2E:case 0x2F: Packet[2] = Packet[3]; Packet[3] = Packet[5]; PolygonDrawingP(); Packet[1] = Packet[7]; PolygonDrawingP(); return; // 30 ポリゴン グーロ case 0x30:case 0x31:case 0x32:case 0x33: Packet[2] = Packet[3]; Packet[3] = Packet[5]; PolygonDrawingP(); return; // 34 ポリゴン グーロ+テクスチャ case 0x34:case 0x35:case 0x36:case 0x37: Packet[2] = Packet[4]; Packet[3] = Packet[7]; PolygonDrawingP(); return; // 38 クワッド グーロ case 0x38:case 0x39:case 0x3A:case 0x3B: Packet[2] = Packet[3]; Packet[3] = Packet[5]; PolygonDrawingP(); Packet[1] = Packet[7]; PolygonDrawingP(); return; // 3C クワッド グーロ+テクスチャ case 0x3C:case 0x3D:case 0x3E:case 0x3F: Packet[2] = Packet[4]; Packet[3] = Packet[7]; PolygonDrawingP(); Packet[1] = Packet[10]; PolygonDrawingP(); return; // 40 ライン フラット case 0x40:case 0x41:case 0x42:case 0x43: StraightLineDrawingP(); return; // 48 ポリライン フラット case 0x48:case 0x49:case 0x4A:case 0x4B: // 4C ポリライン フラット case 0x4C:case 0x4D:case 0x4E:case 0x4F: StraightLineDrawingP(); if ((Packet[3] & 0xF000F000) != 0x50005000) { Packet[1] = Packet[2]; Packet[2] = Packet[3]; ShortOfPacket = 1; PacketIndex = 3; } return; // 50 ライン グーロ case 0x50:case 0x51:case 0x52:case 0x53: Packet[2] = Packet[3]; StraightLineDrawingP(); return; // 58 ポリライン グーロ case 0x58:case 0x59:case 0x5A:case 0x5B: // 5C ポリライン グーロ case 0x5C:case 0x5D:case 0x5E:case 0x5F: Packet[2] = Packet[3]; StraightLineDrawingP(); if ((Packet[4] & 0xF000F000) != 0x50005000) { Packet[1] = Packet[3]; Packet[2] = Packet[4]; ShortOfPacket = 2; PacketIndex = 3; } return; // 60 nxn タイル case 0x60:case 0x61:case 0x62:case 0x63: RectangleDrawingP(); return; // 64 nxn スプライト case 0x64:case 0x65:case 0x66:case 0x67: Packet[0] |= 0x02000000; Packet[2] = Packet[3]; RectangleDrawingP(); return; // 68 1x1 タイル case 0x68:case 0x69:case 0x6A:case 0x6B: Packet[2] = 0x00010001; RectangleDrawingP(); return; // 6C 1x1 スプライト case 0x6C:case 0x6D:case 0x6E:case 0xF: Packet[0] |= 0x02000000; Packet[2] = 0x00010001; RectangleDrawingP(); return; // 70 8x8 タイル case 0x70:case 0x71:case 0x72:case 0x73: Packet[2] = 0x00080008; RectangleDrawingP(); return; // 74 8x8 スプライト case 0x74:case 0x75:case 0x76:case 0x77: Packet[0] |= 0x02000000; Packet[2] = 0x00080008; RectangleDrawingP(); return; // 78 16x16 タイル case 0x78:case 0x79:case 0x7A:case 0x7B: Packet[2] = 0x00100010; RectangleDrawingP(); return; // 7C 16x16 スプライト case 0x7C:case 0x7D:case 0x7E:case 0x7F: Packet[0] |= 0x02000000; Packet[2] = 0x00100010; RectangleDrawingP(); return; // 80 VRAM間コピー case 0x80: if ((Packet[1] == Packet[2]) || (((WORD *)Packet)[6] * ((WORD *)Packet)[7] == 0)) return; if (!DrawingCount) if (((WORD *)Packet)[4] < DisplayArea[2]) if (((WORD *)Packet)[5] < DisplayArea[3]) DrawingCount = 1; x0 = (((WORD *)Packet)[3] << 10) + ((WORD *)Packet)[2]; x1 = (((WORD *)Packet)[5] << 10) + ((WORD *)Packet)[4]; y1 = y0 = 1024 - ((WORD *)Packet)[6]; for (yy = 1; yy <= ((WORD *)Packet)[7]; yy++, x0 += y0, x1 += y1) for (xx = 1; xx <= ((WORD *)Packet)[6]; xx++, x0++, x1++) FrameBuffer[x1 & 0x7FFFF] = FrameBuffer[x0 & 0x7FFFF]; return; // A0 CPU -> GPU コピー設定 case 0xA0: Packet[4] = ((WORD *)Packet)[2]; // 左 Packet[5] = ((WORD *)Packet)[3]; // 上 if (!DrawingCount) if ((int)Packet[4] < DisplayArea[2]) if ((int)Packet[5] < DisplayArea[3]) DrawingCount = 1; Packet[6] = ((WORD *)Packet)[4]; // * 6 幅 Packet[7] = ((WORD *)Packet)[5]; // 高さ Packet[2] = (Packet[5] << 10) + Packet[4]; // * 2 ポジション Packet[3] = Packet[6]; // * 3 水平カウンタ Packet[4] = Packet[7]; // * 4 垂直カウンタ Packet[5] = 1024 - Packet[6]; // * 5 ポジションシフト Packet[0] = 0xA8000000; ShortOfPacket = 1; PacketIndex = 1; return; // A8 CPU -> GPU コピー case 0xA8: FrameBuffer[Packet[2]++ & 0x7FFFF] = ((WORD *)Packet)[2]; if (!(--Packet[3])) { Packet[3] = Packet[6]; if (!(--Packet[4])) return; Packet[2] += Packet[5]; } FrameBuffer[Packet[2]++ & 0x7FFFF] = ((WORD *)Packet)[3]; if (!(--Packet[3])) { Packet[3] = Packet[6]; if (!(--Packet[4])) return; Packet[2] += Packet[5]; } ShortOfPacket = 1; PacketIndex = 1; return; // C0 GPU -> CPU コピー設定 case 0xC0: Packet[4] = ((WORD *)Packet)[2]; // 左 Packet[5] = ((WORD *)Packet)[3]; // 上 Packet[6] = ((WORD *)Packet)[4]; // * 6 幅 Packet[7] = ((WORD *)Packet)[5]; // 高さ Packet[2] = (Packet[5] << 10) + Packet[4]; // * 2 ポジション Packet[3] = Packet[6]; // * 3 水平カウンタ Packet[4] = Packet[7]; // * 4 垂直カウンタ Packet[5] = 1024 - Packet[6]; // * 5 ポジションシフト GP1 |= 0x08000000; // 転送モード Packet[0] = 0xC8000000; ShortOfPacket = 1; return; // C8 GPU -> CPU コピー case 0xC8: GP0 = FrameBuffer[Packet[2]++ & 0x7FFFF]; if (!(--Packet[3])) { Packet[3] = Packet[6]; Packet[4]--; Packet[2] += Packet[5]; } GP0 |= (FrameBuffer[Packet[2]++ & 0x7FFFF] << 16); if (!(--Packet[3])) { Packet[3] = Packet[6]; Packet[4]--; Packet[2] += Packet[5]; } if (!Packet[4]) { GP1 &= ~0x08000000; // 転送モード終了 ShortOfPacket = 0; } return; // E1 描画モード case 0xE1: GP1 = (GP1 & ~0x000007FF) | (Packet[0] & 0x000007FF); SemiTransparencyRate = (GP1 & 0x00000060) >> 5; TexturePage = &FrameBuffer[((GP1 & 0x10) << 14) + ((GP1 & 0x0F) << 6)]; return; // E2 テクスチャウィンドウ case 0xE2: x0 = Packet[0]; for (x1 = x0 & 0x1F, xx = 0xFF; x1; x1 = (x1 + x1) & 0x1F, xx >>= 1); for (x1 = (x0 >> 5) & 0x1F, yy = 0xFF; x1; x1 = (x1 + x1) & 0x1F, yy >>= 1); TextureWindow[0] = ((x0 & 0x00007C00) >> 7) & ~xx; TextureWindow[1] = ((x0 & 0x000F8000) >> 12) & ~yy; TextureWindow[2] = xx; TextureWindow[3] = yy; return; // E3 描画領域 case 0xE3: DrawingArea[0] = Packet[0] & 0x000003FF; DrawingArea[1] = (Packet[0] & 0x00FFC00) >> 10; return; // E4 描画領域 case 0xE4: DrawingArea[2] = Packet[0] & 0x000003FF; DrawingArea[3] = (Packet[0] & 0x00FFC00) >> 10; return; // E5 オフセット case 0xE5: DrawingOffset[0] = Packet[0] & 0x000007FF; DrawingOffset[1] = (Packet[0] & 0x003FF800) >> 11; return; // E6 マスク設定 case 0xE9: GP1 = (GP1 & ~0x00001800) | ((Packet[0] & 3) << 11); DrawingColour[1] = (GP1 & 0x00000800) << 4; // マスクビット return; } } #endif