2024-03-19 22:22:29 +01:00
|
|
|
/*
|
|
|
|
* 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;
|
2024-03-19 22:24:30 +01:00
|
|
|
DWORD dwPort2Size = 0; // 26.06.98 cg, new, size of mapped port2
|
2024-03-19 22:22:29 +01:00
|
|
|
DWORD dwPort2Mask = 0;
|
2024-03-19 22:24:30 +01:00
|
|
|
// UINT nPort2Bank = 0; // 15.12.98 cg, removed, not used any more
|
2024-03-19 22:22:29 +01:00
|
|
|
|
|
|
|
static BYTE pbySignatureE[16] = "Emu48 Document\xFE";
|
|
|
|
static BYTE pbySignatureW[16] = "Win48 Document\xFE";
|
|
|
|
static HANDLE hCurrentFile = NULL;
|
|
|
|
|
|
|
|
static CHIPSET BackupChipset;
|
|
|
|
BOOL bBackup = FALSE;
|
|
|
|
|
2024-03-19 22:24:30 +01:00
|
|
|
//################
|
|
|
|
//#
|
|
|
|
//# Subroutine for Write on Stack
|
|
|
|
//#
|
|
|
|
//################
|
|
|
|
|
|
|
|
WORD WriteStack(LPBYTE lpBuf,DWORD dwSize) // 11.05.98 cg, new, separated from LoadObject()
|
|
|
|
{
|
|
|
|
BOOL bBinary;
|
|
|
|
DWORD dwLength, dwAddress, i;
|
|
|
|
|
|
|
|
bBinary = ((lpBuf[dwSize+0]=='H')
|
|
|
|
&& (lpBuf[dwSize+1]=='P')
|
|
|
|
&& (lpBuf[dwSize+2]=='H')
|
|
|
|
&& (lpBuf[dwSize+3]=='P')
|
|
|
|
&& (lpBuf[dwSize+4]=='4')
|
|
|
|
&& (lpBuf[dwSize+5]=='8')
|
|
|
|
&& (lpBuf[dwSize+6]=='-'));
|
|
|
|
|
|
|
|
for (i=0; i<dwSize; i++)
|
|
|
|
{
|
|
|
|
BYTE byTwoNibs = lpBuf[i+dwSize];
|
|
|
|
lpBuf[i*2 ] = (BYTE)(byTwoNibs&0xF);
|
|
|
|
lpBuf[i*2+1] = (BYTE)(byTwoNibs>>4);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (bBinary == TRUE)
|
|
|
|
{ // load as binary
|
|
|
|
dwLength = RPL_ObjectSize(lpBuf+16);
|
|
|
|
dwAddress = RPL_CreateTemp(dwLength);
|
|
|
|
if (dwAddress == 0) return S_ERR_BINARY;
|
|
|
|
|
|
|
|
// 23.05.98 cg, optimized
|
|
|
|
Nwrite(lpBuf+16, dwAddress, dwLength);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{ // load as string
|
|
|
|
BYTE lpHead[5];
|
|
|
|
dwLength = dwSize*2;
|
|
|
|
dwAddress = RPL_CreateTemp(dwLength+10);
|
|
|
|
if (dwAddress == 0) return S_ERR_ASCII;
|
|
|
|
|
|
|
|
Nunpack(lpHead,0x02A2C,5);
|
|
|
|
Nwrite(lpHead,dwAddress,5);
|
|
|
|
Nunpack(lpHead,dwLength+5,5);
|
|
|
|
Nwrite(lpHead,dwAddress+5,5);
|
|
|
|
// 23.05.98 cg, optimized
|
|
|
|
Nwrite(lpBuf, dwAddress+10, dwLength);
|
|
|
|
}
|
|
|
|
RPL_Push(dwAddress);
|
|
|
|
return S_ERR_NO;
|
|
|
|
}
|
|
|
|
|
2024-03-19 22:22:29 +01:00
|
|
|
|
|
|
|
|
|
|
|
//################
|
|
|
|
//#
|
|
|
|
//# 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
|
|
|
|
//#
|
|
|
|
//################
|
|
|
|
|
2024-03-19 22:24:30 +01:00
|
|
|
static WORD CrcPort2(VOID) // 20.02.99 cg, new, calculate fingerprint of port2
|
|
|
|
{
|
|
|
|
DWORD dwCount;
|
|
|
|
DWORD dwFileSize;
|
|
|
|
WORD wCrc = 0;
|
|
|
|
|
|
|
|
if (pbyPort2==NULL) return wCrc; // port2 isn't available
|
|
|
|
dwFileSize = GetFileSize(hPort2File, &dwCount); // get real filesize
|
|
|
|
_ASSERT(dwCount == 0); // isn't created by MapPort2()
|
|
|
|
|
|
|
|
for (dwCount = 0;dwCount < dwFileSize; ++dwCount)
|
|
|
|
wCrc = (wCrc >> 4) ^ (((wCrc ^ ((WORD) pbyPort2[dwCount])) & 0xf) * 0x1081);
|
|
|
|
return wCrc;
|
|
|
|
}
|
|
|
|
|
2024-03-19 22:22:29 +01:00
|
|
|
BOOL MapPort2(LPCSTR szFilename)
|
|
|
|
{
|
|
|
|
DWORD dwFileSizeLo;
|
|
|
|
DWORD dwFileSizeHi;
|
|
|
|
|
|
|
|
if (pbyPort2 != NULL)
|
|
|
|
{
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
bPort2Writeable = TRUE;
|
2024-03-19 22:24:30 +01:00
|
|
|
dwPort2Size = 0; // 26.06.98 cg, new, reset size of port2
|
2024-03-19 22:22:29 +01:00
|
|
|
|
|
|
|
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;
|
|
|
|
}
|
2024-03-19 22:24:30 +01:00
|
|
|
dwPort2Mask = (dwFileSizeLo >> 17) - 1; // 26.06,98 cg, optimized, calculate bank switching mask
|
2024-03-19 22:22:29 +01:00
|
|
|
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;
|
|
|
|
}
|
2024-03-19 22:24:30 +01:00
|
|
|
dwPort2Size = dwFileSizeLo / 2048; // 26.06.98 cg, new, mapping size of port2
|
|
|
|
if (dwPort2Size > 128) dwPort2Size = 128;
|
2024-03-19 22:22:29 +01:00
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
VOID UnmapPort2()
|
|
|
|
{
|
|
|
|
if (pbyPort2==NULL) return;
|
|
|
|
UnmapViewOfFile(pbyPort2);
|
|
|
|
CloseHandle(hPort2Map);
|
|
|
|
CloseHandle(hPort2File);
|
|
|
|
pbyPort2 = NULL;
|
|
|
|
hPort2Map = NULL;
|
|
|
|
hPort2File = NULL;
|
2024-03-19 22:24:30 +01:00
|
|
|
dwPort2Size = 0; // 26.06.98 cg, new, reset size of port2
|
2024-03-19 22:22:29 +01:00
|
|
|
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;
|
|
|
|
|
2024-03-19 22:24:30 +01:00
|
|
|
// 26.01.98 cg, bugfix, WORD to int conversation failed with negative numbers
|
|
|
|
SetWindowPos(hWnd,NULL,(short)Chipset.wPosX,(short)Chipset.wPosY,0,0,SWP_NOSIZE|SWP_NOZORDER|SWP_NOACTIVATE);
|
2024-03-19 22:22:29 +01:00
|
|
|
|
|
|
|
if (szCurrentKml == NULL)
|
|
|
|
{
|
|
|
|
if (!DisplayChooseKml(Chipset.type))
|
|
|
|
{
|
2024-03-19 22:24:30 +01:00
|
|
|
// CloseHandle(hFile); // 29.01.98 cg, bugfix, will be close at end of function
|
2024-03-19 22:22:29 +01:00
|
|
|
goto restore;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
while (!InitKML(szCurrentKml,FALSE))
|
|
|
|
{
|
|
|
|
if (!DisplayChooseKml(Chipset.type))
|
|
|
|
{
|
2024-03-19 22:24:30 +01:00
|
|
|
// CloseHandle(hFile); // 29.01.98 cg, bugfix, will be close at end of function
|
2024-03-19 22:22:29 +01:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2024-03-19 22:24:30 +01:00
|
|
|
if (Chipset.wPort2Crc != CrcPort2()) // 21.02.99 cg, new, port2 changed
|
|
|
|
{
|
|
|
|
Chipset.HST |= 8; // 21.02.99 cg, new, set Module Pulled
|
|
|
|
Chipset.SoftInt = TRUE; // 21.02.99 cg, new, set interrupt
|
|
|
|
bInterrupt = TRUE; // 21.02.99 cg, new
|
|
|
|
}
|
|
|
|
|
2024-03-19 22:22:29 +01:00
|
|
|
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:
|
2024-03-19 22:24:30 +01:00
|
|
|
if (INVALID_HANDLE_VALUE != hFile) // 29.01.98 cg, bugfix, close if valid handle
|
2024-03-19 22:22:29 +01:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2024-03-19 22:24:30 +01:00
|
|
|
Chipset.wPort2Crc = CrcPort2(); // 21.02.99 cg, new, save fingerprint of port2
|
|
|
|
|
2024-03-19 22:22:29 +01:00
|
|
|
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;
|
|
|
|
|
2024-03-19 22:24:30 +01:00
|
|
|
if (hCurrentFile) // already file in use
|
2024-03-19 22:22:29 +01:00
|
|
|
{
|
|
|
|
if (lstrcmpi(szFilename, szCurrentFilename)==0)
|
|
|
|
{
|
2024-03-19 22:24:30 +01:00
|
|
|
hFile = hCurrentFile; // same file, do not open a new one
|
2024-03-19 22:22:29 +01:00
|
|
|
}
|
|
|
|
}
|
2024-03-19 22:24:30 +01:00
|
|
|
if (hFile == INVALID_HANDLE_VALUE) // not same file, open a new one
|
2024-03-19 22:22:29 +01:00
|
|
|
{
|
|
|
|
hFile = CreateFile(szFilename, GENERIC_READ|GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_ALWAYS, 0, NULL);
|
|
|
|
}
|
2024-03-19 22:24:30 +01:00
|
|
|
if (hFile == INVALID_HANDLE_VALUE) // error, couldn't create a new file
|
2024-03-19 22:22:29 +01:00
|
|
|
{
|
|
|
|
AbortMessage("This file must be currently used by another instance of Emu48.");
|
|
|
|
return FALSE;
|
|
|
|
}
|
2024-03-19 22:24:30 +01:00
|
|
|
if (hCurrentFile) // 02.10.98 cg, previous file in use
|
|
|
|
{
|
|
|
|
CloseHandle(hCurrentFile); // 02.10.98 cg, bugfix, close it
|
|
|
|
}
|
|
|
|
lstrcpy(szCurrentFilename, szFilename); // save new file name
|
|
|
|
hCurrentFile = hFile; // and the corresponding handle
|
|
|
|
SetWindowTitle(szCurrentFilename); // update window title line
|
|
|
|
UpdateWindowStatus(); // and draw it
|
|
|
|
return SaveDocument(); // save current content
|
2024-03-19 22:22:29 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//################
|
|
|
|
//#
|
|
|
|
//# 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();
|
2024-03-19 22:24:30 +01:00
|
|
|
// 02.02.98 cg, moved, need chipset for contrast setting in InitKML()
|
|
|
|
CopyMemory(&Chipset, &BackupChipset, sizeof(Chipset));
|
2024-03-19 22:22:29 +01:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
}
|
2024-03-19 22:24:30 +01:00
|
|
|
// 02.02.98 cg, removed, done before
|
|
|
|
// CopyMemory(&Chipset, &BackupChipset, sizeof(Chipset));
|
2024-03-19 22:22:29 +01:00
|
|
|
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
|
|
|
|
//#
|
|
|
|
//################
|
|
|
|
|
2024-03-19 22:24:30 +01:00
|
|
|
BOOL LoadObject(LPCSTR szFilename) // 11.05.98 cg, changed, separated stack writing part
|
2024-03-19 22:22:29 +01:00
|
|
|
{
|
|
|
|
HANDLE hFile;
|
|
|
|
DWORD dwFileSizeLow;
|
|
|
|
DWORD dwFileSizeHigh;
|
|
|
|
LPBYTE lpBuf;
|
2024-03-19 22:24:30 +01:00
|
|
|
WORD wError;
|
2024-03-19 22:22:29 +01:00
|
|
|
|
|
|
|
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;
|
|
|
|
}
|
2024-03-19 22:24:30 +01:00
|
|
|
ReadFile(hFile, lpBuf+dwFileSizeLow, dwFileSizeLow, &dwFileSizeHigh, NULL);
|
2024-03-19 22:22:29 +01:00
|
|
|
CloseHandle(hFile);
|
|
|
|
|
2024-03-19 22:24:30 +01:00
|
|
|
wError = WriteStack(lpBuf,dwFileSizeLow);
|
2024-03-19 22:22:29 +01:00
|
|
|
|
2024-03-19 22:24:30 +01:00
|
|
|
if (wError == S_ERR_BINARY)
|
|
|
|
AbortMessage("The HP48 has not enough free memory left to load this binary file.");
|
|
|
|
|
|
|
|
if (wError == S_ERR_ASCII)
|
|
|
|
AbortMessage("The HP48 has not enough free memory left to load this text file.");
|
2024-03-19 22:22:29 +01:00
|
|
|
|
|
|
|
LocalFree(lpBuf);
|
2024-03-19 22:24:30 +01:00
|
|
|
return (wError == S_ERR_NO);
|
2024-03-19 22:22:29 +01:00
|
|
|
}
|
|
|
|
|
2024-03-19 22:24:30 +01:00
|
|
|
BOOL SaveObject(LPCSTR szFilename) // 11.05.98 cg, changed, separated stack reading part
|
2024-03-19 22:22:29 +01:00
|
|
|
{
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2024-03-19 22:24:30 +01:00
|
|
|
WriteFile(hFile, BINARYHEADER, 8, &lBytesWritten, NULL);
|
2024-03-19 22:22:29 +01:00
|
|
|
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;
|
|
|
|
|
2024-03-19 22:24:30 +01:00
|
|
|
if (hRomFile == NULL) return NULL; // 17.10.97 cg, bugfix, line moved and error case is NULL
|
2024-03-19 22:22:29 +01:00
|
|
|
SetCurrentDirectory(szEmu48Directory);
|
|
|
|
hFile = CreateFile(szFilename, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
|
|
|
|
SetCurrentDirectory(szCurrentDirectory);
|
2024-03-19 22:24:30 +01:00
|
|
|
// 19.01.98 cg, bugfix, opend with GENERIC_READ -> PAGE_READONLY
|
|
|
|
hMap = CreateFileMapping(hFile, NULL, PAGE_READONLY, 0, 0, NULL);
|
2024-03-19 22:22:29 +01:00
|
|
|
if (hMap == NULL)
|
|
|
|
{
|
|
|
|
CloseHandle(hFile);
|
|
|
|
return NULL;
|
|
|
|
}
|
2024-03-19 22:24:30 +01:00
|
|
|
// 19.01.98 cg, bugfix, opend with GENERIC_READ -> PAGE_READONLY -> FILE_MAP_READ
|
|
|
|
pbyFile = MapViewOfFile(hMap, FILE_MAP_READ, 0, 0, 0);
|
2024-03-19 22:22:29 +01:00
|
|
|
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));
|
|
|
|
|
2024-03-19 22:24:30 +01:00
|
|
|
_ASSERT(hPalette == NULL); // 11.09.98 cg, resource free
|
2024-03-19 22:22:29 +01:00
|
|
|
hPalette = CreateBIPalette(&pBmi->bmiHeader);
|
2024-03-19 22:24:30 +01:00
|
|
|
// 11.09.98 cg, save old palette
|
|
|
|
hOldPalette = SelectPalette(hWindowDC, hPalette, FALSE);
|
2024-03-19 22:22:29 +01:00
|
|
|
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;
|
|
|
|
}
|