//**************************************************************************
//*                     This file is part of the                           *
//*                      Mpxplay - audio player.                           *
//*                  The source code of Mpxplay is                         *
//*        (C) copyright 1998-2006 by PDSoft (Attila Padar)                *
//*                    http://mpxplay.cjb.net                              *
//*                  email: mpxplay@freemail.hu                            *
//**************************************************************************
//*  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.                  *
//*  Please contact with the author (with me) if you want to use           *
//*  or modify this source.                                                *
//**************************************************************************
//function: text-display handing

#include "newfunc.h"
#include "display\display.h"

unsigned long textscreen_linear_address=0xb8000;
unsigned int textscreen_mode,textscreen_maxx,textscreen_maxy,oldposrow;
extern unsigned int dispaymode;

#define TEXTSCREEN_LIN_ADDR textscreen_linear_address

static unsigned int textscreen_oldmaxy,textscreen_oldcursor_y;
static unsigned int textscreen_memory_size;
static unsigned int *vidmemsave_field,vidmemsave_size;

void newfunc_textdisplay_init(void)
{
 textscreen_mode=pds_textdisplay_getmode();
 pds_textdisplay_getresolution();
 textscreen_memory_size=(textscreen_maxx+1)*(textscreen_maxy+1)*TEXTSCREEN_BYTES_PER_CHAR;
 if(vidmemsave_size<textscreen_memory_size){
  vidmemsave_size=textscreen_memory_size*2;
  if(vidmemsave_field)
   pds_free(vidmemsave_field);
  vidmemsave_field=pds_malloc(vidmemsave_size);
  if(!vidmemsave_field)
   vidmemsave_size=0;
 }
 //pds_cpu_mtrr_enable_wc(0xA0000,128);
}

void newfunc_textdisplay_close(void)
{
 //pds_cpu_mtrr_disable_wc(0xA0000);
 if(vidmemsave_field){
  pds_free(vidmemsave_field);
  vidmemsave_field=NULL;
 }
 vidmemsave_size=0;
}

void pds_textdisplay_charxy(unsigned int color,unsigned int outx,unsigned int outy,char outchar)
{
 char *addr;
 outy*=textscreen_maxx;
 outy+=outx;
 outy*=TEXTSCREEN_BYTES_PER_CHAR;
 outy+=TEXTSCREEN_LIN_ADDR;
 addr=(char *)outy;
 addr[0]=outchar;
 addr[1]=color;
}

unsigned int pds_textdisplay_textxy(unsigned int color,unsigned int outx,unsigned int outy,char *string_s)
{
 char *addr,*string=string_s;
 outy*=textscreen_maxx;
 outy+=outx;
 outy*=TEXTSCREEN_BYTES_PER_CHAR;
 outy+=TEXTSCREEN_LIN_ADDR;
 addr=(char *)outy;
 while(string[0]!=0){
  addr[0]=string[0];
  addr[1]=color;
  addr+=2;
  string++;
 }
 return (string-string_s); // lenght of string
}

unsigned int pds_textdisplay_textxyn(unsigned int color,unsigned int outx,unsigned int outy,unsigned int maxlen,char *string_s)
{
 char *addr,*string=string_s;
 outy*=textscreen_maxx;
 outy+=outx;
 outy*=TEXTSCREEN_BYTES_PER_CHAR;
 outy+=TEXTSCREEN_LIN_ADDR;
 addr=(char *)outy;
 while(string[0]!=0 && maxlen){
  addr[0]=string[0];
  addr[1]=color;
  addr+=2;
  string++;
  maxlen--;
 }
 return (string-string_s); // lenght of string
}

void pds_textdisplay_clrscr(void)
{
 const unsigned int cval=(CL_BASE<<24)|(CLB_BASE<<28)|(CL_BASE<<8)|(CLB_BASE<<12);//0x07000700;
 register unsigned int *addr=(unsigned int *)TEXTSCREEN_LIN_ADDR;
 register unsigned int len=textscreen_memory_size/sizeof(unsigned int);
 do{
  *addr++=cval;
 }while(--len);
}

void pds_textdisplay_scrollup(unsigned int num)
{
 register unsigned int *addr=(unsigned int *)TEXTSCREEN_LIN_ADDR,*saveaddr=addr;
 unsigned int i,linesize=textscreen_maxx*TEXTSCREEN_BYTES_PER_CHAR/sizeof(unsigned int);

 for(;num;num--){
  addr=saveaddr;
  i=linesize*textscreen_maxy;
  for(;i;i--){
   addr[0]=addr[linesize];
   addr++;
  }
  i=linesize;
  for(;i;i--)
   *addr++=0x07000700;
 }
}

void pds_textdisplay_printf(char *outtext)
{
 pds_textdisplay_spacecxyn(0,0,oldposrow,textscreen_maxx);
 pds_textdisplay_textxy(7,0,oldposrow,outtext);
 if(oldposrow>=textscreen_maxy)
  pds_textdisplay_scrollup(1);
 else{
  oldposrow++;
  pds_textdisplay_setcursor_position(0,oldposrow);
 }
}

unsigned int pds_textdisplay_getbkcolorxy(unsigned int outx,unsigned int outy)
{
 char *addr;
 outy*=textscreen_maxx;
 outy+=outx;
 outy*=TEXTSCREEN_BYTES_PER_CHAR;
 outy+=TEXTSCREEN_LIN_ADDR+1;
 addr=(char *)outy;
 return(addr[0]>>4);
}

void pds_textdisplay_setcolorxy(unsigned int color,unsigned int outx,unsigned int outy)
{
 unsigned char *addr;
 outy*=textscreen_maxx;
 outy+=outx;
 outy*=TEXTSCREEN_BYTES_PER_CHAR;
 outy+=TEXTSCREEN_LIN_ADDR+1;
 addr=(char *)outy;
 addr[0]&=0xf0;
 addr[0]|=color;
}

void pds_textdisplay_setbkcolorxy(unsigned int bkcolor,unsigned int outx,unsigned int outy)
{
 unsigned char *addr;
 outy*=textscreen_maxx;
 outy+=outx;
 outy*=TEXTSCREEN_BYTES_PER_CHAR;
 outy+=TEXTSCREEN_LIN_ADDR+1;
 addr=(char *)outy;
 addr[0]&=0x0f;
 addr[0]|=(bkcolor<<4);
}

void pds_textdisplay_spacecxyn(unsigned int bkcolor,unsigned int x,unsigned int y,unsigned int len)
{
 bkcolor<<=4;
 bkcolor|=7;
 for(;len;len--)
  pds_textdisplay_charxy(bkcolor,x++,y,32);
}

unsigned int pds_textdisplay_text2buf(unsigned int color,unsigned short *buf,unsigned int buflen,char *string_s)
{
 char *string=string_s;
 if(!buf)
  return 0;
 while(string[0]!=0 && buflen){
  buf[0]=((unsigned short)string[0])|((unsigned short)color<<8);
  string++;
  buf++;
  buflen--;
 }
 buf[0]=0x0000;
 return (string-string_s);
}

void pds_textdisplay_textbufxyn(unsigned int outx,unsigned int outy,unsigned short *buf,unsigned int maxlen)
{
 unsigned short *addr;
 outy*=textscreen_maxx;
 outy+=outx;
 outy*=TEXTSCREEN_BYTES_PER_CHAR;
 outy+=TEXTSCREEN_LIN_ADDR;
 addr=(unsigned short *)outy;
 while(buf[0]!=0 && maxlen){
  addr[0]=buf[0];
  addr++;
  buf++;
  maxlen--;
 }
}

//-------------------------------------------------------------------------

void pds_textdisplay_vidmem_save(void)
{
 unsigned int len;
 unsigned int *addr_scr=(unsigned int *)TEXTSCREEN_LIN_ADDR;
 unsigned int *addr_sav=vidmemsave_field;

 newfunc_textdisplay_init();

 len=min(textscreen_memory_size,vidmemsave_size);
 if(!len)
  return;

 pds_qmemcpy(addr_sav,addr_scr,len/4);

 textscreen_oldmaxy=textscreen_maxy;
 textscreen_oldcursor_y=pds_textdisplay_getcursor_y();
}

void pds_textdisplay_vidmem_restore(void)
{
 unsigned int len;
 unsigned int *addr_scr=(unsigned int *)TEXTSCREEN_LIN_ADDR;
 unsigned int *addr_sav=vidmemsave_field;

 pds_textdisplay_setresolution(textscreen_oldmaxy+1);

 len=min(textscreen_memory_size,vidmemsave_size);
 if(!len)
  return;

 pds_qmemcpy(addr_scr,addr_sav,len/4);

 pds_textdisplay_setcursor_position(0,textscreen_oldcursor_y);
}

//---------------------------------------------------------------------
//bios callings
unsigned int pds_textdisplay_setmode(unsigned int mode)
{
 union REGS regs;
 pds_newfunc_regs_clear(&regs);
 regs.w.ax=mode;
 int386(0x10, &regs, &regs);

 return 1;
}

unsigned int pds_textdisplay_getmode(void)
{
 union REGS regs;
 pds_newfunc_regs_clear(&regs);
 regs.w.ax=0x0f00;
 int386(0x10, &regs, &regs);

 return (regs.w.ax&0xff);
}

unsigned int pds_textdisplay_setlastmode(void)
{
 return pds_textdisplay_setmode(textscreen_mode);
}

void asmset50lines(void);

static void pds_textdisplay_set50lines(void)
{
#ifdef __DOS__
 #if defined(NEWFUNC_ASM) && defined(__WATCOMC__)
  #pragma aux asmset50lines=\
  "mov ax,1112h"\
  "xor ebx,ebx"\
  "int 10h"\
  modify[eax ebx ecx edx edi esi];

  /*#pragma aux asmset50lines=\
  "mov ax,1202h"\
  "mov bl,30h"\
  "int 10h"\
  "mov ax,0003h"\
  "int 10h"\
  "mov ax,1112h"\
  "mov bx,0"\
  "int 10h"\
  modify [eax ebx]*/

  asmset50lines();
 #else
  union REGS regs;
  pds_newfunc_regs_clear(&regs);
  regs.w.ax=0x1112;
  regs.w.bx=0;
  int386(0x10, &regs, &regs);
 #endif
 newfunc_textdisplay_init();
 //redefine_fonts_8x8();
#endif
}

void asmset25lines(void);

static void pds_textdisplay_set25lines(void)
{
#ifdef __DOS__
 #if defined(NEWFUNC_ASM) && defined(__WATCOMC__)
  #pragma aux asmset25lines=\
  "mov ax,1114h"\
  "xor ebx,ebx"\
  "int 10h"\
  modify[eax ebx ecx edx edi esi];

  /*#pragma aux asmset25lines=\
  "mov ax,1202h"\
  "mov bl,30h"\
  "int 10h"\
  "mov ax,0003h"\
  "int 10h"\
  "mov ax,1114h"\
  "mov bx,0"\
  "int 10h"\
  modify [eax ebx]*/

  asmset25lines();
 #else
  union REGS regs;
  pds_newfunc_regs_clear(&regs);
  regs.w.ax=0x1114;
  regs.w.bx=0;
  int386(0x10, &regs, &regs);
 #endif
 newfunc_textdisplay_init();
 //redefine_fonts_8x16();
#endif
}

void pds_textdisplay_setresolution(unsigned int lines)
{
 if(lines>=40)
  pds_textdisplay_set50lines();
 else
  pds_textdisplay_set25lines();
}

void pds_textdisplay_getresolution(void)
{
#ifdef __DOS__
 unsigned char *biosmem=(char *)0;
 textscreen_maxx=biosmem[0x44a];
 textscreen_maxy=biosmem[0x484];
#else
 textscreen_maxx=80;
 textscreen_maxy=50;
#endif
}

unsigned int pds_textdisplay_getcursor_y(void)
{
#ifdef __DOS__
 unsigned char *biosmem=(char *)0;
 return biosmem[0x451];
#else
 return 0;
#endif
}

/*void pds_textdisplay_gotoxy(unsigned int x,unsigned int y)
{
#ifdef __DOS__
 unsigned char *biosmem=(char *)0;
 biosmem[0x450]=(unsigned char)x;
 biosmem[0x451]=(unsigned char)y;
#endif
}*/

void asm_textdisplaysetcursorposition(unsigned int);

void pds_textdisplay_setcursor_position(unsigned int x,unsigned int y)
{
#ifdef __DOS__
 #if defined(NEWFUNC_ASM) && defined (__WATCOMC__)
  #pragma aux asm_textdisplaysetcursorposition=\
  "mov ax,0200h"\
  "xor ebx,ebx"\
  "int 10h"\
  parm[edx] modify[eax ebx ecx edx edi esi];
  asm_textdisplaysetcursorposition((y<<8)|x);
 #else
  union REGS regs;
  pds_newfunc_regs_clear(&regs);
  regs.w.ax=0x0200;
  regs.w.dx=((y<<8)|x);
  int386(0x10,&regs,&regs);
 #endif
#endif
}

void asm_textdisplaysetcursorshape(long);

void pds_textdisplay_setcursorshape(long value)
{
#ifdef __DOS__
 #if defined(NEWFUNC_ASM) && defined (__WATCOMC__)
  #pragma aux asm_textdisplaysetcursorshape=\
  "mov ecx,eax"\
  "mov ax,0100h"\
  "int 10h"\
  parm[eax] modify[eax ebx ecx edx edi esi];
  asm_textdisplaysetcursorshape(value);
 #else
  union REGS regs;
  pds_newfunc_regs_clear(&regs);
  regs.w.ax=0x0100;
  regs.w.cx=value;
  int386(0x10,&regs,&regs);
 #endif
#endif
}

void pds_textdisplay_resetcolorpalette(void)
{
#ifdef __DOS__
 outp(0x03c8,5);  // magenta
 outp(0x03c9,0x2a);
 outp(0x03c9,0);
 outp(0x03c9,0x2a);
#endif
}

//*************************************************************************
// character generator

/*struct{
 unsigned char code;
 unsigned char data[8];
}fontdata8[2]={{219,0x00,0xfe,0xfe,0xfe,0xfe,0xfe,0xfe,0xfe},
	      {220,0x00,0x00,0x00,0x00,0xfe,0xfe,0xfe,0xfe}};*/
// 00000000
// 00000000
// 00000000
// 00000000
// 11100000
// 00010000
// 00011000
// 00011000

/*struct{
 unsigned char code;
 unsigned char ccount;
 unsigned char data[8];
}fontdata8[10]={{219 ,0,0x00,0x6c,0x6c,0x6c,0x6c,0x6c,0x6c,0x6c},
		//{219,10,0x00,0x7e,0x7e,0x7e,0x00,0x7e,0x7e,0x7e},
		{220 ,0,0x00,0x00,0x00,0x00,0xfe,0xfe,0xfe,0xfe},

		{240 ,0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff},
		{241 ,0,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00},

		{242 ,0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0f},
		{243 ,0,0x0f,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
		{244 ,0,0xf0,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
		{245 ,0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xf0},

		{246 ,0,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08},
		{247 ,0,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10}};

void redefine_fonts_8x8(void)
{
 int c,d;
 struct rminfo RMI;

 for(c=0;c<2;c++){
  for(d=0;d<8;d++)
   dosmemput[d]=fontdata8[c].data[d];

  pds_dpmi_rmi_clear(&RMI);
  RMI.EAX = 0x00001100;
  RMI.EBX = 0x00000800;
  RMI.ECX = 0x00000001;
  RMI.EDX = fontdata8[c].code;
  RMI.ES  = segment1;
  RMI.EBP = 0;
  pds_dpmi_realmodeint_call(0x10,&RMI);
 }
}

struct{
 unsigned char code;
 unsigned char data[16];
}fontdata16[2]={
 {219,0x00,0xfe,0xfe,0xfe,0xfe,0xfe,0xfe,0xfe,0x00,0xfe,0xfe,0xfe,0xfe,0xfe,0xfe,0xfe},  // 219
 {220,0x00,0xfe,0xfe,0xfe,0xfe,0xfe,0xfe,0xfe,0x00,0xfe,0xfe,0xfe,0xfe,0xfe,0xfe,0xfe}}; // 220

void redefine_fonts_8x16(void)
{
 int c,d;
 struct rminfo RMI;

 for(c=0;c<2;c++)
  for(d=0;d<16;d++)
   dosmemput[(c*16)+d]=fontdata16[c].data[d];

 pds_dpmi_rmi_clear(&RMI);
 RMI.EAX = 0x00001100;
 RMI.EBX = 0x00001000;
 RMI.ECX = 0x00000002;
 RMI.EDX = fontdata16[0].code;
 RMI.ES  = segment1;
 RMI.EBP = 0;
 pds_dpmi_realmodeint_call(0x10,&RMI);
}*/

