// Emacs style mode select   -*- C++ -*-
//-----------------------------------------------------------------------------
//
// $Id
//
//  Copyright (C) 2004 Carlos Guariglia
//
//  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., 59 Temple Place - Suite 330, Boston, MA 
//  02111-1307, USA.
//
//
// DESCRIPTION:
//      DOOM graphics stuff
//
//-----------------------------------------------------------------------------

#include "z_zone.h"

#include <stdio.h>
#include <dpmi.h>
#include <go32.h>
#include <dos.h>

#include "doomstat.h"
#include "v_video.h"
#include "st_stuff.h"
#include "m_argv.h"
#include "w_wad.h"
#include "r_draw.h"
#include "i_system.h"

extern int usejoystick;
extern int joy_x,joy_y,joy_b1,joy_b2,joy_b3,joy_b4;

void I_StartFrame ()
{
  event_t event;

  if (!usejoystick)
    return;
  poll_joystick();
  event.type = ev_joystick;
  event.data1 = 0;

  if (joy_b1)
    event.data1 |= 1;
  if (joy_b2)
    event.data1 |= 2;
  if (joy_b3)
    event.data1 |= 4;
  if (joy_b4)
    event.data1 |= 8;

  if (joy_x < 0)
    event.data2 = -1;
  else if (joy_x > 0)
    event.data2 = 1;
  else
    event.data2 = 0;
  if (joy_y < 0)
    event.data3 = -1;
  else if (joy_y > 0)
    event.data3 = 1;
  else
    event.data3 = 0;

  D_PostEvent(&event);
}
extern int mouse_b;
extern unsigned char key_table[128];
int I_ScanCode2DoomCode (int a)
{
  switch (a)
    {
    default:   return key_table[a]>8 ? key_table[a] : a+0x80;
    case 0x7b: return KEY_PAUSE;
    case 0x0e: return KEY_BACKSPACE;
    case 0x48: return KEY_UPARROW;
    case 0x4d: return KEY_RIGHTARROW;
    case 0x50: return KEY_DOWNARROW;
    case 0x4b: return KEY_LEFTARROW;
    case 0x38: return KEY_LALT;
    case 0x79: return KEY_RALT;
    case 0x1d:
    case 0x78: return KEY_RCTRL;
    case 0x36:
    case 0x2a: return KEY_RSHIFT;
  }
}

int I_DoomCode2ScanCode (int a)
{
  static int inverse[256], cache;
  for (;cache<256;cache++)
    inverse[I_ScanCode2DoomCode(cache)]=cache;
  return inverse[a];
}

void I_StartTic()
{
 extern int usemouse;
 event_t event;
 int tail;

  while ((tail=keyboard_queue.tail) != keyboard_queue.head)
    {
      int k = keyboard_queue.queue[tail];
      keyboard_queue.tail = (tail+1) & (KQSIZE-1);
      event.type = k & 0x80 ? ev_keyup : ev_keydown;
      event.data1 = I_ScanCode2DoomCode(k & 0x7f);
      D_PostEvent(&event);
    }

  if (mousepresent!=-1 && usemouse)
      {
      static int lastbuttons;
      int xmickeys,ymickeys,buttons=mouse_b;
      get_mouse_mickeys(&xmickeys,&ymickeys);
      if (xmickeys || ymickeys || buttons!=lastbuttons)
        {
          lastbuttons=buttons;
          event.data1=buttons;
          event.data3=-ymickeys;
          event.data2=xmickeys;
          event.type=ev_mouse;
          D_PostEvent(&event);
        }
    }
}

boolean noblit;
static unsigned destscreen;

void I_FinishUpdate()
{
  if (noblit)
    return;
  if (devparm)
    {
      static int lasttic;
      byte *s = screens[0];

      int i = I_GetTime();
      int tics = i - lasttic;
      lasttic = i;
      if (tics > 20)
        tics = 20;
        {
          for (i=0 ; i<tics*2 ; i+=2)
            s[63680 + i] = 0xff;
          for ( ; i<20*2 ; i+=2)
            s[63680 + i] = 0;
        }
    }
  destscreen = (destscreen+0x4000)&0xffff;
  blast(*screens,_dos_ds,0xa0000+destscreen,4000);
  outpw(0x3d4, destscreen | 0x0c); 
}

void I_ReadScreen(byte *scr)
{
  memcpy(scr,*screens,64000);
}

void I_BeginRead()
{
V_DrawPatch(304, 184, 0, W_CacheLumpName(M_CheckParm("-cdrom") ?
                                   "STCDROM" : "STDISK", PU_CACHE));
reading = 8;
}

void I_SetPalette(byte *palette)
{
  int i;
  while (!(inportb(0x3da) & 8));
  outportb(0x3c8,0);
  for (i=256;i--;)
    {
      outportb(0x3c9,gammatable[usegamma][*palette++]>>2);
      outportb(0x3c9,gammatable[usegamma][*palette++]>>2);
      outportb(0x3c9,gammatable[usegamma][*palette++]>>2);
    }
}

void I_ShutdownGraphics()
{
__dpmi_regs r;
r.x.ax = 3;
__dpmi_int(0x10, &r);
}

extern boolean setsizeneeded;
void I_InitGraphics()
{
  __dpmi_regs r;
  asm("fninit");
  if (nodrawers)
    return;
  atexit(I_ShutdownGraphics);
  V_Init();
  r.x.ax = 0x13;
  __dpmi_int(0x10, &r);
  outpw(0x03C4,0x604);
  outpw(0x03C4,0xF02);
  outpw(0x03D4,0x14);
  outpw(0x03D4,0xE317);
  setsizeneeded = 1;
  I_SetPalette(W_CacheLumpName("PLAYPAL",PU_CACHE));
  Z_CheckHeap();
}