emu48-mirror/Emu48/files.c

1103 lines
26 KiB
C
Raw Normal View History

/*
* 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<dwFileSizeLow; i++)
{
BYTE byTwoNibs = lpBuf[i+dwFileSizeLow];
lpBuf[i*2 ] = (BYTE)(byTwoNibs&0xF);
lpBuf[i*2+1] = (BYTE)(byTwoNibs>>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; i<dwLength; i++)
{
Nwrite(lpBuf+i+16, dwAddress+i, 1);
}
}
else
{ // load as string
BYTE lpHead[5];
dwLength = dwFileSizeLow*2;
dwAddress = RPL_CreateTemp(dwLength+10);
if (dwAddress == 0)
{
LocalFree(lpBuf);
AbortMessage("The HP48 has not enough free memory left to load this text file.");
return FALSE;
}
Nunpack(lpHead,0x02A2C,5);
Nwrite(lpHead,dwAddress,5);
Nunpack(lpHead,dwLength+5,5);
Nwrite(lpHead,dwAddress+5,5);
for (i=0; i<dwLength; i++)
{
Nwrite(lpBuf+i, dwAddress+10+i, 1);
}
}
RPL_Push(dwAddress);
LocalFree(lpBuf);
return TRUE;
}
BOOL SaveObject(LPCSTR szFilename)
{
HANDLE hFile;
DWORD lBytesWritten;
DWORD dwAddress;
DWORD dwLength;
dwAddress = RPL_Pick(1);
if (dwAddress == 0)
{
AbortMessage("Too Few Arguments.");
return FALSE;
}
dwLength = (RPL_SkipOb(dwAddress) - dwAddress + 1) / 2;
hFile = CreateFile(szFilename, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_FLAG_SEQUENTIAL_SCAN, NULL);
if (hFile == INVALID_HANDLE_VALUE)
{
AbortMessage("Cannot open file.");
return FALSE;
}
WriteFile(hFile, "HPHP48-W", 8, &lBytesWritten, NULL);
while (dwLength--)
{
BYTE byByte = Read2(dwAddress);
WriteFile(hFile, &byByte, 1, &lBytesWritten, NULL);
dwAddress += 2;
}
CloseHandle(hFile);
return TRUE;
}
//################
//#
//# Load Bitmap
//#
//################
static UINT DibNumColors (LPBITMAPINFOHEADER lpbi)
{
UINT bits;
if (lpbi->biClrUsed != 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;
}