home *** CD-ROM | disk | FTP | other *** search
-
- /* WSpecem.c : Windows interface for WSpecem emulator.
- *
- * Copyright 1996 Rui Fernando Ferreira Ribeiro.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
- #define APPNAME "SpecEmulApp"
-
-
- // main window client area size
- #define X_CORD 256
- #define Y_CORD 192
-
- /*
- * WSpecEm.C
- *
- */
-
- #include <windows.h> // Defines bulk of Windows functions and such...
- #include <windowsx.h>
- #include <mmsystem.h> // Defines additional Multi-Media functions...
- #include <shellapi.h> // Drag-and-drop
- #include <string.h>
- #include "env.h"
- #include "snd/wave.h"
-
- #if !defined(WIN32)
- /*#include "c:/wing/include/wing.h"*/ // Defines WinG functions. Not use on Win32
- #include "wing.h"
- #endif
-
- #include <stdlib.h>
- #include "wspecem.h" // Local header
-
- // ==========================================================================
- // GLOBAL VARIABLES ---------------------------------------------------------
- // ==========================================================================
-
- extern unsigned char keybd_buff[8]; /* Spectrum key states */
- extern unsigned char joystick; /* Joystick positions */
-
- // callback function to interface
- extern BOOL CALLBACK DoPoke(HWND,UINT,WPARAM,LPARAM);
- extern BOOL CALLBACK DoSpeed(HWND,UINT,WPARAM,LPARAM);
-
- char szAppName[]= APPNAME; // A handy string to identify this app
- char szTitle[] = "Spectrum Emulator"; // For the title bar
-
- HINSTANCE hInstApp; // A handle that identifies this 'process'
- HWND hwndApp; // A handle that identifies the main window
- HPALETTE hpalApp; // A handle that identifies the main palette
- BOOL fAppActive; // A boolean that refers to this app being 'foreground'
-
- // var to track state paused/not paused
- static BOOL NotPaused = 1;
-
- // Define a structure that we will be using for keeping information about the
- // image we are currently drawing into.
- typedef struct _IMAGE {
- BITMAPINFOHEADER bi; // Bitmap header information.
- RGBQUAD aColors[256]; // Palette color table
- union { // Now for the pointer to the data buffer we can whack on:
- LPVOID lpvData; // This is the type that WinG likes to deal with
- LPBYTE lpIndex; // This is just to make it easier for us to access it
- } data;
- } _IMAGE;
- _IMAGE image; // Contains most necessary information about the image to display
-
-
- // Define a structure for holding our palette data. This is the color palette
- // that will be assigned to both the above image, and be selected into the
- // 'Device Context' for the screen so we will have an 'Identity' palette which
- // will make for much faster screen updating.
- typedef struct _PALETTE
- {
- WORD Version;
- WORD NumberOfEntries;
- PALETTEENTRY aEntries[256];
- } _PALETTE;
- _PALETTE LogicalPalette = {0x300, 256}; // The 'logical' palette we will use
- // "0x300" = Windows 3.0 or later
- // "256" = Number of colors
-
- long Orientation = 1; // Bitmap Orientation: TopDown=1, BottomUp=-1
- HDC hdcImage = NULL; // A handle to the Device Context for our image
-
- HBITMAP gbmOldMonoBitmap = 0; // Storage for the 'original' bitmap from our
- // Device Context, we need to restore it
- // later on, so we need to save it here.
-
- /* RGB 'Spectrum' colors */
- static unsigned short rgbvals[16][3]={
- /* Normal colours */
- { 0x00, 0x00, 0x00}, { 0x00, 0x00, 0xcf},
- { 0xcf, 0x00, 0x00}, { 0xcf, 0x00, 0xcf},
- { 0x00, 0xcf, 0x00}, { 0x00, 0xcf, 0xcf},
- { 0xcf, 0xcf, 0x00}, { 0xcf, 0xcf, 0xcf},
-
- /* Brigth colours */
- { 0x00, 0x00, 0x00}, { 0x00, 0x00, 0xff},
- { 0xff, 0x00, 0x00}, { 0xff, 0x00, 0xff},
- { 0x00, 0xff, 0x00}, { 0x00, 0xff, 0xff},
- { 0xff, 0xff, 0x00}, { 0xff, 0xff, 0xff}
- };
-
- unsigned char ChangeFlashTime = 0; /* count time till inverting colours */
-
- // ==========================================================================
- // FUNCTION DEFINITIONS -----------------------------------------------------
- // ==========================================================================
-
- // Forward declarations for all functions.
- // Listed in order they appear in this source listing
-
- BOOL AppInit(HINSTANCE hInst,HINSTANCE hPrev,int sw);
- LONG FAR PASCAL AppWndProc(HWND hwnd,UINT msg,WPARAM wParam,LPARAM lParam);
- BOOL AppPaint (HWND hwnd, HDC hdc);
- LONG AppCommand (HWND hwnd,UINT msg,WPARAM wParam,LPARAM lParam);
- BOOL FAR PASCAL AppAbout(HWND hwnd,UINT msg,WPARAM wParam,LPARAM lParam);
- void AppExit(void);
-
-
- /*----------------------------------------------------------------------------*\
- | WinMain( hInst, hPrev, lpszCmdLine, cmdShow ) |
- | |
- | Description: |
- | The main procedure for the App. After initializing, it just goes |
- | into a message-processing loop until it gets a WM_QUIT message |
- | (meaning the app was closed). |
- | |
- | Arguments: |
- | hInst instance handle of this instance of the app |
- | hPrev instance handle of previous instance, NULL if first |
- | szCmdLine ->null-terminated command line |
- | cmdShow specifies how the window is initially displayed |
- | |
- | Returns: |
- | The exit code as specified in the WM_QUIT message. |
- | |
- \*----------------------------------------------------------------------------*/
- int PASCAL WinMain(HINSTANCE hInst, HINSTANCE hPrev, LPSTR szCmdLine, int sw)
- {
- MSG msg;
-
- // NOTE: On Win32, hPrev will -always- be NULL
-
- // Do application initialization stuff
- if (!AppInit(hInst,hPrev,sw)) {
- return 0; // Something failed to initialize
- }
-
- init_emul(hInst);
-
- /* If there is a snapshot in the command line, it is opened */
- if(szCmdLine[0])
- open_sna(szCmdLine);
-
- #if !defined(WIN32)
- /*{
- WORD (FAR PASCAL *SetPriority)(WORD, WORD);
-
- SetPriority = GetProcAddress(GetModuleHandle("KERNEL"), "SetPriority");
- if(SetPriority != NULL) */
- /* -32, 15 -- numbers below 0 are locking system */
- /* SetPriority(GetCurrentTask(), (WORD)0);
- else
- MessageBox(NULL, "!!!", "Not worked", MB_ICONHAND);
- } */
- #endif
-
-
- // Poll for messages from event queue.
- // loop continues until WM_QUIT is encountered
- for (;;) {
- if (PeekMessage(&msg, NULL, 0, 0,PM_REMOVE)) {
- if (msg.message == WM_QUIT) {
- // When WM_QUIT comes through, we're DONE!
- break;
- }
- TranslateMessage(&msg); // Messages for menu keys
- DispatchMessage(&msg);
- }
- else
- {
- if(NotPaused)
- execute();
-
- if(!IsIconic(hwndApp))
- {
- static char FrameCounter = 0;
- #if defined(WINDOWS_SOUND)
- static unsigned short freq;
- #endif
- static unsigned short mscStart = 0;
-
- // if window needs a update
- if(WindowDirty)
- {
- if(FrameCounter++ == ScreenUpdate)
- {
- FrameCounter = 0;
- // Just force a redraw
- InvalidateRect (hwndApp, NULL, FALSE);
- }
- }
-
-
- if(NotPaused)
- {
- if(++ChangeFlashTime == 100)
- {
- // if it's time to invert colours...
- ChangeFlashTime = 0; // reset counter
- FlashState ^= 1; // signal colours inverted
- WindowDirty = 1; // force a window redraw
- if(FrameCounter > 1)
- FrameCounter = ScreenUpdate-2;
- }
-
- #if defined(WINDOWS_SOUND)
- /* Can anyone put Windows .WAV sound to work?
- */
- freq = do_int_tasks();
- #endif
- /* Watch for 20ms */
- while((timeGetTime() - mscStart) < 20);
- #if defined(WINDOWS_SOUND)
- /* More bits needed to Windows .WAV sound... */
- StopSnd();
- FPlaySnd((float)freq, -1, 11025, 8, 1);
- #endif
- mscStart = timeGetTime();
- }
- } /* Iconic */
- else
- /* if program is in icon form and not paused, pause it */
- if(NotPaused)
- {
- PostMessage(hwndApp, WM_COMMAND, IDM_PAUSE, 0L);
- }
- }
- }
- AppExit(); // Do application exiting stuff
-
- return msg.wParam;
- }
-
- /*----------------------------------------------------------------------------*\
- | AppInit( hInst, hPrev) |
- | |
- | Description: |
- | This is called when the application is first loaded into |
- | memory. It performs all initialization that doesn't need to be done |
- | once per instance. |
- | |
- | Arguments: |
- | hInstance instance handle of current instance |
- | hPrev instance handle of previous instance |
- | sw window showmode |
- | |
- | Returns: |
- | TRUE if successful, FALSE if not |
- | |
- \*----------------------------------------------------------------------------*/
- BOOL AppInit(HINSTANCE hInst,HINSTANCE hPrev,int sw)
- {
- WNDCLASS cls;
- char szBuf[260];
-
- // read options
- GetWindowsDirectory((LPSTR)szBuf, 259);
- strcat(szBuf, "\\wspecem.ini");
- open_sna((LPSTR)szBuf);
-
- // Save instance handle for DialogBoxs as a global variable
- hInstApp = hInst;
-
- if (!hPrev) {
- // We don't already have a version running, so we need to
- // register our window class with the system
- cls.hCursor = LoadCursor(NULL,IDC_ARROW);
- cls.hIcon = LoadIcon(hInst,szAppName);
- cls.lpszMenuName = szAppName;
- cls.lpszClassName = szAppName;
- cls.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
- cls.hInstance = hInst;
- cls.style = CS_BYTEALIGNCLIENT | CS_VREDRAW
- | CS_HREDRAW | CS_DBLCLKS;
- cls.lpfnWndProc = (WNDPROC)AppWndProc;
- cls.cbWndExtra = 0;
- cls.cbClsExtra = 0;
-
- if (!RegisterClass(&cls)) {
- return FALSE; // Failed to register class. No need to continue.
- }
- }
- hwndApp = CreateWindow (szAppName, // Class name
- szTitle, // Caption
- WS_OVERLAPPEDWINDOW, // Style bits
- CW_USEDEFAULT, 0, // Position (x,y)
- // Size (w,h)
- X_CORD*Scale+GetSystemMetrics(SM_CYFRAME)*2,
- Y_CORD*Scale+GetSystemMetrics(SM_CXFRAME)*2+
- GetSystemMetrics(SM_CYMENU) +
- GetSystemMetrics(SM_CYCAPTION),
- (HWND)NULL, // Parent window (no parent)
- (HMENU)NULL, // use class menu
- hInst, // handle to current process instance
- (LPSTR)NULL // no params to pass on
- );
-
- if (hwndApp) {
- ShowWindow(hwndApp,sw); // Time to display the window.
- return TRUE;
- }
- else
- {
- return FALSE; // Failed to create window. No need to continue
- }
- }
-
- /*----------------------------------------------------------------------------*\
- | Resize( ) |
- | |
- | Description: |
- | This is called when the main window is about to be resized. | |
- | |
- | Returns: |
- | TRUE if successful, FALSE if not |
- | |
- \*----------------------------------------------------------------------------*/
- BOOL ResizeWindow(void)
- {
- HWND hwndAppOld = hwndApp;
-
- /* It's important destroying the window only after we have created
- a new one, or else we'll lose messages
- */
- hwndApp = CreateWindow (szAppName, // Class name
- szTitle, // Caption
- WS_OVERLAPPEDWINDOW, // Style bits
- CW_USEDEFAULT, 0, // Position (x,y)
- X_CORD*Scale+GetSystemMetrics(SM_CYFRAME)*2,// Size (w, h)
- Y_CORD*Scale+GetSystemMetrics(SM_CXFRAME)*2+
- GetSystemMetrics(SM_CYMENU) +
- GetSystemMetrics(SM_CYCAPTION),
- (HWND)NULL, // Parent window (no parent)
- (HMENU)NULL, // use class menu
- hInstApp, // handle to current process instance
- (LPSTR)NULL // no params to pass on
- );
-
- if (hwndApp) {
- DestroyWindow(hwndAppOld);
- ShowWindow(hwndApp,SW_SHOW); // Time to display the window.
- return TRUE;
- }
- else
- {
- return FALSE; // Failed to create window. No need to continue
- }
- }
-
- /*----------------------------------------------------------------------------*\
- | AppWndProc( hwnd, uiMessage, wParam, lParam ) |
- | |
- | Description: |
- | The window proc for the app's main (tiled) window. This processes all |
- | of the parent window's messages. |
- | |
- \*----------------------------------------------------------------------------*/
- LONG FAR PASCAL AppWndProc(HWND hwnd,UINT msg,WPARAM wParam,LPARAM lParam)
- {
- //static int XOffset, YOffset;
- static int dxClient, dyClient; // The 'Client' size. (drawing area of window)
- PAINTSTRUCT ps;
- HDC hdc;
- UINT uMappedColors;
- HMENU hmenu;
-
- switch (msg) {
- case WM_CREATE:
- // This occures during 'CreateWindow' time. Here is where we can
- // easily initialize some things for this window.
- srand ((int)GetTickCount()); // initialize the random seed
- //SetTimer(hwnd, 1, 1, NULL); // start up the WM_TIMER messages
-
- DragAcceptFiles( hwnd , TRUE );
-
- #if defined(WINDOWS_SOUND)
- /* Init wave driver */
- FInitSnd(); /* if true, init sucessfull*/
- #endif
-
- // Init options on the menu
- hmenu = GetMenu(hwnd);
- CheckMenuItem(hmenu, IDM_SIZE1, (Scale==1)?MF_CHECKED:MF_UNCHECKED);
- CheckMenuItem(hmenu, IDM_SIZE2, (Scale==2)?MF_CHECKED:MF_UNCHECKED);
- CheckMenuItem(hmenu, IDM_SIZE3, (Scale==3)?MF_CHECKED:MF_UNCHECKED);
- CheckMenuItem(hmenu, IDM_SIZE4, (Scale==4)?MF_CHECKED:MF_UNCHECKED);
- CheckMenuItem(hmenu, IDM_SOUND, (bSoundOn)?MF_CHECKED:MF_UNCHECKED);
- CheckMenuItem(hmenu, IDM_COLOUR, (bFlashOn)?MF_CHECKED:MF_UNCHECKED);
- CheckMenuItem(hmenu, IDM_MODEL3, (bModel3)?MF_CHECKED:MF_UNCHECKED);
- CheckMenuItem(hmenu, IDM_DEBUG, MF_UNCHECKED);
- break;
-
- //case WM_TIMER:
- // break;
-
- case WM_ACTIVATEAPP:
- // The application z-ordering has changed. If we are now the
- // foreground application wParm will be TRUE.
- fAppActive = (BOOL)wParam;
- break;
-
- case WM_ERASEBKGND:
- return TRUE;
- /* break; */
-
- case WM_SIZE:
- // This message comes to us because the window size has been
- // changed. It also comes to us when the application is first
- // being executed.
- dxClient = LOWORD(lParam); // The 'new' width of our window
- dyClient = HIWORD(lParam); // The 'new' height of our window
-
- if(!hdcImage) {
- // Create a new WinGDC and 8-bit WinGBitmap
- HBITMAP hbm;
- int Counter;
- HDC Screen;
- //RGBQUAD far *pColorTable;
-
- // Get WinG to recommend the fastest DIB format
- #if defined(WIN32)
- if (FALSE) {
- #else
- if(WinGRecommendDIBFormat((BITMAPINFO far *)&image.bi)) {
- #endif
- // make sure it's 8bpp and remember the orientation
- image.bi.biBitCount = 8;
- image.bi.biCompression = BI_RGB;
- Orientation = -1;
- }
- else {
- // set it up ourselves
- image.bi.biSize = sizeof(BITMAPINFOHEADER);
- image.bi.biPlanes = 1;
- image.bi.biBitCount = 8;
- image.bi.biCompression = BI_RGB;
- image.bi.biSizeImage = 0;
- image.bi.biClrUsed = 0;
- image.bi.biClrImportant = 0;
- }
-
- image.bi.biWidth = X_CORD;
- image.bi.biHeight = Y_CORD * Orientation;
-
- // create an identity palette from the DIB's color table
-
- // Get the Device Context of the screen
- Screen = GetDC(HWND_DESKTOP);
-
-
- // Get the 20 system colors as PALETTEENTRIES
- GetSystemPaletteEntries(Screen,0,10,LogicalPalette.aEntries);
- GetSystemPaletteEntries(Screen,246,10,LogicalPalette.aEntries
- + 246);
-
- // Only a few DCs available, free this up so we aren't a hog
- ReleaseDC(0,Screen);
-
- // Initialize the logical palette and DIB color table
- // Note that we are doing this as double entries. Making
- // sure that we keep both tables -identical- this is to
- // make sure that we can end up with an 'identity palette'
- // which means that both the colortable assigned to the DIB
- // and the palette entries associated with the palette
- // that is selected into the Device Context are identical.
- for(Counter = 0; Counter < 10; Counter++) {
- // copy the system colors into the DIB header
- // WinG will do this in WinGRecommendDIBFormat,
- // but it may have failed above so do it here anyway
-
- // The low end colors...
- image.aColors[Counter].rgbRed =
- LogicalPalette.aEntries[Counter].peRed;
- image.aColors[Counter].rgbGreen =
- LogicalPalette.aEntries[Counter].peGreen;
- image.aColors[Counter].rgbBlue =
- LogicalPalette.aEntries[Counter].peBlue;
- image.aColors[Counter].rgbReserved = 0;
- LogicalPalette.aEntries[Counter].peFlags = 0;
-
- // And the high end colors...
- image.aColors[Counter + 246].rgbRed =
- LogicalPalette.aEntries[Counter + 246].peRed;
- image.aColors[Counter + 246].rgbGreen =
- LogicalPalette.aEntries[Counter + 246].peGreen;
- image.aColors[Counter + 246].rgbBlue =
- LogicalPalette.aEntries[Counter + 246].peBlue;
- image.aColors[Counter + 246].rgbReserved = 0;
- LogicalPalette.aEntries[Counter + 246].peFlags = 0;
- }
-
- // Now fill in all of the colors in the middle to reflect
- // the colors that we are wanting.
- for(Counter = 10;Counter < (10+16);Counter++) {
- image.aColors[Counter].rgbRed =
- LogicalPalette.aEntries[Counter].peRed =
- rgbvals[Counter-10][0];
- image.aColors[Counter].rgbGreen =
- LogicalPalette.aEntries[Counter].peGreen =
- rgbvals[Counter-10][1];
- image.aColors[Counter].rgbBlue =
- LogicalPalette.aEntries[Counter].peBlue =
- rgbvals[Counter-10][2];
- image.aColors[Counter].rgbReserved = 0;
-
- // In order for this to be an identity palette, it is
- // important that we not only get this color, but that
- // we get it in THIS location. Using PC_NOCOLLAPSE tells
- // the system not to 'collapse' this entry to another
- // palette entry that already has this color.
- LogicalPalette.aEntries[Counter].peFlags = PC_NOCOLLAPSE;
- }
-
- // The logical palette table is fully initialized.
- // All we have to do now, is create it.
- hpalApp = CreatePalette((LOGPALETTE far *)&LogicalPalette);
-
- // Create a WinGDC and Bitmap, then select away
- #if defined (WIN32)
- // Create a DC compatible with current screen
- hdcImage = CreateCompatibleDC (NULL);
- #else
- hdcImage = WinGCreateDC();
- #endif
- image.bi.biWidth = X_CORD;
- image.bi.biHeight = Y_CORD * Orientation;
-
- #if defined (WIN32)
- hbm = CreateDIBSection (hdcImage, (BITMAPINFO far *)&image.bi, DIB_PAL_COLORS, &image.lpvData, NULL, 0);
- #else
- hbm = WinGCreateBitmap(hdcImage,(BITMAPINFO far *)&image.bi, &image.data.lpvData);
- #endif
- // Make sure that 'biSizeImage' reflects the
- // size of the bitmap data.
- image.bi.biSizeImage = (image.bi.biWidth * image.bi.biHeight);
- image.bi.biSizeImage *= Orientation;
- // Store the old hbitmap to select back in before deleting
- gbmOldMonoBitmap = (HBITMAP)SelectObject(hdcImage, hbm);
- PatBlt(hdcImage, 0,0,dxClient,dyClient, BLACKNESS);
- }
- break;
-
- case WM_COMMAND:
- return AppCommand(hwnd, msg, wParam, lParam);
-
- case WM_PALETTECHANGED:
- if ((HWND)wParam == hwnd) {
- break;
- }
-
- // fall through to WM_QUERYNEWPALETTE
-
- case WM_QUERYNEWPALETTE:
- hdc = GetDC(hwnd);
-
- if (hpalApp) {
- SelectPalette(hdc, hpalApp, FALSE);
- }
-
- uMappedColors = RealizePalette(hdc);
- ReleaseDC(hwnd,hdc);
-
- if (uMappedColors>0) {
- InvalidateRect(hwnd,NULL,TRUE);
- return TRUE;
- }
- else
- {
- return FALSE;
- }
- /* break; */
-
-
- case WM_PAINT:
-
- if(NotPaused && bFlashOn)
- do_flash(); // Spectrum specific
-
- // hack for flushing byte buffer
- writebyte(0x4000, readbyte(0x4000) );
-
- // Update main window
- hdc = BeginPaint(hwnd,&ps);
- SelectPalette(hdc, hpalApp, FALSE);
- RealizePalette(hdc);
- AppPaint (hwnd,hdc);
- EndPaint(hwnd,&ps);
- return 0L;
-
- case WM_KEYDOWN:
- /* map PC keys in the array that simulates the
- Spectrum keyboard (key down)
- */
- switch(wParam)
- {
- case '1': keybd_buff[3] |= ~0xFE; break;
- case '2': keybd_buff[3] |= ~0xFD; break;
- case '3': keybd_buff[3] |= ~0xFB; break;
- case '4': keybd_buff[3] |= ~0xF7; break;
- case '5': keybd_buff[3] |= ~0xEF; break;
- case 'Q': keybd_buff[2] |= ~0xFE; break;
- case 'W': keybd_buff[2] |= ~0xFD; break;
- case 'E': keybd_buff[2] |= ~0xFB; break;
- case 'R': keybd_buff[2] |= ~0xF7; break;
- case 'T': keybd_buff[2] |= ~0xEF; break;
- case 'A': keybd_buff[1] |= ~0xFE; break;
- case 'S': keybd_buff[1] |= ~0xFD; break;
- case 'D': keybd_buff[1] |= ~0xFB; break;
- case 'F': keybd_buff[1] |= ~0xF7; break;
- case 'G': keybd_buff[1] |= ~0xEF; break;
- case VK_SHIFT:
- if(((lParam >> 16) & 0x7F) == 0x2A)
- keybd_buff[0] |= ~0xFE; /* CAPS SHIFT */
- else
- keybd_buff[7] |= ~0xFD; /* SYMBOL SHIFT */
- break;
- case 'Z': keybd_buff[0] |= ~0xFD; break;
- case 'X': keybd_buff[0] |= ~0xFB; break;
- case 'C': keybd_buff[0] |= ~0xF7; break;
- case VK_DIVIDE:
- keybd_buff[7] |= ~0xFD;
- case 'V': keybd_buff[0] |= ~0xEF; break;
- case '0': keybd_buff[4] |= ~0xFE; break;
- case '9': keybd_buff[4] |= ~0xFD; break;
- case '8': keybd_buff[4] |= ~0xFB; break;
- case '7': keybd_buff[4] |= ~0xF7; break;
- case '6': keybd_buff[4] |= ~0xEF; break;
- case 'P': keybd_buff[5] |= ~0xFE; break;
- case 'O': keybd_buff[5] |= ~0xFD; break;
- case 'I': keybd_buff[5] |= ~0xFB; break;
- case 'U': keybd_buff[5] |= ~0xF7; break;
- case 'Y': keybd_buff[5] |= ~0xEF; break;
- case VK_RETURN: keybd_buff[6] |= ~0xFE; break;
- case 'L': keybd_buff[6] |= ~0xFD; break;
- case VK_ADD:
- keybd_buff[7] |= ~0xFD;
- case 'K': keybd_buff[6] |= ~0xFB; break;
- case VK_SUBTRACT:
- keybd_buff[7] |= ~0xFD;
- case 'J': keybd_buff[6] |= ~0xF7; break;
- case 'H': keybd_buff[6] |= ~0xEF; break;
-
- case VK_ESCAPE:
- keybd_buff[0] |= ~0xFE; /* CAPS SHIFT */
-
- case VK_SPACE: keybd_buff[7] |= ~0xFE; break;
- case 'M': keybd_buff[7] |= ~0xFB; break;
- case 'N': keybd_buff[7] |= ~0xF7; break;
- case VK_MULTIPLY:
- keybd_buff[7] |= ~0xFD;
- case 'B': keybd_buff[7] |= ~0xEF; break;
-
-
- /* Special keys */
- case VK_TAB: keybd_buff[0] |= ~0xFE;
- keybd_buff[7] |= ~0xFD;
- break;
-
- case VK_BACK: keybd_buff[0] |= ~0xFE; /* CAPS SHIFT */
- keybd_buff[4] |= ~0xFE;
- break;
-
- /* kempston joystick */
- case VK_LEFT: joystick |= 2; break;
- case VK_RIGHT: joystick |= 1; break;
- case VK_UP: joystick |= 8; break;
- case VK_DOWN: joystick |= 4; break;
- case VK_CONTROL: joystick |= 16; break;
- /* Sinclair joystick */
- case VK_NUMPAD5:
- case VK_NUMPAD0: keybd_buff[0] |= ~0xFE;
- keybd_buff[4] |= ~0xFE; /* 0 - fire */
- break;
- case VK_NUMPAD4: keybd_buff[0] |= ~0xFE;
- keybd_buff[3] |= ~0xEF; /* 5 - left */
- break;
- case VK_NUMPAD6: keybd_buff[0] |= ~0xFE;
- keybd_buff[4] |= ~0xFB; /* 8 - right */
- break;
- case VK_NUMPAD8: keybd_buff[0] |= ~0xFE;
- keybd_buff[4] |= ~0xF7; /* 7 - up */
- break;
- case VK_NUMPAD2: keybd_buff[0] |= ~0xFE;
- keybd_buff[4] |= ~0xEF; /* 6 - down */
- break;
- }
- return 0L;
-
- case WM_KEYUP:
- /* map PC keys in the array that simulates the
- Spectrum keyboard (key up)
- */
- switch(wParam)
- {
- case '1': keybd_buff[3] &= 0xFE; break;
- case '2': keybd_buff[3] &= 0xFD; break;
- case '3': keybd_buff[3] &= 0xFB; break;
- case '4': keybd_buff[3] &= 0xF7; break;
- case '5': keybd_buff[3] &= 0xEF; break;
- case 'Q': keybd_buff[2] &= 0xFE; break;
- case 'W': keybd_buff[2] &= 0xFD; break;
- case 'E': keybd_buff[2] &= 0xFB; break;
- case 'R': keybd_buff[2] &= 0xF7; break;
- case 'T': keybd_buff[2] &= 0xEF; break;
- case 'A': keybd_buff[1] &= 0xFE; break;
- case 'S': keybd_buff[1] &= 0xFD; break;
- case 'D': keybd_buff[1] &= 0xFB; break;
- case 'F': keybd_buff[1] &= 0xF7; break;
- case 'G': keybd_buff[1] &= 0xEF; break;
- case VK_SHIFT:
- if(((lParam >> 16) & 0x7F) == 0x2A)
- keybd_buff[0] &= 0xFE; /* CAPS SHIFT */
- else
- keybd_buff[7] &= 0xFD; /* SYMBOL SHIFT */
- break;
- case 'Z': keybd_buff[0] &= 0xFD; break;
- case 'X': keybd_buff[0] &= 0xFB; break;
- case 'C': keybd_buff[0] &= 0xF7; break;
- case VK_DIVIDE:
- keybd_buff[7] &= 0xFD;
- case 'V': keybd_buff[0] &= 0xEF; break;
- case '0': keybd_buff[4] &= 0xFE; break;
- case '9': keybd_buff[4] &= 0xFD; break;
- case '8': keybd_buff[4] &= 0xFB; break;
- case '7': keybd_buff[4] &= 0xF7; break;
- case '6': keybd_buff[4] &= 0xEF; break;
- case 'P': keybd_buff[5] &= 0xFE; break;
- case 'O': keybd_buff[5] &= 0xFD; break;
- case 'I': keybd_buff[5] &= 0xFB; break;
- case 'U': keybd_buff[5] &= 0xF7; break;
- case 'Y': keybd_buff[5] &= 0xEF; break;
- case VK_RETURN:keybd_buff[6] &= 0xFE; break;
- case 'L': keybd_buff[6] &= 0xFD; break;
- case VK_ADD:
- keybd_buff[7] &= 0xFD;
- case 'K': keybd_buff[6] &= 0xFB; break;
- case VK_SUBTRACT:
- keybd_buff[7] &= 0xFD;
- case 'J': keybd_buff[6] &= 0xF7; break;
- case 'H': keybd_buff[6] &= 0xEF; break;
-
- case VK_ESCAPE:
- keybd_buff[0] &= 0xFE; /* CAPS SHIFT */
-
- case VK_SPACE: keybd_buff[7] &= 0xFE; break;
- case 'M': keybd_buff[7] &= 0xFB; break;
- case 'N': keybd_buff[7] &= 0xF7; break;
- case VK_MULTIPLY:
- keybd_buff[7] &= 0xFD;
- case 'B': keybd_buff[7] &= 0xEF; break;
- case VK_TAB:
- keybd_buff[0] &= 0xFE;
- keybd_buff[7] &= 0xFD;
- break;
-
- case VK_BACK: keybd_buff[0] &= 0xFE; /* CAPS SHIFT */
- keybd_buff[4] &= 0xFE;
- break;
-
- /* kempston joystick */
- case VK_LEFT: joystick &= ~2; break;
- case VK_RIGHT: joystick &= ~1; break;
- case VK_UP: joystick &= ~8; break;
- case VK_DOWN: joystick &= ~4; break;
- case VK_CONTROL: joystick &= ~16; break;
-
- /* Sinclair joystick */
- case VK_NUMPAD5:
- case VK_NUMPAD0: keybd_buff[0] &= 0xFE;
- keybd_buff[4] &= 0xFE; /* 0 - fire */
- break;
- case VK_NUMPAD4: keybd_buff[0] &= 0xFE;
- keybd_buff[3] &= 0xEF; /* 5 - left */
- break;
- case VK_NUMPAD6: keybd_buff[0] &= 0xFE;
- keybd_buff[4] &= 0xFB; /* 8 - right */
- break;
- case VK_NUMPAD8: keybd_buff[0] &= 0xFE;
- keybd_buff[4] &= 0xF7; /* 7 - up */
- break;
- case VK_NUMPAD2: keybd_buff[0] &= 0xFE;
- keybd_buff[4] &= 0xEF; /* 6 - down */
- break;
-
- /* shortcut key for saveas and load a' la Z80 */
-
- case VK_F2:
- PostMessage(hwnd, WM_COMMAND, IDM_SAVEAS, 0L);
- break;
-
- case VK_F3:
- PostMessage(hwnd, WM_COMMAND, IDM_OPEN, 0L);
- break;
-
- /* for PAUSE */
- case VK_F4:
- PostMessage(hwnd, WM_COMMAND, IDM_PAUSE, 0L);
- break;
-
- /* for RESET */
- case VK_F5:
- PostMessage(hwnd, WM_COMMAND, IDM_RESET, 0L);
- break;
-
- }
- return 0L;
-
- case WM_DROPFILES: // handles drag-and-drop messages (files)
- {
- HANDLE Handle = (HANDLE)wParam;
- int nFileLength; // length of file name
- char *pszFileName; // name of file
-
- nFileLength = DragQueryFile( Handle , 0 , NULL, 0 );
- pszFileName = (char*)malloc(nFileLength + 1);
- DragQueryFile( Handle , 0, pszFileName, nFileLength + 1 );
- DragFinish( Handle ); // signal reception of message
- open_sna(pszFileName); // open file
- free((char *)pszFileName); // free buffer
-
- // handle special case if paused
- if(!NotPaused)
- {
- NotPaused = 1;
- PostMessage(hwnd, WM_COMMAND, IDM_PAUSE, 0L);
- }
-
- return 0L;
- }
-
- case WM_CLOSE: // finish application
- DragAcceptFiles( hwnd , FALSE ); // close drag-and-drop
- /*KillTimer (hwnd, ID_TIMER) ;*/
- #if defined(WINDOWS_SOUND)
- // Close wave driver
- CloseSnd();
- #endif
- DestroyWindow(hwnd);
- PostQuitMessage(0);
- break;
-
- }
-
- // pass messages to windows default handler
- return DefWindowProc(hwnd,msg,wParam,lParam);
- }
-
-
- /*----------------------------------------------------------------------------*\
- | AppPaint(hwnd, hdc) |
- | |
- | Description: |
- | The paint function. |
- | |
- | Arguments: |
- | hwnd window painting into |
- | hdc display context to paint to |
- | |
- | Returns: |
- | nothing |
- | |
- \*----------------------------------------------------------------------------*/
- BOOL AppPaint (HWND hwnd, HDC hdc)
- {
- DWORD l;
- RECT rc;
- #if defined (WIN32)
- BYTE *lpData;
- #else
- BYTE __huge *lpData;
- #endif
-
- GetClientRect (hwnd, &rc); // Get the size of the window on the screen
-
- // And slam the image onto the screen:
- #if defined (WIN32)
- // ************************
- BitBlt(hdc, 0, 0, rc.right-rc.left, rc.bottom-rc.top, hdcImage, 0, 0, SRCCOPY);
- // ************************
- #else
- WinGStretchBlt(hdc, 0, 0, rc.right-rc.left, rc.bottom-rc.top,
- hdcImage, 0, 0, X_CORD, Y_CORD);
- #endif
- WindowDirty = 0;
- return TRUE;
- }
-
- /*----------------------------------------------------------------------------*\
- | pixel_host() |
- | |
- | Description: |
- | Draw a point of (x,y) coord, of colour [colour] in the WinG bitmap |
- | |
- \*----------------------------------------------------------------------------*/
- void pixel_host(unsigned short x, unsigned short y, UCHAR colour)
- {
- // The data in our bitmap image is in 8bit chunks. Each element is an
- // index value to the colortable that is associated with the bitmap,
- // which, since we took pains to create an 'identity palette', is also
- // the same as the palette currently selected into this device context.
-
- #if defined (WIN32)
- *((BYTE *)image.data.lpIndex+((y*X_CORD)+x)) = colour+10;
- #else
- *((BYTE __huge *)image.data.lpIndex+((y*X_CORD)+x)) = colour+10;
- #endif
- }
-
-
- /*----------------------------------------------------------------------------*\
- | AppCommand(hwnd, msg, wParam, lParam ) |
- | |
- | Description: |
- | handles WM_COMMAND messages for the main window (hwndApp) |
- | of the parent window's messages. |
- | |
- \*----------------------------------------------------------------------------*/
- LONG AppCommand (HWND hwnd,UINT msg,WPARAM wParam,LPARAM lParam)
- {
- FARPROC fpAbout;
- int idItem;
- //HWND hwndCtl;
- WORD wNotifyCode;
-
- #if defined(WIN32)
- idItem = LOWORD(wParam); // WIN32: control or menu item identifier
- hwndCtl = (HWND)lParam; // WIN32: handle of control
- //wNotifyCode = HIWORD(wParam); // WIN32: notification message
- #else
- idItem = wParam; // WIN16: control or menu item identifier
- //hwndCtl = (HWND) LOWORD(lParam); // WIN16: handle of control
- //wNotifyCode = HIWORD(lParam); // WIN16: notification message
- #endif
-
- switch(idItem) {
- HMENU hmenu;
- BOOL menu_state;
- static char CaptionCopy[100];
-
- case IDM_OPEN:
- open_menu(hwndApp);
-
- // handle special case if paused
- if(!NotPaused)
- {
- NotPaused = 1;
- PostMessage(hwnd, WM_COMMAND, IDM_PAUSE, 0L);
- }
-
- InvalidateRect(hwnd,NULL,FALSE);
- break;
-
- case IDM_SAVE:
- save_snap();
- break;
-
- case IDM_SAVEAS:
- open_menu_save(hwndApp);
- InvalidateRect(hwnd,NULL,FALSE);
- break;
-
- case IDM_ABOUT:
- fpAbout = MakeProcInstance ((FARPROC)AppAbout, hInstApp);
- DialogBox(hInstApp, szAppName, hwnd, (DLGPROC)fpAbout);
- InvalidateRect(hwnd,NULL,FALSE);
- FreeProcInstance (fpAbout);
- break;
-
- case IDM_FILERELOAD:
- reload_snap();
- break;
-
- case IDM_EXIT:
- PostMessage(hwnd,WM_CLOSE,0,0L);
- break;
-
-
- case IDM_PAUSE:
- {
- NotPaused ^= 1;
- if(!NotPaused)
- {
- // Just force a redraw
- InvalidateRect (hwndApp, NULL, FALSE);
-
- GetWindowText(hwnd, CaptionCopy, 99);
- SetWindowText(hwnd, "Spectrum Emulator [Paused]" );
- }
- else
- SetWindowText(hwnd, CaptionCopy);
- }
- break;
-
- case IDM_POKE:
- {
- FARPROC lpProcedure;
- HINSTANCE hInst;
-
- hInst=(HINSTANCE)GetWindowWord(hwnd,GWW_HINSTANCE);
- lpProcedure=MakeProcInstance((FARPROC)DoPoke,hInst);
- DialogBox(hInst,(LPCSTR)MAKEINTRESOURCE(SP_POKE),
- hwnd,(DLGPROC)lpProcedure);
- FreeProcInstance(lpProcedure);
- InvalidateRect(hwnd,NULL,FALSE);
- break;
- }
-
- case IDM_SPEED:
- {
- FARPROC lpProcedure;
- HINSTANCE hInst;
-
- hInst=(HINSTANCE)GetWindowWord(hwnd,GWW_HINSTANCE);
- lpProcedure=MakeProcInstance((FARPROC)DoSpeed,hInst);
- DialogBox(hInst,(LPCSTR)MAKEINTRESOURCE(SP_SPEED),
- hwnd,(DLGPROC)lpProcedure);
- FreeProcInstance(lpProcedure);
- InvalidateRect(hwnd,NULL,FALSE);
- break;
- }
-
- case IDM_RESET:
- do_reset();
- if(NotPaused)
- {
- SetWindowText(hwnd, "Spectrum Emulator" );
- }
- else
- strcpy(CaptionCopy, "Spectrum Emulator");
- break;
-
- case IDM_NMI:
- do_nmi_int();
- break;
-
- case IDM_SOUND:
- bSoundOn ^= 1;
- hmenu = GetMenu(hwnd);
- CheckMenuItem(hmenu, IDM_SOUND, bSoundOn? MF_CHECKED :MF_UNCHECKED);
- break;
-
- case IDM_COLOUR:
- bFlashOn ^= 1;
- hmenu = GetMenu(hwnd);
- CheckMenuItem(hmenu, IDM_COLOUR,
- bFlashOn? MF_CHECKED : MF_UNCHECKED);
- break;
-
- case IDM_MODEL3:
- bModel3 ^= 1;
- hmenu = GetMenu(hwnd);
- CheckMenuItem(hmenu, IDM_MODEL3,
- bModel3? MF_CHECKED : MF_UNCHECKED);
- break;
-
- case IDM_SIZE1:
- Scale = 1;
- ResizeWindow();
- break;
-
- case IDM_SIZE2:
- Scale = 2;
- ResizeWindow();
- break;
-
- case IDM_SIZE3:
- Scale = 3;
- ResizeWindow();
- break;
-
- case IDM_SIZE4:
- Scale = 4;
- ResizeWindow();
- break;
-
- case IDM_SAVEOPTIONS:
- {
- char szBuf[260];
-
- GetWindowsDirectory((LPSTR)szBuf, 259);
- strcat(szBuf, "\\wspecem.ini");
-
- save_sna((LPSTR)szBuf);
- }
- break;
- }
- return 0L; // returning '0' means we processed this message.
- }
-
-
- /*----------------------------------------------------------------------------*\
- | AppAbout( hDlg, uiMessage, wParam, lParam ) |
- | |
- | Description: |
- | This function handles messages belonging to the "About" dialog box. |
- | The only message that it looks for is WM_COMMAND, indicating the use |
- | has pressed the "OK" button. When this happens, it takes down |
- | the dialog box. |
- | |
- | Arguments: |
- | hDlg window handle of about dialog window |
- | uiMessage message number |
- | wParam message-dependent |
- | lParam message-dependent |
- | |
- | Returns: |
- | TRUE if message has been processed, else FALSE |
- | |
- \*----------------------------------------------------------------------------*/
- BOOL FAR PASCAL AppAbout(HWND hwnd,UINT msg,WPARAM wParam,LPARAM lParam)
- {
- int idItem;
- //HWND hwndCtl;
- //WORD wNotifyCode;
-
- switch (msg) {
- case WM_INITDIALOG:
- // Here is where you could move the dialog around, change
- // some of the text that is going to be displayed, or other
- // things that you want to have happen right before the
- // dialog is brought up.
- return TRUE;
-
- case WM_COMMAND:
- // A 'command' has been recieved by the dialog. Very few are
- // actually possible in this dialog. Usually just the 'OK' button
- #if defined(WIN32)
- idItem = LOWORD(wParam); // WIN32: control or menu item identifier
- //hwndCtl = (HWND)lParam; // WIN32: handle of control
- wNotifyCode = HIWORD(wParam); // WIN32: notification message
- #else
- idItem = wParam; // WIN16: control or menu item identifier
- //hwndCtl = (HWND) LOWORD(lParam); // WIN16: handle of control
- //wNotifyCode = HIWORD(lParam); // WIN16: notification message
- #endif
- if (idItem == IDOK) {
- EndDialog(hwnd,TRUE);
- }
- break;
-
- }
- return FALSE;
- }
-
-
-
- /*----------------------------------------------------------------------------*\
- | AppExit() |
- | |
- | Description: |
- | app is just about to exit, cleanup |
- | |
- \*----------------------------------------------------------------------------*/
- void AppExit()
- {
- // Clean up after ourselves...
-
- if (hdcImage) {
- // Remove our Device Context that we got from WinG:
- HBITMAP hbm;
-
- // Its not nice to delete a bitmap that is selected into a Device
- // Context, so lets swap in the original bitmap, which will return
- // to us our custom bitmap. You -did- remember to save the original
- // bitmap didn't you?
- hbm = (HBITMAP)SelectObject(hdcImage, gbmOldMonoBitmap);
-
- // Now we can delete the bitmap...
- DeleteObject(hbm);
-
- // ...and the Device Context
- DeleteDC(hdcImage);
- }
-
- if(hpalApp) {
- // And finally remove our Palette:
- DeleteObject(hpalApp);
- }
- Close_Z80Emu();
- }
-
-
-
-
- // Should be at snasave.c, but it needs to much windows specific info
- int save_pcx(HFILE hfp)
- {
- long i;
- UCHAR __huge * p;
- UCHAR byte;
- UCHAR f_time = 1;
-
- putbyte(10, hfp); /* Manufacturer == Paintbrush PCX */
- putbyte(5, hfp); /* 3.0 with palette info */
- putbyte(1, hfp); /* .PCX run-length encoding */
-
- putbyte(4, hfp); /* bits per pixel */
- put2(0, hfp); /* COORDS */
- put2(0, hfp);
- put2(X_CORD-1, hfp);
- put2(Y_CORD-1, hfp);
- put2(X_CORD, hfp); /* Horizontal resolution */
- put2(Y_CORD, hfp); /* Vertical resolution */
-
- /* Save Pallete as RGB, 16 colours */
- for(i = 0 ; i < 16 ; i++)
- {
- putbyte(rgbvals[i][0], hfp);
- putbyte(rgbvals[i][1], hfp);
- putbyte(rgbvals[i][2], hfp);
- }
- putbyte(0, hfp);
- putbyte(1, hfp); /* number of colour planes */
- put2(X_CORD/2, hfp); /* bytes per line */
- for(i = 0 ; i < 60 ; i++)
- putbyte(0, hfp);
-
- /* Now save image */
- p = (UCHAR __huge *)image.data.lpIndex;
- i = ((long)X_CORD * (long)Y_CORD)/2;
-
- while(i)
- {
- byte = ((*p++)-10 << 4);
- byte = byte | ((*p++)-10);
- if(byte >= 0xC0)
- putbyte(0xC1, hfp);
- putbyte(byte, hfp);
- i--;
- }
- return 0;
- }
-
- /* buggy function --- if it's corrected we'll save .BMP too
- int save_dib(HFILE hfp)
- {
- long i;
-
- UCHAR __huge * p;
- BITMAPFILEHEADER i_block;
- */
- // I suspected the problem is between this line
- /*
- i_block.bfType = 0x4d42;
- i_block.bfSize = (long)X_CORD * (long)Y_CORD+sizeof(BITMAPINFOHEADER)+
- sizeof(RGBQUAD) * 256 + sizeof(BITMAPFILEHEADER);
- i_block.bfReserved1 = 0;
- i_block.bfReserved2 = 0;
- i_block.bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(RGBQUAD)*256
- + image.bi.biSize;
- */
- // and this one. Someone will give it a try?
-
- /*p = (UCHAR __huge *)&i_block;
- i=sizeof(BITMAPFILEHEADER);
- while(i--)
- putbyte(*p++, hfp);
-
- p = (UCHAR __huge *)&image.bi;
- i=sizeof(BITMAPINFOHEADER);
- while(i--)
- putbyte(*p++, hfp);
-
- p = (UCHAR __huge *)image.aColors;
- i=sizeof(RGBQUAD)*256;
- while(i --)
- putbyte(*p++, hfp);
-
- p = (UCHAR __huge *)image.data.lpIndex;
- i = (long)X_CORD * (long)Y_CORD;
- while(i--)
- putbyte(*p++, hfp);
-
-
- return 0;
- }
- */
- /* EOF: WSpecem.c */
-