/*
    bomb - automatic interactive visual stimulation
    Copyright (C) 1994  Scott Draves <spot@cs.cmu.edu>

    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.
*/



#include <windows.h>
#if use_ddraw
#include <windowsx.h>
#include <ddraw.h>
#include <stdlib.h>
#include <stdarg.h>
#include <stdio.h> 
// #include "ddutil.h"
#endif

#include "defs.h"
#include "bomb.h"
#include "resource.h"
static char szAppName[] = "Bomb" ;

#define disable_cmaps 0

HWND hwnd;

#ifdef use_ddraw

#define TIMER_ID        1
#define TIMER_RATE      250

LPDIRECTDRAW            lpDD;           // DirectDraw object
LPDIRECTDRAWSURFACE     lpDDSPrimary;   // DirectDraw primary surface
LPDIRECTDRAWSURFACE     lpDDSBack;      // DirectDraw back surface
LPDIRECTDRAWPALETTE     lpDDPal;        // DirectDraw palette
BOOL                    bActive;        // is application active?

PALETTEENTRY ape[256];

void image8_set_cmap(int first, int n, int *cmap) {
	int i;
#if disable_cmaps
	return;
#endif
	for (i = 0; i < n; i++) {
		ape[i].peRed = cmap[i*3];
		ape[i].peGreen = cmap[i*3+1];
		ape[i].peBlue = cmap[i*3+2];
		ape[i].peFlags = 0;
//		ape[i].peFlags = PC_NOCOLLAPSE;
	}

	if (DD_OK != lpDDPal->SetEntries(0, first, n, ape)) {
		MessageBox( hwnd, "Set Entries failed", szAppName, MB_OK );
        DestroyWindow( hwnd );
	    exit(0);
	}
}

#define KB_SIZE 10
extern "C" {
	extern int key_buffer[KB_SIZE];
    extern int kb0, kb1;
	extern void DrawBitmap(HDC hdc, HBITMAP hBitmap);
	extern char status_string[status_string_length];
	extern int display_fps;
    BOOL doInit( HINSTANCE hInstance, int nCmdShow );
}
void draw_status(HDC hdc) {
   RECT r;

		r.left = 0;
		r.right = 640;
		r.top = 400;
		r.bottom = 480;

	    FillRect(hdc, &r, (HBRUSH)GetStockObject(BLACK_BRUSH));
	    if (display_fps) {
		  SetTextColor(hdc, RGB(255,255,255));
		  SetBkColor(hdc, RGB(0,0,0));
	      TextOut(hdc, 10, 403, status_string, status_string_length);
		}
}

#if 0
void image8_flush() {
	HBITMAP bm;
	int i, j;
 	HDC hdc;
    extern image8_t fb;
	extern int frame;
	extern double fps;
    hdc = GetDC (hwnd) ;

	if (1) {
		bm = CreateBitmap(320, 200, 1, 8, fb.p);
		DrawBitmap(hdc, bm);
		DeleteObject(bm);
	}
	draw_status(hdc)

	ReleaseDC (hwnd, hdc) ;
}
#endif

#if 1
void image8_flush() {
   int i, j;
   LPDIRECTDRAWSURFACE surf;
    DDSURFACEDESC  ddsd;
	HRESULT r;

	surf = lpDDSBack;
    ddsd.dwSize = sizeof( ddsd );

  if (DD_OK != (r = surf->Lock(NULL,&ddsd,DDLOCK_WAIT|DDLOCK_SURFACEMEMORYPTR,NULL))) {
	  char buf[100];
	  if (r == E_INVALIDARG)
		  sprintf(buf, "%x->lock returned E_INVALIDARG",surf);
	  else
	      sprintf(buf, "lock returned fac=%d code=%d", (r>>16)&0x07ff, r&0xffff);
      MessageBox( hwnd, buf, szAppName, MB_OK );
      DestroyWindow( hwnd );  
	  exit(0);
  }


#if 1
  int s = ddsd.lPitch;
  for (i = 0; i < 200; i++) {
     char *p = ((char*)ddsd.lpSurface + 2 * i * s);
     char *q = (char*)(fb.p + i * fb.stride);
     for (j = 0; j < 320; j ++) {
		char t0 = q[0];
		p[0] = t0;  p[1] = t0;
		p[s] = t0;  p[1+s] = t0;
		q += 1;
		p += 2;
       }
	 }
#endif

	HDC hdc;
    surf->Unlock(0);
    surf->GetDC(&hdc);
    draw_status(hdc);
	surf->ReleaseDC(hdc);

  lpDDSPrimary->Flip(NULL, DDFLIP_WAIT);
}
#endif

/*
 * finiObjects
 *
 * finished with all objects we use; release them
 */
static void finiObjects( void )
{
    if( lpDD != NULL )
    {
        if( lpDDSPrimary != NULL )
        {
            lpDDSPrimary->Release();
            lpDDSPrimary = NULL;
        }
        if( lpDDPal != NULL )
        {
            lpDDPal->Release();
            lpDDPal = NULL;
        }
        lpDD->Release();
        lpDD = NULL;
    }

} /* finiObjects */

extern "C" int mouse_x, mouse_y, mouse_down, x_border, y_border, pix_rep;

long FAR PASCAL WindowProc( HWND hWnd, UINT message, 
                            WPARAM wParam, LPARAM lParam )
{
    static BYTE phase = 0;
    HDC         hdc;

    switch( message )
    {
    case WM_ACTIVATEAPP:
        bActive = wParam;
        break;

    case WM_CREATE:
        break;
 
    case WM_SETCURSOR:
        SetCursor(NULL);
        return TRUE;

  case WM_MOUSEMOVE:
    mouse_down = 1 && (MK_LBUTTON & wParam);
    mouse_x = (LOWORD(lParam)-x_border)/pix_rep;
    mouse_y = (HIWORD(lParam)-y_border)/pix_rep;
    return 0;

    case WM_CHAR:
    key_buffer[kb1]  = (int)wParam;
    kb1 = kb1++ % KB_SIZE;
    // if the buffer is full, throw out the oldest char
		if (kb0 == kb1)
		  kb0 = kb0++ % KB_SIZE;
		
    return 0;

    case WM_DESTROY:
        finiObjects();
        PostQuitMessage( 0 );
        break;
    }

    return DefWindowProc(hWnd, message, wParam, lParam);

} /* WindowProc */


BOOL doInit( HINSTANCE hInstance, int nCmdShow )
{
    WNDCLASS            wc;
    DDSURFACEDESC       ddsd;
    DDSCAPS             ddscaps;
    HRESULT             ddrval;

#ifndef win_saver
	wc.style = CS_HREDRAW | CS_VREDRAW;
    wc.lpfnWndProc = WindowProc;
    wc.cbClsExtra = 0;
    wc.cbWndExtra = 0;
    wc.hInstance = hInstance;
    wc.hIcon = LoadIcon( hInstance, IDI_APPLICATION );
    wc.hCursor = LoadCursor( NULL, IDC_ARROW );
    wc.hbrBackground = NULL;
    wc.lpszMenuName = szAppName;
    wc.lpszClassName = szAppName;
    RegisterClass( &wc );

    
	hwnd = CreateWindowEx(
        WS_EX_TOPMOST,
        szAppName,
        szAppName,
        WS_POPUP,
        0,
        0,
        GetSystemMetrics( SM_CXSCREEN ),
        GetSystemMetrics( SM_CYSCREEN ),
        NULL,
        NULL,
        hInstance,
        NULL );

    if( !hwnd )  { return FALSE;  }

    ShowWindow( hwnd, nCmdShow );
    UpdateWindow( hwnd );
#endif

    ddrval = DirectDrawCreate( NULL, &lpDD, NULL );
    if( ddrval != DD_OK ) goto error;

    ddrval = lpDD->SetCooperativeLevel( hwnd, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN );
    if(ddrval != DD_OK ) goto error;

    ddrval = lpDD->SetDisplayMode( 640, 480, 8);
    if(ddrval != DD_OK) goto error;

    // Create the primary surface with 1 back buffer
    ddsd.dwSize = sizeof( ddsd );
    ddsd.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT;
    ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE |
                          DDSCAPS_FLIP |
                          DDSCAPS_COMPLEX;
    ddsd.dwBackBufferCount = 1;
    ddrval = lpDD->CreateSurface( &ddsd, &lpDDSPrimary, NULL );
    if( ddrval != DD_OK ) goto error;

    ddscaps.dwCaps = DDSCAPS_BACKBUFFER;
    ddrval = lpDDSPrimary->GetAttachedSurface(&ddscaps, &lpDDSBack);

    if( ddrval != DD_OK )  goto error;
	if (1) {
	   fb.p = (u_char *) malloc(320*200);
	   fb.stride = 320;
	   fb.width = 320;
	   fb.height = 200;
	}

#if !disable_cmaps
    lpDD->CreatePalette(DDPCAPS_8BIT, ape, &lpDDPal, NULL);
    if (lpDDPal == NULL)  goto error;

    ddrval = lpDDSPrimary->SetPalette(lpDDPal);
    if( ddrval != DD_OK ) goto error;
#endif

    return TRUE;

error:
    finiObjects();
    MessageBox( hwnd, "DirectDraw Init FAILED", szAppName, MB_OK );
    DestroyWindow( hwnd );
    return FALSE;
} /* doInit */


#ifndef win_saver

extern "C" void init_sound();

int PASCAL WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance,
                        LPSTR lpCmdLine, int nCmdShow)
{
    MSG         msg;


    lpCmdLine = lpCmdLine;
    hPrevInstance = hPrevInstance;

    if( !doInit( hInstance, nCmdShow ) )
    {
        return FALSE;
    }
	read_registry();
	init();
	write_registry();
	rule_mask = -1;

	while (1) {
      if (PeekMessage (&msg, NULL, 0, 0, PM_NOREMOVE)) {

         if (GetMessage(&msg, NULL, 0, 0))
         {
            TranslateMessage(&msg);
            DispatchMessage(&msg);
         }   else {
	  	   win_exit();
	 	  return msg.wParam;
	     }
	  }
	  work();
    }

    return msg.wParam;

} /* WinMain */

#endif

#endif


