mirror of
https://github.com/dgis/emu48android
synced 2024-12-26 09:58:49 +01:00
This commit is contained in:
parent
f27ee86714
commit
93cb73b0f9
3 changed files with 906 additions and 114 deletions
746
app/src/main/cpp/android-display.c
Normal file
746
app/src/main/cpp/android-display.c
Normal file
|
@ -0,0 +1,746 @@
|
||||||
|
/*
|
||||||
|
* display.c
|
||||||
|
*
|
||||||
|
* This file is part of Emu48
|
||||||
|
*
|
||||||
|
* Copyright (C) 1995 Sebastien Carlier
|
||||||
|
* Copyright (C) 2002 Christoph Gießelink
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
#include "pch.h"
|
||||||
|
#include "resource.h"
|
||||||
|
#include "Emu48.h"
|
||||||
|
#include "io.h"
|
||||||
|
#include "kml.h"
|
||||||
|
|
||||||
|
// #define DEBUG_DISPLAY // switch for DISPLAY debug purpose
|
||||||
|
|
||||||
|
#define NOCOLORSGRAY 8 // no. of colors in gray scale mode
|
||||||
|
#define NOCOLORSBW 2 // no. of colors in black and white mode
|
||||||
|
|
||||||
|
#define DISPLAY_FREQ 19 // display update 1/frequency (1/64) in ms (gray scale mode)
|
||||||
|
|
||||||
|
#define B 0x00000000 // black
|
||||||
|
#define W 0x00FFFFFF // white
|
||||||
|
#define I 0xFFFFFFFF // ignore
|
||||||
|
|
||||||
|
#define LCD_ROW (36*4) // max. pixel per line
|
||||||
|
|
||||||
|
#define GRAYMASK(c) (((((c)-1)>>1)<<24) \
|
||||||
|
|((((c)-1)>>1)<<16) \
|
||||||
|
|((((c)-1)>>1)<<8) \
|
||||||
|
|((((c)-1)>>1)))
|
||||||
|
|
||||||
|
#define DIBPIXEL4(d,p) *((DWORD*)(d)) = ((*((DWORD*)(d)) & dwGrayMask) << 1) | (p); \
|
||||||
|
*((LPBYTE*) &(d)) += 4
|
||||||
|
|
||||||
|
BOOL bGrayscale = FALSE;
|
||||||
|
UINT nBackgroundX = 0;
|
||||||
|
UINT nBackgroundY = 0;
|
||||||
|
UINT nBackgroundW = 0;
|
||||||
|
UINT nBackgroundH = 0;
|
||||||
|
UINT nLcdX = 0;
|
||||||
|
UINT nLcdY = 0;
|
||||||
|
UINT nLcdZoom = 1; // memory DC zoom
|
||||||
|
UINT nGdiXZoom = 1; // GDI x zoom
|
||||||
|
UINT nGdiYZoom = 1; // GDI y zoom
|
||||||
|
HDC hLcdDC = NULL;
|
||||||
|
HDC hMainDC = NULL;
|
||||||
|
HDC hAnnunDC = NULL; // annunciator DC
|
||||||
|
|
||||||
|
BYTE (*GetLineCounter)(VOID) = NULL;
|
||||||
|
VOID (*StartDisplay)(BYTE byInitial) = NULL;
|
||||||
|
VOID (*StopDisplay)(VOID) = NULL;
|
||||||
|
|
||||||
|
static BYTE GetLineCounterGray(VOID);
|
||||||
|
static BYTE GetLineCounterBW(VOID);
|
||||||
|
static VOID StartDisplayGray(BYTE byInitial);
|
||||||
|
static VOID StartDisplayBW(BYTE byInitial);
|
||||||
|
static VOID StopDisplayGray(VOID);
|
||||||
|
static VOID StopDisplayBW(VOID);
|
||||||
|
|
||||||
|
static LPBYTE pbyLcd;
|
||||||
|
|
||||||
|
static HBITMAP hLcdBitmap;
|
||||||
|
static HBITMAP hMainBitmap;
|
||||||
|
static HBITMAP hAnnunBitmap;
|
||||||
|
|
||||||
|
static DWORD Pattern[16];
|
||||||
|
static BYTE Buf[36];
|
||||||
|
|
||||||
|
static DWORD dwGrayMask;
|
||||||
|
|
||||||
|
static LARGE_INTEGER lLcdRef; // reference time for VBL counter
|
||||||
|
static UINT uLcdTimerId = 0;
|
||||||
|
|
||||||
|
static BYTE byVblRef = 0; // VBL stop reference
|
||||||
|
|
||||||
|
static DWORD dwKMLColor[64] = // color table loaded by KML script
|
||||||
|
{
|
||||||
|
W,B,B,B,B,B,B,B,B,B,B,B,B,B,B,B,
|
||||||
|
B,B,B,B,B,B,B,B,B,B,B,B,B,B,B,B,
|
||||||
|
I,I,I,I,I,I,I,I,I,I,I,I,I,I,I,I,
|
||||||
|
I,I,I,I,I,I,I,I,I,I,I,I,I,I,I,I
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct
|
||||||
|
{
|
||||||
|
BITMAPINFOHEADER Lcd_bmih;
|
||||||
|
RGBQUAD bmiColors[NOCOLORSGRAY];
|
||||||
|
} bmiLcd =
|
||||||
|
{
|
||||||
|
{0x28,0/*x*/,0/*y*/,1,8,BI_RGB,0,0,0,NOCOLORSGRAY,0}
|
||||||
|
};
|
||||||
|
|
||||||
|
static __inline VOID BuildPattern(VOID)
|
||||||
|
{
|
||||||
|
WORD i,j;
|
||||||
|
for (i=0; i<16; ++i)
|
||||||
|
{
|
||||||
|
Pattern[i] = 0;
|
||||||
|
for (j=8; j>0; j>>=1)
|
||||||
|
{
|
||||||
|
Pattern[i] = (Pattern[i] << 8) | ((i&j) != 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
VOID UpdateContrast(BYTE byContrast)
|
||||||
|
{
|
||||||
|
RGBQUAD c,b;
|
||||||
|
INT i,nColors;
|
||||||
|
|
||||||
|
// table for max. 8 colors
|
||||||
|
const INT nCAdj[] = { 0, 1, 1, 2, 1, 2, 2, 3 };
|
||||||
|
|
||||||
|
// when display is off use contrast 0
|
||||||
|
if ((Chipset.IORam[BITOFFSET] & DON) == 0) byContrast = 0;
|
||||||
|
|
||||||
|
c = *(RGBQUAD*)&dwKMLColor[byContrast]; // pixel on color
|
||||||
|
b = *(RGBQUAD*)&dwKMLColor[byContrast+32]; // pixel off color
|
||||||
|
|
||||||
|
// if background color is undefined, use color 0 for compatibility
|
||||||
|
if (I == *(DWORD*)&b) b = *(RGBQUAD*)&dwKMLColor[0];
|
||||||
|
|
||||||
|
nColors = bGrayscale ? (NOCOLORSGRAY-1) : (NOCOLORSBW-1);
|
||||||
|
|
||||||
|
_ASSERT(nColors <= ARRAYSIZEOF(nCAdj)); // no. of colors must be smaller than entries in the gray color table
|
||||||
|
|
||||||
|
// fill color palette of bitmap
|
||||||
|
for (i = 0; i <= nColors; ++i)
|
||||||
|
{
|
||||||
|
bmiLcd.bmiColors[i] = b;
|
||||||
|
bmiLcd.bmiColors[i].rgbRed += ((INT) c.rgbRed - (INT) b.rgbRed) * nCAdj[i] / nCAdj[nColors];
|
||||||
|
bmiLcd.bmiColors[i].rgbGreen += ((INT) c.rgbGreen - (INT) b.rgbGreen) * nCAdj[i] / nCAdj[nColors];
|
||||||
|
bmiLcd.bmiColors[i].rgbBlue += ((INT) c.rgbBlue - (INT) b.rgbBlue) * nCAdj[i] / nCAdj[nColors];
|
||||||
|
}
|
||||||
|
|
||||||
|
// update palette information
|
||||||
|
_ASSERT(hLcdDC);
|
||||||
|
SetDIBColorTable(hLcdDC,0,ARRAYSIZEOF(bmiLcd.bmiColors),bmiLcd.bmiColors);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
VOID SetLcdColor(UINT nId, UINT nRed, UINT nGreen, UINT nBlue)
|
||||||
|
{
|
||||||
|
dwKMLColor[nId&0x3F] = ((nRed&0xFF)<<16)|((nGreen&0xFF)<<8)|(nBlue&0xFF);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
VOID SetLcdMode(BOOL bMode)
|
||||||
|
{
|
||||||
|
if ((bGrayscale = bMode))
|
||||||
|
{
|
||||||
|
// set pixel update mask
|
||||||
|
dwGrayMask = GRAYMASK(NOCOLORSGRAY);
|
||||||
|
GetLineCounter = GetLineCounterGray;
|
||||||
|
StartDisplay = StartDisplayGray;
|
||||||
|
StopDisplay = StopDisplayGray;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// set pixel update mask
|
||||||
|
dwGrayMask = GRAYMASK(NOCOLORSBW);
|
||||||
|
GetLineCounter = GetLineCounterBW;
|
||||||
|
StartDisplay = StartDisplayBW;
|
||||||
|
StopDisplay = StopDisplayBW;
|
||||||
|
}
|
||||||
|
UpdateContrast(Chipset.contrast);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
VOID CreateLcdBitmap(VOID)
|
||||||
|
{
|
||||||
|
// create LCD bitmap
|
||||||
|
bmiLcd.Lcd_bmih.biWidth = LCD_ROW;
|
||||||
|
bmiLcd.Lcd_bmih.biHeight = -SCREENHEIGHT; // CdB for HP: add 64/80 line display for apples
|
||||||
|
_ASSERT(hLcdDC == NULL);
|
||||||
|
VERIFY(hLcdDC = CreateCompatibleDC(hWindowDC));
|
||||||
|
VERIFY(hLcdBitmap = CreateDIBSection(hWindowDC,(BITMAPINFO*)&bmiLcd,DIB_RGB_COLORS,(VOID **)&pbyLcd,NULL,0));
|
||||||
|
hLcdBitmap = (HBITMAP) SelectObject(hLcdDC,hLcdBitmap);
|
||||||
|
_ASSERT(hPalette != NULL);
|
||||||
|
SelectPalette(hLcdDC,hPalette,FALSE); // set palette for LCD DC
|
||||||
|
RealizePalette(hLcdDC); // realize palette
|
||||||
|
BuildPattern(); // build Nibble -> DIB mask pattern
|
||||||
|
SetLcdMode(bGrayscale); // init display update function pointer
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
VOID DestroyLcdBitmap(VOID)
|
||||||
|
{
|
||||||
|
// set contrast palette to startup colors
|
||||||
|
WORD i = 0; dwKMLColor[i++] = W;
|
||||||
|
while (i < 32) dwKMLColor[i++] = B;
|
||||||
|
while (i < 64) dwKMLColor[i++] = I;
|
||||||
|
|
||||||
|
GetLineCounter = NULL;
|
||||||
|
StartDisplay = NULL;
|
||||||
|
StopDisplay = NULL;
|
||||||
|
|
||||||
|
if (hLcdDC != NULL)
|
||||||
|
{
|
||||||
|
// destroy LCD bitmap
|
||||||
|
DeleteObject(SelectObject(hLcdDC,hLcdBitmap));
|
||||||
|
DeleteDC(hLcdDC);
|
||||||
|
hLcdDC = NULL;
|
||||||
|
hLcdBitmap = NULL;
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOL CreateMainBitmap(LPCTSTR szFilename)
|
||||||
|
{
|
||||||
|
_ASSERT(hWindowDC != NULL);
|
||||||
|
VERIFY(hMainDC = CreateCompatibleDC(hWindowDC));
|
||||||
|
if (hMainDC == NULL) return FALSE; // quit if failed
|
||||||
|
hMainBitmap = LoadBitmapFile(szFilename);
|
||||||
|
if (hMainBitmap == NULL)
|
||||||
|
{
|
||||||
|
DeleteDC(hMainDC);
|
||||||
|
hMainDC = NULL;
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
hMainBitmap = (HBITMAP) SelectObject(hMainDC,hMainBitmap);
|
||||||
|
_ASSERT(hPalette != NULL);
|
||||||
|
VERIFY(SelectPalette(hMainDC,hPalette,FALSE));
|
||||||
|
RealizePalette(hMainDC);
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
VOID DestroyMainBitmap(VOID)
|
||||||
|
{
|
||||||
|
if (hMainDC != NULL)
|
||||||
|
{
|
||||||
|
// destroy Main bitmap
|
||||||
|
DeleteObject(SelectObject(hMainDC,hMainBitmap));
|
||||||
|
DeleteDC(hMainDC);
|
||||||
|
hMainDC = NULL;
|
||||||
|
hMainBitmap = NULL;
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// load annunciator bitmap
|
||||||
|
//
|
||||||
|
BOOL CreateAnnunBitmap(LPCTSTR szFilename)
|
||||||
|
{
|
||||||
|
_ASSERT(hWindowDC != NULL);
|
||||||
|
VERIFY(hAnnunDC = CreateCompatibleDC(hWindowDC));
|
||||||
|
if (hAnnunDC == NULL) return FALSE; // quit if failed
|
||||||
|
hAnnunBitmap = LoadBitmapFile(szFilename);
|
||||||
|
if (hAnnunBitmap == NULL)
|
||||||
|
{
|
||||||
|
DeleteDC(hAnnunDC);
|
||||||
|
hAnnunDC = NULL;
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
hAnnunBitmap = (HBITMAP) SelectObject(hAnnunDC,hAnnunBitmap);
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// destroy annunciator bitmap
|
||||||
|
//
|
||||||
|
VOID DestroyAnnunBitmap(VOID)
|
||||||
|
{
|
||||||
|
if (hAnnunDC != NULL)
|
||||||
|
{
|
||||||
|
VERIFY(DeleteObject(SelectObject(hAnnunDC,hAnnunBitmap)));
|
||||||
|
DeleteDC(hAnnunDC);
|
||||||
|
hAnnunDC = NULL;
|
||||||
|
hAnnunBitmap = NULL;
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
//****************
|
||||||
|
//*
|
||||||
|
//* LCD functions
|
||||||
|
//*
|
||||||
|
//****************
|
||||||
|
|
||||||
|
VOID UpdateDisplayPointers(VOID)
|
||||||
|
{
|
||||||
|
EnterCriticalSection(&csLcdLock);
|
||||||
|
{
|
||||||
|
#if defined DEBUG_DISPLAY
|
||||||
|
{
|
||||||
|
TCHAR buffer[256];
|
||||||
|
wsprintf(buffer,_T("%.5lx: Update Display Pointer\n"),Chipset.pc);
|
||||||
|
OutputDebugString(buffer);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// calculate display width
|
||||||
|
Chipset.width = (34 + Chipset.loffset + (Chipset.boffset / 4) * 2) & 0xFFFFFFFE;
|
||||||
|
Chipset.end1 = Chipset.start1 + MAINSCREENHEIGHT * Chipset.width;
|
||||||
|
if (Chipset.end1 < Chipset.start1)
|
||||||
|
{
|
||||||
|
// calculate first address of main display
|
||||||
|
Chipset.start12 = Chipset.end1 - Chipset.width;
|
||||||
|
// calculate last address of main display
|
||||||
|
Chipset.end1 = Chipset.start1 - Chipset.width;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Chipset.start12 = Chipset.start1;
|
||||||
|
}
|
||||||
|
Chipset.end2 = Chipset.start2 + MENUHEIGHT * 34;
|
||||||
|
}
|
||||||
|
LeaveCriticalSection(&csLcdLock);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
VOID UpdateMainDisplay(VOID)
|
||||||
|
{
|
||||||
|
UINT x, y;
|
||||||
|
BYTE *p = pbyLcd+(Chipset.d0size*LCD_ROW); // CdB for HP: add 64/80 line display for apples
|
||||||
|
DWORD d = Chipset.start1;
|
||||||
|
|
||||||
|
#if defined DEBUG_DISPLAY
|
||||||
|
{
|
||||||
|
TCHAR buffer[256];
|
||||||
|
wsprintf(buffer,_T("%.5lx: Update Main Display\n"),Chipset.pc);
|
||||||
|
OutputDebugString(buffer);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (!(Chipset.IORam[BITOFFSET]&DON))
|
||||||
|
{
|
||||||
|
ZeroMemory(pbyLcd, LCD_ROW * SCREENHEIGHT);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
for (y = 0; y < MAINSCREENHEIGHT; ++y)
|
||||||
|
{
|
||||||
|
Npeek(Buf,d,36);
|
||||||
|
for (x=0; x<36; ++x) // every 4 pixel
|
||||||
|
{
|
||||||
|
DIBPIXEL4(p,Pattern[Buf[x]]);
|
||||||
|
// check for display buffer overflow
|
||||||
|
_ASSERT(p <= pbyLcd + LCD_ROW * SCREENHEIGHT);
|
||||||
|
}
|
||||||
|
d+=Chipset.width;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
EnterCriticalSection(&csGDILock); // solving NT GDI problems
|
||||||
|
{
|
||||||
|
// CdB for HP: add 64/80 line display for apples
|
||||||
|
StretchBlt(hWindowDC, nLcdX, nLcdY+Chipset.d0size*nLcdZoom, 131*nLcdZoom*nGdiXZoom, MAINSCREENHEIGHT*nLcdZoom*nGdiYZoom,
|
||||||
|
hLcdDC, Chipset.boffset, Chipset.d0size, 131, MAINSCREENHEIGHT, SRCCOPY);
|
||||||
|
GdiFlush();
|
||||||
|
}
|
||||||
|
LeaveCriticalSection(&csGDILock);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
VOID UpdateMenuDisplay(VOID)
|
||||||
|
{
|
||||||
|
UINT x, y;
|
||||||
|
BYTE *p;
|
||||||
|
DWORD d = Chipset.start2;
|
||||||
|
|
||||||
|
#if defined DEBUG_DISPLAY
|
||||||
|
{
|
||||||
|
TCHAR buffer[256];
|
||||||
|
wsprintf(buffer,_T("%.5lx: Update Menu Display\n"),Chipset.pc);
|
||||||
|
OutputDebugString(buffer);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (!(Chipset.IORam[BITOFFSET]&DON)) return;
|
||||||
|
if (MENUHEIGHT==0) return; // menu disabled
|
||||||
|
|
||||||
|
// calculate bitmap offset
|
||||||
|
p = pbyLcd + ((Chipset.d0size+MAINSCREENHEIGHT)*LCD_ROW); // CdB for HP: add 64/80 line display for apples
|
||||||
|
for (y = 0; y < MENUHEIGHT; ++y)
|
||||||
|
{
|
||||||
|
Npeek(Buf,d,34); // 34 nibbles are viewed
|
||||||
|
for (x=0; x<34; ++x) // every 4 pixel
|
||||||
|
{
|
||||||
|
DIBPIXEL4(p,Pattern[Buf[x]]);
|
||||||
|
// check for display buffer overflow
|
||||||
|
_ASSERT(p <= pbyLcd + LCD_ROW * SCREENHEIGHT);
|
||||||
|
}
|
||||||
|
// adjust pointer to 36 DIBPIXEL drawing calls
|
||||||
|
p += (36-34) * sizeof(DWORD);
|
||||||
|
d+=34;
|
||||||
|
}
|
||||||
|
EnterCriticalSection(&csGDILock); // solving NT GDI problems
|
||||||
|
{
|
||||||
|
// CdB for HP: add 64/80 line display for apples
|
||||||
|
StretchBlt(hWindowDC,
|
||||||
|
nLcdX, nLcdY+(MAINSCREENHEIGHT+Chipset.d0size)*nLcdZoom*nGdiYZoom,
|
||||||
|
131*nLcdZoom*nGdiXZoom, MENUHEIGHT*nLcdZoom*nGdiYZoom,
|
||||||
|
hLcdDC,
|
||||||
|
0, (MAINSCREENHEIGHT+Chipset.d0size),
|
||||||
|
131, MENUHEIGHT,
|
||||||
|
SRCCOPY);
|
||||||
|
GdiFlush();
|
||||||
|
}
|
||||||
|
LeaveCriticalSection(&csGDILock);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// CdB for HP: add header management
|
||||||
|
VOID RefreshDisp0()
|
||||||
|
{
|
||||||
|
UINT x, y;
|
||||||
|
BYTE *p;
|
||||||
|
BYTE* d = Chipset.d0memory;
|
||||||
|
|
||||||
|
#if defined DEBUG_DISPLAY
|
||||||
|
{
|
||||||
|
TCHAR buffer[256];
|
||||||
|
wsprintf(buffer,_T("%.5lx: Update header Display\n"),Chipset.pc);
|
||||||
|
OutputDebugString(buffer);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (!(Chipset.IORam[BITOFFSET]&DON)) return;
|
||||||
|
|
||||||
|
// calculate bitmap offset
|
||||||
|
p = pbyLcd;
|
||||||
|
for (y = 0; y<Chipset.d0size; ++y)
|
||||||
|
{
|
||||||
|
memcpy(Buf,d,34); // 34 nibbles are viewed
|
||||||
|
for (x=0; x<36; ++x) // every 4 pixel
|
||||||
|
{
|
||||||
|
DIBPIXEL4(p,Pattern[Buf[x]]);
|
||||||
|
}
|
||||||
|
d+=34;
|
||||||
|
}
|
||||||
|
EnterCriticalSection(&csGDILock); // solving NT GDI problems
|
||||||
|
{
|
||||||
|
StretchBlt(hWindowDC, nLcdX, nLcdY,
|
||||||
|
131*nLcdZoom*nGdiXZoom, Chipset.d0size*nLcdZoom*nGdiYZoom,
|
||||||
|
hLcdDC, Chipset.d0offset, 0, 131, Chipset.d0size, SRCCOPY);
|
||||||
|
GdiFlush();
|
||||||
|
}
|
||||||
|
LeaveCriticalSection(&csGDILock);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
VOID WriteToMainDisplay(LPBYTE a, DWORD d, UINT s)
|
||||||
|
{
|
||||||
|
UINT x0, x;
|
||||||
|
UINT y0, y;
|
||||||
|
DWORD *p;
|
||||||
|
|
||||||
|
INT lWidth = abs(Chipset.width); // display width
|
||||||
|
|
||||||
|
if (bGrayscale) return; // no direct writing in grayscale mode
|
||||||
|
|
||||||
|
#if defined DEBUG_DISPLAY
|
||||||
|
{
|
||||||
|
TCHAR buffer[256];
|
||||||
|
wsprintf(buffer,_T("%.5lx: Write Main Display %x,%u\n"),Chipset.pc,d,s);
|
||||||
|
OutputDebugString(buffer);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (!(Chipset.IORam[BITOFFSET]&DON)) // display off
|
||||||
|
return; // no drawing
|
||||||
|
|
||||||
|
if (MAINSCREENHEIGHT == 0) return; // menu disabled
|
||||||
|
|
||||||
|
d -= Chipset.start1; // nibble offset to DISPADDR (start of display)
|
||||||
|
y0 = y = (d / lWidth) + Chipset.d0size; // bitmap row
|
||||||
|
x0 = x = d % lWidth; // bitmap coloumn
|
||||||
|
p = (DWORD*)(pbyLcd + y0*LCD_ROW + x0*sizeof(*p));
|
||||||
|
|
||||||
|
// outside main display area
|
||||||
|
// _ASSERT(y0 >= (INT)Chipset.d0size && y0 < (INT)(MAINSCREENHEIGHT+Chipset.d0size));
|
||||||
|
if (!(y0 >= (INT)Chipset.d0size && y0 < (INT)(MAINSCREENHEIGHT+Chipset.d0size))) return;
|
||||||
|
|
||||||
|
while (s--) // loop for nibbles to write
|
||||||
|
{
|
||||||
|
if (x<36) // only fill visible area
|
||||||
|
{
|
||||||
|
*p = Pattern[*a];
|
||||||
|
}
|
||||||
|
++a; // next value to write
|
||||||
|
++x; // next x position
|
||||||
|
if (((INT) x==lWidth)&&s) // end of display line
|
||||||
|
{
|
||||||
|
x = 0; // first coloumn
|
||||||
|
++y; // next row
|
||||||
|
if (y == (INT) MAINSCREENHEIGHT+Chipset.d0size) break;
|
||||||
|
// recalculate bitmap memory position of new line
|
||||||
|
p = (DWORD*) (pbyLcd+y*LCD_ROW); // CdB for HP: add 64/80 line display for apples
|
||||||
|
}
|
||||||
|
else
|
||||||
|
p++;
|
||||||
|
}
|
||||||
|
if (y==y0) y++;
|
||||||
|
EnterCriticalSection(&csGDILock); // solving NT GDI problems
|
||||||
|
{
|
||||||
|
StretchBlt(hWindowDC, nLcdX, nLcdY+y0*nLcdZoom*nGdiYZoom,
|
||||||
|
131*nLcdZoom*nGdiXZoom, (y-y0)*nLcdZoom*nGdiYZoom,
|
||||||
|
hLcdDC, Chipset.boffset, y0, 131, y-y0, SRCCOPY); // CdB for HP: add 64/80 line display for apples
|
||||||
|
GdiFlush();
|
||||||
|
}
|
||||||
|
LeaveCriticalSection(&csGDILock);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
VOID WriteToMenuDisplay(LPBYTE a, DWORD d, UINT s)
|
||||||
|
{
|
||||||
|
UINT x0, x;
|
||||||
|
UINT y0, y;
|
||||||
|
DWORD *p;
|
||||||
|
|
||||||
|
if (bGrayscale) return; // no direct writing in grayscale mode
|
||||||
|
|
||||||
|
#if defined DEBUG_DISPLAY
|
||||||
|
{
|
||||||
|
TCHAR buffer[256];
|
||||||
|
wsprintf(buffer,_T("%.5lx: Write Menu Display %x,%u\n"),Chipset.pc,d,s);
|
||||||
|
OutputDebugString(buffer);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (!(Chipset.IORam[BITOFFSET]&DON)) return;
|
||||||
|
if (MENUHEIGHT == 0) return; // menu disabled
|
||||||
|
|
||||||
|
d -= Chipset.start2;
|
||||||
|
y0 = y = (d / 34) + MAINSCREENHEIGHT+Chipset.d0size; // bitmap row
|
||||||
|
x0 = x = d % 34;
|
||||||
|
p = (DWORD*)(pbyLcd + y0*LCD_ROW + x0*sizeof(*p));
|
||||||
|
|
||||||
|
// outside menu display area
|
||||||
|
// _ASSERT(y0 >= (INT)(Chipset.d0size+MAINSCREENHEIGHT) && y0 < (INT)(SCREENHEIGHT));
|
||||||
|
if (!(y0 >= (UINT)(Chipset.d0size+MAINSCREENHEIGHT) && y0 < (UINT)(SCREENHEIGHT))) return;
|
||||||
|
|
||||||
|
while (s--) // loop for nibbles to write
|
||||||
|
{
|
||||||
|
if (x<36) // only fill visible area
|
||||||
|
{
|
||||||
|
*p = Pattern[*a];
|
||||||
|
}
|
||||||
|
a++; // next value to write
|
||||||
|
x++; // next x position
|
||||||
|
if ((x==34)&&s) // end of display line
|
||||||
|
{
|
||||||
|
x = 0; // first coloumn
|
||||||
|
y++; // next row
|
||||||
|
if (y == SCREENHEIGHTREAL) break;
|
||||||
|
// recalculate bitmap memory position of new line
|
||||||
|
p=(DWORD*)(pbyLcd+y*LCD_ROW); // CdB for HP: add 64/80 ligne display for apples
|
||||||
|
} else p++;
|
||||||
|
}
|
||||||
|
if (y==y0) y++;
|
||||||
|
EnterCriticalSection(&csGDILock); // solving NT GDI problems
|
||||||
|
{
|
||||||
|
StretchBlt(hWindowDC, nLcdX, nLcdY+y0*nLcdZoom*nGdiYZoom,
|
||||||
|
(131*nLcdZoom)*nGdiXZoom, (y-y0)*nLcdZoom*nGdiYZoom,
|
||||||
|
hLcdDC, 0, y0, 131, y-y0, SRCCOPY); // CdB for HP: add 64/80 line display for apples
|
||||||
|
GdiFlush();
|
||||||
|
}
|
||||||
|
LeaveCriticalSection(&csGDILock);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
VOID UpdateAnnunciators(VOID)
|
||||||
|
{
|
||||||
|
BYTE c;
|
||||||
|
|
||||||
|
c = (BYTE)(Chipset.IORam[ANNCTRL] | (Chipset.IORam[ANNCTRL+1]<<4));
|
||||||
|
// switch annunciators off if timer stopped
|
||||||
|
if ((c & AON) == 0 || (Chipset.IORam[TIMER2_CTRL] & RUN) == 0)
|
||||||
|
c = 0;
|
||||||
|
|
||||||
|
DrawAnnunciator(1,c&LA1);
|
||||||
|
DrawAnnunciator(2,c&LA2);
|
||||||
|
DrawAnnunciator(3,c&LA3);
|
||||||
|
DrawAnnunciator(4,c&LA4);
|
||||||
|
DrawAnnunciator(5,c&LA5);
|
||||||
|
DrawAnnunciator(6,c&LA6);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
VOID ResizeWindow(VOID)
|
||||||
|
{
|
||||||
|
if (hWnd != NULL) // if window created
|
||||||
|
{
|
||||||
|
RECT rectWindow;
|
||||||
|
RECT rectClient;
|
||||||
|
|
||||||
|
rectWindow.left = 0;
|
||||||
|
rectWindow.top = 0;
|
||||||
|
rectWindow.right = nBackgroundW;
|
||||||
|
rectWindow.bottom = nBackgroundH;
|
||||||
|
|
||||||
|
AdjustWindowRect(&rectWindow,
|
||||||
|
(DWORD) GetWindowLongPtr(hWnd,GWL_STYLE),
|
||||||
|
GetMenu(hWnd) != NULL || IsRectEmpty(&rectWindow));
|
||||||
|
SetWindowPos(hWnd, bAlwaysOnTop ? HWND_TOPMOST : HWND_NOTOPMOST, 0, 0,
|
||||||
|
rectWindow.right - rectWindow.left,
|
||||||
|
rectWindow.bottom - rectWindow.top,
|
||||||
|
SWP_NOMOVE);
|
||||||
|
|
||||||
|
// check if menu bar wrapped to two or more rows
|
||||||
|
GetClientRect(hWnd, &rectClient);
|
||||||
|
if (rectClient.bottom < (LONG) nBackgroundH)
|
||||||
|
{
|
||||||
|
rectWindow.bottom += (nBackgroundH - rectClient.bottom);
|
||||||
|
SetWindowPos (hWnd, NULL, 0, 0,
|
||||||
|
rectWindow.right - rectWindow.left,
|
||||||
|
rectWindow.bottom - rectWindow.top,
|
||||||
|
SWP_NOMOVE | SWP_NOZORDER);
|
||||||
|
}
|
||||||
|
|
||||||
|
EnterCriticalSection(&csGDILock); // solving NT GDI problems
|
||||||
|
{
|
||||||
|
_ASSERT(hWindowDC); // move origin of destination window
|
||||||
|
VERIFY(SetWindowOrgEx(hWindowDC, nBackgroundX, nBackgroundY, NULL));
|
||||||
|
GdiFlush();
|
||||||
|
}
|
||||||
|
LeaveCriticalSection(&csGDILock);
|
||||||
|
InvalidateRect(hWnd,NULL,TRUE);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
//################
|
||||||
|
//#
|
||||||
|
//# functions for gray scale implementation
|
||||||
|
//#
|
||||||
|
//################
|
||||||
|
|
||||||
|
// main display update routine
|
||||||
|
static VOID CALLBACK LcdProc(UINT uEventId, UINT uMsg, DWORD dwUser, DWORD dw1, DWORD dw2)
|
||||||
|
{
|
||||||
|
EnterCriticalSection(&csLcdLock);
|
||||||
|
{
|
||||||
|
UpdateMainDisplay(); // update display
|
||||||
|
UpdateMenuDisplay();
|
||||||
|
RefreshDisp0(); // CdB for HP: add header management
|
||||||
|
}
|
||||||
|
LeaveCriticalSection(&csLcdLock);
|
||||||
|
|
||||||
|
QueryPerformanceCounter(&lLcdRef); // actual time
|
||||||
|
|
||||||
|
return;
|
||||||
|
UNREFERENCED_PARAMETER(uEventId);
|
||||||
|
UNREFERENCED_PARAMETER(uMsg);
|
||||||
|
UNREFERENCED_PARAMETER(dwUser);
|
||||||
|
UNREFERENCED_PARAMETER(dw1);
|
||||||
|
UNREFERENCED_PARAMETER(dw2);
|
||||||
|
}
|
||||||
|
|
||||||
|
// LCD line counter calculation
|
||||||
|
static BYTE GetLineCounterGray(VOID)
|
||||||
|
{
|
||||||
|
LARGE_INTEGER lLC;
|
||||||
|
BYTE byTime;
|
||||||
|
|
||||||
|
if (uLcdTimerId == 0) // display off
|
||||||
|
return ((Chipset.IORam[LINECOUNT+1] & (LC5|LC4)) << 4) | Chipset.IORam[LINECOUNT];
|
||||||
|
|
||||||
|
QueryPerformanceCounter(&lLC); // get elapsed time since display update
|
||||||
|
|
||||||
|
// elapsed ticks so far
|
||||||
|
byTime = (BYTE) (((lLC.QuadPart - lLcdRef.QuadPart) << 12) / lFreq.QuadPart);
|
||||||
|
|
||||||
|
if (byTime > 0x3F) byTime = 0x3F; // all counts made
|
||||||
|
|
||||||
|
return 0x3F - byTime; // update display between VBL counter 0x3F-0x3E
|
||||||
|
}
|
||||||
|
|
||||||
|
static VOID StartDisplayGray(BYTE byInitial)
|
||||||
|
{
|
||||||
|
if (uLcdTimerId) // LCD update timer running
|
||||||
|
return; // -> quit
|
||||||
|
|
||||||
|
if (Chipset.IORam[BITOFFSET]&DON) // display on?
|
||||||
|
{
|
||||||
|
QueryPerformanceCounter(&lLcdRef); // actual time of top line
|
||||||
|
|
||||||
|
// adjust startup counter to get the right VBL value
|
||||||
|
_ASSERT(byInitial <= 0x3F); // line counter value 0 - 63
|
||||||
|
lLcdRef.QuadPart -= ((LONGLONG) (0x3F - byInitial) * lFreq.QuadPart) >> 12;
|
||||||
|
|
||||||
|
VERIFY(uLcdTimerId = timeSetEvent(DISPLAY_FREQ,0,(LPTIMECALLBACK)&LcdProc,0,TIME_PERIODIC));
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
static VOID StopDisplayGray(VOID)
|
||||||
|
{
|
||||||
|
BYTE a[2];
|
||||||
|
ReadIO(a,LINECOUNT,2,TRUE); // update VBL at display off time
|
||||||
|
|
||||||
|
if (uLcdTimerId == 0) // timer stopped
|
||||||
|
return; // -> quit
|
||||||
|
|
||||||
|
timeKillEvent(uLcdTimerId); // stop display update
|
||||||
|
uLcdTimerId = 0; // set flag display update stopped
|
||||||
|
|
||||||
|
EnterCriticalSection(&csLcdLock); // update to last condition
|
||||||
|
{
|
||||||
|
UpdateMainDisplay(); // update display
|
||||||
|
UpdateMenuDisplay();
|
||||||
|
RefreshDisp0(); // CdB for HP: add header management
|
||||||
|
}
|
||||||
|
LeaveCriticalSection(&csLcdLock);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
//################
|
||||||
|
//#
|
||||||
|
//# functions for black and white implementation
|
||||||
|
//#
|
||||||
|
//################
|
||||||
|
|
||||||
|
// LCD line counter calculation in BW mode
|
||||||
|
static BYTE F4096Hz(VOID) // get a 6 bit 4096Hz down counter value
|
||||||
|
{
|
||||||
|
LARGE_INTEGER lLC;
|
||||||
|
|
||||||
|
QueryPerformanceCounter(&lLC); // get counter value
|
||||||
|
|
||||||
|
// calculate 4096 Hz frequency down counter value
|
||||||
|
return -(BYTE)(((lLC.QuadPart - lAppStart.QuadPart) << 12) / lFreq.QuadPart) & 0x3F;
|
||||||
|
}
|
||||||
|
|
||||||
|
static BYTE GetLineCounterBW(VOID) // get line counter value
|
||||||
|
{
|
||||||
|
_ASSERT(byVblRef < 0x40);
|
||||||
|
return (0x40 + F4096Hz() - byVblRef) & 0x3F;
|
||||||
|
}
|
||||||
|
|
||||||
|
static VOID StartDisplayBW(BYTE byInitial)
|
||||||
|
{
|
||||||
|
// get positive VBL difference between now and stop time
|
||||||
|
byVblRef = (0x40 + F4096Hz() - byInitial) & 0x3F;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
static VOID StopDisplayBW(VOID)
|
||||||
|
{
|
||||||
|
BYTE a[2];
|
||||||
|
ReadIO(a,LINECOUNT,2,TRUE); // update VBL at display off time
|
||||||
|
return;
|
||||||
|
}
|
|
@ -25,7 +25,7 @@ BOOL SetCurrentDirectory(LPCTSTR path)
|
||||||
return chdir(path);
|
return chdir(path);
|
||||||
}
|
}
|
||||||
|
|
||||||
int CreateFile(LPCTSTR lpFileName, DWORD dwDesiredAccess, DWORD dwShareMode, LPVOID lpSecurityAttributes, DWORD dwCreationDisposition, DWORD dwFlagsAndAttributes, LPVOID hTemplateFile)
|
HANDLE CreateFile(LPCTSTR lpFileName, DWORD dwDesiredAccess, DWORD dwShareMode, LPVOID lpSecurityAttributes, DWORD dwCreationDisposition, DWORD dwFlagsAndAttributes, LPVOID hTemplateFile)
|
||||||
{
|
{
|
||||||
int flags = O_RDWR;
|
int flags = O_RDWR;
|
||||||
int fd = -1;
|
int fd = -1;
|
||||||
|
@ -65,25 +65,50 @@ int CreateFile(LPCTSTR lpFileName, DWORD dwDesiredAccess, DWORD dwShareMode, LPV
|
||||||
// }
|
// }
|
||||||
// }
|
// }
|
||||||
|
|
||||||
return fd;
|
HANDLE result = malloc(sizeof(_HANDLE));
|
||||||
|
result->handleType = HANDLE_TYPE_FILE;
|
||||||
|
result->fileDescriptor = fd;
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOL ReadFile(HANDLE hFile, LPVOID lpBuffer, DWORD nNumberOfBytesToRead, LPDWORD lpNumberOfBytesRead, LPOVERLAPPED lpOverlapped) {
|
BOOL ReadFile(HANDLE hFile, LPVOID lpBuffer, DWORD nNumberOfBytesToRead, LPDWORD lpNumberOfBytesRead, LPOVERLAPPED lpOverlapped) {
|
||||||
return FALSE;
|
DWORD readByteCount = read(hFile->fileDescriptor, lpBuffer, nNumberOfBytesToRead);
|
||||||
}
|
if(lpNumberOfBytesRead)
|
||||||
|
*lpNumberOfBytesRead = readByteCount;
|
||||||
DWORD SetFilePointer(HANDLE hFile, LONG lDistanceToMove, PLONG lpDistanceToMoveHigh, DWORD dwMoveMethod) {
|
return readByteCount >= 0;
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
DWORD GetFileSize(HANDLE hFile, LPDWORD lpFileSizeHigh) {
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOL WriteFile(HANDLE hFile, LPCVOID lpBuffer, DWORD nNumberOfBytesToWrite,LPDWORD lpNumberOfBytesWritten, LPOVERLAPPED lpOverlapped) {
|
BOOL WriteFile(HANDLE hFile, LPCVOID lpBuffer, DWORD nNumberOfBytesToWrite,LPDWORD lpNumberOfBytesWritten, LPOVERLAPPED lpOverlapped) {
|
||||||
|
size_t writenByteCount = write(hFile->fileDescriptor, lpBuffer, nNumberOfBytesToWrite);
|
||||||
|
if(lpNumberOfBytesWritten)
|
||||||
|
*lpNumberOfBytesWritten = writenByteCount;
|
||||||
|
return writenByteCount >= 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
DWORD SetFilePointer(HANDLE hFile, LONG lDistanceToMove, PLONG lpDistanceToMoveHigh, DWORD dwMoveMethod) {
|
||||||
|
int moveMode;
|
||||||
|
if(dwMoveMethod == FILE_BEGIN)
|
||||||
|
moveMode = SEEK_SET;
|
||||||
|
else if(dwMoveMethod == FILE_CURRENT)
|
||||||
|
moveMode = SEEK_CUR;
|
||||||
|
else if(dwMoveMethod == FILE_END)
|
||||||
|
moveMode = SEEK_END;
|
||||||
|
int seekResult = lseek(hFile->fileDescriptor, lDistanceToMove, moveMode);
|
||||||
|
return seekResult < 0 ? INVALID_SET_FILE_POINTER : seekResult;
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOL SetEndOfFile(HANDLE hFile) {
|
||||||
|
//TODO
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DWORD GetFileSize(HANDLE hFile, LPDWORD lpFileSizeHigh) {
|
||||||
|
off_t currentPosition = lseek(hFile->fileDescriptor, 0, SEEK_CUR);
|
||||||
|
off_t fileLength = lseek(hFile->fileDescriptor, 0, SEEK_END) + 1;
|
||||||
|
lseek(hFile->fileDescriptor, currentPosition, SEEK_SET);
|
||||||
|
return fileLength;
|
||||||
|
}
|
||||||
|
|
||||||
HANDLE CreateFileMapping(HANDLE hFile, LPSECURITY_ATTRIBUTES lpFileMappingAttributes, DWORD flProtect, DWORD dwMaximumSizeHigh, DWORD dwMaximumSizeLow, LPCSTR lpName) {
|
HANDLE CreateFileMapping(HANDLE hFile, LPSECURITY_ATTRIBUTES lpFileMappingAttributes, DWORD flProtect, DWORD dwMaximumSizeHigh, DWORD dwMaximumSizeLow, LPCSTR lpName) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
@ -96,10 +121,122 @@ BOOL UnmapViewOfFile(LPCVOID lpBaseAddress) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOL SetEndOfFile(HANDLE hFile) {
|
// https://github.com/NeoSmart/PEvents
|
||||||
|
HANDLE CreateEvent(WORD attr, BOOL is_manual_reset, BOOL is_signaled, WORD name)
|
||||||
|
{
|
||||||
|
// if (nil == gEventLockDict)
|
||||||
|
// {
|
||||||
|
// gEventLockDict = [[NSMutableDictionary alloc] init];
|
||||||
|
// }
|
||||||
|
// ++gEventId;
|
||||||
|
// NSNumber *key = [[NSNumber alloc] initWithInt: gEventId];
|
||||||
|
// NSConditionLock *lock = [[NSConditionLock alloc] initWithCondition: 0];
|
||||||
|
// [gEventLockDict setObject:lock forKey:key];
|
||||||
|
// [lock release];
|
||||||
|
// [key release];
|
||||||
|
//// if (NULL == gEventLock)
|
||||||
|
//// {
|
||||||
|
//// gEventLock = [[NSConditionLock alloc] initWithCondition: 0];
|
||||||
|
//// }
|
||||||
|
|
||||||
|
return gEventId;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SetEvent(HANDLE eventId)
|
||||||
|
{
|
||||||
|
// NSNumber *key = [[NSNumber alloc] initWithInt: eventId];
|
||||||
|
// NSConditionLock *lock = [gEventLockDict objectForKey: key];
|
||||||
|
// [key release];
|
||||||
|
// if (lock)
|
||||||
|
// {
|
||||||
|
// [lock lock];
|
||||||
|
// [lock unlockWithCondition: eventId];
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOL ResetEvent(HANDLE eventId)
|
||||||
|
{
|
||||||
|
// NSNumber *key = [[NSNumber alloc] initWithInt: eventId];
|
||||||
|
// NSConditionLock *lock = [gEventLockDict objectForKey: key];
|
||||||
|
// [key release];
|
||||||
|
// if (lock)
|
||||||
|
// {
|
||||||
|
// [lock lock];
|
||||||
|
// [lock unlockWithCondition: 0];
|
||||||
|
// return TRUE;
|
||||||
|
// }
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void DestroyEvent(HANDLE eventId)
|
||||||
|
{
|
||||||
|
// NSNumber *key = [[NSNumber alloc] initWithInt: eventId];
|
||||||
|
// NSConditionLock *lock = [gEventLockDict objectForKey: key];
|
||||||
|
// if (lock)
|
||||||
|
// {
|
||||||
|
// [gEventLockDict removeObjectForKey: key];
|
||||||
|
// }
|
||||||
|
// [key release];
|
||||||
|
}
|
||||||
|
|
||||||
|
DWORD WaitForSingleObject(HANDLE eventId, int timeout)
|
||||||
|
{
|
||||||
|
DWORD result = WAIT_OBJECT_0;
|
||||||
|
// NSNumber *key = [[NSNumber alloc] initWithInt: eventId];
|
||||||
|
// NSConditionLock *lock = [gEventLockDict objectForKey: key];
|
||||||
|
// [key release];
|
||||||
|
//
|
||||||
|
// if (nil == lock)
|
||||||
|
// return WAIT_FAILED;
|
||||||
|
//
|
||||||
|
// if (timeout > 0)
|
||||||
|
// {
|
||||||
|
// NSDate *timeoutDate = [[NSDate alloc] initWithTimeIntervalSinceNow: (timeout/1000.0)];
|
||||||
|
// if (![lock lockWhenCondition:eventId beforeDate:timeoutDate])
|
||||||
|
// result = WAIT_TIMEOUT;
|
||||||
|
// [timeoutDate release];
|
||||||
|
// }
|
||||||
|
// else
|
||||||
|
// {
|
||||||
|
// [lock lockWhenCondition: eventId];
|
||||||
|
// [lock unlockWithCondition: 0];
|
||||||
|
// }
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
HANDLE WINAPI CreateThread(LPSECURITY_ATTRIBUTES lpThreadAttributes, SIZE_T dwStackSize, LPTHREAD_START_ROUTINE lpStartAddress, LPVOID lpParameter, DWORD dwCreationFlags, LPDWORD lpThreadId) {
|
||||||
|
//TODO
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOL WINAPI CloseHandle(HANDLE hObject) {
|
||||||
|
// Can be a thread/event/file handle!
|
||||||
|
switch(hObject->handleType) {
|
||||||
|
case HANDLE_TYPE_FILE: {
|
||||||
|
int closeResult = close(hObject->fileDescriptor);
|
||||||
|
if(closeResult >= 0) {
|
||||||
|
hObject->fileDescriptor = 0;
|
||||||
|
free(hObject);
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case HANDLE_TYPE_EVENT:
|
||||||
|
//free(hObject);
|
||||||
|
return TRUE;
|
||||||
|
case HANDLE_TYPE_THREAD:
|
||||||
|
//free(hObject);
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Sleep(int ms)
|
||||||
|
{
|
||||||
|
// [[NSRunLoop currentRunLoop] runUntilDate: [NSDate dateWithTimeIntervalSinceNow: (ms / 1000.0)]];
|
||||||
|
//// [NSThread sleepUntilDate: [NSDate dateWithTimeIntervalSinceNow: (ms / 1000.0)]];
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
OSErr ReadFile(FSPtr &file, void *buf, SInt64 size, void *, void *)
|
OSErr ReadFile(FSPtr &file, void *buf, SInt64 size, void *, void *)
|
||||||
{
|
{
|
||||||
|
@ -377,97 +514,6 @@ void LeaveCriticalSection(CRITICAL_SECTION *lock)
|
||||||
pthread_mutex_unlock(lock);
|
pthread_mutex_unlock(lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// https://github.com/NeoSmart/PEvents
|
|
||||||
HANDLE CreateEvent(WORD attr, BOOL is_manual_reset, BOOL is_signaled, WORD name)
|
|
||||||
{
|
|
||||||
// if (nil == gEventLockDict)
|
|
||||||
// {
|
|
||||||
// gEventLockDict = [[NSMutableDictionary alloc] init];
|
|
||||||
// }
|
|
||||||
// ++gEventId;
|
|
||||||
// NSNumber *key = [[NSNumber alloc] initWithInt: gEventId];
|
|
||||||
// NSConditionLock *lock = [[NSConditionLock alloc] initWithCondition: 0];
|
|
||||||
// [gEventLockDict setObject:lock forKey:key];
|
|
||||||
// [lock release];
|
|
||||||
// [key release];
|
|
||||||
//// if (NULL == gEventLock)
|
|
||||||
//// {
|
|
||||||
//// gEventLock = [[NSConditionLock alloc] initWithCondition: 0];
|
|
||||||
//// }
|
|
||||||
|
|
||||||
return gEventId;
|
|
||||||
}
|
|
||||||
|
|
||||||
void SetEvent(HANDLE eventId)
|
|
||||||
{
|
|
||||||
// NSNumber *key = [[NSNumber alloc] initWithInt: eventId];
|
|
||||||
// NSConditionLock *lock = [gEventLockDict objectForKey: key];
|
|
||||||
// [key release];
|
|
||||||
// if (lock)
|
|
||||||
// {
|
|
||||||
// [lock lock];
|
|
||||||
// [lock unlockWithCondition: eventId];
|
|
||||||
// }
|
|
||||||
}
|
|
||||||
|
|
||||||
BOOL ResetEvent(HANDLE eventId)
|
|
||||||
{
|
|
||||||
// NSNumber *key = [[NSNumber alloc] initWithInt: eventId];
|
|
||||||
// NSConditionLock *lock = [gEventLockDict objectForKey: key];
|
|
||||||
// [key release];
|
|
||||||
// if (lock)
|
|
||||||
// {
|
|
||||||
// [lock lock];
|
|
||||||
// [lock unlockWithCondition: 0];
|
|
||||||
// return TRUE;
|
|
||||||
// }
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
void DestroyEvent(HANDLE eventId)
|
|
||||||
{
|
|
||||||
// NSNumber *key = [[NSNumber alloc] initWithInt: eventId];
|
|
||||||
// NSConditionLock *lock = [gEventLockDict objectForKey: key];
|
|
||||||
// if (lock)
|
|
||||||
// {
|
|
||||||
// [gEventLockDict removeObjectForKey: key];
|
|
||||||
// }
|
|
||||||
// [key release];
|
|
||||||
}
|
|
||||||
|
|
||||||
DWORD WaitForSingleObject(HANDLE eventId, int timeout)
|
|
||||||
{
|
|
||||||
DWORD result = WAIT_OBJECT_0;
|
|
||||||
// NSNumber *key = [[NSNumber alloc] initWithInt: eventId];
|
|
||||||
// NSConditionLock *lock = [gEventLockDict objectForKey: key];
|
|
||||||
// [key release];
|
|
||||||
//
|
|
||||||
// if (nil == lock)
|
|
||||||
// return WAIT_FAILED;
|
|
||||||
//
|
|
||||||
// if (timeout > 0)
|
|
||||||
// {
|
|
||||||
// NSDate *timeoutDate = [[NSDate alloc] initWithTimeIntervalSinceNow: (timeout/1000.0)];
|
|
||||||
// if (![lock lockWhenCondition:eventId beforeDate:timeoutDate])
|
|
||||||
// result = WAIT_TIMEOUT;
|
|
||||||
// [timeoutDate release];
|
|
||||||
// }
|
|
||||||
// else
|
|
||||||
// {
|
|
||||||
// [lock lockWhenCondition: eventId];
|
|
||||||
// [lock unlockWithCondition: 0];
|
|
||||||
// }
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Sleep(int ms)
|
|
||||||
{
|
|
||||||
// [[NSRunLoop currentRunLoop] runUntilDate: [NSDate dateWithTimeIntervalSinceNow: (ms / 1000.0)]];
|
|
||||||
//// [NSThread sleepUntilDate: [NSDate dateWithTimeIntervalSinceNow: (ms / 1000.0)]];
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
BOOL GetSystemPowerStatus(LPSYSTEM_POWER_STATUS status)
|
BOOL GetSystemPowerStatus(LPSYSTEM_POWER_STATUS status)
|
||||||
{
|
{
|
||||||
status->ACLineStatus = AC_LINE_ONLINE;
|
status->ACLineStatus = AC_LINE_ONLINE;
|
||||||
|
@ -484,19 +530,10 @@ BOOL GetWindowPlacement(HWND hWnd, WINDOWPLACEMENT *lpwndpl) { return 0; }
|
||||||
BOOL SetWindowPlacement(HWND hWnd, CONST WINDOWPLACEMENT *lpwndpl) { return 0; }
|
BOOL SetWindowPlacement(HWND hWnd, CONST WINDOWPLACEMENT *lpwndpl) { return 0; }
|
||||||
BOOL InvalidateRect(HWND hWnd, CONST RECT *lpRect, BOOL bErase) { return 0; }
|
BOOL InvalidateRect(HWND hWnd, CONST RECT *lpRect, BOOL bErase) { return 0; }
|
||||||
|
|
||||||
HANDLE WINAPI CreateThread(LPSECURITY_ATTRIBUTES lpThreadAttributes, SIZE_T dwStackSize, LPTHREAD_START_ROUTINE lpStartAddress, LPVOID lpParameter, DWORD dwCreationFlags, LPDWORD lpThreadId) {
|
|
||||||
//TODO
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
DWORD ResumeThread(HANDLE hThread) {
|
DWORD ResumeThread(HANDLE hThread) {
|
||||||
//TODO
|
//TODO
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
BOOL WINAPI CloseHandle(HANDLE hObject) {
|
|
||||||
//TODO
|
|
||||||
// Can be a thread/event/file hande!
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
int GetObject(HANDLE h, int c, LPVOID pv) {
|
int GetObject(HANDLE h, int c, LPVOID pv) {
|
||||||
//TODO
|
//TODO
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
@ -50,7 +50,16 @@ typedef ULONG_PTR DWORD_PTR, *PDWORD_PTR;
|
||||||
|
|
||||||
#define CONST const
|
#define CONST const
|
||||||
|
|
||||||
typedef int HANDLE;
|
enum HANDLE_TYPE {
|
||||||
|
HANDLE_TYPE_FILE = 1,
|
||||||
|
HANDLE_TYPE_EVENT,
|
||||||
|
HANDLE_TYPE_THREAD,
|
||||||
|
};
|
||||||
|
typedef struct {
|
||||||
|
int handleType;
|
||||||
|
int fileDescriptor;
|
||||||
|
} _HANDLE;
|
||||||
|
typedef _HANDLE * HANDLE;
|
||||||
typedef HANDLE HPALETTE;
|
typedef HANDLE HPALETTE;
|
||||||
typedef HANDLE HBITMAP;
|
typedef HANDLE HBITMAP;
|
||||||
typedef HANDLE HMENU;
|
typedef HANDLE HMENU;
|
||||||
|
@ -352,7 +361,7 @@ typedef struct _OVERLAPPED {
|
||||||
|
|
||||||
extern DWORD GetCurrentDirectory(DWORD nBufferLength, LPTSTR lpBuffer);
|
extern DWORD GetCurrentDirectory(DWORD nBufferLength, LPTSTR lpBuffer);
|
||||||
extern BOOL SetCurrentDirectory(LPCTSTR); // returns NO if fails
|
extern BOOL SetCurrentDirectory(LPCTSTR); // returns NO if fails
|
||||||
extern int CreateFile(LPCTSTR lpFileName, DWORD dwDesiredAccess, DWORD dwShareMode, LPVOID lpSecurityAttributes, DWORD dwCreationDisposition, DWORD dwFlagsAndAttributes, LPVOID hTemplateFile);
|
extern HANDLE CreateFile(LPCTSTR lpFileName, DWORD dwDesiredAccess, DWORD dwShareMode, LPVOID lpSecurityAttributes, DWORD dwCreationDisposition, DWORD dwFlagsAndAttributes, LPVOID hTemplateFile);
|
||||||
extern BOOL ReadFile(HANDLE hFile, LPVOID lpBuffer, DWORD nNumberOfBytesToRead, LPDWORD lpNumberOfBytesRead, LPOVERLAPPED lpOverlapped);
|
extern BOOL ReadFile(HANDLE hFile, LPVOID lpBuffer, DWORD nNumberOfBytesToRead, LPDWORD lpNumberOfBytesRead, LPOVERLAPPED lpOverlapped);
|
||||||
extern DWORD SetFilePointer(HANDLE hFile, LONG lDistanceToMove, PLONG lpDistanceToMoveHigh, DWORD dwMoveMethod);
|
extern DWORD SetFilePointer(HANDLE hFile, LONG lDistanceToMove, PLONG lpDistanceToMoveHigh, DWORD dwMoveMethod);
|
||||||
extern DWORD GetFileSize(HANDLE hFile, LPDWORD lpFileSizeHigh);
|
extern DWORD GetFileSize(HANDLE hFile, LPDWORD lpFileSizeHigh);
|
||||||
|
|
Loading…
Reference in a new issue