Added sdl stuff from the attic

This commit is contained in:
no-author 2006-07-23 03:37:43 +00:00
parent 83d450d368
commit 71fe9d6662
34 changed files with 5700 additions and 0 deletions

72
drivers/pc/dface.h Normal file
View File

@ -0,0 +1,72 @@
#ifdef __cplusplus
extern "C" {
#endif
#include "../common/args.h"
#include "../common/config.h"
#include "input.h"
extern FCEUGI *CurGame;
extern CFGSTRUCT DriverConfig[];
extern ARGPSTRUCT DriverArgs[];
extern char *DriverUsage;
void DoDriverArgs(void);
uint8 *GetBaseDirectory(void);
int InitSound(FCEUGI *gi);
void WriteSound(int32 *Buffer, int Count);
int KillSound(void);
uint32 GetMaxSound(void);
uint32 GetWriteSound(void);
void SilenceSound(int s); /* DOS and SDL */
int InitMouse(void);
void KillMouse(void);
void GetMouseData(uint32 *MouseData);
int InitJoysticks(void);
int KillJoysticks(void);
uint32 *GetJSOr(void);
int InitKeyboard(void);
int UpdateKeyboard(void);
char *GetKeyboard(void);
void KillKeyboard(void);
int InitVideo(FCEUGI *gi);
int KillVideo(void);
void BlitScreen(uint8 *XBuf);
void LockConsole(void);
void UnlockConsole(void);
void ToggleFS(); /* SDL */
int LoadGame(const char *path);
int CloseGame(void);
int GUI_Init(int argc, char **argv, int (*dofunc)(void));
int GUI_Idle(void);
int GUI_Update(void);
void GUI_Hide(int);
void GUI_RequestExit(void);
int GUI_SetVideo(int fullscreen, int width, int height);
char *GUI_GetKeyboard(void);
void GUI_GetMouseState(uint32 *b, int *x, int *y);
void UpdatePhysicalInput(void);
int DTestButton(ButtConfig *bc);
int DWaitButton(const uint8 *text, ButtConfig *bc, int wb);
int ButtonConfigBegin(void);
void ButtonConfigEnd(void);
void Giggles(int);
void DoFun(void);
int FCEUD_NetworkConnect(void);
#ifdef __cplusplus
}
#endif

200
drivers/pc/dos-joystick.c Normal file
View File

@ -0,0 +1,200 @@
/* FCE Ultra - NES/Famicom Emulator
*
* Copyright notice for this file:
* Copyright (C) 2002 Xodnizel
*
* 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
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <unistd.h>
#include <dpmi.h>
#include <sys/farptr.h>
#include <go32.h>
#include <pc.h>
#include "dos.h"
#include "dos-joystick.h"
#define JOY_A 1
#define JOY_B 2
#define JOY_SELECT 4
#define JOY_START 8
#define JOY_UP 0x10
#define JOY_DOWN 0x20
#define JOY_LEFT 0x40
#define JOY_RIGHT 0x80
int joy=0;
int joyBMap[6];
static int32 joybuttons=0;
static uint32 joyx=0;
static uint32 joyy=0;
static uint32 joyxcenter;
static uint32 joyycenter;
static void ConfigJoystick(void);
volatile int soundjoyer=0;
volatile int soundjoyeron=0;
/* Crude method to detect joystick. */
static int DetectJoystick(void)
{
uint8 b;
outportb(0x201,0);
b=inportb(0x201);
sleep(1);
if((inportb(0x201)&3)==(b&3))
return 0;
else
return 1;
}
void UpdateJoyData(void)
{
uint32 xc,yc;
joybuttons=((inportb(0x201)&0xF0)^0xF0)>>4;
xc=yc=0;
{
outportb(0x201,0);
for(;;)
{
uint8 b;
b=inportb(0x201);
if(!(b&3))
break;
if(b&1) xc++;
if(b&2) yc++;
}
}
joyx=xc;
joyy=yc;
}
uint32 GetJSOr(void)
{
int y;
unsigned long ret;
static int rtoggle=0;
ret=0;
rtoggle^=1;
if(!soundo)
UpdateJoyData();
for(y=0;y<6;y++)
if((y>=4 && rtoggle) || y<4)
if(joybuttons&joyBMap[y]) ret|=(1<<y&3)<<((joy-1)<<3);
if(joyx<=joyxcenter*.25) ret|=JOY_LEFT<<((joy-1)<<3);
else if(joyx>=joyxcenter*1.75) ret|=JOY_RIGHT<<((joy-1)<<3);
if(joyy<=joyycenter*.25) ret|=JOY_UP<<((joy-1)<<3);
else if(joyy>=joyycenter*1.75) ret|=JOY_DOWN<<((joy-1)<<3);
return ret;
}
int InitJoysticks(void)
{
if(!joy) return(0);
if(!DetectJoystick())
{
printf("Joystick not detected!\n");
joy=0;
return 0;
}
if(soundo)
{
soundjoyeron=1;
while(!soundjoyer);
}
else
UpdateJoyData();
joyxcenter=joyx;
joyycenter=joyy;
if(!(joyBMap[0]|joyBMap[1]|joyBMap[2]|joyBMap[3]))
ConfigJoystick();
return(1);
}
static void BConfig(int b)
{
int c=0;
uint32 st=time(0);
while(time(0)< (st+4) )
{
if(!soundo)
UpdateJoyData();
if(joybuttons) c=joybuttons;
else if(c && !joybuttons)
{
joyBMap[b]=c;
break;
}
}
}
void KillJoysticks(void)
{
}
static void ConfigJoystick(void)
{
static char *genb="** Press button for ";
printf("\n\n Joystick button configuration:\n\n");
printf(" Push and release the button to map to the virtual joystick.\n");
printf(" If you do not wish to assign a button, wait a few seconds\n");
printf(" and the configuration will continue.\n\n");
printf(" Press enter to continue...\n");
getchar();
printf("%s\"Select\".\n",genb);
BConfig(2);
printf("%s\"Start\".\n",genb);
BConfig(3);
printf("%s\"B\".\n",genb);
BConfig(1);
printf("%s\"A\".\n",genb);
BConfig(0);
printf("%s\"Rapid fire B\".\n",genb);
BConfig(5);
printf("%s\"Rapid fire A\".\n",genb);
BConfig(4);
}

27
drivers/pc/dos-joystick.h Normal file
View File

@ -0,0 +1,27 @@
/* FCE Ultra - NES/Famicom Emulator
*
* Copyright notice for this file:
* Copyright (C) 2002 Xodnizel
*
* 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
*/
void UpdateJoyData(void);
uint32 GetJSOr(void);
int InitJoysticks(void);
/* Variables to save in config file. */
extern int joy;
extern int joyBMap[6];

131
drivers/pc/dos-keyboard.c Normal file
View File

@ -0,0 +1,131 @@
/* FCE Ultra - NES/Famicom Emulator
*
* Copyright notice for this file:
* Copyright (C) 2002 Xodnizel
*
* 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
*/
#include <stdio.h>
#include <signal.h>
#include <string.h>
#include <pc.h>
#include <dpmi.h>
#include <go32.h>
#include "keyscan.h"
static unsigned char lastsc;
static char keybuf[256];
int newk;
/* Read scan code from port $60 */
/* Acknowledge interrupt( output $20 to port $20) */
static void ihandler(_go32_dpmi_registers *r)
{
unsigned char scode=inp(0x60); /* Get scan code. */
if(scode!=0xE0)
{
int offs=0;
/* I'm only interested in preserving the independent status of the
right ALT and CONTROL keys.
*/
if(lastsc==0xE0)
if((scode&0x7F)==SCAN_LEFTALT || (scode&0x7F)==SCAN_LEFTCONTROL)
offs=0x80;
keybuf[(scode&0x7f)|offs]=((scode&0x80)^0x80);
newk++;
}
lastsc=scode;
outp(0x20,0x20); /* Acknowledge interrupt. */
}
static _go32_dpmi_seginfo KBIBack,KBIBackRM;
static _go32_dpmi_seginfo KBI,KBIRM;
static _go32_dpmi_registers KBIRMRegs;
static int initdone=0;
int InitKeyboard(void)
{
/* I'll assume that the keyboard is in the correct scancode mode(translated
mode 2, I think).
*/
newk=0;
memset(keybuf,0,sizeof(keybuf));
KBIRM.pm_offset=KBI.pm_offset=(int)ihandler;
KBIRM.pm_selector=KBI.pm_selector=_my_cs();
_go32_dpmi_get_real_mode_interrupt_vector(9,&KBIBackRM);
_go32_dpmi_allocate_real_mode_callback_iret(&KBIRM, &KBIRMRegs);
_go32_dpmi_set_real_mode_interrupt_vector(9,&KBIRM);
_go32_dpmi_get_protected_mode_interrupt_vector(9,&KBIBack);
_go32_dpmi_allocate_iret_wrapper(&KBI);
_go32_dpmi_set_protected_mode_interrupt_vector(9,&KBI);
lastsc=0;
initdone=1;
return(1);
}
void KillKeyboard(void)
{
if(initdone)
{
_go32_dpmi_set_protected_mode_interrupt_vector(9,&KBIBack);
_go32_dpmi_free_iret_wrapper(&KBI);
_go32_dpmi_set_real_mode_interrupt_vector(9,&KBIBackRM);
_go32_dpmi_free_real_mode_callback(&KBIRM);
initdone=0;
}
}
/* In FCE Ultra, it doesn't matter if the key states change
in the middle of the keyboard handling code. If you want
to use this code elsewhere, you may want to memcpy() keybuf
to another buffer and return that when GetKeyboard() is
called.
*/
char *GetKeyboard(void)
{
return keybuf;
}
/* Returns 1 on new scan codes generated, 0 on no new scan codes. */
int UpdateKeyboard(void)
{
int t=newk;
if(t)
{
asm volatile(
"subl %%eax,_newk\n\t"
:
: "a" (t)
);
if(keybuf[SCAN_LEFTCONTROL] && keybuf[SCAN_C])
raise(SIGINT);
return(1);
}
return(0);
}

80
drivers/pc/dos-mouse.c Normal file
View File

@ -0,0 +1,80 @@
/* FCE Ultra - NES/Famicom Emulator
*
* Copyright notice for this file:
* Copyright (C) 2002 Xodnizel
*
* 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
*/
#include <dpmi.h>
#include <string.h>
#include "dos.h"
int InitMouse(void)
{
__dpmi_regs regs;
memset(&regs,0,sizeof(regs));
regs.x.ax=0;
__dpmi_int(0x33,&regs);
if(regs.x.ax!=0xFFFF)
return(0);
memset(&regs,0,sizeof(regs));
regs.x.ax=0x7;
regs.x.cx=0; // Min X
regs.x.dx=260; // Max X
__dpmi_int(0x33,&regs);
memset(&regs,0,sizeof(regs));
regs.x.ax=0x8;
regs.x.cx=0; // Min Y
regs.x.dx=260; // Max Y
__dpmi_int(0x33,&regs);
memset(&regs,0,sizeof(regs));
regs.x.ax=0xF;
regs.x.cx=8; // Mickey X
regs.x.dx=8; // Mickey Y
__dpmi_int(0x33,&regs);
memset(&regs,0,sizeof(regs));
regs.x.ax=0x2;
__dpmi_int(0x33,&regs);
return(1);
}
uint32 GetMouseData(uint32 *x, uint32 *y)
{
if(FCEUI_IsMovieActive()<0)
return;
__dpmi_regs regs;
memset(&regs,0,sizeof(regs));
regs.x.ax=0x3;
__dpmi_int(0x33,&regs);
*x=regs.x.cx;
*y=regs.x.dx;
return(regs.x.bx&3);
}
void KillMouse(void)
{
}

567
drivers/pc/dos-sound.c Normal file
View File

@ -0,0 +1,567 @@
/* FCE Ultra - NES/Famicom Emulator
*
* Copyright notice for this file:
* Copyright (C) 2002 Xodnizel
*
* 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
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/farptr.h>
#include <pc.h>
#include <dos.h>
#include <dpmi.h>
#include <go32.h>
#include <ctype.h>
#include "dos.h"
#include "dos-sound.h"
#include "dos-joystick.h"
static void SBIRQHandler(_go32_dpmi_registers *r);
static uint32 LMBuffer; /* Address of low memory DMA playback buffer. */
static int LMSelector;
static uint8 *WaveBuffer;
static unsigned int IVector, SBIRQ, SBDMA, SBDMA16, SBPort;
static int DSPV,hsmode;
static int format;
static int frags, fragsize, fragtotal;
static volatile int WritePtr, ReadPtr;
static volatile int hbusy;
static volatile int whichbuf;
static uint8 PICMask;
/* Protected mode interrupt vector info. */
static _go32_dpmi_seginfo SBIH,SBIHOld;
/* Real mode interrupt vector info. */
static _go32_dpmi_seginfo SBIHRM,SBIHRMOld;
static _go32_dpmi_registers SBIHRMRegs;
static int WriteDSP(uint8 V)
{
int x;
for(x=65536;x;x--)
{
if(!(inportb(SBPort+0xC)&0x80))
{
outportb(SBPort+0xC,V);
return(1);
}
}
return(0);
}
static int ReadDSP(uint8 *V)
{
int x;
for(x=65536;x;x--) /* Should be more than enough time... */
{
if(inportb(SBPort+0xE)&0x80)
{
*V=inportb(SBPort+0xA);
return(1);
}
}
return(0);
}
static int SetVectors(void)
{
SBIH.pm_offset=SBIHRM.pm_offset=(int)SBIRQHandler;
SBIH.pm_selector=SBIHRM.pm_selector=_my_cs();
/* Get and set real mode interrupt vector. */
_go32_dpmi_get_real_mode_interrupt_vector(IVector,&SBIHRMOld);
_go32_dpmi_allocate_real_mode_callback_iret(&SBIHRM, &SBIHRMRegs);
_go32_dpmi_set_real_mode_interrupt_vector(IVector,&SBIHRM);
/* Get and set protected mode interrupt vector. */
_go32_dpmi_get_protected_mode_interrupt_vector(IVector,&SBIHOld);
_go32_dpmi_allocate_iret_wrapper(&SBIH);
_go32_dpmi_set_protected_mode_interrupt_vector(IVector,&SBIH);
return(1);
}
static void ResetVectors(void)
{
_go32_dpmi_set_protected_mode_interrupt_vector(IVector,&SBIHOld);
_go32_dpmi_free_iret_wrapper(&SBIH);
_go32_dpmi_set_real_mode_interrupt_vector(IVector,&SBIHRMOld);
_go32_dpmi_free_real_mode_callback(&SBIHRM);
}
int GetBLASTER(void)
{
int check=0;
char *s;
if(!(s=getenv("BLASTER")))
{
puts(" Error getting BLASTER environment variable.");
return(0);
}
while(*s)
{
switch(toupper(*s))
{
case 'A': check|=(sscanf(s+1,"%x",&SBPort)==1)?1:0;break;
case 'I': check|=(sscanf(s+1,"%d",&SBIRQ)==1)?2:0;break;
case 'D': check|=(sscanf(s+1,"%d",&SBDMA)==1)?4:0;break;
case 'H': check|=(sscanf(s+1,"%d",&SBDMA16)==1)?8:0;break;
}
s++;
}
if((check^7)&7 || SBDMA>=4 || (SBDMA16<=4 && check&8) || SBIRQ>15)
{
puts(" Invalid or incomplete BLASTER environment variable.");
return(0);
}
if(!(check&8))
format=0;
return(1);
}
static int ResetDSP(void)
{
uint8 b;
outportb(SBPort+0x6,0x1);
delay(10);
outportb(SBPort+0x6,0x0);
delay(10);
if(ReadDSP(&b))
if(b==0xAA)
return(1);
return(0);
}
static int GetDSPVersion(void)
{
int ret;
uint8 t;
if(!WriteDSP(0xE1))
return(0);
if(!ReadDSP(&t))
return(0);
ret=t<<8;
if(!ReadDSP(&t))
return(0);
ret|=t;
return(ret);
}
static void KillDMABuffer(void)
{
__dpmi_free_dos_memory(LMSelector);
}
static int MakeDMABuffer(void)
{
uint32 size;
int32 tmp;
size=fragsize*2; /* Two buffers in the DMA buffer. */
size<<=format; /* Twice the size for 16-bit than for 8-bit. */
size<<=1; /* Double the size in case the first 2 buffers
cross a 64KB or 128KB page boundary.
*/
size=(size+15)>>4; /* Convert to paragraphs */
if((tmp=__dpmi_allocate_dos_memory(size,&LMSelector))<0)
return(0);
LMBuffer=tmp<<=4;
if(format) /* Check for and fix 128KB page boundary crossing. */
{
if((LMBuffer&0x20000) != ((LMBuffer+fragsize*2*2-1)&0x20000))
LMBuffer+=fragsize*2*2;
}
else /* Check for and fix 64KB page boundary crossing. */
{
if((LMBuffer&0x10000) != ((LMBuffer+fragsize*2-1)&0x10000))
LMBuffer+=fragsize*2;
}
DOSMemSet(LMBuffer, format?0:128, (fragsize*2)<<format);
return(1);
}
static void ProgramDMA(void)
{
static int PPorts[8]={0x87,0x83,0x81,0x82,0,0x8b,0x89,0x8a};
uint32 tmp;
if(format)
{
outportb(0xd4,(SBDMA16&0x3)|0x4);
outportb(0xd8,0x0);
outportb(0xd6,(SBDMA16&0x3)|0x58);
tmp=((SBDMA16&3)<<2)+0xC2;
}
else
{
outportb(0xA,SBDMA|0x4);
outportb(0xC,0x0);
outportb(0xB,SBDMA|0x58);
tmp=(SBDMA<<1)+1;
}
/* Size of entire buffer. */
outportb(tmp,(fragsize*2-1));
outportb(tmp,(fragsize*2-1)>>8);
/* Page of buffer. */
outportb(PPorts[format?SBDMA16:SBDMA],LMBuffer>>16);
/* Offset of buffer within page. */
if(format)
tmp=((SBDMA16&3)<<2)+0xc0;
else
tmp=SBDMA<<1;
outportb(tmp,(LMBuffer>>format));
outportb(tmp,(LMBuffer>>(8+format)));
}
int InitSB(int Rate, int bittage)
{
hsmode=hbusy=0;
whichbuf=1;
puts("Initializing Sound Blaster...");
format=bittage?1:0;
frags=8;
if(Rate<=11025)
fragsize=1<<5;
else if(Rate<=22050)
fragsize=1<<6;
else
fragsize=1<<7;
fragtotal=frags*fragsize;
WaveBuffer=malloc(fragtotal<<format);
if(format)
memset(WaveBuffer,0,fragtotal*2);
else
memset(WaveBuffer,128,fragtotal);
WritePtr=ReadPtr=0;
if((Rate<8192) || (Rate>65535))
{
printf(" Unsupported playback rate: %d samples per second\n",Rate);
return(0);
}
if(!GetBLASTER())
return(0);
/* Disable IRQ line in PIC0 or PIC1 */
if(SBIRQ>7)
{
PICMask=inportb(0xA1);
outportb(0xA1,PICMask|(1<<(SBIRQ&7)));
}
else
{
PICMask=inportb(0x21);
outportb(0x21,PICMask|(1<<SBIRQ));
}
if(!ResetDSP())
{
puts(" Error resetting the DSP.");
return(0);
}
if(!(DSPV=GetDSPVersion()))
{
puts(" Error getting the DSP version.");
return(0);
}
printf(" DSP Version: %d.%d\n",DSPV>>8,DSPV&0xFF);
if(DSPV<0x201)
{
printf(" DSP version number is too low.\n");
return(0);
}
if(DSPV<0x400)
format=0;
if(!MakeDMABuffer())
{
puts(" Error creating low-memory DMA buffer.");
return(0);
}
if(SBIRQ>7) IVector=SBIRQ+0x68;
else IVector=SBIRQ+0x8;
if(!SetVectors())
{
puts(" Error setting interrupt vectors.");
KillDMABuffer();
return(0);
}
/* Reenable IRQ line. */
if(SBIRQ>7)
outportb(0xA1,PICMask&(~(1<<(SBIRQ&7))));
else
outportb(0x21,PICMask&(~(1<<SBIRQ)));
ProgramDMA();
/* Note that the speaker must always be turned on before the mode transfer
byte is sent to the DSP if we're going into high-speed mode, since
a real Sound Blaster(at least my SBPro) won't accept DSP commands(except
for the reset "command") after it goes into high-speed mode.
*/
WriteDSP(0xD1); // Turn on DAC speaker
if(DSPV>=0x400)
{
WriteDSP(0x41); // Set sampling rate
WriteDSP(Rate>>8); // High byte
WriteDSP(Rate&0xFF); // Low byte
if(!format)
{
WriteDSP(0xC6); // 8-bit output
WriteDSP(0x00); // 8-bit mono unsigned PCM
}
else
{
WriteDSP(0xB6); // 16-bit output
WriteDSP(0x10); // 16-bit mono signed PCM
}
WriteDSP((fragsize-1)&0xFF);// Low byte of size
WriteDSP((fragsize-1)>>8); // High byte of size
}
else
{
int tc,command;
if(Rate>22050)
{
tc=(65536-(256000000/Rate))>>8;
Rate=256000000/(65536-(tc<<8));
command=0x90; // High-speed auto-initialize DMA mode transfer
hsmode=1;
}
else
{
tc=256-(1000000/Rate);
Rate=1000000/(256-tc);
command=0x1c; // Auto-initialize DMA mode transfer
}
WriteDSP(0x40); // Set DSP time constant
WriteDSP(tc); // time constant
WriteDSP(0x48); // Set DSP block transfer size
WriteDSP((fragsize-1)&0xFF);
WriteDSP((fragsize-1)>>8);
WriteDSP(command);
}
/* Enable DMA */
if(format)
outportb(0xd4,SBDMA16&3);
else
outportb(0xa,SBDMA);
printf(" %d hz, %d-bit\n",Rate,8<<format);
return(Rate);
}
extern volatile int soundjoyer;
extern volatile int soundjoyeron;
static int ssilence=0;
static void SBIRQHandler(_go32_dpmi_registers *r)
{
uint32 *src;
uint32 dest;
int32 x;
if(format)
{
uint8 status;
outportb(SBPort+4,0x82);
status=inportb(SBPort+5);
if(status&2)
inportb(SBPort+0x0F);
}
else
inportb(SBPort+0x0E);
#ifdef OLD
{
uint8 status;
outportb(SBPort+4,0x82);
status=inportb(SBPort+5);
if(status&1)
inportb(SBPort+0x0E);
else if(status&2)
inportb(SBPort+0x0F);
else
return; // Mysterious interrupt source! *eerie music*
}
#endif
if(hbusy)
{
outportb(0x20,0x20);
if(SBIRQ>=8)
outportb(0xA0,0x20);
whichbuf^=1;
return;
}
hbusy=1;
{
/* This code seems to fail on many SB emulators. Bah.
SCREW SB EMULATORS. ^_^ */
uint32 count;
uint32 block;
uint32 port;
if(format)
port=((SBDMA16&3)*4)+0xc2;
else
port=(SBDMA*2)+1;
count=inportb(port);
count|=inportb(port)<<8;
if(count>=fragsize)
block=1;
else
block=0;
dest=LMBuffer+((block*fragsize)<<format);
#ifdef MOO
dest=LMBuffer+((whichbuf*fragsize)<<format);
whichbuf^=1;
#endif
}
_farsetsel(_dos_ds);
src=(uint32 *)(WaveBuffer+(ReadPtr<<format));
if(ssilence)
{
uint32 sby;
if(format) sby=0; /* 16-bit silence. */
else sby=0x80808080; /* 8-bit silence. */
for(x=(fragsize<<format)>>2;x;x--,dest+=4)
{
_farnspokel(dest,sby);
}
}
else
{
for(x=(fragsize<<format)>>2;x;x--,dest+=4,src++)
{
_farnspokel(dest,*src);
}
ReadPtr=(ReadPtr+fragsize)&(fragtotal-1);
}
if(soundjoyeron)
{
static int coot=0;
if(!coot)
{
UpdateJoyData();
soundjoyer=1;
}
coot=(coot+1)&3;
}
hbusy=0;
outportb(0x20,0x20);
if(SBIRQ>=8)
outportb(0xA0,0x20);
}
void SilenceSound(int s)
{
ssilence=s;
}
void WriteSBSound(int32 *Buffer, int Count, int NoBlocking)
{
int x;
if(!format)
{
for(x=0;x<Count;x++)
{
while(WritePtr==ReadPtr)
if(NoBlocking)
return;
WaveBuffer[WritePtr]=(uint8)((Buffer[x])>>8)^128;
WritePtr=(WritePtr+1)&(fragtotal-1);
}
}
else // 16 bit
{
for(x=0;x<Count;x++)
{
while(WritePtr==ReadPtr)
if(NoBlocking)
return;
((int16 *)WaveBuffer)[WritePtr]=Buffer[x];
WritePtr=(WritePtr+1)&(fragtotal-1);
}
}
}
void KillSB(void)
{
if(hsmode)
ResetDSP(); /* High-speed mode requires a DSP reset. */
else
WriteDSP(format?0xD9:0xDA); /* Exit auto-init DMA transfer mode. */
WriteDSP(0xD3); /* Turn speaker off. */
outportb((SBIRQ>7)?0xA1:0x21,PICMask|(1<<(SBIRQ&7)));
ResetVectors();
outportb((SBIRQ>7)?0xA1:0x21,PICMask);
KillDMABuffer();
}

26
drivers/pc/dos-sound.h Normal file
View File

@ -0,0 +1,26 @@
/* FCE Ultra - NES/Famicom Emulator
*
* Copyright notice for this file:
* Copyright (C) 2002 Xodnizel
*
* 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
*/
int InitSB(int Rate, int bittage);
void KillSB(void);
void WriteSBSound(int32 *Buffer, int Count, int NoBlocking);
void SilenceSound(int s);

246
drivers/pc/dos-video.c Normal file
View File

@ -0,0 +1,246 @@
/* FCE Ultra - NES/Famicom Emulator
*
* Copyright notice for this file:
* Copyright (C) 1998 \Firebug\
* Copyright (C) 2002 Xodnizel
*
* 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
*/
#include <stdio.h>
#include <string.h>
#include <dpmi.h>
#include <sys/farptr.h>
#include <go32.h>
#include <pc.h>
#include "dos.h"
#include "dos-video.h"
#define TEXT 3
#define G320x200x256 0x13
static void vga_waitretrace(void)
{
while(inp(0x3da)&0x8);
while(!(inp(0x3da)&0x8));
}
static void vga_setmode(int mode)
{
__dpmi_regs regs;
memset(&regs,0,sizeof(regs));
regs.x.ax=mode;
__dpmi_int(0x10,&regs);
}
void vga_setpalette(int i, int r, int g, int b)
{
outp(0x3c8,i);
outp(0x3c9,r);
outp(0x3c9,g);
outp(0x3c9,b);
}
int FCEUDvmode=1;
static int vidready=0;
/* Part of the VGA low-level mass register setting code derived from
code by \Firebug\.
*/
#include "vgatweak.c"
void SetBorder(void)
{
inportb(0x3da);
outportb(0x3c0,(0x11|0x20));
outportb(0x3c0,0x80);
}
void TweakVGA(int VGAMode)
{
int I;
vga_waitretrace();
outportb(0x3C8,0x00);
for(I=0;I<768;I++) outportb(0x3C9,0x00);
outportb(0x3D4,0x11);
I=inportb(0x3D5)&0x7F;
outportb(0x3D4,0x11);
outportb(0x3D5,I);
switch(VGAMode)
{
case 1: for(I=0;I<25;I++) VGAPortSet(v256x240[I]);break;
case 2: for(I=0;I<25;I++) VGAPortSet(v256x256[I]);break;
case 3: for(I=0;I<25;I++) VGAPortSet(v256x256S[I]);break;
case 6: for(I=0;I<25;I++) VGAPortSet(v256x224S[I]);break;
case 8: for(I=0;I<25;I++) VGAPortSet(v256x224_103[I]);break;
default: break;
}
outportb(0x3da,0);
}
static uint8 palettedbr[256],palettedbg[256],palettedbb[256];
static void FlushPalette(void)
{
int x;
for(x=0;x<256;x++)
{
int z=x;
vga_setpalette(z,palettedbr[x]>>2,palettedbg[x]>>2,palettedbb[x]>>2);
}
}
void FCEUD_SetPalette(uint8 index, uint8 r, uint8 g, uint8 b)
{
palettedbr[index]=r;
palettedbg[index]=g;
palettedbb[index]=b;
if(vidready)
{
vga_setpalette(index,r>>2,g>>2,b>>2);
}
}
void FCEUD_GetPalette(uint8 i, uint8 *r, uint8 *g, uint8 *b)
{
*r=palettedbr[i];
*g=palettedbg[i];
*b=palettedbb[i];
}
static uint32 ScreenLoc;
int InitVideo(void)
{
vidready=0;
switch(FCEUDvmode)
{
default:
case 1:
case 2:
case 3:
case 6:
case 8:
vga_setmode(G320x200x256);
vidready|=1;
ScreenLoc=0xa0000;
TweakVGA(FCEUDvmode);
SetBorder();
DOSMemSet(ScreenLoc, 128, 256*256);
break;
}
vidready|=2;
FlushPalette();
return 1;
}
void KillVideo(void)
{
if(vidready)
{
vga_setmode(TEXT);
vidready=0;
}
}
void LockConsole(void){}
void UnlockConsole(void){}
void BlitScreen(uint8 *XBuf)
{
uint32 dest;
int tlines;
if(eoptions&4 && !NoWaiting)
vga_waitretrace();
tlines=erendline-srendline+1;
dest=ScreenLoc;
switch(FCEUDvmode)
{
case 1:dest+=(((240-tlines)>>1)<<8);break;
case 2:
case 3:dest+=(((256-tlines)>>1)<<8);break;
case 4:
case 5:dest+=(((240-tlines)>>1)*640+((640-512)>>1));break;
case 8:
case 6:if(tlines>224) tlines=224;dest+=(((224-tlines)>>1)<<8);break;
}
XBuf+=(srendline<<8)+(srendline<<4);
_farsetsel(_dos_ds);
if(eoptions&DO_CLIPSIDES)
{
asm volatile(
"agoop1:\n\t"
"movl $30,%%eax\n\t"
"agoop2:\n\t"
"movl (%%esi),%%edx\n\t"
"movl 4(%%esi),%%ecx\n\t"
".byte 0x64 \n\t"
"movl %%edx,(%%edi)\n\t"
".byte 0x64 \n\t"
"movl %%ecx,4(%%edi)\n\t"
"addl $8,%%esi\n\t"
"addl $8,%%edi\n\t"
"decl %%eax\n\t"
"jne agoop2\n\t"
"addl $32,%%esi\n\t"
"addl $16,%%edi\n\t"
"decb %%bl\n\t"
"jne agoop1\n\t"
:
: "S" (XBuf+8), "D" (dest+8), "b" (tlines)
: "%eax","%cc","%edx","%ecx" );
}
else
{
asm volatile(
"goop1:\n\t"
"movl $32,%%eax\n\t"
"goop2:\n\t"
"movl (%%esi),%%edx\n\t"
"movl 4(%%esi),%%ecx\n\t"
".byte 0x64 \n\t"
"movl %%edx,(%%edi)\n\t"
".byte 0x64 \n\t"
"movl %%ecx,4(%%edi)\n\t"
"addl $8,%%esi\n\t"
"addl $8,%%edi\n\t"
"decl %%eax\n\t"
"jne goop2\n\t"
"addl $16,%%esi\n\t"
"decb %%bl\n\t"
"jne goop1\n\t"
:
: "S" (XBuf), "D" (dest), "b" (tlines)
: "%eax","%cc","%edx","%ecx" );
}
}

22
drivers/pc/dos-video.h Normal file
View File

@ -0,0 +1,22 @@
/* FCE Ultra - NES/Famicom Emulator
*
* Copyright notice for this file:
* Copyright (C) 2002 Xodnizel
*
* 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
*/
extern int FCEUDvmode;

128
drivers/pc/dos.c Normal file
View File

@ -0,0 +1,128 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <crt0.h>
#include <sys/farptr.h>
#include <go32.h>
#include "dos.h"
#include "dos-joystick.h"
#include "dos-video.h"
#include "dos-sound.h"
#include "../common/args.h"
#include "../common/config.h"
/* _CRT0_FLAG_LOCK_MEMORY might not always result in all memory being locked.
Bummer. I'll add code to explicitly lock the data touched by the sound
interrupt handler(and the handler itself), if necessary(though that might
be tricky...). I'll also to cover the data the keyboard
interrupt handler touches.
*/
int _crt0_startup_flags = _CRT0_FLAG_FILL_SBRK_MEMORY | _CRT0_FLAG_LOCK_MEMORY | _CRT0_FLAG_USE_DOS_SLASHES;
static int f8bit=0;
int soundo=44100;
int doptions=0;
CFGSTRUCT DriverConfig[]={
NAC("sound",soundo),
AC(doptions),
AC(f8bit),
AC(FCEUDvmode),
NACA("joybmap",joyBMap),
AC(joy),
ENDCFGSTRUCT
};
char *DriverUsage=
"-vmode x Select video mode(all are 8 bpp).\n\
1 = 256x240 6 = 256x224(with scanlines)\n\
2 = 256x256 8 = 256x224\n\
3 = 256x256(with scanlines)\n\
-vsync x Wait for the screen's vertical retrace before updating the\n\
screen. Refer to the documentation for caveats.\n\
0 = Disabled.\n\
1 = Enabled.\n\
-sound x Sound.\n\
0 = Disabled.\n\
Otherwise, x = playback rate.\n\
-f8bit x Force 8-bit sound.\n\
0 = Disabled.\n\
1 = Enabled.";
ARGPSTRUCT DriverArgs[]={
{"-vmode",0,&FCEUDvmode,0},
{"-sound",0,&soundo,0},
{"-f8bit",0,&f8bit,0},
{"-vsync",0,&doptions,DO_VSYNC},
{0,0,0,0}
};
void DoDriverArgs(void)
{
if(!joy) memset(joyBMap,0,sizeof(joyBMap));
}
int InitSound(void)
{
if(soundo)
{
if(soundo==1)
soundo=44100;
soundo=InitSB(soundo,f8bit?0:1);
FCEUI_Sound(soundo);
}
return(soundo);
}
void WriteSound(int32 *Buffer, int Count, int NoWaiting)
{
WriteSBSound(Buffer,Count,NoWaiting);
}
void KillSound(void)
{
if(soundo)
KillSB();
}
void DOSMemSet(uint32 A, uint8 V, uint32 count)
{
uint32 x;
_farsetsel(_dos_ds);
for(x=0;x<count;x++)
_farnspokeb(A+x,V);
}
static char *arg0;
uint8 *GetBaseDirectory(void)
{
int x=0;
uint8 *ret = 0;
if(arg0)
for(x=strlen(arg0);x>=0;x--)
{
if(arg0[x]=='/' || arg0[x]=='\\')
{
ret = malloc(x + 1);
strncpy(ret,arg0,x);
break;
}
}
if(!ret) { x=0; ret = malloc(1); }
BaseDirectory[x]=0;
}
int main(int argc, char *argv[])
{
puts("\nStarting FCE Ultra "VERSION_STRING"...\n");
arg0=argv[0];
return(CLImain(argc,argv));
}

27
drivers/pc/dos.h Normal file
View File

@ -0,0 +1,27 @@
/* FCE Ultra - NES/Famicom Emulator
*
* Copyright notice for this file:
* Copyright (C) 2002 Xodnizel
*
* 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
*/
#include "main.h"
#include "dface.h"
#include "input.h"
void DOSMemSet(uint32 A, uint8 V, uint32 count);
#define DO_VSYNC 1

720
drivers/pc/input.c Normal file
View File

@ -0,0 +1,720 @@
/* FCE Ultra - NES/Famicom Emulator
*
* Copyright notice for this file:
* Copyright (C) 2002 Xodnizel
*
* 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
*/
#include <string.h>
#include "main.h"
#include "dface.h"
#include "input.h"
#include "../common/cheat.h"
/* UsrInputType[] is user-specified. InputType[] is current
(game loading can override user settings)
*/
int UsrInputType[3]={SI_GAMEPAD,SI_GAMEPAD,SIFC_NONE};
int InputType[3]={0,0,0};
static int cspec=0;
int gametype=0;
/* Necessary for proper GUI functioning(configuring when a game isn't loaded). */
void InputUserActiveFix(void)
{
int x;
for(x=0;x<3;x++) InputType[x]=UsrInputType[x];
}
void ParseGIInput(FCEUGI *gi)
{
gametype=gi->type;
InputType[0]=UsrInputType[0];
InputType[1]=UsrInputType[1];
InputType[2]=UsrInputType[2];
if(gi->input[0]>=0)
InputType[0]=gi->input[0];
if(gi->input[1]>=0)
InputType[1]=gi->input[1];
if(gi->inputfc>=0)
InputType[2]=gi->inputfc;
cspec = gi->cspecial;
#ifdef EXTGUI
Giggles(gi->cspecial);
#endif
}
static uint8 QuizKingData=0;
static uint8 HyperShotData=0;
static uint32 MahjongData=0;
static uint32 FTrainerData=0;
static uint8 TopRiderData=0;
static uint8 BWorldData[1+13+1];
static void UpdateFKB(void);
static void UpdateGamepad(void);
static void UpdateQuizKing(void);
static void UpdateHyperShot(void);
static void UpdateMahjong(void);
static void UpdateFTrainer(void);
static void UpdateTopRider(void);
static uint32 JSreturn=0;
int NoWaiting=1;
#ifndef EXTGUI
static void DoCheatSeq(void)
{
#if defined(DOS) || defined(SDL)
SilenceSound(1);
#endif
KillKeyboard();
KillVideo();
DoConsoleCheatConfig();
InitVideo(CurGame);
InitKeyboard();
#if defined(DOS) || defined(SDL)
SilenceSound(0);
#endif
}
#endif
#include "keyscan.h"
static char *keys=0;
static int DIPS=0;
static uint8 keyonce[MKK_COUNT];
#define KEY(__a) keys[MKK(__a)]
static int _keyonly(int a)
{
if(keys[a])
{
if(!keyonce[a])
{
keyonce[a]=1;
return(1);
}
}
else
keyonce[a]=0;
return(0);
}
#define keyonly(__a) _keyonly(MKK(__a))
static int cidisabled=0;
static void KeyboardCommands(void)
{
int is_shift, is_alt;
keys=GetKeyboard();
if(InputType[2]==SIFC_FKB)
{
if(keyonly(SCROLLLOCK))
{
cidisabled^=1;
FCEUI_DispMessage("Family Keyboard %sabled.",cidisabled?"en":"dis");
}
#ifdef SDL
SDL_WM_GrabInput(cidisabled?SDL_GRAB_ON:SDL_GRAB_OFF);
#endif
if(cidisabled) return;
}
is_shift = KEY(LEFTSHIFT) | KEY(RIGHTSHIFT);
is_alt = KEY(LEFTALT) | KEY(RIGHTALT);
if(keyonly(F4))
{
if(is_shift) FCEUI_SetRenderDisable(-1, 2);
else FCEUI_SetRenderDisable(2, -1);
}
#ifdef SDL
if(keyonly(ENTER) && is_alt) ToggleFS();
#endif
NoWaiting&=~1;
if(KEY(GRAVE))
NoWaiting|=1;
if(gametype==GIT_FDS)
{
if(keyonly(F6)) FCEUI_FDSSelect();
if(keyonly(F8)) FCEUI_FDSInsert();
}
if(keyonly(F9)) FCEUI_SaveSnapshot();
if(gametype!=GIT_NSF)
{
#ifndef EXTGUI
if(keyonly(F2)) DoCheatSeq();
#endif
if(keyonly(F5))
{
if(is_shift)
FCEUI_SaveMovie(NULL,0,NULL);
else
FCEUI_SaveState(NULL);
}
if(keyonly(F7))
{
if(is_shift)
FCEUI_LoadMovie(NULL,0);
else
FCEUI_LoadState(NULL);
}
}
if(keyonly(F1)) FCEUI_ToggleTileView();
if(keyonly(MINUS)) DecreaseEmulationSpeed();
if(keyonly(EQUAL)) IncreaseEmulationSpeed();
if(keyonly(BACKSPACE)) FCEUI_MovieToggleFrameDisplay();
if(keyonly(BACKSLASH)) FCEUI_ToggleEmulationPause();
if(keyonly(RIGHTCONTROL)) FCEUI_FrameAdvance();
if(keyonly(F10)) FCEUI_ResetNES();
if(keyonly(F11)) FCEUI_PowerNES();
#ifdef EXTGUI
if(keyonly(F3)) GUI_Hide(-1);
if(KEY(F12)) GUI_RequestExit();
if(KEY(ESCAPE)) CloseGame();
#else
if(KEY(F12) || KEY(ESCAPE)) CloseGame();
#endif
if(gametype==GIT_VSUNI)
{
if(keyonly(F8)) FCEUI_VSUniCoin();
if(keyonly(F6))
{
DIPS^=1;
FCEUI_VSUniToggleDIPView();
}
if(!(DIPS&1)) goto DIPSless;
if(keyonly(1)) FCEUI_VSUniToggleDIP(0);
if(keyonly(2)) FCEUI_VSUniToggleDIP(1);
if(keyonly(3)) FCEUI_VSUniToggleDIP(2);
if(keyonly(4)) FCEUI_VSUniToggleDIP(3);
if(keyonly(5)) FCEUI_VSUniToggleDIP(4);
if(keyonly(6)) FCEUI_VSUniToggleDIP(5);
if(keyonly(7)) FCEUI_VSUniToggleDIP(6);
if(keyonly(8)) FCEUI_VSUniToggleDIP(7);
}
else
{
static uint8 bbuf[32];
static int bbuft;
static int barcoder = 0;
if(keyonly(H)) FCEUI_NTSCSELHUE();
if(keyonly(T)) FCEUI_NTSCSELTINT();
if(KEY(KP_MINUS) || KEY(MINUS)) FCEUI_NTSCDEC();
if(KEY(KP_PLUS) || KEY(EQUAL)) FCEUI_NTSCINC();
if((InputType[2] == SIFC_BWORLD) || (cspec == SIS_DATACH))
{
if(keyonly(F8))
{
barcoder ^= 1;
if(!barcoder)
{
if(InputType[2] == SIFC_BWORLD)
{
strcpy(&BWorldData[1],bbuf);
BWorldData[0]=1;
}
else
FCEUI_DatachSet(bbuf);
FCEUI_DispMessage("Barcode Entered");
}
else { bbuft = 0; FCEUI_DispMessage("Enter Barcode");}
}
} else barcoder = 0;
#define SSM(x) \
{ if(barcoder) { if(bbuft < 13) {bbuf[bbuft++] = '0' + x; bbuf[bbuft] = 0;} FCEUI_DispMessage("Barcode: %s",bbuf);} \
else { \
if(is_shift) FCEUI_SelectMovie(x,1); \
else FCEUI_SelectState(x,1); \
} }
DIPSless:
if(keyonly(0)) SSM(0);
if(keyonly(1)) SSM(1);
if(keyonly(2)) SSM(2);
if(keyonly(3)) SSM(3);
if(keyonly(4)) SSM(4);
if(keyonly(5)) SSM(5);
if(keyonly(6)) SSM(6);
if(keyonly(7)) SSM(7);
if(keyonly(8)) SSM(8);
if(keyonly(9)) SSM(9);
#undef SSM
}
}
#define MK(x) {{BUTTC_KEYBOARD},{0},{MKK(x)},1}
#define MK2(x1,x2) {{BUTTC_KEYBOARD},{0},{MKK(x1),MKK(x2)},2}
#define MKZ() {{0},{0},{0},0}
#define GPZ() {MKZ(), MKZ(), MKZ(), MKZ()}
ButtConfig GamePadConfig[4][10]={
/* Gamepad 1 */
{
MK(KP3), MK(KP2), MK(TAB), MK(ENTER), MK(W),MK(Z),
MK(A), MK(S), MKZ(), MKZ()
},
/* Gamepad 2 */
GPZ(),
/* Gamepad 3 */
GPZ(),
/* Gamepad 4 */
GPZ()
};
static void UpdateGamepad(void)
{
if(FCEUI_IsMovieActive()<0)
return;
static int rapid=0;
uint32 JS=0;
int x;
int wg;
rapid^=1;
for(wg=0;wg<4;wg++)
{
for(x=0;x<8;x++)
if(DTestButton(&GamePadConfig[wg][x]))
JS|=(1<<x)<<(wg<<3);
if(rapid)
for(x=0;x<2;x++)
if(DTestButton(&GamePadConfig[wg][8+x]))
JS|=(1<<x)<<(wg<<3);
}
// for(x=0;x<32;x+=8) /* Now, test to see if anything weird(up+down at same time)
// is happening, and correct */
// {
// if((JS & (0xC0<<x) ) == (0xC0<<x) ) JS&=~(0xC0<<x);
// if((JS & (0x30<<x) ) == (0x30<<x) ) JS&=~(0x30<<x);
// }
JSreturn=JS;
}
ButtConfig powerpadsc[2][12]={
{
MK(O),MK(P),MK(BRACKET_LEFT),
MK(BRACKET_RIGHT),MK(K),MK(L),MK(SEMICOLON),
MK(APOSTROPHE),
MK(M),MK(COMMA),MK(PERIOD),MK(SLASH)
},
{
MK(O),MK(P),MK(BRACKET_LEFT),
MK(BRACKET_RIGHT),MK(K),MK(L),MK(SEMICOLON),
MK(APOSTROPHE),
MK(M),MK(COMMA),MK(PERIOD),MK(SLASH)
}
};
static uint32 powerpadbuf[2]={0,0};
static uint32 UpdatePPadData(int w)
{
if(FCEUI_IsMovieActive()<0)
return;
uint32 r=0;
ButtConfig *ppadtsc=powerpadsc[w];
int x;
for(x=0;x<12;x++)
if(DTestButton(&ppadtsc[x])) r|=1<<x;
return r;
}
static uint32 MouseData[3]={0,0,0};
static uint8 fkbkeys[0x48];
void FCEUD_UpdateInput(void)
{
int x;
int t=0;
UpdatePhysicalInput();
KeyboardCommands();
for(x=0;x<2;x++)
switch(InputType[x])
{
case SI_GAMEPAD:t|=1;break;
case SI_ARKANOID:t|=2;break;
case SI_ZAPPER:t|=2;break;
case SI_POWERPADA:
case SI_POWERPADB:powerpadbuf[x]=UpdatePPadData(x);break;
}
switch(InputType[2])
{
case SIFC_ARKANOID:t|=2;break;
case SIFC_SHADOW:t|=2;break;
case SIFC_FKB:if(cidisabled) UpdateFKB();break;
case SIFC_HYPERSHOT: UpdateHyperShot();break;
case SIFC_MAHJONG: UpdateMahjong();break;
case SIFC_QUIZKING: UpdateQuizKing();break;
case SIFC_FTRAINERB:
case SIFC_FTRAINERA: UpdateFTrainer();break;
case SIFC_TOPRIDER: UpdateTopRider();break;
case SIFC_OEKAKIDS:t|=2;break;
}
if(t&1)
UpdateGamepad();
if(t&2)
GetMouseData(MouseData);
}
void InitOtherInput(void)
{
void *InputDPtr;
int t;
int x;
int attrib;
for(t=0,x=0;x<2;x++)
{
attrib=0;
InputDPtr=0;
switch(InputType[x])
{
case SI_POWERPADA:
case SI_POWERPADB:InputDPtr=&powerpadbuf[x];break;
case SI_GAMEPAD:InputDPtr=&JSreturn;break;
case SI_ARKANOID:InputDPtr=MouseData;t|=1;break;
case SI_ZAPPER:InputDPtr=MouseData;
t|=1;
attrib=1;
break;
}
FCEUI_SetInput(x,InputType[x],InputDPtr,attrib);
}
attrib=0;
InputDPtr=0;
switch(InputType[2])
{
case SIFC_SHADOW:InputDPtr=MouseData;t|=1;attrib=1;break;
case SIFC_OEKAKIDS:InputDPtr=MouseData;t|=1;attrib=1;break;
case SIFC_ARKANOID:InputDPtr=MouseData;t|=1;break;
case SIFC_FKB:InputDPtr=fkbkeys;break;
case SIFC_HYPERSHOT:InputDPtr=&HyperShotData;break;
case SIFC_MAHJONG:InputDPtr=&MahjongData;break;
case SIFC_QUIZKING:InputDPtr=&QuizKingData;break;
case SIFC_TOPRIDER:InputDPtr=&TopRiderData;break;
case SIFC_BWORLD:InputDPtr=BWorldData;break;
case SIFC_FTRAINERA:
case SIFC_FTRAINERB:InputDPtr=&FTrainerData;break;
}
FCEUI_SetInputFC(InputType[2],InputDPtr,attrib);
FCEUI_DisableFourScore(eoptions&EO_NOFOURSCORE);
if(t)
InitMouse();
}
ButtConfig fkbmap[0x48]=
{
MK(F1),MK(F2),MK(F3),MK(F4),MK(F5),MK(F6),MK(F7),MK(F8),
MK(1),MK(2),MK(3),MK(4),MK(5),MK(6),MK(7),MK(8),MK(9),MK(0),
MK(MINUS),MK(EQUAL),MK(BACKSLASH),MK(BACKSPACE),
MK(ESCAPE),MK(Q),MK(W),MK(E),MK(R),MK(T),MK(Y),MK(U),MK(I),MK(O),
MK(P),MK(GRAVE),MK(BRACKET_LEFT),MK(ENTER),
MK(LEFTCONTROL),MK(A),MK(S),MK(D),MK(F),MK(G),MK(H),MK(J),MK(K),
MK(L),MK(SEMICOLON),MK(APOSTROPHE),MK(BRACKET_RIGHT),MK(INSERT),
MK(LEFTSHIFT),MK(Z),MK(X),MK(C),MK(V),MK(B),MK(N),MK(M),MK(COMMA),
MK(PERIOD),MK(SLASH),MK(RIGHTALT),MK(RIGHTSHIFT),MK(LEFTALT),MK(SPACE),
MK(DELETE),MK(END),MK(PAGEDOWN),
MK(CURSORUP),MK(CURSORLEFT),MK(CURSORRIGHT),MK(CURSORDOWN)
};
static void UpdateFKB(void)
{
int x;
for(x=0;x<0x48;x++)
{
fkbkeys[x]=0;
if(DTestButton(&fkbmap[x]))
fkbkeys[x]=1;
}
}
static ButtConfig HyperShotButtons[4]=
{
MK(Q),MK(W),MK(E),MK(R)
};
static void UpdateHyperShot(void)
{
int x;
HyperShotData=0;
for(x=0;x<0x4;x++)
{
if(DTestButton(&HyperShotButtons[x]))
HyperShotData|=1<<x;
}
}
static ButtConfig MahjongButtons[21]=
{
MK(Q),MK(W),MK(E),MK(R),MK(T),
MK(A),MK(S),MK(D),MK(F),MK(G),MK(H),MK(J),MK(K),MK(L),
MK(Z),MK(X),MK(C),MK(V),MK(B),MK(N),MK(M)
};
static void UpdateMahjong(void)
{
int x;
MahjongData=0;
for(x=0;x<21;x++)
{
if(DTestButton(&MahjongButtons[x]))
MahjongData|=1<<x;
}
}
ButtConfig QuizKingButtons[6]=
{
MK(Q),MK(W),MK(E),MK(R),MK(T),MK(Y)
};
static void UpdateQuizKing(void)
{
int x;
QuizKingData=0;
for(x=0;x<6;x++)
{
if(DTestButton(&QuizKingButtons[x]))
QuizKingData|=1<<x;
}
}
ButtConfig TopRiderButtons[8]=
{
MK(Q),MK(W),MK(E),MK(R),MK(T),MK(Y),MK(U),MK(I)
};
static void UpdateTopRider(void)
{
int x;
TopRiderData=0;
for(x=0;x<8;x++)
if(DTestButton(&TopRiderButtons[x]))
TopRiderData|=1<<x;
}
ButtConfig FTrainerButtons[12]=
{
MK(O),MK(P),MK(BRACKET_LEFT),
MK(BRACKET_RIGHT),MK(K),MK(L),MK(SEMICOLON),
MK(APOSTROPHE),
MK(M),MK(COMMA),MK(PERIOD),MK(SLASH)
};
static void UpdateFTrainer(void)
{
int x;
FTrainerData=0;
for(x=0;x<12;x++)
{
if(DTestButton(&FTrainerButtons[x]))
FTrainerData|=1<<x;
}
}
static void subcon(char *text, ButtConfig *bc)
{
uint8 buf[256];
int wc;
for(wc=0;wc<MAXBUTTCONFIG;wc++)
{
sprintf(buf,"%s (%d)",text,wc+1);
DWaitButton(buf,bc,wc);
if(wc && bc->ButtType[wc]==bc->ButtType[wc-1] && bc->DeviceNum[wc]==bc->DeviceNum[wc-1] &&
bc->ButtonNum[wc]==bc->ButtonNum[wc-1])
break;
}
bc->NumC=wc;
}
void ConfigDevice(int which, int arg)
{
uint8 buf[256];
int x;
ButtonConfigBegin();
switch(which)
{
case FCFGD_QUIZKING:
for(x=0;x<6;x++)
{
sprintf(buf,"Quiz King Buzzer #%d", x+1);
subcon(buf,&QuizKingButtons[x]);
}
break;
case FCFGD_HYPERSHOT:
for(x=0;x<4;x++)
{
sprintf(buf,"Hyper Shot %d: %s",((x&2)>>1)+1,(x&1)?"JUMP":"RUN");
subcon(buf,&HyperShotButtons[x]);
}
break;
case FCFGD_POWERPAD:
for(x=0;x<12;x++)
{
sprintf(buf,"PowerPad %d: %d", (arg&1)+1,x+11);
subcon(buf,&powerpadsc[arg&1][x]);
}
break;
case FCFGD_GAMEPAD:
{
char *str[10]={"A","B","SELECT","START","UP","DOWN","LEFT","RIGHT","Rapid A","Rapid B"};
for(x=0;x<10;x++)
{
sprintf(buf,"GamePad #%d: %s",arg+1,str[x]);
subcon(buf,&GamePadConfig[arg][x]);
}
}
break;
}
ButtonConfigEnd();
}
CFGSTRUCT InputConfig[]={
ACA(UsrInputType),
AC(powerpadsc),
AC(QuizKingButtons),
AC(FTrainerButtons),
AC(HyperShotButtons),
AC(MahjongButtons),
AC(GamePadConfig),
AC(fkbmap),
ENDCFGSTRUCT
};
static void InputCfg(char *text)
{
if(!strncasecmp(text,"gamepad",strlen("gamepad")))
{
ConfigDevice(FCFGD_GAMEPAD,(text[strlen("gamepad")]-'1')&3);
}
else if(!strncasecmp(text,"powerpad",strlen("powerpad")))
{
ConfigDevice(FCFGD_POWERPAD,(text[strlen("powerpad")]-'1')&1);
}
else if(!strcasecmp(text,"hypershot"))
ConfigDevice(FCFGD_HYPERSHOT,0);
else if(!strcasecmp(text,"quizking"))
ConfigDevice(FCFGD_QUIZKING,0);
}
static void FCExp(char *text)
{
static char *fccortab[11]={"none","arkanoid","shadow","4player","fkb","hypershot",
"mahjong","quizking","ftrainera","ftrainerb","oekakids"};
static int fccortabi[11]={SIFC_NONE,SIFC_ARKANOID,SIFC_SHADOW,
SIFC_4PLAYER,SIFC_FKB,SIFC_HYPERSHOT,SIFC_MAHJONG,SIFC_QUIZKING,
SIFC_FTRAINERA,SIFC_FTRAINERB,SIFC_OEKAKIDS};
int y;
for(y=0;y<11;y++)
if(!strcmp(fccortab[y],text))
UsrInputType[2]=fccortabi[y];
}
static char *cortab[6]={"none","gamepad","zapper","powerpada","powerpadb","arkanoid"};
static int cortabi[6]={SI_NONE,SI_GAMEPAD,
SI_ZAPPER,SI_POWERPADA,SI_POWERPADB,SI_ARKANOID};
static void Input1(char *text)
{
int y;
for(y=0;y<6;y++)
if(!strcmp(cortab[y],text))
UsrInputType[0]=cortabi[y];
}
static void Input2(char *text)
{
int y;
for(y=0;y<6;y++)
if(!strcmp(cortab[y],text))
UsrInputType[1]=cortabi[y];
}
ARGPSTRUCT InputArgs[]={
{"-inputcfg",0,(void *)InputCfg,0x2000},
{"-fcexp",0,(void *)FCExp,0x2000},
{"-input1",0,(void *)Input1,0x2000},
{"-input2",0,(void *)Input2,0x2000},
{0,0,0,0}
};

38
drivers/pc/input.h Normal file
View File

@ -0,0 +1,38 @@
#ifndef _aosdfjk02fmasf
#define _aosdfjk02fmasf
#define MAXBUTTCONFIG 4
typedef struct {
uint8 ButtType[MAXBUTTCONFIG];
uint8 DeviceNum[MAXBUTTCONFIG];
uint16 ButtonNum[MAXBUTTCONFIG];
uint32 NumC;
//uint64 DeviceID[MAXBUTTCONFIG]; /* TODO */
} ButtConfig;
extern CFGSTRUCT InputConfig[];
extern ARGPSTRUCT InputArgs[];
void ParseGIInput(FCEUGI *GI);
#define BUTTC_KEYBOARD 0x00
#define BUTTC_JOYSTICK 0x01
#define BUTTC_MOUSE 0x02
#define FCFGD_GAMEPAD 1
#define FCFGD_POWERPAD 2
#define FCFGD_HYPERSHOT 3
#define FCFGD_QUIZKING 4
void InitOtherInput(void);
void InputUserActiveFix(void);
#ifdef EXTGUI
extern ButtConfig GamePadConfig[4][10];
extern ButtConfig powerpadsc[2][12];
extern ButtConfig QuizKingButtons[6];
extern ButtConfig FTrainerButtons[12];
#endif
void IncreaseEmulationSpeed(void);
void DecreaseEmulationSpeed(void);
void FCEUD_UpdateInput(void);
#endif

161
drivers/pc/keyscan.h Normal file
View File

@ -0,0 +1,161 @@
#ifdef SDL
#include <SDL.h>
#define SDLK_A SDLK_a
#define SDLK_B SDLK_b
#define SDLK_C SDLK_c
#define SDLK_D SDLK_d
#define SDLK_E SDLK_e
#define SDLK_F SDLK_f
#define SDLK_G SDLK_g
#define SDLK_H SDLK_h
#define SDLK_I SDLK_i
#define SDLK_J SDLK_j
#define SDLK_K SDLK_k
#define SDLK_L SDLK_l
#define SDLK_M SDLK_m
#define SDLK_N SDLK_n
#define SDLK_O SDLK_o
#define SDLK_P SDLK_p
#define SDLK_Q SDLK_q
#define SDLK_R SDLK_r
#define SDLK_S SDLK_s
#define SDLK_T SDLK_t
#define SDLK_U SDLK_u
#define SDLK_V SDLK_v
#define SDLK_W SDLK_w
#define SDLK_X SDLK_x
#define SDLK_Y SDLK_y
#define SDLK_Z SDLK_z
#define SDLK_LEFTCONTROL SDLK_LCTRL
#define SDLK_RIGHTCONTROL SDLK_RCTRL
#define SDLK_LEFTALT SDLK_LALT
#define SDLK_RIGHTALT SDLK_RALT
#define SDLK_LEFTSHIFT SDLK_LSHIFT
#define SDLK_RIGHTSHIFT SDLK_RSHIFT
#define SDLK_CURSORDOWN SDLK_DOWN
#define SDLK_CURSORUP SDLK_UP
#define SDLK_CURSORLEFT SDLK_LEFT
#define SDLK_CURSORRIGHT SDLK_RIGHT
#define SDLK_ENTER SDLK_RETURN
#define SDLK_EQUAL SDLK_EQUALS
#define SDLK_APOSTROPHE SDLK_QUOTE
#define SDLK_BRACKET_LEFT SDLK_LEFTBRACKET
#define SDLK_BRACKET_RIGHT SDLK_RIGHTBRACKET
#define SDLK_SCROLLLOCK SDLK_SCROLLOCK /* I guess the SDL people don't like lots of Ls... */
#define SDLK_GRAVE SDLK_BACKQUOTE
#define MKK(k) SDLK_##k
#define MKK_COUNT (SDLK_LAST+1)
#elif DOS
#define SCAN_GRAVE 0x29
#define SCAN_1 0x02
#define SCAN_2 0x03
#define SCAN_3 0x04
#define SCAN_4 0x05
#define SCAN_5 0x06
#define SCAN_6 0x07
#define SCAN_7 0x08
#define SCAN_8 0x09
#define SCAN_9 0x0A
#define SCAN_0 0x0B
#define SCAN_MINUS 0x0C
#define SCAN_EQUAL 0x0D
#define SCAN_BACKSLASH 0x2B
#define SCAN_BACKSPACE 0x0E
#define SCAN_TAB 0x0F
#define SCAN_Q 0x10
#define SCAN_W 0x11
#define SCAN_E 0x12
#define SCAN_R 0x13
#define SCAN_T 0x14
#define SCAN_Y 0x15
#define SCAN_U 0x16
#define SCAN_I 0x17
#define SCAN_O 0x18
#define SCAN_P 0x19
#define SCAN_BRACKET_LEFT 0x1A
#define SCAN_BRACKET_RIGHT 0x1B
#define SCAN_LOWBACKSLASH 0x2B
#define SCAN_CAPSLOCK 0x3A
#define SCAN_A 0x1E
#define SCAN_S 0x1F
#define SCAN_D 0x20
#define SCAN_F 0x21
#define SCAN_G 0x22
#define SCAN_H 0x23
#define SCAN_J 0x24
#define SCAN_K 0x25
#define SCAN_L 0x26
#define SCAN_SEMICOLON 0x27
#define SCAN_APOSTROPHE 0x28
#define SCAN_ENTER 0x1C
#define SCAN_LEFTSHIFT 0x2A
#define SCAN_Z 0x2C
#define SCAN_X 0x2D
#define SCAN_C 0x2E
#define SCAN_V 0x2F
#define SCAN_B 0x30
#define SCAN_N 0x31
#define SCAN_M 0x32
#define SCAN_COMMA 0x33
#define SCAN_PERIOD 0x34
#define SCAN_SLASH 0x35
#define SCAN_RIGHTSHIFT 0x36
#define SCAN_LEFTCONTROL 0x1D
#define SCAN_LEFTALT 0x38
#define SCAN_SPACE 0x39
/* Extended keys. */
#define SCAN_RIGHTALT (0x38|0x80)
#define SCAN_RIGHTCONTROL (0x1D|0x80)
#define SCAN_BL_INSERT (0x52|0x80)
#define SCAN_BL_DELETE (0x53|0x80)
#define SCAN_BL_CURSORLEFT (0x4B|0x80)
#define SCAN_BL_HOME (0x47|0x80)
#define SCAN_BL_END (0x4F|0x80)
#define SCAN_BL_CURSORUP (0x48|0x80)
#define SCAN_BL_CURSORDOWN (0x50|0x80)
#define SCAN_BL_PAGEUP (0x49|0x80)
#define SCAN_BL_PAGEDOWN (0x51|0x80)
#define SCAN_BL_CURSORRIGHT (0x4D|0x80)
#define SCAN_SCROLLLOCK 0x46
/* Keys often found in the key pad area. */
#define SCAN_NUMLOCK 0x45
#define SCAN_HOME 0x47
#define SCAN_CURSORLEFT 0x4B
#define SCAN_END 0x4F
#define SCAN_SLASH 0x35
#define SCAN_CURSORUP 0x48
#define SCAN_CENTER 0x4C
#define SCAN_CURSORDOWN 0x50
#define SCAN_INSERT 0x52
#define SCAN_PAUSE 0xC5
#define SCAN_ASTERISK 0x37
#define SCAN_PAGEUP 0x49
#define SCAN_CURSORRIGHT 0x4D
#define SCAN_PAGEDOWN 0x51
#define SCAN_DELETE 0x53
#define SCAN_KP_MINUS 0x4A
#define SCAN_KP_PLUS 0x4E
#define SCAN_KP_ENTER 0x1C
#define SCAN_ESCAPE 0x01
#define SCAN_F1 0x3B
#define SCAN_F2 0x3C
#define SCAN_F3 0x3D
#define SCAN_F4 0x3E
#define SCAN_F5 0x3F
#define SCAN_F6 0x40
#define SCAN_F7 0x41
#define SCAN_F8 0x42
#define SCAN_F9 0x43
#define SCAN_F10 0x44
#define SCAN_F11 0x57
#define SCAN_F12 0x58
#define MK_COUNT 256
#define MK(k) SCAN_##k
#endif

553
drivers/pc/main.c Normal file
View File

@ -0,0 +1,553 @@
/* FCE Ultra - NES/Famicom Emulator
*
* Copyright notice for this file:
* Copyright (C) 2002 Xodnizel
*
* 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
*/
#include <unistd.h>
#include <sys/types.h>
#include <signal.h>
#include <sys/time.h>
#include <sys/stat.h>
#include <string.h>
#include <strings.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include "main.h"
#include "throttle.h"
#include "../common/cheat.h"
#include "input.h"
#include "dface.h"
extern int32 fps_scale;
int CloseGame(void);
static char *soundrecfn=0; /* File name of sound recording. */
static int ntsccol=0,ntschue=0,ntsctint=0;
int soundvol=100;
long soundq=0;
int _sound=1;
long soundrate=48000;
#ifdef WIN32
long soundbufsize=52;
#else
long soundbufsize=24;
#endif
#ifdef FRAMESKIP
static int frameskip=0;
#endif
static int inited=0;
static int isloaded=0; // Is game loaded?
int srendlinev[2]={8,0};
int erendlinev[2]={231,239};
static uint8 *DrBaseDirectory;
int eoptions=0;
static void DriverKill(void);
static int DriverInitialize(FCEUGI *gi);
int gametype;
FCEUGI *CurGame=NULL;
static void ParseGI(FCEUGI *gi)
{
ParseGIInput(gi);
gametype=gi->type;
}
#ifndef EXTGUI
void FCEUD_PrintError(char *s)
{
puts(s);
}
void FCEUD_Message(char *s)
{
fputs(s,stdout);
}
#endif
static char *cpalette=0;
static void LoadCPalette(void)
{
uint8 tmpp[192];
FILE *fp;
if(!(fp=FCEUD_UTF8fopen(cpalette,"rb")))
{
printf(" Error loading custom palette from file: %s\n",cpalette);
return;
}
fread(tmpp,1,192,fp);
FCEUI_SetPaletteArray(tmpp);
fclose(fp);
}
#ifdef EXTGUI
extern CFGSTRUCT GUIConfig;
#endif
static CFGSTRUCT fceuconfig[]={
AC(soundrate),
AC(soundq),
AC(_sound),
AC(soundvol),
AC(soundbufsize),
ACS(cpalette),
AC(ntsctint),
AC(ntschue),
AC(ntsccol),
AC(eoptions),
ACA(srendlinev),
ACA(erendlinev),
ADDCFGSTRUCT(InputConfig),
ADDCFGSTRUCT(DriverConfig),
#ifdef EXTGUI
ADDCFGSTRUCT(GUIConfig),
#endif
ENDCFGSTRUCT
};
static void SaveConfig(void)
{
char tdir[2048];
sprintf(tdir,"%s"PSS"fceu98.cfg",DrBaseDirectory);
FCEUI_GetNTSCTH(&ntsctint, &ntschue);
SaveFCEUConfig(tdir,fceuconfig);
}
static void LoadConfig(void)
{
char tdir[2048];
sprintf(tdir,"%s"PSS"fceu98.cfg",DrBaseDirectory);
FCEUI_GetNTSCTH(&ntsctint, &ntschue); /* Get default settings for if
no config file exists. */
LoadFCEUConfig(tdir,fceuconfig);
InputUserActiveFix();
}
static void CreateDirs(void)
{
char *subs[7]={"fcs","fcm","snaps","gameinfo","sav","cheats","movie"};
char tdir[2048];
int x;
#ifdef WIN32
mkdir(DrBaseDirectory);
for(x=0;x<6;x++)
{
sprintf(tdir,"%s"PSS"%s",DrBaseDirectory,subs[x]);
mkdir(tdir);
}
#else
mkdir(DrBaseDirectory,S_IRWXU);
for(x=0;x<6;x++)
{
sprintf(tdir,"%s"PSS"%s",DrBaseDirectory,subs[x]);
mkdir(tdir,S_IRWXU);
}
#endif
}
#ifndef WIN32
static void SetSignals(void (*t)(int))
{
int sigs[11]={SIGINT,SIGTERM,SIGHUP,SIGPIPE,SIGSEGV,SIGFPE,SIGKILL,SIGALRM,SIGABRT,SIGUSR1,SIGUSR2};
int x;
for(x=0;x<11;x++)
signal(sigs[x],t);
}
static void CloseStuff(int signum)
{
DriverKill();
printf("\nSignal %d has been caught and dealt with...\n",signum);
switch(signum)
{
case SIGINT:printf("How DARE you interrupt me!\n");break;
case SIGTERM:printf("MUST TERMINATE ALL HUMANS\n");break;
case SIGHUP:printf("Reach out and hang-up on someone.\n");break;
case SIGPIPE:printf("The pipe has broken! Better watch out for floods...\n");break;
case SIGSEGV:printf("Iyeeeeeeeee!!! A segmentation fault has occurred. Have a fluffy day.\n");break;
/* So much SIGBUS evil. */
#ifdef SIGBUS
#if(SIGBUS!=SIGSEGV)
case SIGBUS:printf("I told you to be nice to the driver.\n");break;
#endif
#endif
case SIGFPE:printf("Those darn floating points. Ne'er know when they'll bite!\n");break;
case SIGALRM:printf("Don't throw your clock at the meowing cats!\n");break;
case SIGABRT:printf("Abort, Retry, Ignore, Fail?\n");break;
case SIGUSR1:
case SIGUSR2:printf("Killing your processes is not nice.\n");break;
}
exit(1);
}
#endif
static void DoArgs(int argc, char *argv[])
{
int x;
static ARGPSTRUCT FCEUArgs[]={
{"-soundbufsize",0,&soundbufsize,0},
{"-soundrate",0,&soundrate,0},
{"-soundq",0,&soundq,0},
#ifdef FRAMESKIP
{"-frameskip",0,&frameskip,0},
#endif
{"-sound",0,&_sound,0},
{"-soundvol",0,&soundvol,0},
{"-cpalette",0,&cpalette,0x4001},
{"-soundrecord",0,&soundrecfn,0x4001},
{"-ntsccol",0,&ntsccol,0},
{"-pal",0,&eoptions,0x8000|EO_PAL},
{"-lowpass",0,&eoptions,0x8000|EO_LOWPASS},
{"-gg",0,&eoptions,0x8000|EO_GAMEGENIE},
{"-no8lim",0,&eoptions,0x8001},
{"-snapname",0,&eoptions,0x8000|EO_SNAPNAME},
{"-nofs",0,&eoptions,0x8000|EO_NOFOURSCORE},
{"-clipsides",0,&eoptions,0x8000|EO_CLIPSIDES},
{"-nothrottle",0,&eoptions,0x8000|EO_NOTHROTTLE},
{"-slstart",0,&srendlinev[0],0},{"-slend",0,&erendlinev[0],0},
{"-slstartp",0,&srendlinev[1],0},{"-slendp",0,&erendlinev[1],0},
{0,(int *)InputArgs,0,0},
{0,(int *)DriverArgs,0,0},
{0,0,0,0}
};
ParseArguments(argc, argv, FCEUArgs);
if(cpalette)
{
if(cpalette[0]=='0')
if(cpalette[1]==0)
{
free(cpalette);
cpalette=0;
}
}
FCEUI_SetVidSystem((eoptions&EO_PAL)?1:0);
FCEUI_SetGameGenie((eoptions&EO_GAMEGENIE)?1:0);
FCEUI_SetLowPass((eoptions&EO_LOWPASS)?1:0);
FCEUI_DisableSpriteLimitation(eoptions&1);
FCEUI_SetSnapName(eoptions&EO_SNAPNAME);
for(x=0;x<2;x++)
{
if(srendlinev[x]<0 || srendlinev[x]>239) srendlinev[x]=0;
if(erendlinev[x]<srendlinev[x] || erendlinev[x]>239) erendlinev[x]=239;
}
FCEUI_SetRenderedLines(srendlinev[0],erendlinev[0],srendlinev[1],erendlinev[1]);
DoDriverArgs();
}
#include "usage.h"
/* Loads a game, given a full path/filename. The driver code must be
initialized after the game is loaded, because the emulator code
provides data necessary for the driver code(number of scanlines to
render, what virtual input devices to use, etc.).
*/
int LoadGame(const char *path)
{
FCEUGI *tmp;
CloseGame();
if(!(tmp=FCEUI_LoadGame(path,1)))
return 0;
CurGame=tmp;
ParseGI(tmp);
RefreshThrottleFPS();
if(!DriverInitialize(tmp))
return(0);
if(soundrecfn)
{
if(!FCEUI_BeginWaveRecord(soundrecfn))
{
free(soundrecfn);
soundrecfn=0;
}
}
isloaded=1;
#ifdef EXTGUI
if(eoptions&EO_AUTOHIDE) GUI_Hide(1);
#endif
FCEUD_NetworkConnect();
return 1;
}
/* Closes a game. Frees memory, and deinitializes the drivers. */
int CloseGame(void)
{
if(!isloaded) return(0);
FCEUI_CloseGame();
DriverKill();
isloaded=0;
CurGame=0;
if(soundrecfn)
FCEUI_EndWaveRecord();
#ifdef EXTGUI
GUI_Hide(0);
#endif
InputUserActiveFix();
return(1);
}
void FCEUD_Update(uint8 *XBuf, int32 *Buffer, int Count);
void DoFun(void)
{
uint8 *gfx;
int32 *sound;
int32 ssize;
static int fskipc=0;
static int opause=0;
#ifdef FRAMESKIP
fskipc=(fskipc+1)%(frameskip+1);
#endif
if(NoWaiting) {gfx=0;}
FCEUI_Emulate(&gfx, &sound, &ssize, fskipc);
FCEUD_Update(gfx, sound, ssize);
if(opause!=FCEUI_EmulationPaused())
{
opause=FCEUI_EmulationPaused();
SilenceSound(opause);
}
}
int CLImain(int argc, char *argv[])
{
int ret;
if(!(ret=FCEUI_Initialize()))
return(0);
DrBaseDirectory=GetBaseDirectory();
FCEUI_SetBaseDirectory(DrBaseDirectory);
CreateDirs();
#ifdef EXTGUI
if(argc==2 && !strcmp(argv[1],"-help")) // I hope no one has a game named "-help" :b
#else
if(argc<=1)
#endif
{
ShowUsage(argv[0]);
return(0);
}
LoadConfig();
DoArgs(argc-2,&argv[1]);
FCEUI_SetNTSCTH(ntsccol, ntsctint, ntschue);
if(cpalette)
LoadCPalette();
/* All the config files and arguments are parsed now. */
#ifdef EXTGUI
return(1);
#else
if(!LoadGame(argv[argc-1]))
{
DriverKill();
return(0);
}
while(CurGame)
DoFun();
#if(0)
{
int x;
for(x=1;x<argc;x++)
{ LoadGame(argv[x]); while(CurGame) DoFun(); }
}
#endif
CloseGame();
SaveConfig();
FCEUI_Kill();
#endif
return(1);
}
static int DriverInitialize(FCEUGI *gi)
{
#ifndef WIN32
SetSignals(CloseStuff);
#endif
/* Initialize video before all else, due to some wacko dependencies
in the SexyAL code(DirectSound) that need to be fixed.
*/
if(!InitVideo(gi)) return 0;
inited|=4;
if(InitSound(gi))
inited|=1;
if(InitJoysticks())
inited|=2;
if(!InitKeyboard()) return 0;
inited|=8;
InitOtherInput();
return 1;
}
static void DriverKill(void)
{
SaveConfig();
#ifndef WIN32
SetSignals(SIG_IGN);
#endif
if(inited&2)
KillJoysticks();
if(inited&8)
KillKeyboard();
if(inited&4)
KillVideo();
if(inited&1)
KillSound();
if(inited&16)
KillMouse();
inited=0;
}
void FCEUD_Update(uint8 *XBuf, int32 *Buffer, int Count)
{
#ifdef NETWORK
extern int FCEUDnetplay;
#endif
int ocount = Count;
// apply frame scaling to Count
Count = (Count<<8)/fps_scale;
if(Count)
{
int32 can=GetWriteSound();
static int uflow=0;
int32 tmpcan;
// don't underflow when scaling fps
if(can >= GetMaxSound() && fps_scale<=256) uflow=1; /* Go into massive underflow mode. */
if(can > Count) can=Count;
else uflow=0;
WriteSound(Buffer,can);
//if(uflow) puts("Underflow");
tmpcan = GetWriteSound();
// don't underflow when scaling fps
if(fps_scale>256 || ((tmpcan < Count*0.90) && !uflow))
{
if(XBuf && (inited&4) && !(NoWaiting & 2))
BlitScreen(XBuf);
Buffer+=can;
Count-=can;
if(Count)
{
if(NoWaiting)
{
can=GetWriteSound();
if(Count>can) Count=can;
WriteSound(Buffer,Count);
}
else
{
while(Count>0)
{
WriteSound(Buffer,(Count<ocount) ? Count : ocount);
Count -= ocount;
}
}
}
} //else puts("Skipped");
#ifdef NETWORK
else if(!NoWaiting && FCEUDnetplay && (uflow || tmpcan >= (Count * 1.8)))
{
if(Count > tmpcan) Count=tmpcan;
while(tmpcan > 0)
{
// printf("Overwrite: %d\n", (Count <= tmpcan)?Count : tmpcan);
WriteSound(Buffer, (Count <= tmpcan)?Count : tmpcan);
tmpcan -= Count;
}
}
#endif
}
else
{
if(!NoWaiting && (!(eoptions&EO_NOTHROTTLE) || FCEUI_EmulationPaused()))
SpeedThrottle();
if(XBuf && (inited&4))
{
BlitScreen(XBuf);
}
}
FCEUD_UpdateInput();
//if(!Count && !NoWaiting && !(eoptions&EO_NOTHROTTLE))
// SpeedThrottle();
//if(XBuf && (inited&4))
//{
// BlitScreen(XBuf);
//}
//if(Count)
// WriteSound(Buffer,Count,NoWaiting);
//FCEUD_UpdateInput();
}
/* Maybe ifndef WXWINDOWS would be better? ^_^ */
#ifndef EXTGUI
FILE *FCEUD_UTF8fopen(const char *fn, const char *mode)
{
return(fopen(fn,mode));
}
#endif

55
drivers/pc/main.h Normal file
View File

@ -0,0 +1,55 @@
/* FCE Ultra - NES/Famicom Emulator
*
* Copyright notice for this file:
* Copyright (C) 2002 Xodnizel
*
* 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
*/
#ifdef __cplusplus
extern "C" {
#endif
#include "../../driver.h"
#include "../common/config.h"
#include "../common/args.h"
extern int eoptions;
#define EO_NO8LIM 1
#define EO_SUBASE 2
#define EO_CLIPSIDES 8
#define EO_SNAPNAME 16
#define EO_NOFOURSCORE 32
#define EO_NOTHROTTLE 64
#define EO_GAMEGENIE 128
#define EO_PAL 256
#define EO_LOWPASS 512
#define EO_AUTOHIDE 1024
extern int srendlinev[2],erendlinev[2];
extern int NoWaiting;
extern int soundvol;
extern long soundq;
extern int _sound;
extern long soundrate;
extern long soundbufsize;
int CLImain(int argc, char *argv[]);
#ifdef __cplusplus
}
#endif

134
drivers/pc/sdl-icon.h Normal file
View File

@ -0,0 +1,134 @@
static const struct {
unsigned int width;
unsigned int height;
unsigned int bytes_per_pixel; /* 3:RGB, 4:RGBA */
uint8 pixel_data[32 * 32 * 3 + 1];
} fceu_playicon = {
32, 32, 3,
"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\\\223\373\\\223\373\\\223\373\\\223"
"\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373"
"\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\"
"\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223"
"\373\\\223\373\\\223\373\0\0\0\0\0\0\0\0\0\\\223\373\\\223\373\267\317\373"
"\246\304\373\260\312\373\222\267\373\246\304\373\\\223\373\\\223\373\\\223"
"\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373"
"\267\317\373\246\304\373\260\312\373\210\261\373\246\304\373\\\223\373\\"
"\223\373\210\261\373\222\267\373\267\317\373\241\301\373\\\223\373\\\223"
"\373\0\0\0\0\0\0\\\223\373\\\223\373\227\272\373\227\272\373\227\272\373"
"\227\272\373\227\272\373\227\272\373\\\223\373\\\223\373z`sr\242\373\227"
"\272\373\227\272\373\\\223\373\\\223\373\\\223\373\\\223\373\213\261\373"
"z\247\373\213\261\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\"
"\223\373\\\223\373\\\223\373\\\223\373\0\0\0\0\0\0\\\223\373\\\223\373\\"
"\223\373\\\223\373\313i=\315Z\40\315Z\40\315Z\40\315Z\40\315Z\40\315Z\40"
"\315Z\40\315Z\40\315Z\40\315Z\40\315Z\40\315Z\40\315Z\40\315Z\40\315Z\40"
"\315Z\40\315Z\40\315Z\40\315Z\40\315Z\40\257T*\\\223\373\\\223\373\\\223"
"\373\\\223\373\0\0\0\0\0\0\\\223\373\\\223\373\\\223\373\\\223\373\315Z\40"
"\355\235\203\355\235\203\341\232\205\341\232\205\365\255\233\355\235\203"
"\355\235\203\350\250\232\365\255\233\355\235\203\307L\14\307L\14\307L\14"
"\307L\14\307L\14\307L\14\307L\14\307L\14\307L\14\307L\14\256B\12\\\223\373"
"\\\223\373\\\223\373\\\223\373\0\0\0\0\0\0\\\223\373\\\223\373\\\223\373"
"\\\223\373\315Z\40\273zc\233l_\325\225\205\325\225\205\325\225\205\273\212"
"\201\325\225\205\237qd\325\225\205\317\231\216\307L\14\307L\14\307L\14\307"
"L\14\307L\14\307L\14\307L\14\307L\14\307L\14\307L\14\256B\12\\\223\373\\"
"\223\373\\\223\373\\\223\373\0\0\0\0\0\0\\\223\373\\\223\373\\\223\373\\"
"\223\373\315Z\40\344\232\203\301\215\201\344\232\203\273\212\201\325\225"
"\205\2114\10\344\232\203\350\250\232\325\225\205\333\230\205\307L\14\307"
"L\14\307L\14\307L\14\307L\14\307L\14\307L\14\307L\14\307L\14\307L\14\256"
"B\12\\\223\373\\\223\373\\\223\373\\\223\373\0\0\0\0\0\0\\\223\373\\\223"
"\373\\\223\373\\\223\373\315Z\40\2259\11}0\10\2259\11}0\10}0\10\307L\14\225"
"9\11d&\6}0\10}0\10\307L\14\307L\14\307L\14\307L\14\307L\14\307L\14\307L\14"
"\307L\14\307L\14\307L\14\256B\12\\\223\373\\\223\373\\\223\373\\\223\373"
"\0\0\0\0\0\0\\\223\373\\\223\373\\\223\373\\\223\373\315Z\40\355\235\203"
"\355\233\201\355\235\203\355\235\203\355\235\203\365\255\233\355\235\203"
"\341\232\205\355\235\203\355\235\203\307L\14\365\255\233\355\235\203\365"
"\255\233\355\235\203\355\235\203\355\235\203\355\235\203\355\235\203\307"
"L\14\256B\12\\\223\373\\\223\373\\\223\373\\\223\373\0\0\0\0\0\0\\\223\373"
"\\\223\373\\\223\373\\\223\373\315Z\40\325\225\205\311\221\204\311\221\204"
"\325\225\205\311\221\204\325\225\205\311\221\204\325\225\205\325\225\205"
"\311\221\204\307L\14\325\225\205\311\221\204\325\225\205\311\221\204\325"
"\225\205\311\221\204\325\225\205\311\221\204\307L\14\256B\12\\\223\373\\"
"\223\373\\\223\373\\\223\373\0\0\0\0\0\0\\\223\373\\\223\373\\\223\373\\"
"\223\373\315Z\40\325\225\205\325\225\205\325\225\205\325\225\205\325\225"
"\205\325\225\205\317\231\216\325\225\205\325\225\205\325\225\205\307L\14"
"\325\225\205\317\231\216\325\225\205\317\231\216\325\225\205\325\225\205"
"\273zc\241n_\307L\14\256B\12\\\223\373\\\223\373\\\223\373\\\223\373\0\0"
"\0\0\0\0\\\223\373\\\223\373\\\223\373\\\223\373\315Z\40\325\225\205\325"
"\225\205\325\225\205\365\255\233\333\243\231\325\225\205\333\230\205\325"
"\225\205\325\225\205\325\225\205\307L\14\325\225\205\317\223\204\325\225"
"\205\333\230\205\325\225\205\325\225\205\333\230\205\317\223\204\307L\14"
"\256B\12\\\223\373\\\223\373\\\223\373\\\223\373\0\0\0\0\0\0\\\223\373\\"
"\223\373\\\223\373\\\223\373\315Z\40\325\225\205\325\225\205\325\225\205"
"\325\225\205\311\221\204\325\225\205\325\225\205\325\225\205\344\232\203"
"\273\212\201\307L\14\325\225\205\273\212\201\325\225\205\325\225\205\344"
"\232\203\273\212\201\344\232\203\273\212\201\341\232\205\256B\12\\\223\373"
"\\\223\373\\\223\373\\\223\373\0\0\0\0\0\0\\\223\373\\\223\373\\\223\373"
"\\\223\373\257T*d&\6d&\6d&\6d&\6d&\6d&\6d&\6d&\6}0\10d&\6\256B\12d&\6p+\7"
"d&\6d&\6}0\10d&\6}0\10d&\6d&\6\223@\26\\\223\373\\\223\373\\\223\373\\\223"
"\373\0\0\0\0\0\0\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223"
"\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\234\243"
"\335\213\237\344\237\244\333\251\247\326\237\244\333\\\223\373\267\252\317"
"\222\241\341\267\252\317\210\237\346\241\245\332\267\252\317\246\246\327"
"\246\246\327\\\223\373\\\223\373\\\223\373\\\223\373\0\0\0\0\0\0\\\223\373"
"\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\"
"\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223"
"\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373"
"\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\0"
"\0\0\0\0\0\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\"
"\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223"
"\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373"
"\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\"
"\223\373\\\223\373\0\0\0\0\0\0\\\223\373\\\223\373\\\223\373\\\223\373\\"
"\223\373\\\223\373\\\223\373\\\223\373\257hT\\\223\373\213\261\373\\\223"
"\373\241\301\373\210\261\373\246\304\373\222\267\373\241\301\373\260\312"
"\373\\\223\373\237\277\373\246\304\373\267\317\373\241\301\373\\\223\373"
"\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\0\0\0\0\0\0"
"\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\"
"\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223"
"\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373"
"\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\"
"\223\373\0\0\0\0\0\0\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\"
"\223\373\\\223\373\\\223\373\\\223\373\\\223\373\246\304\373\\\223\373\241"
"\301\373\210\261\373\246\304\373\222\267\373\241\301\373\260\312\373\\\223"
"\373\237\277\373\246\304\373\267\317\373\241\301\373\\\223\373\\\223\373"
"\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\0\0\0\0\0\0\\\223\373"
"\\\223\373\\\223\373D\203\270D\203\270\\\223\373\\\223\373\\\223\373\\\223"
"\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373"
"\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\"
"\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\0\0"
"\0\0\0\0\\\223\373\\\223\373(\211n\0\247\0\0n\0(\211n\\\223\373\\\223\373"
"\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\"
"\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223"
"\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373"
"\0\0\0\0\0\0\\\223\373(\211n\0\247\0\0\247\0\0\247\0\0\247\0(\211n\\\223"
"\373\\\223\373\\\223\373\\\223\373\210\261\373\246\304\373\241\301\373z\247"
"\373\\\223\373\227\272\373\227\272\373\227\272\373\227\272\373\227\272\373"
"\227\272\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373"
"\\\223\373\\\223\373\0\0\0\0\0\0(\211n\0\247\0\0n\0\0\247\0\\\215\12fs\16"
"\0\247\0(\211n\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373"
"\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\"
"\223\373\\\223\373Z\231Z[\230SZ\231Z[\230SZ\231Z[\230S\\\223\373\0\0\0\0"
"\0\0\0\247\0\0\247\0\0\247\0\0\247\0vy\7p|\7\0\247\0\0\247\0(\211n\\\223"
"\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373"
"\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373b\237L\200\317\20\200\317"
"\20\200\317\20\200\317\20\200\317\20\200\317\20[\223H\0\0\0\0\0\0\230P.\323"
"d0\230P.\323d0\221M&\313`%\230P.\323d0\230P.\323d0\230P.\323d0\230P.\323"
"d0\230P.\323d0\230P.\323d0\230P.\323d0\230P.\323d0\230P.\323d0\230P.\323"
"d0\230P.\323d0\230P.\323d0\0\0\0\0\0\0\0\0\0\237N(\225E\35\237N(\225E\35"
"\237N(\225E\35\237N(\225E\35\237N(\225E\35\237N(\225E\35\237N(\225E\35\237"
"N(\225E\35\237N(\225E\35\237N(\225E\35\237N(\225E\35\237N(\225E\35\237N("
"\225E\35\237N(\225E\35\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0",
};

99
drivers/pc/sdl-joystick.c Normal file
View File

@ -0,0 +1,99 @@
/* FCE Ultra - NES/Famicom Emulator
*
* Copyright notice for this file:
* Copyright (C) 2002 Xodnizel
* Copyright (C) 2002 Paul Kuliniewicz
*
* 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
*/
/* PK: SDL joystick input stuff */
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include "sdl.h"
#define MAX_JOYSTICKS 32
static SDL_Joystick *Joysticks[MAX_JOYSTICKS] = {NULL};
int DTestButtonJoy(ButtConfig *bc)
{
int x;
for(x=0;x<bc->NumC;x++)
{
if(bc->ButtonNum[x]&0x8000) /* Axis "button" */
{
int pos;
pos = SDL_JoystickGetAxis(Joysticks[bc->DeviceNum[x]], bc->ButtonNum[x]&16383);
if ((bc->ButtonNum[x]&0x4000) && pos <= -16383)
return(1);
else if (!(bc->ButtonNum[x]&0x4000) && pos >= 16363)
return(1);
}
else if(bc->ButtonNum[x]&0x2000) /* Hat "button" */
{
if( SDL_JoystickGetHat(Joysticks[bc->DeviceNum[x]],(bc->ButtonNum[x]>>8)&0x1F) & (bc->ButtonNum[x]&0xFF))
return(1);
}
else
if(SDL_JoystickGetButton(Joysticks[bc->DeviceNum[x]], bc->ButtonNum[x] ))
return(1);
}
return(0);
}
static int jinited=0;
/* Cleanup opened joysticks. */
int KillJoysticks (void)
{
int n; /* joystick index */
if(!jinited) return(0);
for (n = 0; n < MAX_JOYSTICKS; n++)
{
if (Joysticks[n] != 0)
SDL_JoystickClose(Joysticks[n]);
Joysticks[n]=0;
}
SDL_QuitSubSystem(SDL_INIT_JOYSTICK);
return(1);
}
/* Initialize joysticks. */
int InitJoysticks (void)
{
int n; /* joystick index */
int total;
SDL_InitSubSystem(SDL_INIT_JOYSTICK);
total=SDL_NumJoysticks();
if(total>MAX_JOYSTICKS) total=MAX_JOYSTICKS;
for (n = 0; n < total; n++)
{
/* Open the joystick under SDL. */
Joysticks[n] = SDL_JoystickOpen(n);
//printf("Could not open joystick %d: %s.\n",
//joy[n] - 1, SDL_GetError());
continue;
}
jinited=1;
return(1);
}

224
drivers/pc/sdl-netplay.c Normal file
View File

@ -0,0 +1,224 @@
#include "sdl.h"
#include <SDL/SDL_net.h>
#include "sdl-netplay.h"
char *ServerHost;
static int LocalPortTCP=0xFCE;
static int LocalPortUDP=0xFCE;
static int RemotePortTCP=0xFCE;
static int RemotePortUDP; /* Not configurable, figured out during handshake. */
static TCPsocket Socket;
static UDPsocket UDPSocket;
static SDLNet_SocketSet set;
static void en32(uint8 *buf, uint32 morp)
{
buf[0]=morp;
buf[1]=morp>>8;
buf[2]=morp>>16;
buf[3]=morp>>24;
}
static uint32 de32(uint8 *morp)
{
return(morp[0]|(morp[1]<<8)|(morp[2]<<16)|(morp[3]<<24));
}
int FCEUD_NetworkConnect(void)
{
IPaddress rip;
SDLNet_Init();
if(netplay==1) /* Be a server. */
{
TCPsocket tmp;
Uint16 p=LocalPortUDP;
SDLNet_ResolveHost(&rip,NULL,LocalPortTCP);
UDPSocket=SDLNet_UDP_Open(&p);
tmp=SDLNet_TCP_Open(&rip);
Socket=SDLNet_TCP_Accept(&tmp);
memcpy(&rip,SDLNet_TCP_GetPeerAddress(Socket),sizeof(IPaddress));
{
uint8 buf[12];
uint32 player=1;
magic=SDL_GetTicks();
SDLNet_Write32(buf,uport);
SDLNet_Write32(buf+4,1);
SDLNet_Write32(buf+8,magic);
SDLNet_TCP_Send(Socket, buf, 12);
/* Get the UDP port the client is waiting for data on. */
SDLNet_TCP_Recv(Socket, buf, 2);
RemotePortUDP=de32(buf);
}
}
else /* Be a client */
{
SDLNet_ResolveHost(&rip,ServerHost,RemotePortTCP);
Socket=SDLNet_TCP_Open(&rip);
{
Uint16 p=LocalPortUDP;
uint8 buf[12];
UDPSocket=SDLNet_UDP_Open(&p);
/* Now, tell the server what local UDP port it should send to. */
en32(buf,p);
SDLNet_TCP_Send(Socket, buf, 4);
/* Get the UDP port from the server we should send data to. */
SDLNet_TCP_Recv(Socket, buf, 12);
RemotePortUDP=de32(buf);
magic=de32(buf+8);
}
set=SDLNet_AllocSocketSet(1);
SDLNet_TCP_AddSocket(set,TCPSocket);
SDLNet_UDP_AddSocket(set,UDPSocket);
} // End client connect code.
rip.port=RemotePortUDP;
SDLNet_UDP_Bind(UDPSocket, 0, &rip);
}
static int CheckUDP(uint8 *packet, int32 len, int32 alt)
{
uint32 crc;
uint32 repcrc;
crc=FCEUI_CRC32(0,packet+4,len+8);
repcrc=de32(packet);
if(crc!=repcrc) return(0); /* CRC32 mismatch, bad packet. */
packet+=4;
if(de32(packet)!=magic) /* Magic number mismatch, bad or spoofed packet. */
return(0);
packet+=4;
if(alt)
{
if(de32(packet)<incounter) /* Time warped packet. */
return(0);
}
else
if(de32(packet)!=incounter) /* Time warped packet. */
return(0);
return(1);
}
/* Be careful where these MakeXXX() functions are used. */
static uint8 *MakeUDP(uint8 *data, int32 len)
{
/* UDP packet data header is 12 bytes in length. */
static uint8 buf[12+32]; // arbitrary 32.
en32(buf+4,magic);
en32(buf+8,outcounter);
memcpy(buf+12,data,len);
en32(buf,FCEUI_CRC32(0,buf+4,8+len));
return(buf);
}
static uint8 *MakeTCP(uint8 *data, int32 len)
{
/* TCP packet data header is 4 bytes in length. */
static uint8 buf[4+32]; // arbitrary 32.
en32(buf,outcounter);
memcpy(buf+4,data,len);
return(buf);
}
#define UDPHEADSIZE 12
#define TCPHEADSIZE 4
void FCEUD_NetworkClose(void)
{
SDLNet_Quit();
}
/* 1 byte to server */
int FCEUD_SendDataToServer(uint8 v,uint8 cmd)
{
UDPpacket upack;
upack.channel=0;
upack.data=MakeUDP(data,1);
upack.len=upack.maxlen=UDPHEADSIZE+1;
upack.status=0;
SDLNet_UDP_Send(UDPSocket,0,&upack);
outcounter++;
return(1);
}
void FCEUD_SendDataToClients(uint8 *data)
{
UDPpacket upack;
SDLNet_TCP_Send(Socket,MakeTCP(data,5),TCPHEADSIZE+5);
upack.channel=0;
upack.data=MakeUDP(data,5);
upack.len=upack.maxlen=UDPHEADSIZE+5;
upack.status=0;
SDLNet_UDP_Send(UDPSocket,0,&upack);
outcounter++;
return(1);
}
int FCEUD_GetDataFromServer(uint8 *data)
{
uint8 buf[128];
NoWaiting&=~2;
while(SDLNet_CheckSockets(set,1)==0)
{
// do something here.
}
if(SDLNet_SocketReady(Socket))
{
SDLNet_TCP_Recv
if(de32(buf)==incounter) /* New packet, keep. */
{
unsigned long beefie;
memcpy(data,buf+TCPHEADSIZE,5);
incounter++;
if(!ioctl(Socket,FIONREAD,&beefie))
if(beefie)
NoWaiting|=2;
return(1);
}
}
if(SDLNet_SocketReady(UDPSocket)
{
}
}

0
drivers/pc/sdl-netplay.h Normal file
View File

241
drivers/pc/sdl-opengl.c Normal file
View File

@ -0,0 +1,241 @@
#define GL_GLEXT_LEGACY
#ifdef APPLEOPENGL
#include <OpenGL/gl.h>
#include <OpenGL/glu.h>
#include <OpenGL/glext.h>
#else
#include <GL/gl.h>
#include <GL/glu.h>
#include <GL/glext.h>
#endif
#include <string.h>
#include <stdlib.h>
#include "sdl.h"
#include "sdl-opengl.h"
#include "../common/vidblit.h"
#ifndef APIENTRY
#define APIENTRY
#endif
static GLuint textures[2]={0,0}; // Normal image, scanline overlay.
static int left,right,top,bottom; // right and bottom are not inclusive.
static int scanlines;
static void *HiBuffer;
void APIENTRY (*p_glBindTexture)(GLenum target,GLuint texture);
void APIENTRY (*p_glColorTableEXT)(GLenum target, GLenum internalformat, GLsizei width, GLenum format, GLenum type, const GLvoid *table);
void APIENTRY (*p_glTexImage2D)( GLenum target, GLint level,
GLint internalFormat,
GLsizei width, GLsizei height, GLint border,
GLenum format, GLenum type,
const GLvoid *pixels );
void APIENTRY (*p_glBegin)(GLenum mode);
void APIENTRY (*p_glVertex2f)(GLfloat x, GLfloat y);
void APIENTRY (*p_glTexCoord2f)(GLfloat s, GLfloat t);
void APIENTRY (*p_glEnd)(void);
void APIENTRY (*p_glEnable)(GLenum cap);
void APIENTRY (*p_glBlendFunc)(GLenum sfactor, GLenum dfactor);
const GLubyte* APIENTRY (*p_glGetString)(GLenum name);
void APIENTRY (*p_glViewport)(GLint x, GLint y,GLsizei width, GLsizei height);
void APIENTRY (*p_glGenTextures)(GLsizei n, GLuint *textures);
void APIENTRY (*p_glDeleteTextures)(GLsizei n,const GLuint *textures);
void APIENTRY (*p_glTexParameteri)(GLenum target, GLenum pname, GLint param);
void APIENTRY (*p_glClearColor)(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha);
void APIENTRY (*p_glLoadIdentity)(void);
void APIENTRY (*p_glClear)(GLbitfield mask);
void APIENTRY (*p_glMatrixMode)(GLenum mode);
void APIENTRY (*p_glDisable)(GLenum cap);
void SetOpenGLPalette(uint8 *data)
{
if(!HiBuffer)
{
p_glBindTexture(GL_TEXTURE_2D, textures[0]);
p_glColorTableEXT(GL_TEXTURE_2D,GL_RGB,256,GL_RGBA,GL_UNSIGNED_BYTE,data);
}
else
SetPaletteBlitToHigh((uint8*)data);
}
void BlitOpenGL(uint8 *buf)
{
p_glBindTexture(GL_TEXTURE_2D, textures[0]);
if(HiBuffer)
{
static int xo=0;
xo=(xo+1)&3;
Blit8ToHigh(buf,(uint8*)HiBuffer,256,240,256*4,1,1);
if(!xo)
p_glTexImage2D(GL_TEXTURE_2D,0,GL_RGBA8,256,256, 0, GL_RGBA,GL_UNSIGNED_BYTE,
HiBuffer);
}
else
{
//glPixelStorei(GL_UNPACK_ROW_LENGTH, 256);
p_glTexImage2D(GL_TEXTURE_2D, 0, GL_COLOR_INDEX8_EXT, 256, 256, 0,
GL_COLOR_INDEX,GL_UNSIGNED_BYTE,buf);
}
p_glBegin(GL_QUADS);
p_glTexCoord2f(1.0f*left/256, 1.0f*bottom/256); // Bottom left of our picture.
p_glVertex2f(-1.0f, -1.0f); // Bottom left of target.
p_glTexCoord2f(1.0f*right/256, 1.0f*bottom/256); // Bottom right of our picture.
p_glVertex2f( 1.0f, -1.0f); // Bottom right of target.
p_glTexCoord2f(1.0f*right/256, 1.0f*top/256); // Top right of our picture.
p_glVertex2f( 1.0f, 1.0f); // Top right of target.
p_glTexCoord2f(1.0f*left/256, 1.0f*top/256); // Top left of our picture.
p_glVertex2f(-1.0f, 1.0f); // Top left of target.
p_glEnd();
//glDisable(GL_BLEND);
if(scanlines)
{
p_glEnable(GL_BLEND);
p_glBindTexture(GL_TEXTURE_2D, textures[1]);
p_glBlendFunc(GL_DST_COLOR, GL_SRC_ALPHA);
p_glBegin(GL_QUADS);
p_glTexCoord2f(1.0f*left/256, 1.0f*bottom/256); // Bottom left of our picture.
p_glVertex2f(-1.0f, -1.0f); // Bottom left of target.
p_glTexCoord2f(1.0f*right/256, 1.0f*bottom/256); // Bottom right of our picture.
p_glVertex2f( 1.0f, -1.0f); // Bottom right of target.
p_glTexCoord2f(1.0f*right/256, 1.0f*top/256); // Top right of our picture.
p_glVertex2f( 1.0f, 1.0f); // Top right of target.
p_glTexCoord2f(1.0f*left/256, 1.0f*top/256); // Top left of our picture.
p_glVertex2f(-1.0f, 1.0f); // Top left of target.
p_glEnd();
p_glDisable(GL_BLEND);
}
SDL_GL_SwapBuffers();
}
void KillOpenGL(void)
{
if(textures[0])
p_glDeleteTextures(2, &textures[0]);
textures[0]=0;
if(HiBuffer)
{
free(HiBuffer);
HiBuffer=0;
}
}
/* Rectangle, left, right(not inclusive), top, bottom(not inclusive). */
int InitOpenGL(int l, int r, int t, int b, double xscale,double yscale, int efx, int ipolate,
int stretchx, int stretchy, SDL_Surface *screen)
{
const char *extensions;
#define LFG(x) if(!(p_##x = SDL_GL_GetProcAddress(#x))) return(0);
#define LFGN(x) p_##x = SDL_GL_GetProcAddress(#x)
LFG(glBindTexture);
LFGN(glColorTableEXT);
LFG(glTexImage2D);
LFG(glBegin);
LFG(glVertex2f);
LFG(glTexCoord2f);
LFG(glEnd);
LFG(glEnable);
LFG(glBlendFunc);
LFG(glGetString);
LFG(glViewport);
LFG(glGenTextures);
LFG(glDeleteTextures);
LFG(glTexParameteri);
LFG(glClearColor);
LFG(glLoadIdentity);
LFG(glClear);
LFG(glMatrixMode);
LFG(glDisable);
left=l;
right=r;
top=t;
bottom=b;
HiBuffer=0;
extensions=(const char*)p_glGetString(GL_EXTENSIONS);
if((efx&2) || !extensions || !p_glColorTableEXT || !strstr(extensions,"GL_EXT_paletted_texture"))
{
if(!(efx&2)) // Don't want to print out a warning message in this case...
FCEU_printf("Paletted texture extension not found. Using slower texture format...");
HiBuffer=malloc(4*256*256);
memset(HiBuffer,0x00,4*256*256);
#ifndef LSB_FIRST
InitBlitToHigh(4,0xFF000000,0xFF0000,0xFF00,efx&2,0);
#else
InitBlitToHigh(4,0xFF,0xFF00,0xFF0000,efx&2,0);
#endif
}
{
int rw=(r-l)*xscale;
int rh=(b-t)*yscale;
int sx=(screen->w-rw)/2; // Start x
int sy=(screen->h-rh)/2; // Start y
if(stretchx) { sx=0; rw=screen->w; }
if(stretchy) { sy=0; rh=screen->h; }
p_glViewport(sx, sy, rw, rh);
}
p_glGenTextures(2, &textures[0]);
scanlines=0;
if(efx&1)
{
uint8 *buf;
int x,y;
scanlines=1;
p_glBindTexture(GL_TEXTURE_2D, textures[1]);
p_glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,ipolate?GL_LINEAR:GL_NEAREST);
p_glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,ipolate?GL_LINEAR:GL_NEAREST);
buf=(uint8*)malloc(256*(256*2)*4);
for(y=0;y<(256*2);y++)
for(x=0;x<256;x++)
{
buf[y*256*4+x*4]=0;
buf[y*256*4+x*4+1]=0;
buf[y*256*4+x*4+2]=0;
buf[y*256*4+x*4+3]=(y&1)?0x00:0xFF; //?0xa0:0xFF; // <-- Pretty
//buf[y*256+x]=(y&1)?0x00:0xFF;
}
p_glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 256, (scanlines==2)?256*4:512, 0,
GL_RGBA,GL_UNSIGNED_BYTE,buf);
free(buf);
}
p_glBindTexture(GL_TEXTURE_2D, textures[0]);
p_glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,ipolate?GL_LINEAR:GL_NEAREST);
p_glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,ipolate?GL_LINEAR:GL_NEAREST);
p_glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_CLAMP);
p_glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_CLAMP);
p_glEnable(GL_TEXTURE_2D);
p_glClearColor(0.0f, 0.0f, 0.0f, 0.0f); // Background color to black.
p_glMatrixMode(GL_MODELVIEW);
p_glClear(GL_COLOR_BUFFER_BIT);
p_glLoadIdentity();
return(1);
}

6
drivers/pc/sdl-opengl.h Normal file
View File

@ -0,0 +1,6 @@
void SetOpenGLPalette(uint8 *data);
void BlitOpenGL(uint8 *buf);
void KillOpenGL(void);
int InitOpenGL(int l, int r, int t, int b, double xscale,double yscale, int efx, int ipolate,
int stretchx, int stretchy, SDL_Surface *screen);

373
drivers/pc/sdl-sound.c Normal file
View File

@ -0,0 +1,373 @@
/* FCE Ultra - NES/Famicom Emulator
*
* Copyright notice for this file:
* Copyright (C) 2002 Xodnizel
*
* 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
*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "sdl.h"
#ifdef USE_SEXYAL
#include "../sexyal/sexyal.h"
static SexyAL *Interface;
static SexyAL_device *Output;
static SexyAL_format format;
static SexyAL_buffering buffering;
uint32 GetMaxSound(void)
{
return(buffering.totalsize);
}
uint32 GetWriteSound(void)
{
return(Output->CanWrite(Output));
}
void WriteSound(int32 *Buffer, int Count)
{
//printf("%d\n",Output->CanWrite(Output));
Output->Write(Output, Buffer, Count);
}
int InitSound(FCEUGI *gi)
{
if(!_sound) return(0);
memset(&format,0,sizeof(format));
memset(&buffering,0,sizeof(buffering));
FCEUI_SetSoundVolume(soundvol);
FCEUI_SetSoundQuality(soundq);
Interface=SexyAL_Init(0);
format.sampformat=SEXYAL_FMT_PCMS32S16;
format.channels=gi->soundchan?gi->soundchan:1;
format.rate=gi->soundrate?gi->soundrate:soundrate;
buffering.fragcount=buffering.fragsize=0;
buffering.ms=soundbufsize;
FCEUI_printf("\nInitializing sound...");
if(!(Output=Interface->Open(Interface,SEXYAL_ID_UNUSED,&format,&buffering)))
{
FCEUD_PrintError("Error opening a sound device.");
Interface->Destroy(Interface);
Interface=0;
return(0);
}
if(soundq && format.rate!=48000 && format.rate!=44100 && format.rate!=96000)
{
FCEUD_PrintError("Set sound playback rate neither 44100, 48000, nor 96000, but needs to be when in high-quality sound mode.");
KillSound();
return(0);
}
if(format.rate<8192 || format.rate > 96000)
{
FCEUD_PrintError("Set rate is out of range [8192-96000]");
KillSound();
return(0);
}
FCEUI_printf("\n Bits: %u\n Rate: %u\n Channels: %u\n Byte order: CPU %s\n Buffer size: %u sample frames(%f ms)\n",(format.sampformat>>4)*8,format.rate,format.channels,format.byteorder?"Reversed":"Native",buffering.totalsize,(double)buffering.totalsize*1000/format.rate);
format.sampformat=SEXYAL_FMT_PCMS32S16;
format.channels=gi->soundchan?gi->soundchan:1;
format.byteorder=0;
//format.rate=gi->soundrate?gi->soundrate:soundrate;
Output->SetConvert(Output,&format);
FCEUI_Sound(format.rate);
return(1);
}
void SilenceSound(int n)
{
}
int KillSound(void)
{
FCEUI_Sound(0);
if(Output)
Output->Close(Output);
if(Interface)
Interface->Destroy(Interface);
Interface=0;
if(!Output) return(0);
Output=0;
return(1);
}
#elif USE_JACKACK /* Use JACK Audio Connection Kit */
#include <jack/jack.h>
#include <jack/ringbuffer.h>
static jack_port_t *output_port = NULL;
static jack_client_t *client = NULL;
static jack_ringbuffer_t *tmpbuf = NULL;
static unsigned int BufferSize;
static int process(jack_nframes_t nframes, void *arg)
{
jack_default_audio_sample_t *out = (jack_default_audio_sample_t *) jack_port_get_buffer(output_port, nframes);
size_t canread;
canread = jack_ringbuffer_read_space(tmpbuf) / sizeof(jack_default_audio_sample_t);
if(canread > nframes)
canread = nframes;
jack_ringbuffer_read(tmpbuf, out,canread * sizeof(jack_default_audio_sample_t));
nframes -= canread;
if(nframes) /* Buffer underflow. Hmm. */
{
}
}
uint32 GetMaxSound(void)
{
return(BufferSize);
}
uint32 GetWriteSound(void)
{
return(jack_readbuffer_write_space / sizeof(jack_default_audio_sample_t));
}
static void DeadSound(void *arg)
{
puts("AGH! Sound server hates us! Let's go on a rampage.");
}
int InitSound(FCEUGI *gi)
{
const char **ports;
client = jack_client_new("FCE Ultra");
jack_set_process_callback(client, process, 0);
jack_on_shutdown(client, DeadSound, 0);
printf("%ld\n",jack_get_sample_rate(client));
output_port = jack_port_register(client, "output", JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0);
BufferSize = soundbufsize * soundrate / 1000;
tmpbuf = jack_ringbuffer_create(BufferSize * sizeof(jack_default_audio_sample_t));
jack_activate(client);
ports = jack_get_ports(client, NULL, NULL, JackPortIsPhysical | JackPortIsInput);
jack_connect(client, jack_port_name(output_port), ports[0]);
free(ports);
}
void WriteSound(int32 *buf, int Count)
{
jack_default_audio_sample_t jbuf[Count];
int x;
for(x=0;x<Count;x++,buf++)
jbuf[x] = *buf;
jack_ringbuffer_write(tmpbuf, jbuf, sizeof(jack_default_audio_sample_t) * Count);
}
void SilenceSound(int n)
{
}
int KillSound(void)
{
if(tmpbuf)
{
jack_ringbuffer_free(tmpbuf);
tmpbuf = NULL;
}
if(client)
{
jack_client_close(client);
client = NULL;
}
return(1);
}
#else /* So we'll use SDL's evil sound support. Ok. */
static volatile int *Buffer = 0;
static unsigned int BufferSize;
static unsigned int BufferRead;
static unsigned int BufferWrite;
static volatile unsigned int BufferIn;
static void fillaudio(void *udata, uint8 *stream, int len)
{
int16 *tmps = (int16*)stream;
len >>= 1;
while(len)
{
int16 sample = 0;
if(BufferIn)
{
sample = Buffer[BufferRead];
BufferRead = (BufferRead + 1) % BufferSize;
BufferIn--;
}
else sample = 0;
*tmps = sample;
tmps++;
len--;
}
}
int InitSound(FCEUGI *gi)
{
SDL_AudioSpec spec;
if(!_sound) return(0);
memset(&spec,0,sizeof(spec));
if(SDL_InitSubSystem(SDL_INIT_AUDIO)<0)
{
puts(SDL_GetError());
KillSound();
return(0);
}
spec.freq = soundrate;
spec.format = AUDIO_S16SYS;
spec.channels = 1;
spec.samples = 256;
spec.callback = fillaudio;
spec.userdata = 0;
BufferSize = soundbufsize * soundrate / 1000;
BufferSize -= spec.samples * 2; /* SDL uses at least double-buffering, so
multiply by 2. */
if(BufferSize < spec.samples) BufferSize = spec.samples;
Buffer = malloc(sizeof(int) * BufferSize);
BufferRead = BufferWrite = BufferIn = 0;
//printf("SDL Size: %d, Internal size: %d\n",spec.samples,BufferSize);
if(SDL_OpenAudio(&spec,0)<0)
{
puts(SDL_GetError());
KillSound();
return(0);
}
SDL_PauseAudio(0);
FCEUI_Sound(soundrate);
return(1);
}
uint32 GetMaxSound(void)
{
return(BufferSize);
}
uint32 GetWriteSound(void)
{
return(BufferSize - BufferIn);
}
void WriteSound(int32 *buf, int Count)
{
while(Count)
{
while(BufferIn == BufferSize) SDL_Delay(1);
Buffer[BufferWrite] = *buf;
Count--;
BufferWrite = (BufferWrite + 1) % BufferSize;
BufferIn++;
buf++;
}
}
void SilenceSound(int n)
{
SDL_PauseAudio(n);
}
int KillSound(void)
{
FCEUI_Sound(0);
SDL_CloseAudio();
SDL_QuitSubSystem(SDL_INIT_AUDIO);
if(Buffer)
{
free(Buffer);
Buffer = 0;
}
return(0);
}
#endif
static int mute=0;
static int soundvolume=100;
void FCEUD_SoundVolumeAdjust(int n)
{
switch(n)
{
case -1: soundvolume-=10; if(soundvolume<0) soundvolume=0; break;
case 0: soundvolume=100; break;
case 1: soundvolume+=10; if(soundvolume>150) soundvolume=150; break;
}
mute=0;
FCEUI_SetSoundVolume(soundvolume);
FCEU_DispMessage("Sound volume %d.", soundvolume);
}
void FCEUD_SoundToggle(void)
{
if(mute)
{
mute=0;
FCEUI_SetSoundVolume(soundvolume);
FCEU_DispMessage("Sound mute off.");
}
else
{
mute=1;
FCEUI_SetSoundVolume(0);
FCEU_DispMessage("Sound mute on.");
}
}

86
drivers/pc/sdl-throttle.c Normal file
View File

@ -0,0 +1,86 @@
#include "sdl.h"
#include "throttle.h"
static uint64 tfreq;
static uint64 desiredfps;
static int32 fps_scale_table[]=
{ 3, 3, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048, 2048 };
int32 fps_scale = 256;
#define fps_table_size (sizeof(fps_scale_table)/sizeof(fps_scale_table[0]))
void RefreshThrottleFPS(void)
{
desiredfps=FCEUI_GetDesiredFPS()>>8;
desiredfps=(desiredfps*fps_scale)>>8;
tfreq=10000000;
tfreq<<=16; /* Adjustment for fps returned from FCEUI_GetDesiredFPS(). */
}
void SpeedThrottle(void)
{
static uint64 ttime,ltime=0;
waiter:
ttime=SDL_GetTicks();
ttime*=10000;
if( (ttime-ltime) < (tfreq/desiredfps) )
{
int64 delay;
delay=(tfreq/desiredfps)-(ttime-ltime);
if(delay>0)
SDL_Delay(delay/10000);
//printf("%d\n",(tfreq/desiredfps)-(ttime-ltime));
//SDL_Delay((tfreq/desiredfps)-(ttime-ltime));
goto waiter;
}
if( (ttime-ltime) >= (tfreq*4/desiredfps))
ltime=ttime;
else
ltime+=tfreq/desiredfps;
}
void IncreaseEmulationSpeed(void)
{
int i;
for(i=1; fps_scale_table[i]<fps_scale; i++)
;
fps_scale = fps_scale_table[i+1];
RefreshThrottleFPS();
FCEU_DispMessage("emulation speed %d%%",(fps_scale*100)>>8);
}
void DecreaseEmulationSpeed(void)
{
int i;
for(i=1; fps_scale_table[i]<fps_scale; i++)
;
fps_scale = fps_scale_table[i-1];
RefreshThrottleFPS();
FCEU_DispMessage("emulation speed %d%%",(fps_scale*100)>>8);
}
void FCEUD_SetEmulationSpeed(int cmd)
{
switch(cmd)
{
case EMUSPEED_SLOWEST: fps_scale=fps_scale_table[0]; break;
case EMUSPEED_SLOWER: DecreaseEmulationSpeed(); break;
case EMUSPEED_NORMAL: fps_scale=256; break;
case EMUSPEED_FASTER: IncreaseEmulationSpeed(); break;
case EMUSPEED_FASTEST: fps_scale=fps_scale_table[fps_table_size-1]; break;
default:
return;
}
RefreshThrottleFPS();
FCEU_DispMessage("emulation speed %d%%",(fps_scale*100)>>8);
}

432
drivers/pc/sdl-video.c Normal file
View File

@ -0,0 +1,432 @@
/* FCE Ultra - NES/Famicom Emulator
*
* Copyright notice for this file:
* Copyright (C) 2002 Xodnizel
*
* 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
*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "sdl.h"
#include "sdl-opengl.h"
#include "../common/vidblit.h"
#include "sdl-icon.h"
#include "dface.h"
SDL_Surface *screen;
SDL_Surface *BlitBuf; // Used as a buffer when using hardware-accelerated blits.
SDL_Surface *IconSurface=NULL;
static int curbpp;
static int srendline,erendline;
static int tlines;
static int inited=0;
#ifdef OPENGL
extern int sdlhaveogl;
static int usingogl;
static double exs,eys;
#else
static int exs,eys;
#endif
static int eefx;
#define NWIDTH (256-((eoptions&EO_CLIPSIDES)?16:0))
#define NOFFSET (eoptions&EO_CLIPSIDES?8:0)
static int paletterefresh;
/* Return 1 if video was killed, 0 otherwise(video wasn't initialized). */
int KillVideo(void)
{
if(IconSurface)
{
SDL_FreeSurface(IconSurface);
IconSurface=0;
}
if(inited&1)
{
#ifdef OPENGL
if(usingogl)
KillOpenGL();
else
#endif
if(curbpp>8)
KillBlitToHigh();
SDL_QuitSubSystem(SDL_INIT_VIDEO);
inited&=~1;
return(1);
}
inited=0;
return(0);
}
static int sponge;
int InitVideo(FCEUGI *gi)
{
const SDL_VideoInfo *vinf;
int flags=0;
FCEUI_printf("Initializing video...");
FCEUI_GetCurrentVidSystem(&srendline,&erendline);
if(_fullscreen) sponge=Settings.specialfs;
else sponge=Settings.special;
#ifdef OPENGL
usingogl=0;
if(_opengl && sdlhaveogl && !sponge)
{
flags=SDL_OPENGL;
usingogl=1;
}
#endif
#ifdef EXTGUI
GUI_SetVideo(_fullscreen, 0, 0);
#endif
if(!(SDL_WasInit(SDL_INIT_VIDEO)&SDL_INIT_VIDEO))
if(SDL_InitSubSystem(SDL_INIT_VIDEO)==-1)
{
FCEUD_PrintError(SDL_GetError());
return(0);
}
inited|=1;
SDL_ShowCursor(0);
tlines=erendline-srendline+1;
vinf=SDL_GetVideoInfo();
if(vinf->hw_available)
flags|=SDL_HWSURFACE;
if(_fullscreen)
flags|=SDL_FULLSCREEN;
flags|=SDL_HWPALETTE;
//flags|=SDL_DOUBLEBUF;
#ifdef OPENGL
if(usingogl)
{
FCEU_printf("\n Initializing with OpenGL(Use \"-opengl 0\" to disable).\n");
if(_doublebuf)
SDL_GL_SetAttribute( SDL_GL_DOUBLEBUFFER, 1 );
}
else
#endif
if(_doublebuf && (flags&SDL_HWSURFACE))
flags|=SDL_DOUBLEBUF;
if(_fullscreen)
{
int desbpp=_bpp;
exs=_xscalefs;
eys=_yscalefs;
eefx=_efxfs;
#ifdef OPENGL
if(!usingogl) {exs=(int)exs;eys=(int)eys;}
else desbpp=0;
if(sponge)
{
exs=eys=2;
if(sponge == 3 || sponge == 4) exs = eys = 3;
eefx=0;
if(sponge == 1 || sponge == 3) desbpp = 32;
}
if( (usingogl && !_stretchx) || !usingogl)
#endif
if(_xres<NWIDTH*exs || exs <= 0.01)
{
FCEUD_PrintError("xscale out of bounds.");
KillVideo();
return(0);
}
#ifdef OPENGL
if( (usingogl && !_stretchy) || !usingogl)
#endif
if(_yres<tlines*eys || eys <= 0.01)
{
FCEUD_PrintError("yscale out of bounds.");
KillVideo();
return(0);
}
#ifdef EXTGUI
GUI_SetVideo(_fullscreen, _xres, _yres);
#endif
#ifdef OPENGL
if(!(screen = SDL_SetVideoMode(_xres, _yres, desbpp, flags)))
#else
if(!(screen = SDL_SetVideoMode(_xres, _yres, desbpp, flags)))
#endif
{
FCEUD_PrintError(SDL_GetError());
return(0);
}
}
else
{
int desbpp=0;
exs=_xscale;
eys=_yscale;
eefx=_efx;
if(sponge)
{
exs=eys=2;
if(sponge >= 3) exs=eys=3;
eefx=0;
// SDL's 32bpp->16bpp code is slighty faster than mine, at least :/
if(sponge == 1 || sponge == 3) desbpp=32;
}
#ifdef OPENGL
if(!usingogl) {exs=(int)exs;eys=(int)eys;}
if(exs <= 0.01)
{
FCEUD_PrintError("xscale out of bounds.");
KillVideo();
return(0);
}
if(eys <= 0.01)
{
FCEUD_PrintError("yscale out of bounds.");
KillVideo();
return(0);
}
#endif
#ifdef EXTGUI
GUI_SetVideo(_fullscreen, (NWIDTH*exs), tlines*eys);
#endif
screen = SDL_SetVideoMode((NWIDTH*exs), tlines*eys, desbpp, flags);
}
curbpp=screen->format->BitsPerPixel;
if(!screen)
{
FCEUD_PrintError(SDL_GetError());
KillVideo();
return(0);
}
//BlitBuf=SDL_CreateRGBSurface(SDL_HWSURFACE,256,240,screen->format->BitsPerPixel,screen->format->Rmask,screen->format->Gmask,screen->format->Bmask,0);
inited=1;
FCEU_printf(" Video Mode: %d x %d x %d bpp %s\n",screen->w,screen->h,screen->format->BitsPerPixel,_fullscreen?"full screen":"");
if(curbpp!=16 && curbpp!=24 && curbpp!=8 && curbpp!=32)
{
FCEU_printf(" Sorry, %dbpp modes are not supported by FCE Ultra. Supported bit depths are 8bpp, 16bpp, and 32bpp.\n",curbpp);
KillVideo();
return(0);
}
if(gi->name)
SDL_WM_SetCaption(gi->name,gi->name);
else
SDL_WM_SetCaption("FCE Ultra","FCE Ultra");
#ifdef LSB_FIRST
IconSurface=SDL_CreateRGBSurfaceFrom((void *)fceu_playicon.pixel_data,32,32,24,32*3,0xFF,0xFF00,0xFF0000,0x00);
#else
IconSurface=SDL_CreateRGBSurfaceFrom((void *)fceu_playicon.pixel_data,32,32,24,32*3,0xFF0000,0xFF00,0xFF,0x00);
#endif
SDL_WM_SetIcon(IconSurface,0);
paletterefresh=1;
if(curbpp>8)
#ifdef OPENGL
if(!usingogl)
#endif
InitBlitToHigh(curbpp>>3,screen->format->Rmask,screen->format->Gmask,screen->format->Bmask,eefx,sponge);
#ifdef OPENGL
if(usingogl)
if(!InitOpenGL((eoptions&EO_CLIPSIDES)?8:0,256-((eoptions&EO_CLIPSIDES)?8:0),srendline,erendline+1,exs,eys,eefx,_openglip,_stretchx,_stretchy,screen))
{
FCEUD_PrintError("Error initializing OpenGL.");
KillVideo();
return(0);
}
#endif
return 1;
}
void ToggleFS(void)
{
extern FCEUGI *CurGame;
KillVideo();
_fullscreen=!_fullscreen;
if(!InitVideo(CurGame))
{
_fullscreen=!_fullscreen;
InitVideo(CurGame);
}
}
static SDL_Color psdl[256];
void FCEUD_SetPalette(uint8 index, uint8 r, uint8 g, uint8 b)
{
psdl[index].r=r;
psdl[index].g=g;
psdl[index].b=b;
paletterefresh=1;
}
void FCEUD_GetPalette(uint8 index, uint8 *r, uint8 *g, uint8 *b)
{
*r=psdl[index].r;
*g=psdl[index].g;
*b=psdl[index].b;
}
static void RedoPalette(void)
{
#ifdef OPENGL
if(usingogl)
SetOpenGLPalette((uint8*)psdl);
else
#endif
{
if(curbpp>8)
SetPaletteBlitToHigh((uint8*)psdl);
else
{
SDL_SetPalette(screen,SDL_PHYSPAL,psdl,0,256);
}
}
}
void LockConsole(){}
void UnlockConsole(){}
void BlitScreen(uint8 *XBuf)
{
SDL_Surface *TmpScreen;
uint8 *dest;
int xo=0,yo=0;
if(!screen) return;
if(paletterefresh)
{
RedoPalette();
paletterefresh=0;
}
#ifdef OPENGL
if(usingogl)
{
BlitOpenGL(XBuf);
return;
}
#endif
XBuf+=srendline*256;
if(BlitBuf) TmpScreen=BlitBuf;
else TmpScreen=screen;
if(SDL_MUSTLOCK(TmpScreen))
if(SDL_LockSurface(TmpScreen))
{
return;
}
dest=(uint8*)TmpScreen->pixels;
if(_fullscreen)
{
xo=(((TmpScreen->w-NWIDTH*exs))/2);
dest+=xo*(curbpp>>3);
if(TmpScreen->h>(tlines*eys))
{
yo=((TmpScreen->h-tlines*eys)/2);
dest+=yo*TmpScreen->pitch;
}
}
if(curbpp>8)
{
if(BlitBuf)
Blit8ToHigh(XBuf+NOFFSET,dest, NWIDTH, tlines, TmpScreen->pitch,1,1);
else
Blit8ToHigh(XBuf+NOFFSET,dest, NWIDTH, tlines, TmpScreen->pitch,exs,eys);
}
else
{
if(BlitBuf)
Blit8To8(XBuf+NOFFSET,dest, NWIDTH, tlines, TmpScreen->pitch,1,1,0,sponge);
else
Blit8To8(XBuf+NOFFSET,dest, NWIDTH, tlines, TmpScreen->pitch,exs,eys,eefx,sponge);
}
if(SDL_MUSTLOCK(TmpScreen))
SDL_UnlockSurface(TmpScreen);
if(BlitBuf)
{
SDL_Rect srect;
SDL_Rect drect;
srect.x=0;
srect.y=0;
srect.w=NWIDTH;
srect.h=tlines;
drect.x=0;
drect.y=0;
drect.w=exs*NWIDTH;
drect.h=eys*tlines;
SDL_BlitSurface(BlitBuf, &srect,screen,&drect);
}
SDL_UpdateRect(screen, xo, yo, NWIDTH*exs, tlines*eys);
if(screen->flags&SDL_DOUBLEBUF)
SDL_Flip(screen);
}
uint32 PtoV(uint16 x, uint16 y)
{
y=(double)y/eys;
x=(double)x/exs;
if(eoptions&EO_CLIPSIDES)
x+=8;
y+=srendline;
return(x|(y<<16));
}

1
drivers/pc/sdl-video.h Normal file
View File

@ -0,0 +1 @@
uint32 PtoV(uint16 x, uint16 y);

429
drivers/pc/sdl.c Normal file
View File

@ -0,0 +1,429 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "sdl.h"
#include "sdl-video.h"
#ifdef NETWORK
#include "unix-netplay.h"
#endif
DSETTINGS Settings;
CFGSTRUCT DriverConfig[]={
#ifdef OPENGL
AC(_stretchx),
AC(_stretchy),
AC(_opengl),
AC(_openglip),
#endif
AC(Settings.special),
AC(Settings.specialfs),
AC(_doublebuf),
AC(_xscale),
AC(_yscale),
AC(_xscalefs),
AC(_yscalefs),
AC(_bpp),
AC(_efx),
AC(_efxfs),
AC(_fullscreen),
AC(_xres),
AC(_yres),
#ifdef NETWORK
ACS(netplaynick),
AC(netlocalplayers),
AC(tport),
ACS(netpassword),
ACS(netgamekey),
#endif
ENDCFGSTRUCT
};
//-fshack x Set the environment variable SDL_VIDEODRIVER to \"x\" when
// entering full screen mode and x is not \"0\".
char *DriverUsage=
"-xres x Set horizontal resolution to x for full screen mode.\n\
-yres x Set vertical resolution to x for full screen mode.\n\
-xscale(fs) x Multiply width by x(Real numbers >0 with OpenGL, otherwise integers >0).\n\
-yscale(fs) x Multiply height by x(Real numbers >0 with OpenGL, otherwise integers >0).\n\
-bpp(fs) x Bits per pixel for SDL surface(and video mode in fs). 8, 16, 32.\n\
-opengl x Enable OpenGL support if x is 1.\n\
-openglip x Enable OpenGL linear interpolation if x is 1.\n\
-doublebuf x \n\
-special(fs) x Specify special scaling filter.\n\
-stretch(x/y) x Stretch to fill surface on x or y axis(fullscreen, only with OpenGL).\n\
-efx(fs) x Enable special effects. Logically OR the following together:\n\
1 = scanlines(for yscale>=2).\n\
2 = TV blur(for bpp of 16 or 32).\n\
-fs x Select full screen mode if x is non zero.\n\
-connect s Connect to server 's' for TCP/IP network play.\n\
-netnick s Set the nickname to use in network play.\n\
-netgamekey s Use key 's' to create a unique session for the game loaded.\n\
-netpassword s Password to use for connecting to the server.\n\
-netlocalplayers x Set the number of local players.\n\
-netport x Use TCP/IP port x for network play.";
ARGPSTRUCT DriverArgs[]={
#ifdef OPENGL
{"-opengl",0,&_opengl,0},
{"-openglip",0,&_openglip,0},
{"-stretchx",0,&_stretchx,0},
{"-stretchy",0,&_stretchy,0},
#endif
{"-special",0,&Settings.special,0},
{"-specialfs",0,&Settings.specialfs,0},
{"-doublebuf",0,&_doublebuf,0},
{"-bpp",0,&_bpp,0},
{"-xscale",0,&_xscale,2},
{"-yscale",0,&_yscale,2},
{"-efx",0,&_efx,0},
{"-xscalefs",0,&_xscalefs,2},
{"-yscalefs",0,&_yscalefs,2},
{"-efxfs",0,&_efxfs,0},
{"-xres",0,&_xres,0},
{"-yres",0,&_yres,0},
{"-fs",0,&_fullscreen,0},
//{"-fshack",0,&_fshack,0x4001},
#ifdef NETWORK
{"-connect",0,&netplayhost,0x4001},
{"-netport",0,&tport,0},
{"-netlocalplayers",0,&netlocalplayers,0},
{"-netnick",0,&netplaynick,0x4001},
{"-netpassword",0,&netpassword,0x4001},
#endif
{0,0,0,0}
};
static void SetDefaults(void)
{
Settings.special=Settings.specialfs=0;
_bpp=8;
_xres=640;
_yres=480;
_fullscreen=0;
_xscale=2.50;
_yscale=2;
_xscalefs=_yscalefs=2;
_efx=_efxfs=0;
//_fshack=_fshacksave=0;
#ifdef OPENGL
_opengl=1;
_stretchx=1;
_stretchy=0;
_openglip=1;
#endif
}
void DoDriverArgs(void)
{
#ifdef BROKEN
if(_fshack)
{
if(_fshack[0]=='0')
if(_fshack[1]==0)
{
free(_fshack);
_fshack=0;
}
}
#endif
}
int InitMouse(void)
{
return(0);
}
void KillMouse(void){}
void GetMouseData(uint32 *d)
{
if(FCEUI_IsMovieActive()<0)
return;
int x,y;
uint32 t;
t=SDL_GetMouseState(&x,&y);
#ifdef EXTGUI
GUI_GetMouseState(&t,&x,&y);
#endif
d[2]=0;
if(t&SDL_BUTTON(1))
d[2]|=1;
if(t&SDL_BUTTON(3))
d[2]|=2;
t=PtoV(x,y);
d[0]=t&0xFFFF;
d[1]=(t>>16)&0xFFFF;
}
int InitKeyboard(void)
{
return(1);
}
int UpdateKeyboard(void)
{
return(1);
}
void KillKeyboard(void)
{
}
void UpdatePhysicalInput(void)
{
SDL_Event event;
while(SDL_PollEvent(&event))
{
switch(event.type)
{
//case SDL_SYSWMEVENT: puts("Nifty keen");break;
//case SDL_VIDEORESIZE: puts("Okie dokie");break;
case SDL_QUIT: CloseGame();puts("Quit");break;
}
//printf("Event: %d\n",event.type);
//fflush(stdout);
}
//SDL_PumpEvents();
}
static uint8 *KeyState=NULL;
char *GetKeyboard(void)
{
KeyState=SDL_GetKeyState(0);
#ifdef EXTGUI
{ char *tmp=GUI_GetKeyboard(); if(tmp) KeyState=tmp; }
#endif
return((char *)KeyState);
}
#ifdef WIN32
#include <windows.h>
/* Stupid SDL */
#ifdef main
#undef main
#endif
#endif
#ifndef EXTGUI
uint8 *GetBaseDirectory(void)
{
uint8 *ol;
uint8 *ret;
ol=getenv("HOME");
if(ol)
{
ret=malloc(strlen(ol)+1+strlen("./fceultra"));
strcpy(ret,ol);
strcat(ret,"/.fceultra");
}
else
{
#ifdef WIN32
char *sa;
ret=malloc(MAX_PATH+1);
GetModuleFileName(NULL,ret,MAX_PATH+1);
sa=strrchr(ret,'\\');
if(sa)
*sa = 0;
#else
ret=malloc(1);
ret[0]=0;
#endif
printf("%s\n",ret);
}
return(ret);
}
#endif
#ifdef OPENGL
int sdlhaveogl;
#endif
int DTestButton(ButtConfig *bc)
{
int x;
for(x=0;x<bc->NumC;x++)
{
if(bc->ButtType[x]==BUTTC_KEYBOARD)
{
if(KeyState[bc->ButtonNum[x]])
return(1);
}
else if(bc->ButtType[x]==BUTTC_JOYSTICK)
{
if(DTestButtonJoy(bc))
return(1);
}
}
return(0);
}
static int bcpv,bcpj;
int ButtonConfigBegin(void)
{
SDL_Surface *screen;
SDL_QuitSubSystem(SDL_INIT_VIDEO);
bcpv=KillVideo();
bcpj=KillJoysticks();
if(!(SDL_WasInit(SDL_INIT_VIDEO)&SDL_INIT_VIDEO))
if(SDL_InitSubSystem(SDL_INIT_VIDEO)==-1)
{
FCEUD_Message(SDL_GetError());
return(0);
}
screen = SDL_SetVideoMode(300, 1, 8, 0);
SDL_WM_SetCaption("Button Config",0);
InitJoysticks();
return(1);
}
void ButtonConfigEnd(void)
{
extern FCEUGI *CurGame;
KillJoysticks();
SDL_QuitSubSystem(SDL_INIT_VIDEO);
if(bcpv) InitVideo(CurGame);
if(bcpj) InitJoysticks();
}
int DWaitButton(const uint8 *text, ButtConfig *bc, int wb)
{
SDL_Event event;
static int32 LastAx[64][64];
int x,y;
SDL_WM_SetCaption(text,0);
#ifndef EXTGUI
puts(text);
#endif
for(x=0;x<64;x++)
for(y=0;y<64;y++)
LastAx[x][y]=0x100000;
while(SDL_WaitEvent(&event))
{
switch(event.type)
{
case SDL_KEYDOWN:bc->ButtType[wb]=BUTTC_KEYBOARD;
bc->DeviceNum[wb]=0;
bc->ButtonNum[wb]=event.key.keysym.sym;
return(1);
case SDL_JOYBUTTONDOWN:bc->ButtType[wb]=BUTTC_JOYSTICK;
bc->DeviceNum[wb]=event.jbutton.which;
bc->ButtonNum[wb]=event.jbutton.button;
return(1);
case SDL_JOYHATMOTION:if(event.jhat.value != SDL_HAT_CENTERED)
{
bc->ButtType[wb]=BUTTC_JOYSTICK;
bc->DeviceNum[wb]=event.jhat.which;
bc->ButtonNum[wb]=0x2000|((event.jhat.hat&0x1F)<<8)|event.jhat.value;
return(1);
}
break;
case SDL_JOYAXISMOTION:
if(LastAx[event.jaxis.which][event.jaxis.axis]==0x100000)
{
if(abs(event.jaxis.value)<1000)
LastAx[event.jaxis.which][event.jaxis.axis]=event.jaxis.value;
}
else
{
if(abs(LastAx[event.jaxis.which][event.jaxis.axis]-event.jaxis.value)>=8192)
{
bc->ButtType[wb]=BUTTC_JOYSTICK;
bc->DeviceNum[wb]=event.jaxis.which;
bc->ButtonNum[wb]=0x8000|(event.jaxis.axis)|((event.jaxis.value<0)?0x4000:0);
return(1);
}
}
break;
}
}
return(0);
}
#ifdef EXTGUI
int FCEUSDLmain(int argc, char *argv[])
#else
int main(int argc, char *argv[])
#endif
{
FCEUD_Message("\nStarting FCE Ultra "FCEU_VERSION"...\n");
#ifdef WIN32
/* Taken from win32 sdl_main.c */
SDL_SetModuleHandle(GetModuleHandle(NULL));
#endif
if(SDL_Init(SDL_INIT_VIDEO)) /* SDL_INIT_VIDEO Needed for (joystick config) event processing? */
{
printf("Could not initialize SDL: %s.\n", SDL_GetError());
return(-1);
}
#ifdef OPENGL
#ifdef APPLEOPENGL
sdlhaveogl = 1; /* Stupid something... Hack. */
#else
if(!SDL_GL_LoadLibrary(0)) sdlhaveogl=1;
else sdlhaveogl=0;
#endif
#endif
SetDefaults();
{
int ret=CLImain(argc,argv);
SDL_Quit();
return(ret?0:-1);
}
}
uint64 FCEUD_GetTime(void)
{
return(SDL_GetTicks());
}
uint64 FCEUD_GetTimeFreq(void)
{
return(1000);
}
// dummy functions
#define DUMMY(f) void f(void) {FCEU_DispMessage("Not implemented.");}
DUMMY(FCEUD_HideMenuToggle)
DUMMY(FCEUD_TurboOn)
DUMMY(FCEUD_TurboOff)
DUMMY(FCEUD_SaveStateAs)
DUMMY(FCEUD_LoadStateFrom)
DUMMY(FCEUD_MovieRecordTo)
DUMMY(FCEUD_MovieReplayFrom)
DUMMY(FCEUD_ToggleStatusIcon)
DUMMY(FCEUD_AviRecordTo)
DUMMY(FCEUD_AviStop)
void FCEUI_AviVideoUpdate(const unsigned char* buffer) {FCEU_DispMessage("Not implemented.");}
int FCEUD_ShowStatusIcon(void) {FCEU_DispMessage("Not implemented."); return 0; }
int FCEUI_AviIsRecording(void) {return 0;}

50
drivers/pc/sdl.h Normal file
View File

@ -0,0 +1,50 @@
#include <SDL.h>
#include "main.h"
#include "dface.h"
#include "input.h"
int DTestButtonJoy(ButtConfig *bc);
typedef struct {
int xres;
int yres;
double xscale,yscale;
double xscalefs,yscalefs;
int efx,efxfs;
int bpp;
int fullscreen;
int doublebuf;
char *fshack;
char *fshacksave;
#ifdef OPENGL
int opengl;
int openglip;
int stretchx,stretchy;
#endif
int special,specialfs;
} DSETTINGS;
extern DSETTINGS Settings;
#define _doublebuf Settings.doublebuf
#define _bpp Settings.bpp
#define _xres Settings.xres
#define _yres Settings.yres
#define _fullscreen Settings.fullscreen
#define _xscale Settings.xscale
#define _yscale Settings.yscale
#define _xscalefs Settings.xscalefs
#define _yscalefs Settings.yscalefs
#define _efx Settings.efx
#define _efxfs Settings.efxfs
#define _ebufsize Settings.ebufsize
#define _fshack Settings.fshack
#define _fshacksave Settings.fshacksave
#ifdef OPENGL
#define _opengl Settings.opengl
#define _openglip Settings.openglip
#define _stretchx Settings.stretchx
#define _stretchy Settings.stretchy
#endif

41
drivers/pc/throttle.c Normal file
View File

@ -0,0 +1,41 @@
#include <sys/time.h>
#include "main.h"
#include "throttle.h"
static uint64 tfreq;
static uint64 desiredfps;
void RefreshThrottleFPS(void)
{
desiredfps=FCEUI_GetDesiredFPS()>>8;
tfreq=1000000;
tfreq<<=16; /* Adjustment for fps returned from FCEUI_GetDesiredFPS(). */
}
static uint64 GetCurTime(void)
{
uint64 ret;
struct timeval tv;
gettimeofday(&tv,0);
ret=(uint64)tv.tv_sec*1000000;
ret+=tv.tv_usec;
return(ret);
}
void SpeedThrottle(void)
{
static uint64 ttime,ltime=0;
waiter:
ttime=GetCurTime();
if( (ttime-ltime) < (tfreq/desiredfps) )
goto waiter;
if( (ttime-ltime) >= (tfreq*4/desiredfps))
ltime=ttime;
else
ltime+=tfreq/desiredfps;
}

2
drivers/pc/throttle.h Normal file
View File

@ -0,0 +1,2 @@
void RefreshThrottleFPS(void);
void SpeedThrottle(void);

292
drivers/pc/unix-netplay.c Normal file
View File

@ -0,0 +1,292 @@
#ifdef NETWORK
/* FCE Ultra - NES/Famicom Emulator
*
* Copyright notice for this file:
* Copyright (C) 2002 Xodnizel
*
* 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
*/
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <sys/time.h>
#include <stdlib.h>
#include <netinet/in.h>
#include <netinet/tcp.h>
#include <arpa/inet.h>
#include <stdio.h>
#include <unistd.h>
#include <netdb.h>
#include <errno.h>
#include <fcntl.h>
#include "main.h"
#include "dface.h"
#include "unix-netplay.h"
#include "../../md5.h"
#ifndef socklen_t
#define socklen_t int
#endif
#ifndef SOL_TCP
#define SOL_TCP IPPROTO_TCP
#endif
char *netplayhost=0;
char *netplaynick=0;
char *netgamekey = 0;
char *netpassword = 0;
int netlocalplayers = 1;
int Port=0xFCE;
int FCEUDnetplay=0;
int tport=0xFCE;
static int Socket=-1;
static void en32(uint8 *buf, uint32 morp)
{
buf[0]=morp;
buf[1]=morp>>8;
buf[2]=morp>>16;
buf[3]=morp>>24;
}
/*
static uint32 de32(uint8 *morp)
{
return(morp[0]|(morp[1]<<8)|(morp[2]<<16)|(morp[3]<<24));
}
*/
int FCEUD_NetworkConnect(void)
{
struct sockaddr_in sockin; /* I want to play with fighting robots. */
struct hostent *phostentb;
unsigned long hadr;
int TSocket;
int netdivisor;
if(!netplayhost) return(0);
if( (TSocket=socket(AF_INET,SOCK_STREAM,0))==-1)
{
puts("Error creating stream socket.");
FCEUD_NetworkClose();
return(0);
}
{
int tcpopt = 1;
#ifdef BEOS
if(setsockopt(TSocket, SOL_SOCKET, TCP_NODELAY, &tcpopt, sizeof(int)))
#else
if(setsockopt(TSocket, SOL_TCP, TCP_NODELAY, &tcpopt, sizeof(int)))
#endif
puts("Nodelay fail");
}
memset(&sockin,0,sizeof(sockin));
sockin.sin_family=AF_INET;
hadr=inet_addr(netplayhost);
if(hadr!=INADDR_NONE)
sockin.sin_addr.s_addr=hadr;
else
{
puts("*** Looking up host name...");
if(!(phostentb=gethostbyname((const char *)netplayhost)))
{
puts("Error getting host network information.");
close(TSocket);
FCEUD_NetworkClose();
return(0);
}
memcpy(&sockin.sin_addr,phostentb->h_addr,phostentb->h_length);
}
sockin.sin_port=htons(tport);
puts("*** Connecting to remote host...");
if(connect(TSocket,(struct sockaddr *)&sockin,sizeof(sockin))==-1)
{
puts("Error connecting to remote host.");
close(TSocket);
FCEUD_NetworkClose();
return(0);
}
Socket=TSocket;
puts("*** Sending initialization data to server...");
{
uint8 *sendbuf;
uint8 buf[5];
uint32 sblen;
sblen = 4 + 16 + 16 + 64 + 1 + (netplaynick?strlen(netplaynick):0);
sendbuf = malloc(sblen);
memset(sendbuf, 0, sblen);
en32(sendbuf, sblen - 4);
if(netgamekey)
{
struct md5_context md5;
uint8 md5out[16];
md5_starts(&md5);
md5_update(&md5, CurGame->MD5, 16);
md5_update(&md5, netgamekey, strlen(netgamekey));
md5_finish(&md5, md5out);
memcpy(sendbuf + 4, md5out, 16);
}
else
memcpy(sendbuf + 4, CurGame->MD5, 16);
if(netpassword)
{
struct md5_context md5;
uint8 md5out[16];
md5_starts(&md5);
md5_update(&md5, netpassword, strlen(netpassword));
md5_finish(&md5, md5out);
memcpy(sendbuf + 4 + 16, md5out, 16);
}
memset(sendbuf + 4 + 16 + 16, 0, 64);
sendbuf[4 + 16 + 16 + 64] = netlocalplayers;
if(netplaynick)
memcpy(sendbuf + 4 + 16 + 16 + 64 + 1,netplaynick,strlen(netplaynick));
send(Socket, sendbuf, sblen, 0);
free(sendbuf);
recv(Socket, buf, 1, MSG_WAITALL);
netdivisor = buf[0];
}
puts("*** Connection established.");
FCEUDnetplay = 1;
FCEUI_NetplayStart(netlocalplayers, netdivisor);
return(1);
}
int FCEUD_SendData(void *data, uint32 len)
{
int check;
if(!ioctl(fileno(stdin),FIONREAD,&check))
if(check)
{
char buf[1024];
char *f;
fgets(buf,1024,stdin);
if((f=strrchr(buf,'\n')))
*f=0;
FCEUI_NetplayText(buf);
}
send(Socket, data, len ,0);
return(1);
}
int FCEUD_RecvData(void *data, uint32 len)
{
NoWaiting&=~2;
for(;;)
{
fd_set funfun;
struct timeval popeye;
popeye.tv_sec=0;
popeye.tv_usec=100000;
FD_ZERO(&funfun);
FD_SET(Socket,&funfun);
switch(select(Socket + 1,&funfun,0,0,&popeye))
{
case 0: continue;
case -1:return(0);
}
if(FD_ISSET(Socket,&funfun))
{
if(recv(Socket,data,len,MSG_WAITALL) == len)
{
//unsigned long beefie;
FD_ZERO(&funfun);
FD_SET(Socket, &funfun);
popeye.tv_sec = popeye.tv_usec = 0;
if(select(Socket + 1, &funfun, 0, 0, &popeye) == 1)
//if(!ioctl(Socket,FIONREAD,&beefie))
// if(beefie)
{
NoWaiting|=2;
//puts("Yaya");
}
return(1);
}
else
return(0);
}
}
return 0;
}
void FCEUD_NetworkClose(void)
{
if(Socket>0)
{
#ifdef BEOS
closesocket(Socket);
#else
close(Socket);
#endif
}
Socket=-1;
if(FCEUDnetplay)
FCEUI_NetplayStop();
FCEUDnetplay = 0;
}
void FCEUD_NetplayText(uint8 *text)
{
char *tot = malloc(strlen(text) + 1);
char *tmp;
strcpy(tot, text);
tmp = tot;
while(*tmp)
{
if(*tmp < 0x20) *tmp = ' ';
tmp++;
}
puts(tot);
free(tot);
}
#endif

View File

@ -0,0 +1,9 @@
#ifdef NETWORK
extern char *netplaynick;
extern char *netplayhost;
extern char *netpassword;
extern char *netgamekey;
extern int tport;
extern int netlocalplayers;
#endif

60
drivers/pc/usage.h Normal file
View File

@ -0,0 +1,60 @@
/* FCE Ultra - NES/Famicom Emulator
*
* Copyright notice for this file:
* Copyright (C) 2002 Xodnizel
*
* 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
*/
void ShowUsage(char *prog)
{
printf("\nUsage is as follows:\n%s <options> filename\n\n",prog);
puts("Options:");
puts(DriverUsage);
puts("-cpalette x Load a custom global palette from file x.\n\
-ntsccol x Emulate an NTSC's TV's colors.\n\
0 = Disabled.\n\
1 = Enabled.\n\
-pal x Emulate a PAL NES if x is 1.\n\
-sound x Sound.\n\
0 = Disabled.\n\
Otherwise, x = playback rate.\n\
-soundvol x Sound volume. x is an integral percentage value.\n\
-soundq x Sets sound quality.\n\
0 = Low quality.\n\
1 = High quality.\n\
-inputx str Select device mapped to virtual input port x(1-2).\n\
str may be: none, gamepad, zapper, powerpada, powerpadb,\n\
arkanoid\n\
-fcexp str Select Famicom expansion port device.\n\
str may be: none, shadow, arkanoid, 4player, fkb\n\
-inputcfg s Configure virtual input device \"s\".\n\
-nofs x Disables Four-Score emulation if x is 1.\n\
-gg x Enable Game Genie emulation if x is 1.\n\
-no8lim x Disables the 8 sprites per scanline limitation.\n\
0 = Limitation enabled.\n\
1 = Limitation disabled.\n\
-snapname x Selects what type of file name snapshots will have.\n\
0 = Numeric(0.png)\n\
1 = File base and numeric(mario-0.png)\n\
-nothrottle x Disable artificial speed throttling if x is non-zero.\n\
-clipsides x Clip leftmost and rightmost 8 columns of pixels of video output.\n\
0 = No clipping.\n\
1 = Clipping.\n\
-slstart x Set the first drawn emulated scanline. Valid values for x are\n\
0 through 239.\n\
-slend x Set the last drawn emulated scanline. Valid values for x are\n\
0 through 239.");
}

168
drivers/pc/vgatweak.c Normal file
View File

@ -0,0 +1,168 @@
/* This file is "#include"d from dos-video.c and svga-video.c */
typedef struct {
uint8 p;
uint8 i;
uint8 v;
} vgareg;
vgareg v256x224_103[25] =
{
{ 0xc2, 0x0, 0xe7},
{ 0xd4, 0x0, 0x45},
{ 0xd4, 0x1, 0x3f},
{ 0xd4, 0x2, 0x40},
{ 0xd4, 0x3, 0x86},
{ 0xd4, 0x4, 0x3f},
{ 0xd4, 0x5, 0x10},
{ 0xd4, 0x6, 0xcd},
{ 0xd4, 0x7, 0x1f},
{ 0xd4, 0x8, 0x0},
{ 0xd4, 0x9, 0x41},
{ 0xd4, 0x10, 0xc0},
{ 0xd4, 0x11, 0xac},
{ 0xd4, 0x12, 0xbf},
{ 0xd4, 0x13, 0x20},
{ 0xd4, 0x14, 0x40}, //
{ 0xd4, 0x15, 0xe7},
{ 0xd4, 0x16, 0x06}, //
{ 0xd4, 0x17, 0xa3},
{ 0xc4, 0x1, 0x1},
{ 0xc4, 0x4, 0xe}, //
{ 0xce, 0x5, 0x40},
{ 0xce, 0x6, 0x5},
{ 0xc0, 0x10, 0x41},
{ 0xc0, 0x13, 0x0},
};
vgareg v256x240[25] =
{
{ 0xc2, 0x0, 0xe3},
{ 0xd4, 0x0, 0x4f},
{ 0xd4, 0x1, 0x3f},
{ 0xd4, 0x2, 0x40},
{ 0xd4, 0x3, 0x92},
{ 0xd4, 0x4, 0x44},
{ 0xd4, 0x5, 0x10},
{ 0xd4, 0x6, 0x0a},
{ 0xd4, 0x7, 0x3e},
{ 0xd4, 0x8, 0x00},
{ 0xd4, 0x9, 0x41},
{ 0xd4, 0x10, 0xea},
{ 0xd4, 0x11, 0xac},
{ 0xd4, 0x12, 0xdf},
{ 0xd4, 0x13, 0x20},
{ 0xd4, 0x14, 0x40},
{ 0xd4, 0x15, 0xe7},
{ 0xd4, 0x16, 0x06},
{ 0xd4, 0x17, 0xa3},
{ 0xc4, 0x1, 0x1},
{ 0xc4, 0x4, 0xe},
{ 0xce, 0x5, 0x40},
{ 0xce, 0x6, 0x5},
{ 0xc0, 0x10, 0x41},
{ 0xc0, 0x13, 0x0}
};
vgareg v256x224S[25] =
{
{ 0xc2, 0x0, 0xe3},
{ 0xd4, 0x0, 0x5f},
{ 0xd4, 0x1, 0x3f},
{ 0xd4, 0x2, 0x40},
{ 0xd4, 0x3, 0x82},
{ 0xd4, 0x4, 0x4e},
{ 0xd4, 0x5, 0x96},
{ 0xd4, 0x6, 0x5},
{ 0xd4, 0x7, 0x1},
{ 0xd4, 0x8, 0x0},
{ 0xd4, 0x9, 0x40},
{ 0xd4, 0x10, 0xea},
{ 0xd4, 0x11, 0xac},
{ 0xd4, 0x12, 0xdf},
{ 0xd4, 0x13, 0x20},
{ 0xd4, 0x14, 0x40},
{ 0xd4, 0x15, 0xe7},
{ 0xd4, 0x16, 0x0},
{ 0xd4, 0x17, 0xe3},
{ 0xc4, 0x1, 0x1},
{ 0xc4, 0x4, 0xe},
{ 0xce, 0x5, 0x40},
{ 0xce, 0x6, 0x5},
{ 0xc0, 0x10, 0x41},
{ 0xc0, 0x13, 0x0}
};
vgareg v256x256[25] =
{
{ 0xc2, 0x0, 0xe7},
{ 0xd4, 0x0, 0x5f},
{ 0xd4, 0x1, 0x3f},
{ 0xd4, 0x2, 0x40},
{ 0xd4, 0x3, 0x82},
{ 0xd4, 0x4, 0x4a},
{ 0xd4, 0x5, 0x9a},
{ 0xd4, 0x6, 0x23},
{ 0xd4, 0x7, 0xb2},
{ 0xd4, 0x8, 0x0},
{ 0xd4, 0x9, 0x61},
{ 0xd4, 0x10, 0xa},
{ 0xd4, 0x11, 0xac},
{ 0xd4, 0x12, 0xff},
{ 0xd4, 0x13, 0x20},
{ 0xd4, 0x14, 0x40},
{ 0xd4, 0x15, 0x7},
{ 0xd4, 0x16, 0x1a},
{ 0xd4, 0x17, 0xa3},
{ 0xc4, 0x1, 0x1},
{ 0xc4, 0x4, 0xe},
{ 0xce, 0x5, 0x40},
{ 0xce, 0x6, 0x5},
{ 0xc0, 0x10, 0x41},
{ 0xc0, 0x13, 0x0}
};
vgareg v256x256S[25] =
{
{ 0xc2, 0x00, 0xe7},{ 0xd4, 0x00, 0x5F},{ 0xd4, 0x01, 0x3f},
{ 0xd4, 0x02, 0x40},{ 0xd4, 0x03, 0x82},{ 0xd4, 0x04, 0x4a},
{ 0xd4, 0x05, 0x9a},{ 0xd4, 0x06, 0x25},{ 0xd4, 0x07, 0x15},
{ 0xd4, 0x08, 0x00},{ 0xd4, 0x09, 0x60},{ 0xd4, 0x10, 0x0a},
{ 0xd4, 0x11, 0xac},{ 0xd4, 0x12, 0xff},{ 0xd4, 0x13, 0x20},
{ 0xd4, 0x14, 0x40},{ 0xd4, 0x15, 0x07},{ 0xd4, 0x16, 0x1a},
{ 0xd4, 0x17, 0xa3},{ 0xc4, 0x01, 0x01},{ 0xc4, 0x04, 0x0e},
{ 0xce, 0x05, 0x40},{ 0xce, 0x06, 0x05},{ 0xc0, 0x10, 0x41},
{ 0xc0, 0x13, 0x00}
};
static void VGAPortSet(vgareg R)
{
int p,i,v;
p=0x300|R.p;
i=R.i;
v=R.v;
switch(p)
{
case 0x3C0: inportb(0x3DA);
outportb(0x3C0,i);
outportb(0x3C0,v);
break;
case 0x3C2:
case 0x3C3:
default: outportb(p, v);
break;
case 0x3C4: if(i==1)
{
outportw(0x3c4,0x100);
outportw(0x3c4,(v<<8)|1);
outportw(0x3c4,0x300);
break;
}
case 0x3CE:
case 0x3D4: outportw(p,i|(v<<8));
break;
}
}