/* * files.c * * This file is part of Emu48 * * Copyright (C) 1995 Sebastien Carlier * */ #include "pch.h" #include "Emu48.h" #include "kml.h" char szEmu48Directory[260]; char szCurrentDirectory[260]; char szCurrentKml[260]; char szBackupKml[260]; char szCurrentFilename[260]; char szBackupFilename[260]; char szBufferFilename[260]; char szPort2Filename[260]; LPBYTE pbyRom = NULL; static HANDLE hRomFile = NULL; static HANDLE hRomMap = NULL; DWORD dwRomSize = 0; char cCurrentRomType = 0; static HANDLE hPort2File = NULL; static HANDLE hPort2Map = NULL; LPBYTE pbyPort2 = NULL; BOOL bPort2Writeable = FALSE; BOOL bPort2IsShared = FALSE; DWORD dwPort2Mask = 0; UINT nPort2Bank = 0; static BYTE pbySignatureE[16] = "Emu48 Document\xFE"; static BYTE pbySignatureW[16] = "Win48 Document\xFE"; static HANDLE hCurrentFile = NULL; static CHIPSET BackupChipset; BOOL bBackup = FALSE; //################ //# //# ROM //# //################ BOOL MapRom(LPCSTR szFilename) { DWORD dwFileSizeHigh; if (pbyRom != NULL) { return FALSE; } SetCurrentDirectory(szEmu48Directory); hRomFile = CreateFile(szFilename, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL); SetCurrentDirectory(szCurrentDirectory); if (hRomFile == INVALID_HANDLE_VALUE) { hRomFile = NULL; return FALSE; } dwRomSize = GetFileSize(hRomFile, &dwFileSizeHigh); if (dwFileSizeHigh != 0) { // file is too large. CloseHandle(hRomFile); hRomFile = NULL; dwRomSize = 0; return FALSE; } hRomMap = CreateFileMapping(hRomFile, NULL, PAGE_WRITECOPY, 0, dwRomSize, NULL); if (hRomMap == NULL) { CloseHandle(hRomFile); hRomFile = NULL; dwRomSize = 0; return FALSE; } if (GetLastError() == ERROR_ALREADY_EXISTS) { AbortMessage("Sharing file mapping handle."); } pbyRom = MapViewOfFile(hRomMap, FILE_MAP_COPY, 0, 0, dwRomSize); if (pbyRom == NULL) { CloseHandle(hRomMap); CloseHandle(hRomFile); hRomMap = NULL; hRomFile = NULL; dwRomSize = 0; return FALSE; } return TRUE; } VOID UnmapRom() { if (pbyRom==NULL) return; UnmapViewOfFile(pbyRom); CloseHandle(hRomMap); CloseHandle(hRomFile); pbyRom = NULL; hRomMap = NULL; hRomFile = NULL; dwRomSize = 0; return; } //################ //# //# Port2 //# //################ BOOL MapPort2(LPCSTR szFilename) { DWORD dwFileSizeLo; DWORD dwFileSizeHi; if (pbyPort2 != NULL) { return FALSE; } bPort2Writeable = TRUE; SetCurrentDirectory(szEmu48Directory); if (bPort2IsShared) { hPort2File = CreateFile(szFilename, GENERIC_READ|GENERIC_WRITE, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL); SetCurrentDirectory(szCurrentDirectory); if (hPort2File == INVALID_HANDLE_VALUE) { bPort2Writeable = FALSE; SetCurrentDirectory(szEmu48Directory); hPort2File = CreateFile(szFilename, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL); SetCurrentDirectory(szCurrentDirectory); if (hPort2File == INVALID_HANDLE_VALUE) { hPort2File = NULL; return FALSE; } } } else { hPort2File = CreateFile(szFilename, GENERIC_READ|GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL); SetCurrentDirectory(szCurrentDirectory); if (hPort2File == INVALID_HANDLE_VALUE) { hPort2File = NULL; return FALSE; } } dwFileSizeLo = GetFileSize(hPort2File, &dwFileSizeHi); if (dwFileSizeHi != 0) { // file is too large. CloseHandle(hPort2File); hPort2File = NULL; dwPort2Mask = 0; bPort2Writeable = FALSE; return FALSE; } if (dwFileSizeLo & 0x3FFFF) { // file size is wrong CloseHandle(hPort2File); hPort2File = NULL; dwPort2Mask = 0; bPort2Writeable = FALSE; return FALSE; } dwPort2Mask = 0; dwFileSizeHi = dwFileSizeLo >> 18; while ((dwFileSizeHi&1)==0) { dwPort2Mask = (dwPort2Mask<<1)+1; dwFileSizeHi>>=1; } dwPort2Mask = (dwPort2Mask<<1)+1; if (bPort2Writeable) hPort2Map = CreateFileMapping(hPort2File, NULL, PAGE_READWRITE, 0, dwFileSizeLo, NULL); else hPort2Map = CreateFileMapping(hPort2File, NULL, PAGE_READONLY, 0, dwFileSizeLo, NULL); if (hPort2Map == NULL) { CloseHandle(hPort2File); hPort2File = NULL; dwPort2Mask = 0; bPort2Writeable = FALSE; return FALSE; } if (bPort2Writeable) pbyPort2 = MapViewOfFile(hPort2Map, FILE_MAP_WRITE, 0, 0, dwFileSizeLo); else pbyPort2 = MapViewOfFile(hPort2Map, FILE_MAP_READ, 0, 0, dwFileSizeLo); if (pbyPort2 == NULL) { CloseHandle(hPort2Map); CloseHandle(hPort2File); hPort2Map = NULL; hPort2File = NULL; dwPort2Mask = 0; bPort2Writeable = FALSE; return FALSE; } return TRUE; } VOID UnmapPort2() { if (pbyPort2==NULL) return; UnmapViewOfFile(pbyPort2); CloseHandle(hPort2Map); CloseHandle(hPort2File); pbyPort2 = NULL; hPort2Map = NULL; hPort2File = NULL; dwPort2Mask = 0; bPort2Writeable = FALSE; return; } //################ //# //# Patch //# //################ static BYTE Asc2Nib(char c) { if (c<'0') return 0; if (c<='9') return c-'0'; if (c<'A') return 0; if (c<='F') return c-'A'+10; if (c<'a') return 0; if (c<='f') return c-'a'+10; return 0; } static DWORD Asc2Nib5(LPSTR lpBuf) { return ( ((DWORD)Asc2Nib(lpBuf[0])<<16) |((DWORD)Asc2Nib(lpBuf[1])<<12) |((DWORD)Asc2Nib(lpBuf[2])<<8) |((DWORD)Asc2Nib(lpBuf[3])<<4) |((DWORD)Asc2Nib(lpBuf[4]))); } BOOL PatchRom(LPCSTR szFilename) { HANDLE hFile = NULL; DWORD dwFileSizeLow = 0; DWORD dwFileSizeHigh = 0; DWORD lBytesRead = 0; LPBYTE lpBuf = NULL; DWORD dwAddress = 0; UINT nPos = 0; if (pbyRom == NULL) return FALSE; SetCurrentDirectory(szEmu48Directory); hFile = CreateFile(szFilename, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_FLAG_SEQUENTIAL_SCAN, NULL); SetCurrentDirectory(szCurrentDirectory); if (hFile == INVALID_HANDLE_VALUE) return FALSE; dwFileSizeLow = GetFileSize(hFile, &dwFileSizeHigh); if (dwFileSizeLow <= 5) { // file is too small. CloseHandle(hFile); return FALSE; } if (dwFileSizeHigh != 0) { // file is too large. CloseHandle(hFile); return FALSE; } lpBuf = (LPBYTE)LocalAlloc(0,dwFileSizeLow+1); if (lpBuf == NULL) { CloseHandle(hFile); return FALSE; } ReadFile(hFile, lpBuf, dwFileSizeLow, &lBytesRead, NULL); CloseHandle(hFile); lpBuf[dwFileSizeLow] = 0; nPos = 0; while (lpBuf[nPos]) { if (lpBuf[nPos]==';') // comment ? { do { if (lpBuf[nPos]=='\n') break; nPos++; } while (lpBuf[nPos]); if (lpBuf[nPos]==0) { LocalFree(lpBuf); return TRUE; } } do // remove blank space { if ( (lpBuf[nPos]!=' ') &&(lpBuf[nPos]!='\n') &&(lpBuf[nPos]!='\r') &&(lpBuf[nPos]!='\t')) break; nPos++; } while (lpBuf[nPos]); if (lpBuf[nPos] == 0) break; if (lpBuf[nPos+5]!=':') { nPos++; continue; } dwAddress = Asc2Nib5(lpBuf+nPos); nPos+=6; while (lpBuf[nPos]) { if (lpBuf[nPos]<'0') break; if (lpBuf[nPos]>'9') { if (lpBuf[nPos]<'A') break; if (lpBuf[nPos]>'F') break; pbyRom[dwAddress] = lpBuf[nPos]-'A'+10; } else { pbyRom[dwAddress] = lpBuf[nPos]-'0'; } dwAddress = (dwAddress+1)&0xFFFFF; nPos++; } } LocalFree(lpBuf); return TRUE; } //################ //# //# Documents //# //################ VOID ResetDocument() { if (szCurrentKml[0]) { KillKML(); } if (hCurrentFile) { CloseHandle(hCurrentFile); hCurrentFile = NULL; } szCurrentKml[0] = 0; szCurrentFilename[0]=0; if (Chipset.Port0) LocalFree(Chipset.Port0); if (Chipset.Port1) LocalFree(Chipset.Port1); FillMemory(&Chipset,sizeof(Chipset),0); UpdateWindowStatus(); return; } BOOL NewDocument() { SaveBackup(); ResetDocument(); if (!DisplayChooseKml(0)) goto restore; if (!InitKML(szCurrentKml,FALSE)) goto restore; Chipset.type = cCurrentRomType; if (Chipset.type == 'S') { Chipset.Port0Size = 32; Chipset.Port1Size = 128; Chipset.Port1_Writeable = TRUE; Chipset.Port0 = (LPBYTE)LocalAlloc(0,Chipset.Port0Size*2048); _ASSERT(Chipset.Port0 != NULL); FillMemory(Chipset.Port0, Chipset.Port0Size*2048, 0); Chipset.Port1 = (LPBYTE)LocalAlloc(0,Chipset.Port1Size*2048); _ASSERT(Chipset.Port1 != NULL); FillMemory(Chipset.Port1, Chipset.Port1Size*2048, 0); Chipset.cards_status = 0x5; } else { Chipset.Port0Size = 128; Chipset.Port1Size = 128; Chipset.Port1_Writeable = TRUE; Chipset.Port0 = (LPBYTE)LocalAlloc(0,Chipset.Port0Size*2048); _ASSERT(Chipset.Port0 != NULL); FillMemory(Chipset.Port0, Chipset.Port0Size*2048, 0); Chipset.Port1 = (LPBYTE)LocalAlloc(0,Chipset.Port1Size*2048); _ASSERT(Chipset.Port1 != NULL); FillMemory(Chipset.Port1, Chipset.Port1Size*2048, 0); Chipset.cards_status = 0xA; } Map(0x00,0xFF); return TRUE; restore: RestoreBackup(); ResetBackup(); if (pbyRom) { SetWindowPos(hWnd,NULL,(int)Chipset.wPosX,(int)Chipset.wPosY,0,0,SWP_NOSIZE|SWP_NOZORDER|SWP_NOACTIVATE); Map(0x00,0xFF); } return FALSE; } BOOL OpenDocument(LPCSTR szFilename) { HANDLE hFile = INVALID_HANDLE_VALUE; DWORD lBytesRead; DWORD lSizeofChipset; BYTE pbyFileSignature[16]; UINT ctBytesCompared; UINT nLength; SaveBackup(); ResetDocument(); // Open file if (lstrcmpi(szBackupFilename, szFilename)==0) { if (YesNoMessage("Do you want to reload this document ?") == IDNO) goto restore; } hFile = CreateFile(szFilename, GENERIC_READ|GENERIC_WRITE, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL); if (hFile == INVALID_HANDLE_VALUE) { AbortMessage("This file is missing or already loaded in another instance of Emu48.\n"); goto restore; } // Read and Compare signature ReadFile(hFile, pbyFileSignature, 16, &lBytesRead, NULL); switch (pbyFileSignature[0]) { case 'E': for (ctBytesCompared=0; ctBytesCompared<14; ctBytesCompared++) { if (pbyFileSignature[ctBytesCompared]!=pbySignatureE[ctBytesCompared]) { AbortMessage("This file is not a valid Emu48 document."); goto restore; } } break; case 'W': for (ctBytesCompared=0; ctBytesCompared<14; ctBytesCompared++) { if (pbyFileSignature[ctBytesCompared]!=pbySignatureW[ctBytesCompared]) { AbortMessage("This file is not a valid Win48 document."); goto restore; } } break; default: AbortMessage("This file is not a valid document."); goto restore; } switch (pbyFileSignature[14]) { case 0xFE: // Win48 2.1 / Emu48 0.99.x format ReadFile(hFile, &nLength, sizeof(nLength), &lBytesRead, NULL); ReadFile(hFile, szCurrentKml, nLength, &lBytesRead, NULL); if (nLength != lBytesRead) goto read_err; szCurrentKml[nLength] = 0; break; case 0xFF: // Win48 2.05 format break; default: AbortMessage("This file is for an unknown version of Emu48.\n" "Please contact the author (see Emu48.txt)."); goto restore; } ReadFile(hFile, &lSizeofChipset, sizeof(lSizeofChipset), &lBytesRead, NULL); if (lBytesRead != sizeof(lSizeofChipset)) goto read_err; if (lSizeofChipset!=sizeof(CHIPSET)) { AbortMessage("This file is probably corrupted, and cannot be loaded."); goto restore; } ReadFile(hFile, &Chipset, lSizeofChipset, &lBytesRead, NULL); if (lBytesRead != lSizeofChipset) goto read_err; Chipset.Port0 = NULL; Chipset.Port1 = NULL; SetWindowPos(hWnd,NULL,(int)Chipset.wPosX,(int)Chipset.wPosY,0,0,SWP_NOSIZE|SWP_NOZORDER|SWP_NOACTIVATE); if (szCurrentKml == NULL) { if (!DisplayChooseKml(Chipset.type)) { CloseHandle(hFile); goto restore; } } while (!InitKML(szCurrentKml,FALSE)) { if (!DisplayChooseKml(Chipset.type)) { CloseHandle(hFile); goto restore; } } if (Chipset.Port0Size) { Chipset.Port0 = (LPBYTE)LocalAlloc(0,Chipset.Port0Size*2048); if (Chipset.Port0 == NULL) { AbortMessage("Memory Allocation Failure."); goto restore; } ReadFile(hFile, Chipset.Port0, Chipset.Port0Size*2048, &lBytesRead, NULL); if (lBytesRead != Chipset.Port0Size*2048) goto read_err; } if (Chipset.Port1Size) { Chipset.Port1 = (LPBYTE)LocalAlloc(0,Chipset.Port1Size*2048); if (Chipset.Port1 == NULL) { AbortMessage("Memory Allocation Failure."); goto restore; } ReadFile(hFile, Chipset.Port1, Chipset.Port1Size*2048, &lBytesRead, NULL); if (lBytesRead != Chipset.Port1Size*2048) goto read_err; } lstrcpy(szCurrentFilename, szFilename); hCurrentFile = hFile; Map(0x00,0xFF); SetWindowTitle(szCurrentFilename); UpdateWindowStatus(); return TRUE; read_err: AbortMessage("This file must be truncated, and cannot be loaded."); restore: if (INVALID_HANDLE_VALUE == hFile) CloseHandle(hFile); RestoreBackup(); ResetBackup(); return FALSE; } BOOL SaveDocument() { DWORD lBytesWritten; DWORD lSizeofChipset; UINT nLength; RECT Rect; if (hCurrentFile == NULL) return FALSE; GetWindowRect(hWnd, &Rect); Chipset.wPosX = (WORD)Rect.left; Chipset.wPosY = (WORD)Rect.top; SetFilePointer(hCurrentFile,0,0,FILE_BEGIN); if (!WriteFile(hCurrentFile, pbySignatureE, 16, &lBytesWritten, NULL)) { AbortMessage("Could not write into file !"); return FALSE; } nLength = strlen(szCurrentKml); WriteFile(hCurrentFile, &nLength, sizeof(nLength), &lBytesWritten, NULL); WriteFile(hCurrentFile, szCurrentKml, nLength, &lBytesWritten, NULL); lSizeofChipset = sizeof(CHIPSET); WriteFile(hCurrentFile, &lSizeofChipset, sizeof(lSizeofChipset), &lBytesWritten, NULL); WriteFile(hCurrentFile, &Chipset, lSizeofChipset, &lBytesWritten, NULL); if (Chipset.Port0Size) WriteFile(hCurrentFile, Chipset.Port0, Chipset.Port0Size*2048, &lBytesWritten, NULL); if (Chipset.Port1Size) WriteFile(hCurrentFile, Chipset.Port1, Chipset.Port1Size*2048, &lBytesWritten, NULL); return TRUE; } BOOL SaveDocumentAs(LPCTSTR szFilename) { HANDLE hFile = INVALID_HANDLE_VALUE; if (hCurrentFile) { if (lstrcmpi(szFilename, szCurrentFilename)==0) { hFile = hCurrentFile; } } if (hFile == INVALID_HANDLE_VALUE) { hFile = CreateFile(szFilename, GENERIC_READ|GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_ALWAYS, 0, NULL); } if (hFile == INVALID_HANDLE_VALUE) { AbortMessage("This file must be currently used by another instance of Emu48."); return FALSE; } lstrcpy(szCurrentFilename, szFilename); hCurrentFile = hFile; SetWindowTitle(szCurrentFilename); UpdateWindowStatus(); return SaveDocument(); } //################ //# //# Backup //# //################ BOOL SaveBackup() { if (pbyRom == NULL) return FALSE; lstrcpy(szBackupFilename, szCurrentFilename); lstrcpy(szBackupKml, szCurrentKml); if (BackupChipset.Port0) LocalFree(BackupChipset.Port0); if (BackupChipset.Port1) LocalFree(BackupChipset.Port1); CopyMemory(&BackupChipset, &Chipset, sizeof(Chipset)); BackupChipset.Port0 = (LPBYTE)LocalAlloc(0,Chipset.Port0Size*2048); CopyMemory(BackupChipset.Port0, Chipset.Port0, Chipset.Port0Size*2048); BackupChipset.Port1 = (LPBYTE)LocalAlloc(0,Chipset.Port1Size*2048); CopyMemory(BackupChipset.Port1, Chipset.Port1, Chipset.Port1Size*2048); bBackup = TRUE; UpdateWindowStatus(); return TRUE; } BOOL RestoreBackup() { if (!bBackup) return FALSE; ResetDocument(); if (!InitKML(szBackupKml,TRUE)) { InitKML(szCurrentKml,TRUE); return FALSE; } lstrcpy(szCurrentKml, szBackupKml); lstrcpy(szCurrentFilename, szBackupFilename); if (szCurrentFilename[0]) { hCurrentFile = CreateFile(szCurrentFilename, GENERIC_READ|GENERIC_WRITE, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL); if (hCurrentFile == INVALID_HANDLE_VALUE) { hCurrentFile = NULL; szCurrentFilename[0] = 0; } } CopyMemory(&Chipset, &BackupChipset, sizeof(Chipset)); Chipset.Port0 = (LPBYTE)LocalAlloc(0,Chipset.Port0Size*2048); CopyMemory(Chipset.Port0, BackupChipset.Port0, Chipset.Port0Size*2048); Chipset.Port1 = (LPBYTE)LocalAlloc(0,Chipset.Port1Size*2048); CopyMemory(Chipset.Port1, BackupChipset.Port1, Chipset.Port1Size*2048); SetWindowPos(hWnd,NULL,(int)Chipset.wPosX,(int)Chipset.wPosY,0,0,SWP_NOSIZE|SWP_NOZORDER|SWP_NOACTIVATE); UpdateWindowStatus(); Map(0x00,0xFF); return TRUE; } BOOL ResetBackup() { if (!bBackup) return FALSE; szBackupFilename[0] = 0; szBackupKml[0] = 0; if (BackupChipset.Port0) LocalFree(BackupChipset.Port0); if (BackupChipset.Port1) LocalFree(BackupChipset.Port1); FillMemory(&BackupChipset,sizeof(BackupChipset),0); bBackup = FALSE; UpdateWindowStatus(); return TRUE; } //################ //# //# Open File Common Dialog Boxes //# //################ static VOID InitializeOFN(LPOPENFILENAME ofn) { FillMemory((LPVOID)ofn, sizeof(OPENFILENAME), 0); ofn->lStructSize = sizeof(OPENFILENAME); ofn->hwndOwner = hWnd; ofn->Flags = OFN_EXPLORER|OFN_HIDEREADONLY; return; } BOOL GetOpenFilename() { OPENFILENAME ofn; InitializeOFN(&ofn); ofn.lpstrFilter = "Emu48 Document (*.E48)\0*.E48\0" "Win48 Document (*.W48)\0*.W48\0" "\0\0"; ofn.lpstrDefExt = "E48"; ofn.nFilterIndex = 1; ofn.lpstrFile = LocalAlloc(0,512); ofn.lpstrFile[0] = 0; ofn.nMaxFile = 512; ofn.Flags |= OFN_FILEMUSTEXIST|OFN_PATHMUSTEXIST; if (GetOpenFileName(&ofn) == FALSE) { LocalFree(ofn.lpstrFile); return FALSE; } lstrcpy(szBufferFilename, ofn.lpstrFile); LocalFree(ofn.lpstrFile); return TRUE; } BOOL GetSaveAsFilename() { OPENFILENAME ofn; InitializeOFN(&ofn); ofn.lpstrFilter = "Emu48 Document (*.E48)\0*.E48\0" "Win48 Document (*.W48)\0*.W48\0" "\0\0"; ofn.lpstrDefExt = "E48"; ofn.nFilterIndex = 1; ofn.lpstrFile = LocalAlloc(0,512); ofn.lpstrFile[0] = 0; ofn.nMaxFile = 512; ofn.Flags |= OFN_CREATEPROMPT|OFN_OVERWRITEPROMPT; if (GetSaveFileName(&ofn) == FALSE) { LocalFree(ofn.lpstrFile); return FALSE; } lstrcpy(szBufferFilename, ofn.lpstrFile); LocalFree(ofn.lpstrFile); return TRUE; } BOOL GetLoadObjectFilename() { OPENFILENAME ofn; InitializeOFN(&ofn); ofn.lpstrFilter = "All Files (*.*)\0*.*\0" "\0\0"; ofn.nFilterIndex = 1; ofn.lpstrFile = LocalAlloc(0,512); ofn.lpstrFile[0] = 0; ofn.nMaxFile = 512; ofn.Flags |= OFN_FILEMUSTEXIST|OFN_PATHMUSTEXIST; if (GetOpenFileName(&ofn) == FALSE) { LocalFree(ofn.lpstrFile); return FALSE; } lstrcpy(szBufferFilename, ofn.lpstrFile); LocalFree(ofn.lpstrFile); return TRUE; } BOOL GetSaveObjectFilename() { OPENFILENAME ofn; InitializeOFN(&ofn); ofn.lpstrFilter = "All Files (*.*)\0*.*\0" "\0\0"; ofn.nFilterIndex = 1; ofn.lpstrFile = LocalAlloc(0,512); ofn.lpstrFile[0] = 0; ofn.nMaxFile = 512; ofn.Flags |= OFN_CREATEPROMPT|OFN_OVERWRITEPROMPT; if (GetSaveFileName(&ofn) == FALSE) { LocalFree(ofn.lpstrFile); return FALSE; } lstrcpy(szBufferFilename, ofn.lpstrFile); LocalFree(ofn.lpstrFile); return TRUE; } //################ //# //# Load and Save HP48 Objects //# //################ BOOL LoadObject(LPCSTR szFilename) { HANDLE hFile; DWORD dwFileSizeLow; DWORD dwFileSizeHigh; DWORD lBytesRead; LPBYTE lpBuf; BOOL bKermit = FALSE; DWORD dwLength, dwAddress; DWORD i; hFile = CreateFile(szFilename, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_FLAG_SEQUENTIAL_SCAN, NULL); if (hFile == INVALID_HANDLE_VALUE) return FALSE; dwFileSizeLow = GetFileSize(hFile, &dwFileSizeHigh); if (dwFileSizeHigh != 0) { // file is too large. CloseHandle(hFile); return FALSE; } lpBuf = (LPBYTE)LocalAlloc(0,dwFileSizeLow*2); if (lpBuf == NULL) { CloseHandle(hFile); return FALSE; } ReadFile(hFile, lpBuf+dwFileSizeLow, dwFileSizeLow, &lBytesRead, NULL); CloseHandle(hFile); if ((lpBuf[dwFileSizeLow+0]=='H') &&(lpBuf[dwFileSizeLow+1]=='P') &&(lpBuf[dwFileSizeLow+2]=='H') &&(lpBuf[dwFileSizeLow+3]=='P') &&(lpBuf[dwFileSizeLow+4]=='4') &&(lpBuf[dwFileSizeLow+5]=='8') &&(lpBuf[dwFileSizeLow+6]=='-')) bKermit = TRUE; for (i=0; i>4); } if (bKermit == TRUE) { // load as binary dwLength = RPL_ObjectSize(lpBuf+16); dwAddress = RPL_CreateTemp(dwLength); if (dwAddress == 0) { LocalFree(lpBuf); AbortMessage("The HP48 has not enough free memory left to load this binary file."); return FALSE; } for (i=0; ibiClrUsed != 0) return (UINT)lpbi->biClrUsed; bits = lpbi->biBitCount; switch (bits) { case 1: return 2; case 4: return 16; case 8: return 256; default: /* A 24 bitcount DIB has no color table */ return 0; } } static HPALETTE CreateBIPalette(LPBITMAPINFOHEADER lpbi) { LOGPALETTE* pPal; HPALETTE hpal = NULL; UINT nNumColors; BYTE red; BYTE green; BYTE blue; UINT i; RGBQUAD* pRgb; if (!lpbi) return NULL; if (lpbi->biSize != sizeof(BITMAPINFOHEADER)) return NULL; // Get a pointer to the color table and the number of colors in it pRgb = (RGBQUAD FAR *)((LPSTR)lpbi + (WORD)lpbi->biSize); nNumColors = DibNumColors(lpbi); if (nNumColors) { // Allocate for the logical palette structure pPal = (LOGPALETTE*)LocalAlloc(LPTR,sizeof(LOGPALETTE) + nNumColors * sizeof(PALETTEENTRY)); if (!pPal) return NULL; pPal->palNumEntries = nNumColors; pPal->palVersion = 0x300; // Fill in the palette entries from the DIB color table and // create a logical color palette. for (i = 0; i < nNumColors; i++) { pPal->palPalEntry[i].peRed = pRgb[i].rgbRed; pPal->palPalEntry[i].peGreen = pRgb[i].rgbGreen; pPal->palPalEntry[i].peBlue = pRgb[i].rgbBlue; pPal->palPalEntry[i].peFlags = (BYTE)0; } hpal = CreatePalette(pPal); LocalFree((HANDLE)pPal); } else { if (lpbi->biBitCount == 24) { // A 24 bitcount DIB has no color table entries so, set the // number of to the maximum value (256). nNumColors = 256; pPal = (LOGPALETTE*)LocalAlloc(LPTR,sizeof(LOGPALETTE) + nNumColors * sizeof(PALETTEENTRY)); if (!pPal) return NULL; pPal->palNumEntries = nNumColors; pPal->palVersion = 0x300; red = green = blue = 0; // Generate 256 (= 8*8*4) RGB combinations to fill the palette // entries. for (i = 0; i < pPal->palNumEntries; i++) { pPal->palPalEntry[i].peRed = red; pPal->palPalEntry[i].peGreen = green; pPal->palPalEntry[i].peBlue = blue; pPal->palPalEntry[i].peFlags = (BYTE)0; if (!(red += 32)) if (!(green += 32)) blue += 64; } hpal = CreatePalette(pPal); LocalFree((HANDLE)pPal); } } return hpal; } HBITMAP LoadBitmapFile(LPCSTR szFilename) { HANDLE hFile; HANDLE hMap; LPBYTE pbyFile; HBITMAP hBitmap; LPBITMAPFILEHEADER pBmfh; LPBITMAPINFO pBmi; SetCurrentDirectory(szEmu48Directory); hFile = CreateFile(szFilename, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL); SetCurrentDirectory(szCurrentDirectory); if (hRomFile == INVALID_HANDLE_VALUE) return NULL; hMap = CreateFileMapping(hFile, NULL, PAGE_WRITECOPY, 0, 0, NULL); if (hMap == NULL) { CloseHandle(hFile); return NULL; } pbyFile = MapViewOfFile(hMap, FILE_MAP_COPY, 0, 0, 0); if (pbyFile == NULL) { CloseHandle(hMap); CloseHandle(hFile); return NULL; } hBitmap = NULL; pBmfh = (LPBITMAPFILEHEADER)pbyFile; if (pBmfh->bfType != 0x4D42) goto quit; // "BM" pBmi = (LPBITMAPINFO)(pbyFile+sizeof(BITMAPFILEHEADER)); hPalette = CreateBIPalette(&pBmi->bmiHeader); SelectPalette(hWindowDC, hPalette, FALSE); RealizePalette(hWindowDC); if (FALSE&&(pBmi->bmiHeader.biBitCount <= 8)) { UINT i; LPDWORD pdwTable = ((LPDWORD)&(pBmi->bmiColors[0])); if (pBmi->bmiHeader.biClrUsed) for (i=0; i<(UINT)pBmi->bmiHeader.biClrUsed; i++) pdwTable[i]=i; else for (i=0; i<256; i++) pdwTable[i]=i; hBitmap = CreateDIBitmap( hWindowDC, &pBmi->bmiHeader, CBM_INIT, pbyFile+pBmfh->bfOffBits, pBmi, DIB_PAL_COLORS); } else { hBitmap = CreateDIBitmap( hWindowDC, &pBmi->bmiHeader, CBM_INIT, pbyFile+pBmfh->bfOffBits, pBmi, DIB_RGB_COLORS); } quit: UnmapViewOfFile(pbyFile); CloseHandle(hMap); CloseHandle(hFile); return hBitmap; }