o cleanup
This commit is contained in:
358
tools/zsnes/src/linux/audio.c
Normal file
358
tools/zsnes/src/linux/audio.c
Normal file
@@ -0,0 +1,358 @@
|
||||
/*
|
||||
Copyright (C) 1997-2007 ZSNES Team ( zsKnight, _Demo_, pagefault, Nach )
|
||||
|
||||
http://www.zsnes.com
|
||||
http://sourceforge.net/projects/zsnes
|
||||
https://zsnes.bountysource.com
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License
|
||||
version 2 as published by the Free Software Foundation.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
#include "../gblhdr.h"
|
||||
#include <stdbool.h>
|
||||
|
||||
#ifdef __LIBAO__
|
||||
#include <ao/ao.h>
|
||||
#include <pthread.h>
|
||||
#include <signal.h>
|
||||
#endif
|
||||
|
||||
#include "../asm_call.h"
|
||||
#include "../cfg.h"
|
||||
|
||||
#ifdef __LIBAO__
|
||||
static pthread_t audio_thread;
|
||||
static pthread_mutex_t audio_mutex;
|
||||
static pthread_cond_t audio_wait;
|
||||
static ao_device *audio_device = 0;
|
||||
static volatile unsigned int samples_waiting = 0;
|
||||
#endif
|
||||
|
||||
unsigned char *sdl_audio_buffer = 0;
|
||||
int sdl_audio_buffer_len = 0, sdl_audio_buffer_fill = 0;
|
||||
int sdl_audio_buffer_head = 0, sdl_audio_buffer_tail = 0;
|
||||
unsigned char sound_sdl = false;
|
||||
|
||||
int SoundEnabled = 1;
|
||||
unsigned char PrevStereoSound;
|
||||
unsigned int PrevSoundQuality;
|
||||
|
||||
#define SAMPLE_NTSC_HI_SCALE 995ULL
|
||||
#define SAMPLE_NTSC_LO 59649ULL
|
||||
#define SAMPLE_PAL_HI_SCALE 1ULL
|
||||
#define SAMPLE_PAL_LO 50ULL
|
||||
static const int freqtab[7] = { 8000, 11025, 22050, 44100, 16000, 32000, 48000 };
|
||||
#define RATE freqtab[SoundQuality = ((SoundQuality > 6) ? 1 : SoundQuality)]
|
||||
|
||||
struct
|
||||
{
|
||||
unsigned long long hi;
|
||||
unsigned long long lo;
|
||||
unsigned long long balance;
|
||||
} sample_control;
|
||||
|
||||
void InitSampleControl()
|
||||
{
|
||||
extern unsigned char romispal;
|
||||
if (romispal)
|
||||
{
|
||||
sample_control.hi = SAMPLE_PAL_HI_SCALE*RATE;
|
||||
sample_control.lo = SAMPLE_PAL_LO;
|
||||
}
|
||||
else
|
||||
{
|
||||
sample_control.hi = SAMPLE_NTSC_HI_SCALE*RATE;
|
||||
sample_control.lo = SAMPLE_NTSC_LO;
|
||||
}
|
||||
sample_control.balance = sample_control.hi;
|
||||
}
|
||||
|
||||
|
||||
#ifdef __LIBAO__
|
||||
static void SoundWriteSamples_ao(unsigned int samples)
|
||||
{
|
||||
extern unsigned int BufferSizeB, BufferSizeW;
|
||||
extern int DSPBuffer[1280];
|
||||
void ProcessSoundBuffer();
|
||||
short stemp[1280];
|
||||
|
||||
int *d = DSPBuffer, *end_d = 0;
|
||||
short *p = stemp;
|
||||
|
||||
while (samples > 1280)
|
||||
{
|
||||
SoundWriteSamples_ao(1280);
|
||||
samples -= 1280;
|
||||
}
|
||||
|
||||
//printf("samples %d\n", samples);
|
||||
|
||||
BufferSizeB = samples;
|
||||
BufferSizeW = samples<<1;
|
||||
|
||||
asm_call(ProcessSoundBuffer);
|
||||
|
||||
end_d = DSPBuffer+samples;
|
||||
for (; d < end_d; d++, p++)
|
||||
{
|
||||
if ((unsigned int)(*d + 0x7FFF) < 0xFFFF) { *p = *d; continue; }
|
||||
if (*d > 0x7FFF) { *p = 0x7FFF; }
|
||||
else { *p = 0x8001; }
|
||||
}
|
||||
|
||||
ao_play(audio_device, (char *)stemp, samples*2);
|
||||
}
|
||||
|
||||
void SoundWrite_ao()
|
||||
{
|
||||
unsigned int samples = 0;
|
||||
|
||||
if (!pthread_mutex_trylock(&audio_mutex))
|
||||
{
|
||||
if (!samples_waiting && sample_control.lo)
|
||||
{
|
||||
samples = (unsigned int)((sample_control.balance/sample_control.lo) << StereoSound);
|
||||
sample_control.balance %= sample_control.lo;
|
||||
sample_control.balance += sample_control.hi;
|
||||
|
||||
samples_waiting = samples;
|
||||
pthread_cond_broadcast(&audio_wait); //Send signal
|
||||
}
|
||||
pthread_mutex_unlock(&audio_mutex);
|
||||
}
|
||||
else
|
||||
{
|
||||
pthread_cond_broadcast(&audio_wait); //Send signal
|
||||
}
|
||||
}
|
||||
|
||||
static void *SoundThread_ao(void *useless)
|
||||
{
|
||||
unsigned int samples;
|
||||
|
||||
for (;;)
|
||||
{
|
||||
pthread_mutex_lock(&audio_mutex);
|
||||
|
||||
//The while() is there to prevent error codes from breaking havoc
|
||||
while (!samples_waiting)
|
||||
{
|
||||
pthread_cond_wait(&audio_wait, &audio_mutex); //Wait for signal
|
||||
}
|
||||
|
||||
samples = samples_waiting;
|
||||
samples_waiting = 0;
|
||||
pthread_mutex_unlock(&audio_mutex);
|
||||
|
||||
SoundWriteSamples_ao(samples);
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
|
||||
static int SoundInit_ao()
|
||||
{
|
||||
int driver_id = ao_driver_id(libAoDriver);
|
||||
if (driver_id < 0) { driver_id = ao_default_driver_id(); }
|
||||
|
||||
ao_sample_format driver_format;
|
||||
driver_format.bits = 16;
|
||||
driver_format.channels = StereoSound+1;
|
||||
driver_format.rate = freqtab[SoundQuality = ((SoundQuality > 6) ? 1 : SoundQuality)];
|
||||
driver_format.byte_format = AO_FMT_LITTLE;
|
||||
|
||||
if (audio_device)
|
||||
{
|
||||
ao_close(audio_device);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (pthread_create(&audio_thread, 0, SoundThread_ao, 0))
|
||||
{
|
||||
puts("pthread_create() failed.");
|
||||
}
|
||||
else if (pthread_mutex_init(&audio_mutex, 0))
|
||||
{
|
||||
puts("pthread_mutex_init() failed.");
|
||||
}
|
||||
else if (pthread_cond_init(&audio_wait, 0))
|
||||
{
|
||||
puts("pthread_cond_init() failed.");
|
||||
}
|
||||
InitSampleControl();
|
||||
}
|
||||
|
||||
//ao_option driver_options = { "buf_size", "32768", 0 };
|
||||
|
||||
audio_device = ao_open_live(driver_id, &driver_format, 0);
|
||||
if (audio_device)
|
||||
{
|
||||
ao_info *di = ao_driver_info(driver_id);
|
||||
printf("\nAudio Opened.\nDriver: %s\nChannels: %u\nRate: %u\n\n", di->name, driver_format.channels, driver_format.rate);
|
||||
}
|
||||
else
|
||||
{
|
||||
SoundEnabled = 0;
|
||||
puts("Audio Open Failed");
|
||||
return(false);
|
||||
}
|
||||
return(true);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
void SoundWrite_sdl()
|
||||
{
|
||||
extern int DSPBuffer[];
|
||||
extern unsigned char DSPDisable;
|
||||
extern unsigned int BufferSizeB, BufferSizeW, T36HZEnabled;
|
||||
|
||||
// Process sound
|
||||
BufferSizeB = 256;
|
||||
BufferSizeW = BufferSizeB+BufferSizeB;
|
||||
|
||||
// take care of the things we left behind last time
|
||||
SDL_LockAudio();
|
||||
while (sdl_audio_buffer_fill < sdl_audio_buffer_len)
|
||||
{
|
||||
short *p = (short*)&sdl_audio_buffer[sdl_audio_buffer_tail];
|
||||
|
||||
if (soundon && !DSPDisable) { asm_call(ProcessSoundBuffer); }
|
||||
|
||||
if (T36HZEnabled)
|
||||
{
|
||||
memset(p, 0, BufferSizeW);
|
||||
}
|
||||
else
|
||||
{
|
||||
int *d = DSPBuffer, *end_d = DSPBuffer+BufferSizeB;
|
||||
|
||||
for (; d < end_d; d++, p++)
|
||||
{
|
||||
if ((unsigned int)(*d + 0x7fff) < 0xffff) { *p = *d; continue; }
|
||||
if (*d > 0x7fff) { *p = 0x7fff; }
|
||||
else { *p = 0x8001; }
|
||||
}
|
||||
}
|
||||
|
||||
sdl_audio_buffer_fill += BufferSizeW;
|
||||
sdl_audio_buffer_tail += BufferSizeW;
|
||||
if (sdl_audio_buffer_tail >= sdl_audio_buffer_len) { sdl_audio_buffer_tail = 0; }
|
||||
}
|
||||
SDL_UnlockAudio();
|
||||
}
|
||||
|
||||
static void SoundUpdate_sdl(void *userdata, unsigned char *stream, int len)
|
||||
{
|
||||
int left = sdl_audio_buffer_len - sdl_audio_buffer_head;
|
||||
|
||||
if (left > 0)
|
||||
{
|
||||
if (left <= len)
|
||||
{
|
||||
memcpy(stream, &sdl_audio_buffer[sdl_audio_buffer_head], left);
|
||||
stream += left;
|
||||
len -= left;
|
||||
sdl_audio_buffer_head = 0;
|
||||
sdl_audio_buffer_fill -= left;
|
||||
}
|
||||
|
||||
if (len)
|
||||
{
|
||||
memcpy(stream, &sdl_audio_buffer[sdl_audio_buffer_head], len);
|
||||
sdl_audio_buffer_head += len;
|
||||
sdl_audio_buffer_fill -= len;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static int SoundInit_sdl()
|
||||
{
|
||||
const int samptab[7] = { 1, 1, 2, 4, 2, 4, 4 };
|
||||
SDL_AudioSpec audiospec;
|
||||
SDL_AudioSpec wanted;
|
||||
|
||||
SDL_CloseAudio();
|
||||
|
||||
if (sdl_audio_buffer)
|
||||
{
|
||||
free(sdl_audio_buffer);
|
||||
sdl_audio_buffer = 0;
|
||||
}
|
||||
sdl_audio_buffer_len = 0;
|
||||
|
||||
wanted.freq = RATE;
|
||||
wanted.channels = StereoSound+1;
|
||||
wanted.samples = samptab[SoundQuality] * 128 * wanted.channels;
|
||||
wanted.format = AUDIO_S16LSB;
|
||||
wanted.userdata = 0;
|
||||
wanted.callback = SoundUpdate_sdl;
|
||||
|
||||
if (SDL_OpenAudio(&wanted, &audiospec) < 0)
|
||||
{
|
||||
SoundEnabled = 0;
|
||||
return(false);
|
||||
}
|
||||
SDL_PauseAudio(0);
|
||||
|
||||
sdl_audio_buffer_len = audiospec.size*2;
|
||||
sdl_audio_buffer_len = (sdl_audio_buffer_len + 255) & ~255; // Align to SPCSize
|
||||
if (!(sdl_audio_buffer = malloc(sdl_audio_buffer_len)))
|
||||
{
|
||||
SDL_CloseAudio();
|
||||
puts("Audio Open Failed");
|
||||
SoundEnabled = 0;
|
||||
return(false);
|
||||
}
|
||||
|
||||
sound_sdl = true;
|
||||
printf("\nAudio Opened.\nDriver: Simple DirectMedia Layer output\nChannels: %u\nRate: %u\n\n", wanted.channels, wanted.freq);
|
||||
return(true);
|
||||
}
|
||||
|
||||
|
||||
int InitSound()
|
||||
{
|
||||
sound_sdl = false;
|
||||
if (!SoundEnabled)
|
||||
{
|
||||
return(false);
|
||||
}
|
||||
|
||||
PrevSoundQuality = SoundQuality;
|
||||
PrevStereoSound = StereoSound;
|
||||
|
||||
#ifdef __LIBAO__
|
||||
if (strcmp(libAoDriver, "sdl") && !(!strcmp(libAoDriver, "auto") && !strcmp(ao_driver_info(ao_default_driver_id())->name, "null")))
|
||||
{
|
||||
return(SoundInit_ao());
|
||||
}
|
||||
#endif
|
||||
return(SoundInit_sdl());
|
||||
}
|
||||
|
||||
void DeinitSound()
|
||||
{
|
||||
#ifdef __LIBAO__
|
||||
if (audio_device)
|
||||
{
|
||||
pthread_kill(audio_thread, SIGTERM);
|
||||
pthread_mutex_destroy(&audio_mutex);
|
||||
pthread_cond_destroy(&audio_wait);
|
||||
ao_close(audio_device);
|
||||
}
|
||||
#endif
|
||||
SDL_CloseAudio();
|
||||
if (sdl_audio_buffer) { free(sdl_audio_buffer); }
|
||||
}
|
||||
|
||||
39
tools/zsnes/src/linux/audio.h
Normal file
39
tools/zsnes/src/linux/audio.h
Normal file
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
Copyright (C) 1997-2007 ZSNES Team ( zsKnight, _Demo_, pagefault, Nach )
|
||||
|
||||
http://www.zsnes.com
|
||||
http://sourceforge.net/projects/zsnes
|
||||
https://zsnes.bountysource.com
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License
|
||||
version 2 as published by the Free Software Foundation.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
#ifndef AUDIO_H
|
||||
#define AUDIO_H
|
||||
|
||||
void InitSampleControl();
|
||||
int InitSound();
|
||||
void DeinitSound();
|
||||
|
||||
#ifdef __LIBAO__
|
||||
void SoundWrite_ao();
|
||||
#endif
|
||||
void SoundWrite_sdl();
|
||||
|
||||
extern int SoundEnabled;
|
||||
extern unsigned char PrevStereoSound;
|
||||
extern unsigned int PrevSoundQuality;
|
||||
extern unsigned char sound_sdl;
|
||||
|
||||
#endif
|
||||
446
tools/zsnes/src/linux/battery.c
Normal file
446
tools/zsnes/src/linux/battery.c
Normal file
@@ -0,0 +1,446 @@
|
||||
/*
|
||||
Copyright (C) 1997-2007 ZSNES Team ( zsKnight, _Demo_, pagefault, Nach )
|
||||
|
||||
http://www.zsnes.com
|
||||
http://sourceforge.net/projects/zsnes
|
||||
https://zsnes.bountysource.com
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License
|
||||
version 2 as published by the Free Software Foundation.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
#include "../gblhdr.h"
|
||||
|
||||
|
||||
|
||||
|
||||
/*
|
||||
Functions for battery probing on Linux by Nach
|
||||
I believe Linux 2.4.x+ is needed for ACPI support
|
||||
but it'll compile fine for older versions too
|
||||
|
||||
Special thanks David Lee Lambert for most of the code here
|
||||
*/
|
||||
|
||||
#ifdef linux
|
||||
#include <dirent.h>
|
||||
#include <math.h>
|
||||
|
||||
int CheckBattery()
|
||||
{
|
||||
int battery = -1; //No battery / Can't get info
|
||||
const char *ac = "/proc/acpi/ac_adapter/";
|
||||
|
||||
//Check ac adapter
|
||||
DIR *ac_dir = opendir(ac);
|
||||
if (ac_dir)
|
||||
{
|
||||
char fnbuf[40]; // longer than len(ac)+len(HEXDIGIT*4)+len({state|info})
|
||||
FILE *fp;
|
||||
const char *pattern = " %39[^:]: %39[ -~]"; // for sscanf
|
||||
char line[80], key[40], arg[40];
|
||||
|
||||
struct dirent *ent;
|
||||
while ((ent = readdir(ac_dir)))
|
||||
{
|
||||
if (ent->d_name[0] == '.') { continue; }
|
||||
|
||||
snprintf(fnbuf, 40, "%s%s/state", ac, ent->d_name);
|
||||
fp = fopen(fnbuf, "r");
|
||||
if (fp)
|
||||
{
|
||||
while (fgets(line, 80, fp) && sscanf(line, pattern, key, arg) == 2)
|
||||
{
|
||||
if (!strcmp(key, "state"))
|
||||
{
|
||||
if (!strcmp(arg, "on-line"))
|
||||
{
|
||||
battery = 0;
|
||||
}
|
||||
else if (!strcmp(arg, "off-line"))
|
||||
{
|
||||
battery = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
fclose(fp);
|
||||
}
|
||||
}
|
||||
closedir(ac_dir);
|
||||
}
|
||||
return(battery);
|
||||
}
|
||||
|
||||
static int BatteryLifeTime;
|
||||
static int BatteryLifePercent;
|
||||
|
||||
static void update_battery_info()
|
||||
{
|
||||
const char *batt = "/proc/acpi/battery/";
|
||||
|
||||
//Check batteries
|
||||
DIR *batt_dir = opendir(batt);
|
||||
if (batt_dir)
|
||||
{
|
||||
char fnbuf[40]; // longer than len(ac)+len(HEXDIGIT*4)+len({state|info})
|
||||
FILE *fp;
|
||||
const char *pattern = " %39[^:]: %39[ -~]"; // for sscanf
|
||||
char line[80], key[40], arg[40];
|
||||
|
||||
float x, design_capacity = 0.0f, remaining_capacity = 0.0f, present_rate = 0.0f, full_capacity = 0.0f;
|
||||
|
||||
struct dirent *ent;
|
||||
while ((ent = readdir(batt_dir)))
|
||||
{
|
||||
if (ent->d_name[0] == '.') { continue; }
|
||||
snprintf(fnbuf, 40, "%s%s/info", batt, ent->d_name);
|
||||
fp = fopen(fnbuf, "r");
|
||||
if (fp)
|
||||
{
|
||||
while (fgets(line, 80, fp) && sscanf(line, pattern, key, arg) == 2)
|
||||
{
|
||||
if (!strcmp(key, "design capacity") && sscanf(arg, "%g", &x) == 1)
|
||||
{
|
||||
design_capacity += x;
|
||||
}
|
||||
else if (!strcmp(key, "last full capacity") && sscanf(arg, "%g", &x) == 1)
|
||||
{
|
||||
full_capacity += x;
|
||||
}
|
||||
}
|
||||
fclose(fp);
|
||||
}
|
||||
snprintf(fnbuf, 40, "%s%s/state", batt, ent->d_name);
|
||||
fp = fopen(fnbuf, "r");
|
||||
if (fp)
|
||||
{
|
||||
int charging = 0;
|
||||
while (fgets(line, 80, fp) && sscanf(line, pattern, key, arg) == 2)
|
||||
{
|
||||
if (!strcmp(key, "charging state"))
|
||||
{
|
||||
if (!strcmp(arg, "discharging"))
|
||||
{
|
||||
charging = -1;
|
||||
}
|
||||
else if (!strcmp(arg, "charging"))
|
||||
{
|
||||
charging = 1;
|
||||
}
|
||||
}
|
||||
else if (!strcmp(key, "present rate") && sscanf(arg, "%g", &x) == 1)
|
||||
{
|
||||
present_rate += charging * x;
|
||||
charging = 0;
|
||||
}
|
||||
else if (!strcmp(key, "remaining capacity") && sscanf(arg, "%g:", &x) == 1)
|
||||
{
|
||||
remaining_capacity += x;
|
||||
charging = 0;
|
||||
}
|
||||
}
|
||||
fclose(fp);
|
||||
}
|
||||
}
|
||||
if (design_capacity > 0.0f)
|
||||
{
|
||||
BatteryLifePercent = (int)floorf(remaining_capacity / ((full_capacity > 0.0f) ? full_capacity : design_capacity) * 100.0);
|
||||
if (BatteryLifePercent > 100) { BatteryLifePercent = 100; }
|
||||
if (present_rate < 0.0f)
|
||||
{
|
||||
// Linux specifies rates in mWh or mAh
|
||||
BatteryLifeTime = (int)floorf(remaining_capacity / (-present_rate) * 3600.0);
|
||||
}
|
||||
}
|
||||
closedir(batt_dir);
|
||||
}
|
||||
}
|
||||
|
||||
int CheckBatteryTime()
|
||||
{
|
||||
BatteryLifeTime = -1;
|
||||
update_battery_info();
|
||||
return(BatteryLifeTime);
|
||||
}
|
||||
|
||||
int CheckBatteryPercent()
|
||||
{
|
||||
BatteryLifePercent = -1;
|
||||
update_battery_info();
|
||||
return(BatteryLifePercent);
|
||||
}
|
||||
|
||||
/*
|
||||
Functions for battery on FreeBSD/DragonFly by Nach
|
||||
|
||||
If there's another FreeBSD based OS that doesn't
|
||||
define one of these three, please let me know.
|
||||
*/
|
||||
#elif (defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__DragonFly__))
|
||||
#include <sys/types.h>
|
||||
#include <sys/sysctl.h>
|
||||
|
||||
int CheckBattery()
|
||||
{
|
||||
int state;
|
||||
size_t state_len = sizeof(state);
|
||||
if (!sysctlbyname("hw.acpi.battery.state", &state, &state_len, 0, 0))
|
||||
{
|
||||
if ((state > -1) && (state < 7)) //7 == failure
|
||||
{
|
||||
if (!state || state&2)
|
||||
{
|
||||
return(0); //Plugged in
|
||||
}
|
||||
return(1); //Running off of battery
|
||||
}
|
||||
}
|
||||
return(-1);
|
||||
}
|
||||
|
||||
//Note that I have not yet gotten anyone to test if this function has correct info returned
|
||||
int CheckBatteryTime()
|
||||
{
|
||||
int batt_time;
|
||||
size_t batt_time_len = sizeof(batt_time);
|
||||
if (!sysctlbyname("hw.acpi.battery.time", &batt_time, &batt_time_len, 0, 0))
|
||||
{
|
||||
if (batt_time > -1)
|
||||
{
|
||||
return(batt_time * 60);
|
||||
}
|
||||
}
|
||||
return(-1);
|
||||
}
|
||||
|
||||
int CheckBatteryPercent()
|
||||
{
|
||||
int life = -1;
|
||||
size_t life_len = sizeof(life);
|
||||
sysctlbyname("hw.acpi.battery.life", &life, &life_len, 0, 0);
|
||||
return(life);
|
||||
}
|
||||
|
||||
/*
|
||||
Functions for battery on NetBSD/OpenBSD by Nach
|
||||
|
||||
If there's another NetBSD based OS that uses
|
||||
the same API, please let me know.
|
||||
|
||||
Note this was the least tested section for all
|
||||
the battery specific code.
|
||||
*/
|
||||
|
||||
#elif (defined(__NetBSD__) || defined(__OpenBSD__))
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <machine/apmvar.h>
|
||||
|
||||
#ifndef APM_BATT_ABSENT
|
||||
#define APM_BATT_ABSENT APM_BATTERY_ABSENT
|
||||
#endif
|
||||
|
||||
int CheckBattery()
|
||||
{
|
||||
int fd = open("/dev/apm", O_RDONLY);
|
||||
if (fd != -1)
|
||||
{
|
||||
struct apm_power_info info;
|
||||
if (!ioctl(fd, APM_IOC_GETPOWER, &info) &&
|
||||
(info.battery_state != APM_BATT_UNKNOWN) && (info.battery_state != APM_BATT_ABSENT))
|
||||
{
|
||||
close(fd);
|
||||
if ((info.battery_state == APM_BATT_CHARGING) || (info.ac_state == APM_AC_ON)) { return(0); } //Plugged in
|
||||
return(1); //Running off of battery
|
||||
}
|
||||
close(fd);
|
||||
}
|
||||
return(-1);
|
||||
}
|
||||
|
||||
int CheckBatteryTime()
|
||||
{
|
||||
int fd = open("/dev/apm", O_RDONLY);
|
||||
if (fd != -1)
|
||||
{
|
||||
struct apm_power_info info;
|
||||
if (!ioctl(fd, APM_IOC_GETPOWER, &info) && (info.minutes_left > 0) && (info.minutes_left < 0xFFFF))
|
||||
{
|
||||
close(fd);
|
||||
return(info.minutes_left*60);
|
||||
}
|
||||
close(fd);
|
||||
}
|
||||
return(-1);
|
||||
}
|
||||
|
||||
int CheckBatteryPercent()
|
||||
{
|
||||
int fd = open("/dev/apm", O_RDONLY);
|
||||
if (fd != -1)
|
||||
{
|
||||
struct apm_power_info info;
|
||||
if (!ioctl(fd, APM_IOC_GETPOWER, &info))
|
||||
{
|
||||
close(fd);
|
||||
return((info.battery_life == 255) ? 100 : info.battery_life);
|
||||
}
|
||||
close(fd);
|
||||
}
|
||||
return(-1);
|
||||
}
|
||||
|
||||
/*
|
||||
Functions for battery on Mac OS X by drizztbsd, Nach
|
||||
|
||||
If you have issues, please report.
|
||||
*/
|
||||
|
||||
#elif defined(__APPLE__)
|
||||
#include <sys/types.h>
|
||||
#include <math.h>
|
||||
#include <CoreFoundation/CoreFoundation.h>
|
||||
#include <IOKit/ps/IOPowerSources.h>
|
||||
#include <IOKit/ps/IOPSkeys.h>
|
||||
|
||||
static int stringsAreEqual(CFStringRef a, CFStringRef b)
|
||||
{
|
||||
if (!a || !b)
|
||||
{
|
||||
return(0);
|
||||
}
|
||||
return(CFStringCompare(a, b, 0) == kCFCompareEqualTo);
|
||||
}
|
||||
|
||||
static int BatteryLifeTime;
|
||||
static int BatteryLifePercent;
|
||||
static int HasBattery;
|
||||
|
||||
static void update_battery_info()
|
||||
{
|
||||
CFTypeRef powerBlob = IOPSCopyPowerSourcesInfo();
|
||||
CFArrayRef powerSourcesList = IOPSCopyPowerSourcesList(powerBlob);
|
||||
unsigned int count = CFArrayGetCount(powerSourcesList);
|
||||
unsigned int i;
|
||||
unsigned int tmp;
|
||||
char ret;
|
||||
|
||||
int totalCurrentCapacity = 0, totalMaxCapacity = 0;
|
||||
|
||||
BatteryLifeTime = -1;
|
||||
BatteryLifePercent = -1;
|
||||
HasBattery = -1;
|
||||
|
||||
for (i = 0; i < count; ++i)
|
||||
{
|
||||
CFTypeRef powerSource;
|
||||
CFDictionaryRef description;
|
||||
|
||||
powerSource = CFArrayGetValueAtIndex(powerSourcesList, i);
|
||||
description = IOPSGetPowerSourceDescription(powerBlob, powerSource);
|
||||
|
||||
//continue if one battery is not present
|
||||
if (CFDictionaryGetValue(description, CFSTR(kIOPSIsPresentKey)) == kCFBooleanFalse)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (stringsAreEqual(CFDictionaryGetValue(description, CFSTR(kIOPSTransportTypeKey)), CFSTR(kIOPSInternalType)))
|
||||
{
|
||||
int currentCapacity, maxCapacity;
|
||||
|
||||
CFStringRef currentState = CFDictionaryGetValue(description, CFSTR(kIOPSPowerSourceStateKey));
|
||||
CFNumberRef timeToEmptyNum = CFDictionaryGetValue(description, CFSTR(kIOPSTimeToEmptyKey));
|
||||
|
||||
if (CFEqual(currentState, CFSTR(kIOPSACPowerValue)) && (HasBattery != 1))
|
||||
{
|
||||
HasBattery = 0;
|
||||
}
|
||||
else if (CFEqual(currentState, CFSTR(kIOPSBatteryPowerValue)))
|
||||
{
|
||||
CFNumberRef timeToEmptyNum = CFDictionaryGetValue(description, CFSTR(kIOPSTimeToEmptyKey));
|
||||
if(CFNumberGetValue(timeToEmptyNum, kCFNumberIntType, &tmp))
|
||||
{
|
||||
if (BatteryLifeTime > -1)
|
||||
{
|
||||
BatteryLifeTime += tmp;
|
||||
}
|
||||
else
|
||||
{
|
||||
BatteryLifeTime = tmp;
|
||||
}
|
||||
}
|
||||
HasBattery = 1;
|
||||
}
|
||||
CFNumberRef currentCapacityNum = CFDictionaryGetValue(description, CFSTR(kIOPSCurrentCapacityKey));
|
||||
CFNumberRef maxCapacityNum = CFDictionaryGetValue(description, CFSTR(kIOPSMaxCapacityKey));
|
||||
|
||||
if (CFNumberGetValue(currentCapacityNum, kCFNumberIntType, ¤tCapacity) && CFNumberGetValue(maxCapacityNum, kCFNumberIntType, &maxCapacity))
|
||||
{
|
||||
totalCurrentCapacity += currentCapacity;
|
||||
totalMaxCapacity += maxCapacity;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
CFRelease(powerSourcesList);
|
||||
CFRelease(powerBlob);
|
||||
|
||||
if (totalCurrentCapacity && totalMaxCapacity)
|
||||
{
|
||||
BatteryLifePercent = (int)roundf((totalCurrentCapacity / (float)totalMaxCapacity) * 100.0f);
|
||||
}
|
||||
}
|
||||
|
||||
int CheckBattery()
|
||||
{
|
||||
update_battery_info();
|
||||
return(HasBattery);
|
||||
}
|
||||
|
||||
int CheckBatteryTime()
|
||||
{
|
||||
update_battery_info();
|
||||
if (BatteryLifeTime > -1)
|
||||
{
|
||||
return(BatteryLifeTime * 60);
|
||||
}
|
||||
return(-1);
|
||||
}
|
||||
|
||||
int CheckBatteryPercent()
|
||||
{
|
||||
update_battery_info();
|
||||
return(BatteryLifePercent);
|
||||
}
|
||||
|
||||
#else //Not Linux, FreeBSD/DragonFlyBSD, NetBSD/OpenBSD, Mac OS X
|
||||
|
||||
int CheckBattery()
|
||||
{
|
||||
return(-1);
|
||||
}
|
||||
|
||||
int CheckBatteryTime()
|
||||
{
|
||||
return(-1);
|
||||
}
|
||||
|
||||
int CheckBatteryPercent()
|
||||
{
|
||||
return(-1);
|
||||
}
|
||||
|
||||
#endif
|
||||
412
tools/zsnes/src/linux/gl_draw.c
Normal file
412
tools/zsnes/src/linux/gl_draw.c
Normal file
@@ -0,0 +1,412 @@
|
||||
/*
|
||||
Copyright (C) 1997-2007 ZSNES Team ( zsKnight, _Demo_, pagefault, Nach )
|
||||
|
||||
http://www.zsnes.com
|
||||
http://sourceforge.net/projects/zsnes
|
||||
https://zsnes.bountysource.com
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License
|
||||
version 2 as published by the Free Software Foundation.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
|
||||
#include "../cfg.h"
|
||||
#include "../gblhdr.h"
|
||||
#include "../asm_call.h"
|
||||
|
||||
#define BYTE unsigned char
|
||||
#define WORD unsigned short
|
||||
#define DWORD unsigned long
|
||||
|
||||
//C++ style code in C
|
||||
#define bool unsigned char
|
||||
#define true 1
|
||||
#define false 0
|
||||
|
||||
// FUNCTIONS
|
||||
void hq2x_16b(void);
|
||||
|
||||
// VIDEO VARIABLES
|
||||
extern SDL_Surface *surface;
|
||||
extern int SurfaceX, SurfaceY;
|
||||
extern int SurfaceLocking;
|
||||
extern DWORD BitDepth;
|
||||
|
||||
// OPENGL VARIABLES
|
||||
static unsigned short *glvidbuffer = 0;
|
||||
static GLuint gltextures[4];
|
||||
static int gltexture256, gltexture512;
|
||||
static int glfilters = GL_NEAREST;
|
||||
static int glscanready = 0;
|
||||
extern Uint8 GUIOn2;
|
||||
|
||||
extern unsigned int vidbuffer;
|
||||
extern unsigned char curblank;
|
||||
extern BYTE GUIRESIZE[];
|
||||
|
||||
void gl_clearwin();
|
||||
void UpdateVFrame();
|
||||
|
||||
void gl_scanlines();
|
||||
|
||||
bool OGLModeCheck();
|
||||
|
||||
int gl_start(int width, int height, int req_depth, int FullScreen)
|
||||
{
|
||||
Uint32 flags = SDL_DOUBLEBUF | SDL_HWSURFACE | SDL_HWPALETTE | SDL_OPENGL;
|
||||
int i;
|
||||
|
||||
flags |= (GUIRESIZE[cvidmode] ? SDL_RESIZABLE : 0);
|
||||
flags |= (FullScreen ? SDL_FULLSCREEN : 0);
|
||||
|
||||
|
||||
SurfaceX = width; SurfaceY = height;
|
||||
surface = SDL_SetVideoMode(SurfaceX, SurfaceY, req_depth, flags);
|
||||
if (surface == NULL)
|
||||
{
|
||||
fprintf(stderr, "Could not set %dx%d-GL video mode.\n",SurfaceX, SurfaceY);
|
||||
return false;
|
||||
}
|
||||
|
||||
SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
|
||||
#if (SDL_MAJOR_VERSION > 1) || ((SDL_MINOR_VERSION > 2) || ((SDL_MINOR_VERSION == 2) && (SDL_PATCHLEVEL >= 10)))
|
||||
SDL_GL_SetAttribute(SDL_GL_SWAP_CONTROL, 1);
|
||||
#endif
|
||||
|
||||
if (!glvidbuffer)
|
||||
{
|
||||
glvidbuffer = (unsigned short *) malloc(512 * 512 * sizeof(short));
|
||||
}
|
||||
gl_clearwin();
|
||||
SDL_WarpMouse(SurfaceX / 4, SurfaceY / 4);
|
||||
|
||||
// Grab mouse in fullscreen mode
|
||||
FullScreen ? SDL_WM_GrabInput(SDL_GRAB_ON) :
|
||||
SDL_WM_GrabInput(SDL_GRAB_OFF);
|
||||
|
||||
SDL_WM_SetCaption("ZSNES", "ZSNES");
|
||||
SDL_ShowCursor(0);
|
||||
|
||||
/* Setup some GL stuff */
|
||||
|
||||
glEnable(GL_TEXTURE_1D);
|
||||
glEnable(GL_TEXTURE_2D);
|
||||
|
||||
glViewport(0, 0, SurfaceX, SurfaceY);
|
||||
|
||||
/*
|
||||
* gltextures[0]: 2D texture, 256x224
|
||||
* gltextures[1]: 2D texture, 512x224
|
||||
* gltextures[3]: 1D texture, 256 lines of alternating alpha
|
||||
*/
|
||||
glGenTextures(4, gltextures);
|
||||
for (i = 0; i < 3; i++) {
|
||||
glBindTexture(GL_TEXTURE_2D, gltextures[i]);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, glfilters);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, glfilters);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
|
||||
}
|
||||
|
||||
if (scanlines) gl_scanlines();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void gl_end()
|
||||
{
|
||||
if (glvidbuffer)
|
||||
{
|
||||
glDeleteTextures(4, gltextures);
|
||||
free(glvidbuffer);
|
||||
glvidbuffer = 0;
|
||||
}
|
||||
}
|
||||
|
||||
extern DWORD AddEndBytes;
|
||||
extern DWORD NumBytesPerLine;
|
||||
extern unsigned char *WinVidMemStart;
|
||||
extern unsigned char NGNoTransp;
|
||||
void copy640x480x16bwin(void);
|
||||
extern unsigned char SpecialLine[224]; /* 0 if lo-res, > 0 if hi-res */
|
||||
|
||||
void gl_clearwin()
|
||||
{
|
||||
glClear(GL_COLOR_BUFFER_BIT);
|
||||
memset(glvidbuffer, 0, 512 * 448 * 2);
|
||||
}
|
||||
|
||||
/* gl_drawspan:
|
||||
* Puts a quad on the screen for hires/lores portions, starting at line start,
|
||||
* and ending at line end..
|
||||
* Builds the 256x256/512x256 textures if gltexture256 or gltexture512 == 0
|
||||
*/
|
||||
static void gl_drawspan(int hires, int start, int end)
|
||||
{
|
||||
int i, j;
|
||||
|
||||
switch (hires)
|
||||
{
|
||||
case 0:
|
||||
break;
|
||||
case 3:
|
||||
case 7:
|
||||
hires = 2;
|
||||
break;
|
||||
default:
|
||||
hires = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
if (hires)
|
||||
{
|
||||
if (hires != gltexture512)
|
||||
{
|
||||
unsigned short *vbuf1 = &((unsigned short *) vidbuffer)[16];
|
||||
unsigned short *vbuf2 = &((unsigned short *) vidbuffer)[75036 * 2 + 16];
|
||||
unsigned short *vbuf = &glvidbuffer[0];
|
||||
|
||||
if (hires>1) // mode 7
|
||||
{
|
||||
for (j = 224; j--;)
|
||||
{
|
||||
for (i = 256; i--;)
|
||||
*vbuf++ = *vbuf1++;
|
||||
for (i = 256; i--;)
|
||||
*vbuf++ = *vbuf2++;
|
||||
vbuf1 += 32;
|
||||
vbuf2 += 32;
|
||||
}
|
||||
glBindTexture(GL_TEXTURE_2D, gltextures[1]);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, 3, 256, 512, 0,
|
||||
GL_RGB, GL_UNSIGNED_SHORT_5_6_5,
|
||||
glvidbuffer);
|
||||
|
||||
gltexture512 = 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
for (j = 224; j--;)
|
||||
{
|
||||
for (i = 256; i--;)
|
||||
{
|
||||
*vbuf++ = *vbuf1++;
|
||||
*vbuf++ = *vbuf2++;
|
||||
}
|
||||
vbuf1 += 32;
|
||||
vbuf2 += 32; // skip the two 16-pixel-wide columns
|
||||
}
|
||||
|
||||
glBindTexture(GL_TEXTURE_2D, gltextures[1]);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, 3, 512, 256, 0,
|
||||
GL_RGB, GL_UNSIGNED_SHORT_5_6_5,
|
||||
glvidbuffer);
|
||||
|
||||
gltexture512 = 1;
|
||||
}
|
||||
}
|
||||
|
||||
glBindTexture(GL_TEXTURE_2D, gltextures[1]);
|
||||
glBegin(GL_QUADS);
|
||||
glTexCoord2f(0.0f, (224.0 / 256.0) * (start / 224.0));
|
||||
glVertex2f(-1.0f, (112 - start) / 112.0);
|
||||
glTexCoord2f(1.0f, (224.0 / 256.0) * (start / 224.0));
|
||||
glVertex2f(1.0f, (112 - start) / 112.0);
|
||||
glTexCoord2f(1.0f, (224.0 / 256.0) * (end / 224.0));
|
||||
glVertex2f(1.0f, (112 - end) / 112.0);
|
||||
glTexCoord2f(0.0f, (224.0 / 256.0) * (end / 224.0));
|
||||
glVertex2f(-1.0f, (112 - end) / 112.0);
|
||||
glEnd();
|
||||
}
|
||||
else
|
||||
{
|
||||
glBindTexture(GL_TEXTURE_2D, gltextures[0]);
|
||||
if (!gltexture256)
|
||||
{
|
||||
glPixelStorei(GL_UNPACK_SKIP_PIXELS, 16);
|
||||
glPixelStorei(GL_UNPACK_ROW_LENGTH, 288);
|
||||
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, 3, 256, 256, 0,
|
||||
GL_RGB, GL_UNSIGNED_SHORT_5_6_5,
|
||||
((unsigned short *) vidbuffer) + 288);
|
||||
|
||||
glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0);
|
||||
glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
|
||||
|
||||
gltexture256 = 1;
|
||||
}
|
||||
|
||||
glBegin(GL_QUADS);
|
||||
glTexCoord2f(0.0f, (224.0 / 256.0) * (start / 224.0));
|
||||
glVertex2f(-1.0f, (112 - start) / 112.0);
|
||||
glTexCoord2f(1.0f, (224.0 / 256.0) * (start / 224.0));
|
||||
glVertex2f(1.0f, (112 - start) / 112.0);
|
||||
glTexCoord2f(1.0f, (224.0 / 256.0) * (end / 224.0));
|
||||
glVertex2f(1.0f, (112 - end) / 112.0);
|
||||
glTexCoord2f(0.0f, (224.0 / 256.0) * (end / 224.0));
|
||||
glVertex2f(-1.0f, (112 - end) / 112.0);
|
||||
glEnd();
|
||||
}
|
||||
}
|
||||
|
||||
void gl_drawwin()
|
||||
{
|
||||
int i;
|
||||
|
||||
NGNoTransp = 0; // Set this value to 1 within the appropriate
|
||||
// video mode if you want to add a custom
|
||||
// transparency routine or hardware
|
||||
// transparency. This only works if
|
||||
// the value of newengen is equal to 1.
|
||||
// (see ProcessTransparencies in newgfx16.asm
|
||||
// for ZSNES' current transparency code)
|
||||
UpdateVFrame();
|
||||
if (curblank || !OGLModeCheck())
|
||||
return;
|
||||
|
||||
if (BilinearFilter)
|
||||
{
|
||||
glfilters = GL_LINEAR;
|
||||
if (GUIOn2 && !FilteredGUI)
|
||||
glfilters = GL_NEAREST;
|
||||
}
|
||||
else
|
||||
{
|
||||
glfilters = GL_NEAREST;
|
||||
}
|
||||
|
||||
if (SurfaceX >= 512 && (hqFilter || En2xSaI))
|
||||
{
|
||||
AddEndBytes = 0;
|
||||
NumBytesPerLine = 1024;
|
||||
WinVidMemStart = (void *) glvidbuffer;
|
||||
|
||||
if (hqFilter) hq2x_16b();
|
||||
else asm_call(copy640x480x16bwin);
|
||||
|
||||
/* Display 1 512x448 quad for the 512x448 buffer */
|
||||
glBindTexture(GL_TEXTURE_2D, gltextures[1]);
|
||||
glTexEnvi(GL_TEXTURE_2D, GL_TEXTURE_ENV_MODE, GL_DECAL);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 512, 512, 0,
|
||||
GL_RGB, GL_UNSIGNED_SHORT_5_6_5, glvidbuffer);
|
||||
|
||||
glDisable (GL_DEPTH_TEST);
|
||||
glDisable (GL_LIGHTING);
|
||||
glDisable (GL_BLEND);
|
||||
|
||||
glBegin(GL_QUADS);
|
||||
glTexCoord2f(0.0f, 0.0f);
|
||||
glVertex3f(-1.0f, 1.0f, -1.0f);
|
||||
glTexCoord2f(1.0f, 0.0f);
|
||||
glVertex3f(1.0f, 1.0f, -1.0f);
|
||||
glTexCoord2f(1.0f, 448.0f / 512.0f);
|
||||
glVertex3f(1.0f, -1.0f, -1.0f);
|
||||
glTexCoord2f(0.0f, 448.0f / 512.0f);
|
||||
glVertex3f(-1.0f, -1.0f, -1.0f);
|
||||
glEnd();
|
||||
}
|
||||
else
|
||||
{
|
||||
/*
|
||||
* This code splits the hires/lores portions up, and draws
|
||||
* them with gl_drawspan
|
||||
*/
|
||||
int lasthires, lasthires_line = 0;
|
||||
|
||||
gltexture256 = gltexture512 = 0;
|
||||
|
||||
lasthires = SpecialLine[1];
|
||||
for (i = 0; i < 224; i++)
|
||||
{
|
||||
if (SpecialLine[i + 1])
|
||||
{
|
||||
if (lasthires)
|
||||
continue;
|
||||
gl_drawspan(lasthires, lasthires_line, i);
|
||||
|
||||
lasthires = SpecialLine[i + 1];
|
||||
lasthires_line = i;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!lasthires)
|
||||
continue;
|
||||
gl_drawspan(lasthires, lasthires_line, i);
|
||||
|
||||
lasthires = SpecialLine[i + 1];
|
||||
lasthires_line = i;
|
||||
}
|
||||
}
|
||||
|
||||
if (i - lasthires_line > 1)
|
||||
gl_drawspan(lasthires, lasthires_line, i);
|
||||
|
||||
/*
|
||||
* This is here rather than right outside this if because the
|
||||
* GUI doesn't allow scanlines to be selected while filters are
|
||||
* on.. There is no technical reason they can't be on while
|
||||
* filters are on, however. Feel free to change the GUI, and
|
||||
* move this outside the if (En2xSaI) {}, if you do.
|
||||
*/
|
||||
if (scanlines)
|
||||
{
|
||||
glDisable(GL_TEXTURE_2D);
|
||||
glEnable(GL_BLEND);
|
||||
|
||||
if (scanlines != glscanready) gl_scanlines();
|
||||
|
||||
glBlendFunc(GL_DST_COLOR, GL_ZERO);
|
||||
glBindTexture(GL_TEXTURE_1D, gltextures[3]);
|
||||
glBegin(GL_QUADS);
|
||||
for (i = 0; i < SurfaceY; i += 256)
|
||||
{
|
||||
glTexCoord1f(0.0f);
|
||||
glVertex3f(-1.0f, (SurfaceY - i * 2.0) / SurfaceY, -1.0f);
|
||||
glTexCoord1f(0.0f);
|
||||
glVertex3f(1.0f, (SurfaceY - i * 2.0) / SurfaceY, -1.0f);
|
||||
glTexCoord1f(1.0f);
|
||||
glVertex3f(1.0f, (SurfaceY - (i + 256) * 2.0) / SurfaceY, -1.0f);
|
||||
glTexCoord1f(1.0f);
|
||||
glVertex3f(-1.0f, (SurfaceY - (i + 256) * 2.0) / SurfaceY, -1.0f);
|
||||
}
|
||||
glEnd();
|
||||
|
||||
glDisable(GL_BLEND);
|
||||
glEnable(GL_TEXTURE_2D);
|
||||
}
|
||||
}
|
||||
SDL_GL_SwapBuffers();
|
||||
}
|
||||
|
||||
void gl_scanlines(void)
|
||||
{
|
||||
GLubyte scanbuffer[256][4];
|
||||
int i, j = scanlines==1 ? 0 : (scanlines==2 ? 192 : 128);
|
||||
|
||||
for (i = 0; i < 256; i += 2)
|
||||
{
|
||||
scanbuffer[i][0] = scanbuffer[i][1] = scanbuffer[i][2] = j;
|
||||
scanbuffer[i][3] = 0xFF;
|
||||
|
||||
scanbuffer[i+1][0] = scanbuffer[i+1][1] = scanbuffer[i+1][2] = 0xFF;
|
||||
scanbuffer[i+1][3] = 0xFF;
|
||||
}
|
||||
|
||||
glBindTexture(GL_TEXTURE_1D, gltextures[3]);
|
||||
glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||
glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||
glTexImage1D(GL_TEXTURE_1D, 0, GL_RGBA, 256, 0, GL_RGBA,
|
||||
GL_UNSIGNED_BYTE, scanbuffer);
|
||||
|
||||
glscanready = scanlines;
|
||||
}
|
||||
33
tools/zsnes/src/linux/gl_draw.h
Normal file
33
tools/zsnes/src/linux/gl_draw.h
Normal file
@@ -0,0 +1,33 @@
|
||||
/*
|
||||
Copyright (C) 1997-2007 ZSNES Team ( zsKnight, _Demo_, pagefault, Nach )
|
||||
|
||||
http://www.zsnes.com
|
||||
http://sourceforge.net/projects/zsnes
|
||||
https://zsnes.bountysource.com
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License
|
||||
version 2 as published by the Free Software Foundation.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef GL_DRAW_h
|
||||
#define GL_DRAW_h 1
|
||||
|
||||
int gl_start(int width, int height, int req_depth, int FullScreen);
|
||||
void gl_end();
|
||||
void gl_clearwin();
|
||||
void gl_drawwin();
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
355
tools/zsnes/src/linux/safelib.c
Normal file
355
tools/zsnes/src/linux/safelib.c
Normal file
@@ -0,0 +1,355 @@
|
||||
/*
|
||||
Copyright (C) 1997-2007 ZSNES Team ( zsKnight, _Demo_, pagefault, Nach )
|
||||
|
||||
http://www.zsnes.com
|
||||
http://sourceforge.net/projects/zsnes
|
||||
https://zsnes.bountysource.com
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License
|
||||
version 2 as published by the Free Software Foundation.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
#include "gblhdr.h"
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/wait.h>
|
||||
#include <signal.h>
|
||||
#include <paths.h>
|
||||
#include <grp.h>
|
||||
#include <pwd.h>
|
||||
|
||||
#ifndef OPEN_MAX
|
||||
#define OPEN_MAX 256
|
||||
#endif
|
||||
|
||||
#include "safelib.h"
|
||||
|
||||
#include "../argv.h"
|
||||
|
||||
//C++ style code in C
|
||||
#define bool unsigned char
|
||||
#define true 1
|
||||
#define false 0
|
||||
|
||||
|
||||
//Introducing secure forking ;) -Nach
|
||||
|
||||
//Taken from the secure programming cookbook, somewhat modified
|
||||
static bool spc_drop_privileges()
|
||||
{
|
||||
gid_t newgid = getgid(), oldgid = getegid();
|
||||
uid_t newuid = getuid(), olduid = geteuid();
|
||||
|
||||
char *name = getlogin();
|
||||
struct passwd *userinfo;
|
||||
|
||||
if (!olduid && name && (userinfo = getpwnam(name)) && userinfo->pw_uid)
|
||||
{
|
||||
setgroups(1, &userinfo->pw_gid);
|
||||
|
||||
#if !defined(linux)
|
||||
setegid(userinfo->pw_gid);
|
||||
if (setgid(userinfo->pw_gid) == -1) { return(false); }
|
||||
#else
|
||||
if (setregid(userinfo->pw_gid, userinfo->pw_gid) == -1) { return(false); }
|
||||
#endif
|
||||
|
||||
#if !defined(linux)
|
||||
seteuid(userinfo->pw_uid);
|
||||
if (setuid(userinfo->pw_uid) == -1) { return(false); }
|
||||
#else
|
||||
if (setreuid(userinfo->pw_uid, userinfo->pw_uid) == -1) { return(false); }
|
||||
#endif
|
||||
|
||||
if ((setegid(oldgid) != -1) || (getegid() != userinfo->pw_gid)) { return(false); }
|
||||
if ((seteuid(olduid) != -1) || (geteuid() != userinfo->pw_uid)) { return(false); }
|
||||
}
|
||||
else
|
||||
{
|
||||
//If root privileges are to be dropped, be sure to pare down the ancillary
|
||||
//groups for the process before doing anything else because the setgroups()
|
||||
//system call requires root privileges. Drop ancillary groups regardless of
|
||||
//whether privileges are being dropped temporarily or permanently.
|
||||
|
||||
if (!olduid) setgroups(1, &newgid);
|
||||
|
||||
if (newgid != oldgid)
|
||||
{
|
||||
#if !defined(linux)
|
||||
setegid(newgid);
|
||||
if (setgid(newgid) == -1) { return(false); }
|
||||
#else
|
||||
if (setregid(newgid, newgid) == -1) { return(false); }
|
||||
#endif
|
||||
}
|
||||
|
||||
if (newuid != olduid)
|
||||
{
|
||||
#if !defined(linux)
|
||||
seteuid(newuid);
|
||||
if (setuid(newuid) == -1) { return(false); }
|
||||
#else
|
||||
if (setreuid(newuid, newuid) == -1) { return(false); }
|
||||
#endif
|
||||
}
|
||||
|
||||
//verify that the changes were successful
|
||||
if (newgid != oldgid && (setegid(oldgid) != -1 || getegid() != newgid)) { return(false); }
|
||||
if (newuid != olduid && (seteuid(olduid) != -1 || geteuid() != newuid)) { return(false); }
|
||||
}
|
||||
return(true);
|
||||
}
|
||||
|
||||
static int open_devnull(int fd)
|
||||
{
|
||||
FILE *f = 0;
|
||||
|
||||
if (!fd) { f = freopen(_PATH_DEVNULL, "rb", stdin); }
|
||||
else if (fd == 1) { f = freopen(_PATH_DEVNULL, "wb", stdout); }
|
||||
else if (fd == 2) { f = freopen(_PATH_DEVNULL, "wb", stderr); }
|
||||
return(f && fileno(f) == fd);
|
||||
}
|
||||
|
||||
static bool array_contains(int *a, size_t size, int key)
|
||||
{
|
||||
size_t i;
|
||||
for (i = 0; i < size; i++)
|
||||
{
|
||||
if (a[i] == key) { return(true); }
|
||||
}
|
||||
return(false);
|
||||
}
|
||||
|
||||
static bool spc_sanitize_files(int *a, size_t size, int skip)
|
||||
{
|
||||
int fd, fds;
|
||||
struct stat st;
|
||||
|
||||
//Make sure all open descriptors other than the standard ones are closed
|
||||
if ((fds = getdtablesize()) == -1)
|
||||
{
|
||||
fds = OPEN_MAX;
|
||||
}
|
||||
for (fd = 3; fd < fds; fd++)
|
||||
{
|
||||
if ((fd != skip) && !array_contains(a, size, fd)) { close(fd); }
|
||||
}
|
||||
|
||||
//Verify that the standard descriptors are open. If they're not, attempt to
|
||||
//open them using /dev/null. If any are unsuccessful, fail.
|
||||
for (fd = 0; fd < 3; fd++)
|
||||
{
|
||||
if (fstat(fd, &st) == -1 && (errno != EBADF || !open_devnull(fd)))
|
||||
{
|
||||
return(false);
|
||||
}
|
||||
}
|
||||
return(true);
|
||||
}
|
||||
|
||||
//Pass array of file descriptors to leave open
|
||||
pid_t safe_fork(int *a, size_t size)
|
||||
{
|
||||
int filedes[2];
|
||||
if (!pipe(filedes))
|
||||
{
|
||||
char success = 0;
|
||||
pid_t childpid;
|
||||
if ((childpid = fork()) == -1) //Fork Failed
|
||||
{
|
||||
close(filedes[0]);
|
||||
close(filedes[1]);
|
||||
return(-1);
|
||||
}
|
||||
|
||||
if (childpid) //Parent Process
|
||||
{
|
||||
close(filedes[1]); //Close writing
|
||||
read(filedes[0], &success, 1);
|
||||
close(filedes[0]);
|
||||
if (success)
|
||||
{
|
||||
return(childpid);
|
||||
}
|
||||
waitpid(childpid, 0, 0);
|
||||
return(-1);
|
||||
}
|
||||
|
||||
|
||||
//This is the child proccess
|
||||
|
||||
close(filedes[0]); //Close reading
|
||||
|
||||
if (!spc_sanitize_files(a, size, filedes[1]) || !spc_drop_privileges())
|
||||
{
|
||||
write(filedes[1], &success, 1);
|
||||
close(filedes[1]);
|
||||
_exit(0);
|
||||
}
|
||||
|
||||
success = 1;
|
||||
write(filedes[1], &success, 1);
|
||||
close(filedes[1]);
|
||||
return(0);
|
||||
}
|
||||
return(-1);
|
||||
}
|
||||
|
||||
|
||||
//Introducing a popen which doesn't return until it knows for sure of program launched or couldn't open -Nach
|
||||
|
||||
|
||||
//Forks, parent is paused until child successfully execs (returns child pid) or child exits (returns failure)
|
||||
static pid_t parent_pause_fork()
|
||||
{
|
||||
int filedes[2];
|
||||
if (!pipe(filedes))
|
||||
{
|
||||
int pid = fork();
|
||||
if (pid == -1) //Failed
|
||||
{
|
||||
close(filedes[0]);
|
||||
close(filedes[1]);
|
||||
}
|
||||
else if (pid > 0) //Parent
|
||||
{
|
||||
char success = 1;
|
||||
close(filedes[1]);
|
||||
read(filedes[0], &success, 1);
|
||||
close(filedes[0]);
|
||||
if (success)
|
||||
{
|
||||
return(pid);
|
||||
}
|
||||
waitpid(pid, 0, 0);
|
||||
}
|
||||
else //Child
|
||||
{
|
||||
close(filedes[0]);
|
||||
fcntl(filedes[1], F_SETFD, FD_CLOEXEC);
|
||||
return(-filedes[1]);
|
||||
}
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
|
||||
static void close_child(pid_t pid)
|
||||
{
|
||||
char success = 0;
|
||||
write(-pid, &success, 1);
|
||||
close(-pid);
|
||||
_exit(0);
|
||||
}
|
||||
|
||||
#define IS_PARENT(x) ((x) > 0)
|
||||
#define IS_CHILD(x) ((x) < 0)
|
||||
#define IS_FAIL(x) ((x) == 0)
|
||||
|
||||
|
||||
static struct fp_pid_link
|
||||
{
|
||||
FILE *fp;
|
||||
pid_t pid;
|
||||
struct fp_pid_link *next;
|
||||
} fp_pids = { 0, 0, 0 };
|
||||
|
||||
|
||||
FILE *safe_popen(char *command, const char *mode)
|
||||
{
|
||||
//filedes[0] is for reading
|
||||
//filedes[1] is for writing.
|
||||
int filedes[2];
|
||||
|
||||
if (mode && (*mode == 'r' || *mode == 'w') && !pipe(filedes))
|
||||
{
|
||||
pid_t childpid = parent_pause_fork();
|
||||
if (IS_PARENT(childpid))
|
||||
{
|
||||
FILE *fp;
|
||||
if (*mode == 'r')
|
||||
{
|
||||
close(filedes[1]);
|
||||
fp = fdopen(filedes[0], "r");
|
||||
}
|
||||
else
|
||||
{
|
||||
close(filedes[0]);
|
||||
fp = fdopen(filedes[1], "w");
|
||||
}
|
||||
|
||||
if (fp)
|
||||
{
|
||||
struct fp_pid_link *link = &fp_pids;
|
||||
while (link->next)
|
||||
{
|
||||
link = link->next;
|
||||
}
|
||||
|
||||
link->next = (struct fp_pid_link *)malloc(sizeof(struct fp_pid_link));
|
||||
if (link->next)
|
||||
{
|
||||
link->next->fp = fp;
|
||||
link->next->pid = childpid;
|
||||
link->next->next = 0;
|
||||
return(fp);
|
||||
}
|
||||
fclose(fp);
|
||||
}
|
||||
kill(childpid, SIGTERM);
|
||||
waitpid(childpid, 0, 0);
|
||||
}
|
||||
else if (IS_CHILD(childpid))
|
||||
{
|
||||
char **argv = build_argv(command);
|
||||
if (argv)
|
||||
{
|
||||
if (*mode == 'r')
|
||||
{
|
||||
dup2(filedes[1], STDOUT_FILENO);
|
||||
}
|
||||
else
|
||||
{
|
||||
dup2(filedes[0], STDIN_FILENO);
|
||||
}
|
||||
|
||||
if (spc_sanitize_files(0, 0, -childpid) && spc_drop_privileges())
|
||||
{
|
||||
execvp(argv[0], argv);
|
||||
}
|
||||
free(argv);
|
||||
}
|
||||
close_child(childpid);
|
||||
}
|
||||
close(filedes[0]);
|
||||
close(filedes[1]);
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
|
||||
void safe_pclose(FILE *fp)
|
||||
{
|
||||
struct fp_pid_link *link = &fp_pids;
|
||||
|
||||
while (link->next && link->next->fp != fp)
|
||||
{
|
||||
link = link->next;
|
||||
}
|
||||
if (link->next->fp == fp)
|
||||
{
|
||||
struct fp_pid_link *dellink = link->next;
|
||||
fclose(fp);
|
||||
waitpid(link->next->pid, 0, 0);
|
||||
link->next = link->next->next;
|
||||
free(dellink);
|
||||
}
|
||||
}
|
||||
36
tools/zsnes/src/linux/safelib.h
Normal file
36
tools/zsnes/src/linux/safelib.h
Normal file
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
Copyright (C) 1997-2007 ZSNES Team ( zsKnight, _Demo_, pagefault, Nach )
|
||||
|
||||
http://www.zsnes.com
|
||||
http://sourceforge.net/projects/zsnes
|
||||
https://zsnes.bountysource.com
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License
|
||||
version 2 as published by the Free Software Foundation.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
#ifndef SAFELIB_H
|
||||
#define SAFELIB_H
|
||||
|
||||
#include <stdio.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
pid_t safe_fork(int *, size_t);
|
||||
|
||||
FILE *safe_popen(char *, const char *);
|
||||
void safe_pclose(FILE *);
|
||||
|
||||
#define popen safe_popen
|
||||
#define pclose safe_pclose
|
||||
|
||||
#endif
|
||||
806
tools/zsnes/src/linux/sdlintrf.asm
Normal file
806
tools/zsnes/src/linux/sdlintrf.asm
Normal file
@@ -0,0 +1,806 @@
|
||||
;Copyright (C) 1997-2007 ZSNES Team ( zsKnight, _Demo_, pagefault, Nach )
|
||||
;
|
||||
;http://www.zsnes.com
|
||||
;http://sourceforge.net/projects/zsnes
|
||||
;https://zsnes.bountysource.com
|
||||
;
|
||||
;This program is free software; you can redistribute it and/or
|
||||
;modify it under the terms of the GNU General Public License
|
||||
;version 2 as published by the Free Software Foundation.
|
||||
;
|
||||
;This program is distributed in the hope that it will be useful,
|
||||
;but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
;MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
;GNU General Public License for more details.
|
||||
;
|
||||
;You should have received a copy of the GNU General Public License
|
||||
;along with this program; if not, write to the Free Software
|
||||
;Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
|
||||
|
||||
|
||||
%include "macros.mac"
|
||||
|
||||
EXTSYM getchar,PrevFSMode,sem_sleep,SBHDMA,putchar,Start60HZ
|
||||
EXTSYM pressed,AdjustFrequency,vidbufferofsb,vidbuffer,clearwin
|
||||
EXTSYM Stop60HZ,initwinvideo,vesa2_rpos,vesa2_gpos,vesa2_bpos,vesa2_rposng
|
||||
EXTSYM vesa2_gposng,vesa2_bposng,vesa2_usbit,vesa2_clbit,vesa2_clbitng
|
||||
EXTSYM vesa2_clbitng2,vesa2_clbitng3,vesa2red10,res640,res480,cbitmode,cvidmode
|
||||
EXTSYM vesa2_bits,vesa2_x,vesa2_y,genfulladdtab,GUICPC,drawscreenwin
|
||||
EXTSYM ConvertToAFormat,HalfTrans,UnusedBit,UnusedBitXor
|
||||
EXTSYM ngrposng,nggposng,ngbposng,HalfTransB,HalfTransC,UpdateVFrame,GetMouseX
|
||||
EXTSYM GetMouseY,GetMouseMoveX,GetMouseMoveY,GetMouseButton,T36HZEnabled
|
||||
EXTSYM MouseButton,Start36HZ,Stop36HZ,CheckTimers,vesa2_rfull,vesa2_rtrcl
|
||||
EXTSYM vesa2_rtrcla,vesa2_gfull,vesa2_gtrcl,vesa2_gtrcla,vesa2_bfull,vesa2_btrcl
|
||||
EXTSYM vesa2_btrcla,Init_2xSaIMMXW,V8Mode,GrayscaleMode,PrevWinMode
|
||||
EXTSYM pl1upk,pl1downk,pl1leftk,pl1rightk,pl1startk,pl1selk
|
||||
EXTSYM pl1Ak,pl1Bk,pl1Xk,pl1Yk,pl1Lk,pl1Rk
|
||||
EXTSYM pl2upk,pl2downk,pl2leftk,pl2rightk,pl2startk,pl2selk
|
||||
EXTSYM pl2Ak,pl2Bk,pl2Xk,pl2Yk,pl2Lk,pl2Rk
|
||||
EXTSYM pl3upk,pl3downk,pl3leftk,pl3rightk,pl3startk,pl3selk
|
||||
EXTSYM pl3Ak,pl3Bk,pl3Xk,pl3Yk,pl3Lk,pl3Rk
|
||||
EXTSYM pl4upk,pl4downk,pl4leftk,pl4rightk,pl4startk,pl4selk
|
||||
EXTSYM pl4Ak,pl4Bk,pl4Xk,pl4Yk,pl4Lk,pl4Rk
|
||||
EXTSYM pl5upk,pl5downk,pl5leftk,pl5rightk,pl5startk,pl5selk
|
||||
EXTSYM pl5Ak,pl5Bk,pl5Xk,pl5Yk,pl5Lk,pl5Rk
|
||||
|
||||
%ifdef __OPENGL__
|
||||
EXTSYM Clear2xSaIBuffer
|
||||
%endif
|
||||
|
||||
; NOTE: For timing, Game60hzcall should be called at 50hz or 60hz (depending
|
||||
; on romispal) after a call to InitPreGame and before DeInitPostGame are
|
||||
; made. GUI36hzcall should be called at 36hz after a call GUIInit and
|
||||
; before GUIDeInit.
|
||||
|
||||
SECTION .text
|
||||
|
||||
NEWSYM StartUp
|
||||
ret
|
||||
|
||||
; SystemInit - Initialize all Joystick stuff, load in all configuration data,
|
||||
; parse commandline data, obtain current directory (One time initialization)
|
||||
|
||||
NEWSYM SystemInit
|
||||
; Be sure to set SBHDMA to a value other than 0 if 16bit sound exists
|
||||
mov byte[SBHDMA],1
|
||||
ret
|
||||
|
||||
NEWSYM PrintStr ; Print ASCIIZ string
|
||||
pushad
|
||||
.next
|
||||
mov al,[edx]
|
||||
or al,al
|
||||
jz .finish
|
||||
push edx
|
||||
mov dl,al
|
||||
push edx
|
||||
call putchar
|
||||
pop edx
|
||||
pop edx
|
||||
inc edx
|
||||
jmp .next
|
||||
.finish
|
||||
popad
|
||||
ret
|
||||
|
||||
SECTION .data
|
||||
NEWSYM wfkey, db 0
|
||||
|
||||
SECTION .text
|
||||
NEWSYM WaitForKey ; Wait for a key to be pressed
|
||||
pushad
|
||||
call getchar
|
||||
mov [wfkey],al
|
||||
popad
|
||||
mov al,[wfkey]
|
||||
; return key in al
|
||||
ret
|
||||
|
||||
SECTION .data
|
||||
NEWSYM CurKeyPos, dd 0
|
||||
NEWSYM CurKeyReadPos, dd 0
|
||||
NEWSYM KeyBuffer, times 16 dd 0
|
||||
|
||||
SECTION .text
|
||||
NEWSYM Check_Key
|
||||
mov al,[CurKeyPos]
|
||||
cmp al,[CurKeyReadPos]
|
||||
jne .yeskey
|
||||
xor al,al
|
||||
ret
|
||||
.yeskey
|
||||
mov al,0FFh
|
||||
ret
|
||||
|
||||
NEWSYM Get_Key
|
||||
; wait if there are no keys in buffer, then return key in al
|
||||
; for extended keys, return a 0, then the extended key afterwards
|
||||
xor eax,eax
|
||||
.nokey
|
||||
; call JoyRead
|
||||
mov al,[CurKeyReadPos]
|
||||
cmp al,[CurKeyPos]
|
||||
je .nokey
|
||||
test word[KeyBuffer+eax*4],100h
|
||||
jnz .upper
|
||||
mov al,[KeyBuffer+eax*4]
|
||||
inc dword[CurKeyReadPos]
|
||||
and dword[CurKeyReadPos],0Fh
|
||||
ret
|
||||
.upper
|
||||
sub word[KeyBuffer+eax*4],100h
|
||||
xor al,al
|
||||
ret
|
||||
|
||||
NEWSYM Get_Memfree
|
||||
mov eax,02000000h
|
||||
ret
|
||||
|
||||
NEWSYM Output_Text ; Output character (ah=02h) or string (ah=09h)
|
||||
pushad
|
||||
|
||||
; This function usually displays an error message on-screen
|
||||
cmp ah,02h
|
||||
je .char
|
||||
cmp ah,09h
|
||||
je .string
|
||||
ret
|
||||
.char
|
||||
push edx
|
||||
call putchar
|
||||
pop edx
|
||||
popad
|
||||
ret
|
||||
.string
|
||||
pushad
|
||||
call PrintStr ; print edx
|
||||
popad
|
||||
popad
|
||||
ret
|
||||
|
||||
NEWSYM InitPreGame ; Executes before starting/continuing a game
|
||||
mov byte[pressed+1],2
|
||||
pushad
|
||||
call Start60HZ
|
||||
%ifdef __OPENGL__
|
||||
call drawscreenwin
|
||||
%endif
|
||||
call initwinvideo
|
||||
popad
|
||||
|
||||
mov al,[GrayscaleMode]
|
||||
cmp al,[V8Mode]
|
||||
je .nochangemode
|
||||
xor byte[V8Mode],1
|
||||
xor al,al
|
||||
.nochangemode
|
||||
|
||||
pushad
|
||||
call AdjustFrequency
|
||||
popad
|
||||
|
||||
pushad
|
||||
xor eax,eax
|
||||
mov edi,[vidbufferofsb]
|
||||
mov ecx,288*128
|
||||
rep stosd
|
||||
popad
|
||||
|
||||
pushad
|
||||
call clearwin
|
||||
popad
|
||||
ret
|
||||
|
||||
NEWSYM SetupPreGame ; Executes after pre-game init, can execute multiple
|
||||
; times after a single InitPreGame
|
||||
mov byte[pressed+1],2
|
||||
ret
|
||||
|
||||
|
||||
NEWSYM DeInitPostGame ; Called after game is ended
|
||||
pushad
|
||||
call Stop60HZ
|
||||
popad
|
||||
ret
|
||||
|
||||
; ****************************
|
||||
; Video Stuff
|
||||
; ****************************
|
||||
|
||||
; ** init video mode functions **
|
||||
SECTION .data
|
||||
NEWSYM firstvideo, dd 1
|
||||
SECTION .text
|
||||
|
||||
NEWSYM initvideo ; Returns 1 in videotroub if trouble occurs
|
||||
mov byte[res640],1
|
||||
mov byte[res480],1
|
||||
mov byte[cbitmode],1
|
||||
mov word[vesa2_x],512
|
||||
mov word[vesa2_y],480
|
||||
mov byte[vesa2_bits],16
|
||||
mov dword[vesa2_bits],16
|
||||
mov dword[vesa2_rpos],11
|
||||
mov dword[vesa2_gpos],5
|
||||
mov dword[vesa2_bpos],0
|
||||
mov byte[vesa2red10],0
|
||||
mov byte[vesa2_rposng],11
|
||||
mov byte[vesa2_gposng],5
|
||||
mov byte[vesa2_bposng],0
|
||||
mov dword[vesa2_clbitng],1111011111011110b
|
||||
mov dword[vesa2_clbitng2],11110111110111101111011111011110b
|
||||
mov dword[vesa2_clbitng2+4],11110111110111101111011111011110b
|
||||
mov dword[vesa2_clbitng3],0111101111101111b
|
||||
|
||||
pushad
|
||||
call initwinvideo
|
||||
popad
|
||||
|
||||
movzx eax,byte[cvidmode]
|
||||
cmp byte[GUIWFVID+eax],0
|
||||
je .prevwinmode
|
||||
mov [PrevFSMode],al
|
||||
jmp .doneprevmode
|
||||
.prevwinmode
|
||||
mov [PrevWinMode],al
|
||||
.doneprevmode
|
||||
|
||||
cmp dword[firstvideo],1
|
||||
je .skipinitgfx
|
||||
pushad
|
||||
call InitializeGfxStuff
|
||||
popad
|
||||
|
||||
.skipinitgfx
|
||||
mov dword[firstvideo],0
|
||||
|
||||
pushad
|
||||
call InitializeGfxStuff
|
||||
popad
|
||||
|
||||
ret
|
||||
|
||||
|
||||
NEWSYM deinitvideo
|
||||
ret
|
||||
|
||||
; ** copy video mode functions **
|
||||
SECTION .data
|
||||
NEWSYM converta, dd 0
|
||||
%ifdef __OPENGL__
|
||||
NEWSYM blinit, db 1
|
||||
%endif
|
||||
|
||||
SECTION .text
|
||||
NEWSYM DrawScreen ; In-game screen render w/ triple buffer check
|
||||
cmp dword[converta],1
|
||||
jne near .skipconv
|
||||
pushad
|
||||
mov dword[UnusedBit], 10000000000000001000000000000000b
|
||||
mov dword[HalfTrans], 01111011110111100111101111011110b
|
||||
mov dword[UnusedBitXor], 01111111111111110111111111111111b
|
||||
mov dword[UnusedBit+4], 10000000000000001000000000000000b
|
||||
mov dword[HalfTrans+4], 01111011110111100111101111011110b
|
||||
mov dword[UnusedBitXor+4],01111111111111110111111111111111b
|
||||
mov dword[HalfTransB], 00000100001000010000010000100001b
|
||||
mov dword[HalfTransB+4], 00000100001000010000010000100001b
|
||||
mov dword[HalfTransC], 01111011110111100111101111011110b
|
||||
mov dword[HalfTransC+4], 01111011110111100111101111011110b
|
||||
mov dword[ngrposng],10
|
||||
mov dword[nggposng],5
|
||||
mov dword[ngbposng],0
|
||||
|
||||
call ConvertToAFormat
|
||||
|
||||
popad
|
||||
|
||||
.skipconv
|
||||
pushad
|
||||
call drawscreenwin
|
||||
%ifdef __OPENGL__
|
||||
cmp byte[blinit],1
|
||||
jne .noreinit
|
||||
call initwinvideo
|
||||
call Clear2xSaIBuffer
|
||||
mov byte[blinit],0
|
||||
.noreinit
|
||||
%endif
|
||||
popad
|
||||
|
||||
ret
|
||||
|
||||
NEWSYM vidpastecopyscr ; GUI screen render
|
||||
pushad
|
||||
mov eax,[vidbuffer]
|
||||
mov ecx,224*288
|
||||
mov edx,ecx
|
||||
sub ecx,288
|
||||
dec edx
|
||||
.loop
|
||||
movzx ebx,byte[eax+edx]
|
||||
mov bx,[GUICPC+ebx*2]
|
||||
mov [eax+edx*2],bx
|
||||
dec edx
|
||||
dec ecx
|
||||
jnz .loop
|
||||
popad
|
||||
jmp DrawScreen
|
||||
|
||||
; ** Video Mode Variables **
|
||||
SECTION .data
|
||||
|
||||
; Total Number of Video Modes
|
||||
%ifdef __OPENGL__
|
||||
NEWSYM NumVideoModes, dd 23
|
||||
%else
|
||||
NEWSYM NumVideoModes, dd 5
|
||||
%endif
|
||||
|
||||
; GUI Video Mode Names - Make sure that all names are of the same length
|
||||
; and end with a NULL terminator
|
||||
NEWSYM GUIVideoModeNames
|
||||
db '256x224 R W',0 ;0
|
||||
db '256x224 R F',0 ;1
|
||||
db '512x448 DR W',0 ;2
|
||||
db '512x448 DR F',0 ;3
|
||||
db '640x480 DR F',0 ;4
|
||||
%ifdef __OPENGL__
|
||||
db '256x224 O R W',0 ;5
|
||||
db '512x448 ODR W',0 ;6
|
||||
db '640x480 ODS F',0 ;7
|
||||
db '640x480 ODS W',0 ;8
|
||||
db '640x560 ODR W',0 ;9
|
||||
db '768x672 ODR W',0 ;10
|
||||
db '800x600 ODS F',0 ;11
|
||||
db '800x600 ODS W',0 ;12
|
||||
db '896x784 ODR W',0 ;13
|
||||
db '1024x768 ODS F',0 ;14
|
||||
db '1024x768 ODS W',0 ;15
|
||||
db '1024x896 ODR W',0 ;16
|
||||
db '1280x960 ODS F',0 ;17
|
||||
db '1280x1024 ODS F',0 ;18
|
||||
db '1600x1200 ODS F',0 ;19
|
||||
db 'VARIABLE ODR W',0 ;20
|
||||
db 'VARIABLE ODS W',0 ;21
|
||||
db 'CUSTOM OD F',0 ;22
|
||||
%endif
|
||||
|
||||
; Video Mode Feature Availability (1 = Available, 0 = Not Available)
|
||||
; Left side starts with Video Mode 0
|
||||
; vid mode column = 0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2
|
||||
NEWSYM GUII2VID, db 0,0,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 ; Interpolation
|
||||
NEWSYM GUIWFVID, db 0,1,0,1,1,0,0,1,0,0,0,1,0,0,1,0,0,1,1,1,0,0,1 ; Fullscreen
|
||||
NEWSYM GUIDSIZE, db 0,0,1,1,1,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1 ; D Modes
|
||||
NEWSYM GUIKEEP43, db 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,1,1 ; Keep 4:3 Ratio
|
||||
NEWSYM GUIM7VID, db 0,0,1,1,1,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1 ; Hires Mode 7
|
||||
NEWSYM GUIHQ2X, db 0,0,1,1,1,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1 ; Hq2x Filter
|
||||
NEWSYM GUIHQ3X, db 0,0,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 ; (Hq3x Filter)
|
||||
NEWSYM GUIHQ4X, db 0,0,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 ; (Hq4x Filter)
|
||||
NEWSYM GUINTVID, db 0,0,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 ; NTSC Filter
|
||||
NEWSYM GUIRESIZE, db 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0 ; SDL Resizable
|
||||
%ifdef __OPENGL__
|
||||
NEWSYM GUIBIFIL, db 0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1 ; SDL Bilinear Filter
|
||||
%endif
|
||||
|
||||
SECTION .text
|
||||
|
||||
; ****************************
|
||||
; Input Device Stuff
|
||||
; ****************************
|
||||
|
||||
; Variables related to Input Device Routines:
|
||||
; pl1selk,pl1startk,pl1upk,pl1downk,pl1leftk,pl1rightk,pl1Xk,
|
||||
; pl1Ak,pl1Lk,pl1Yk,pl1Bk,pl1Rk
|
||||
; (Change 1 to 2,3,4 for other players)
|
||||
; Each of these variables contains the corresponding key pressed value
|
||||
; for the key data
|
||||
; pressed[]
|
||||
; - This is an array of pressed/released data (bytes) where the
|
||||
; corresponding key pressed value is used as the index. The value
|
||||
; for each entry is 0 for released and 1 for pressed. Also, when
|
||||
; writing keyboard data to this array, be sure to first check if
|
||||
; the value of the array entry is 2 or not. If it is 2, do not write 1
|
||||
; to that array entry. (however, you can write 0 to it)
|
||||
; As an example, to access Player 1 L button press data, it is
|
||||
; done like : pressed[pl1Lk]
|
||||
; The 3 character key description of that array entry is accessed by the
|
||||
; GUI through ScanCodeListing[pl1Lk*3]
|
||||
|
||||
; Note: When storing the input device configuration of a dynamic input
|
||||
; device system (ie. Win9x) rather than a static system (ie. Dos), it
|
||||
; is best to store in the name of the device and relative button
|
||||
; assignments in the configuration file, then convert it to ZSNES'
|
||||
; numerical corresponding key format after reading from it. And then
|
||||
; convert it back when writing to it back.
|
||||
|
||||
NEWSYM UpdateDevices ; One-time input device init
|
||||
ret
|
||||
|
||||
NEWSYM JoyRead
|
||||
pushad
|
||||
call UpdateVFrame
|
||||
popad
|
||||
ret
|
||||
|
||||
SECTION .data
|
||||
|
||||
; Total Number of Input Devices
|
||||
NEWSYM NumInputDevices, dd 2
|
||||
|
||||
; Input Device Names
|
||||
NEWSYM GUIInputNames
|
||||
db 'NONE ',0
|
||||
db 'KEYBOARD/GAMEPAD',0
|
||||
db ' ',0
|
||||
db ' ',0
|
||||
db ' ',0
|
||||
db ' ',0
|
||||
db ' ',0
|
||||
db ' ',0
|
||||
db ' ',0
|
||||
db ' ',0
|
||||
db ' ',0
|
||||
db ' ',0
|
||||
db ' ',0
|
||||
db ' ',0
|
||||
db ' ',0
|
||||
db ' ',0
|
||||
|
||||
; GUI Description codes for each corresponding key pressed value
|
||||
NEWSYM ScanCodeListing
|
||||
db '---','ESC',' 1 ',' 2 ',' 3 ',' 4 ',' 5 ',' 6 ' ; 00h
|
||||
db ' 7 ',' 8 ',' 9 ',' 0 ',' - ',' = ','BKS','TAB'
|
||||
db ' Q ',' W ',' E ',' R ',' T ',' Y ',' U ',' I ' ; 10h
|
||||
db ' O ',' P ',' [ ',' ] ','RET','LCT',' A ',' S '
|
||||
db ' D ',' F ',' G ',' H ',' J ',' K ',' L ',' : ' ; 20h
|
||||
db ' " ',' ~ ','LSH',' \ ',' Z ',' X ',' C ',' V '
|
||||
db ' B ',' N ',' M ',' , ',' . ',' / ','RSH',' * ' ; 30h
|
||||
db 'LAL','SPC','CAP','F1 ','F2 ','F3 ','F4 ','F5 '
|
||||
db 'F6 ','F7 ','F8 ','F9 ','F10','NUM','SCR','KP7' ; 40h
|
||||
db 'KP8','KP9','KP-','KP4','KP5','KP6','KP+','KP1'
|
||||
db 'KP2','KP3','KP0','KP.',' ',' ','OEM','F11' ; 50h
|
||||
db 'F12','HOM','UP ','PGU','LFT','5DH','RGT','END'
|
||||
db 'DWN','PGD','INS','DEL','64H','65H','66H','67H' ; 60h
|
||||
db '68H','69H','6AH','6BH','6CH','6DH','6EH','6FH'
|
||||
db '70H','71H','72H','73H','74H','75H','76H','77H' ; 70h
|
||||
db '78H','79H','7AH','7BH','7CH','7DH','7EH','7FH'
|
||||
; Keyboard continued (Direct Input)
|
||||
db '80H','81H','82H','83H','84H','85H','86H','87H' ; 80h
|
||||
db '88H','89H','8AH','8BH','8CH','8DH','8EH','8FH'
|
||||
db '90H','91H','92H','93H','94H','95H','96H','97H' ; 90h
|
||||
db '98H','99H','9AH','9BH','9CH','9DH','9EH','9FH'
|
||||
db 'A0H','A1H','A2H','A3H','A4H','A5H','A6H','A7H' ; A0h
|
||||
db 'A8H','A9H','AAH','ABH','ACH','ADH','AEH','AFH'
|
||||
db 'B0H','B1H','B2H','B3H','B4H','B5H','B6H','B7H' ; B0h
|
||||
db 'B8H','B9H','BAH','BBH','BCH','BDH','BEH','BFH'
|
||||
db 'C0H','C1H','C2H','C3H','C4H','C5H','C6H','C7H' ; C0h
|
||||
db 'C8H','C9H','CAH','CBH','CCH','CDH','CEH','CFH'
|
||||
db 'D0H','D1H','D2H','D3H','D4H','D5H','D6H','D7H' ; D0h
|
||||
db 'D8H','D9H','DAH','DBH','DCH','DDH','DEH','DFH'
|
||||
db 'E0H','E1H','E2H','E3H','E4H','E5H','E6H','E7H' ; E0h
|
||||
db 'E8H','E9H','EAH','EBH','ECH','EDH','EEH','EFH'
|
||||
db 'F0H','F1H','F2H','F3H','F4H','F5H','F6H','F7H' ; F0h
|
||||
db 'F8H','F9H','FAH','FBH','FCH','FDH','FEH','FFH'
|
||||
; Joystick Stuff
|
||||
db 'J00','J01','J02','J03','J04','J05','J06','J07' ; 100h
|
||||
db 'J08','J09','J0A','J0B','J0C','J0D','J0E','J0F'
|
||||
db 'J10','J11','J12','J13','J14','J15','J16','J17' ; 110h
|
||||
db 'J18','J19','J1A','J1B','J1C','J1D','J1E','J1F'
|
||||
db 'J20','J21','J22','J23','J24','J25','J26','J27' ; 120h
|
||||
db 'J28','J29','J2A','J2B','J2C','J2D','J2E','J2F'
|
||||
db 'J30','J31','J32','J33','J34','J35','J36','J37' ; 130h
|
||||
db 'J38','J39','J3A','J3B','J3C','J3D','J3E','J3F'
|
||||
db 'J40','J41','J42','J43','J44','J45','J46','J47' ; 140h
|
||||
db 'J48','J49','J4A','J4B','J4C','J4D','J4E','J4F'
|
||||
db 'J50','J51','J52','J53','J54','J55','J56','J57' ; 150h
|
||||
db 'J58','J59','J5A','J5B','J5C','J5D','J5E','J5F'
|
||||
db 'J60','J61','J62','J63','J64','J65','J66','J67' ; 160h
|
||||
db 'J68','J69','J6A','J6B','J6C','J6D','J6E','J6F'
|
||||
db 'J70','J71','J72','J73','J74','J75','J76','J77' ; 170h
|
||||
db 'J78','J79','J7A','J7B','J7C','J7D','J7E','J7F'
|
||||
%ifdef __UNIXSDL__
|
||||
; Extra Joystick Stuff
|
||||
db 'J80','J81','J82','J83','J84','J85','J86','J87' ; 180h
|
||||
db 'J88','J89','J8A','J8B','J8C','J8D','J8E','J8F'
|
||||
db 'J90','J91','J92','J93','J94','J95','J96','J97' ; 190h
|
||||
db 'J98','J99','J9A','J9B','J9C','J9D','J9E','J9F'
|
||||
db 'JA0','JA1','JA2','JA3','JA4','JA5','JA6','JA7' ; 2A0h
|
||||
db 'JA8','JA9','JAA','JAB','JAC','JAD','JAE','JAF'
|
||||
db 'JB0','JB1','JB2','JB3','JB4','JB5','JB6','JB7' ; 2B0h
|
||||
db 'JB8','JB9','JBA','JBB','JBC','JBD','JBE','JBF'
|
||||
%else
|
||||
; Extra Stuff (180h) (Parallel Port)
|
||||
db 'PPB','PPY','PSL','PST','PUP','PDN','PLT','PRT' ; 180h
|
||||
db 'PPA','PPX','PPL','PPR',' ',' ',' ',' '
|
||||
db 'P2B','P2Y','P2S','P2T','P2U','P2D','P2L','P2R' ; 190h
|
||||
db 'P2A','P2X','P2L','P2R',' ',' ',' ',' '
|
||||
db 'PPB','PPY','PSL','PST','PUP','PDN','PLT','PRT' ; 2A0h
|
||||
db 'PPA','PPX','PPL','PPR',' ',' ',' ',' '
|
||||
db 'P2B','P2Y','P2S','P2T','P2U','P2D','P2L','P2R' ; 2B0h
|
||||
db 'P2A','P2X','P2L','P2R',' ',' ',' ',' '
|
||||
%endif
|
||||
|
||||
SECTION .text
|
||||
|
||||
; ****************************
|
||||
; Mouse Stuff
|
||||
; ****************************
|
||||
|
||||
NEWSYM Init_Mouse
|
||||
; return non-zero if successful
|
||||
mov eax,01h
|
||||
ret
|
||||
|
||||
SECTION .data
|
||||
NEWSYM WMouseX, dd 0
|
||||
NEWSYM WMouseY, dd 0
|
||||
NEWSYM WMouseMoveX, dd 0
|
||||
NEWSYM WMouseMoveY, dd 0
|
||||
NEWSYM WMouseButton, dd 0
|
||||
|
||||
SECTION .text
|
||||
NEWSYM Get_MouseData ; Returns both pressed and coordinates
|
||||
; bx : bit 0 = left button, bit 1 = right button
|
||||
; cx = Mouse X Position, dx = Mouse Y Position
|
||||
pushad
|
||||
call GetMouseX
|
||||
mov [WMouseX],eax
|
||||
call GetMouseY
|
||||
mov [WMouseY],eax
|
||||
call GetMouseButton
|
||||
mov [WMouseButton],eax
|
||||
popad
|
||||
mov cx,[WMouseX]
|
||||
mov dx,[WMouseY]
|
||||
mov bx,[WMouseButton]
|
||||
ret
|
||||
|
||||
NEWSYM Set_MouseXMax
|
||||
ret
|
||||
|
||||
NEWSYM Set_MouseYMax
|
||||
ret
|
||||
|
||||
NEWSYM Set_MousePosition
|
||||
ret
|
||||
|
||||
NEWSYM Get_MousePositionDisplacement
|
||||
; returns x,y displacement in pixel in cx,dx
|
||||
pushad
|
||||
call GetMouseMoveX
|
||||
mov [WMouseMoveX],eax
|
||||
call GetMouseMoveY
|
||||
mov [WMouseMoveY],eax
|
||||
popad
|
||||
mov cx,[WMouseMoveX]
|
||||
mov dx,[WMouseMoveY]
|
||||
ret
|
||||
|
||||
|
||||
NEWSYM MouseWindow
|
||||
pushad
|
||||
or byte[MouseButton],2
|
||||
mov byte[T36HZEnabled],1
|
||||
call GetMouseButton
|
||||
and byte[MouseButton],0FDh
|
||||
popad
|
||||
ret
|
||||
|
||||
NEWSYM GUIInit
|
||||
pushad
|
||||
call Start36HZ
|
||||
popad
|
||||
ret
|
||||
|
||||
NEWSYM GUIDeInit
|
||||
pushad
|
||||
call Stop36HZ
|
||||
popad
|
||||
ret
|
||||
|
||||
; ****************************
|
||||
; Sound Stuff
|
||||
; ****************************
|
||||
|
||||
NEWSYM StopSound
|
||||
call Start36HZ
|
||||
call JoyRead
|
||||
ret
|
||||
|
||||
NEWSYM StartSound
|
||||
call Start60HZ
|
||||
call JoyRead
|
||||
ret
|
||||
|
||||
NEWSYM delay
|
||||
ret
|
||||
|
||||
NEWSYM Check60hz
|
||||
; Call the timer update function here
|
||||
pushad
|
||||
call CheckTimers
|
||||
call sem_sleep
|
||||
popad
|
||||
ret
|
||||
|
||||
SECTION .data
|
||||
BitPosR db 11
|
||||
BitPosG db 5
|
||||
BitPosB db 0
|
||||
BitSizeR db 5
|
||||
BitSizeG db 6
|
||||
BitSizeB db 5
|
||||
SECTION .text
|
||||
|
||||
InitializeGfxStuff:
|
||||
; Process Red Stuff
|
||||
mov al,[BitPosR]
|
||||
mov cl,al
|
||||
mov bx,1
|
||||
shl bx,cl
|
||||
cmp byte[BitSizeR],6
|
||||
jne .no6bit
|
||||
mov [vesa2_usbit],bx
|
||||
inc al
|
||||
.no6bit
|
||||
or [vesa2_clbit],bx
|
||||
mov [vesa2_rpos],al
|
||||
dec al
|
||||
mov cl,al
|
||||
mov bx,001Fh
|
||||
cmp cl,0FFh
|
||||
je .shrr
|
||||
shl bx,cl
|
||||
jmp .shlr
|
||||
.shrr
|
||||
shr bx,1
|
||||
.shlr
|
||||
mov [vesa2_rfull],bx
|
||||
add al,5
|
||||
mov bx,1
|
||||
mov cl,al
|
||||
shl bx,cl
|
||||
mov [vesa2_rtrcl],bx
|
||||
xor bx,0FFFFh
|
||||
mov [vesa2_rtrcla],bx
|
||||
|
||||
; Process Green Stuff
|
||||
mov al,[BitPosG]
|
||||
mov cl,al
|
||||
mov bx,1
|
||||
shl bx,cl
|
||||
cmp byte[BitSizeG],6
|
||||
jne .no6bitb
|
||||
mov [vesa2_usbit],bx
|
||||
inc al
|
||||
.no6bitb
|
||||
or [vesa2_clbit],bx
|
||||
mov [vesa2_gpos],al
|
||||
dec al
|
||||
mov cl,al
|
||||
mov bx,001Fh
|
||||
cmp cl,0FFh
|
||||
je .shrg
|
||||
shl bx,cl
|
||||
jmp .shlg
|
||||
.shrg
|
||||
shr bx,1
|
||||
.shlg
|
||||
mov [vesa2_gfull],bx
|
||||
add al,5
|
||||
mov bx,1
|
||||
mov cl,al
|
||||
shl bx,cl
|
||||
mov [vesa2_gtrcl],bx
|
||||
xor bx,0FFFFh
|
||||
mov [vesa2_gtrcla],bx
|
||||
|
||||
; Process Blue Stuff
|
||||
mov al,[BitPosB]
|
||||
mov cl,al
|
||||
mov bx,1
|
||||
shl bx,cl
|
||||
cmp byte[BitSizeB],6
|
||||
jne .no6bitc
|
||||
mov [vesa2_usbit],bx
|
||||
inc al
|
||||
.no6bitc
|
||||
or [vesa2_clbit],bx
|
||||
mov [vesa2_bpos],al
|
||||
dec al
|
||||
mov cl,al
|
||||
mov bx,001Fh
|
||||
cmp cl,0FFh
|
||||
je .shrb
|
||||
shl bx,cl
|
||||
jmp .shlb
|
||||
.shrb
|
||||
shr bx,1
|
||||
.shlb
|
||||
mov [vesa2_bfull],bx
|
||||
add al,5
|
||||
mov bx,1
|
||||
mov cl,al
|
||||
shl bx,cl
|
||||
mov [vesa2_btrcl],bx
|
||||
xor bx,0FFFFh
|
||||
mov [vesa2_btrcla],bx
|
||||
|
||||
xor word[vesa2_clbit],0FFFFh
|
||||
call genfulladdtab
|
||||
cmp byte[converta],1
|
||||
je .red10
|
||||
mov eax,565
|
||||
jmp .red11
|
||||
.red10
|
||||
mov eax,555
|
||||
.red11
|
||||
push eax
|
||||
call Init_2xSaIMMXW
|
||||
pop eax
|
||||
|
||||
ret
|
||||
|
||||
%macro SetDefaultKey2 13
|
||||
mov dword[%1upk],%4 ; Up
|
||||
mov dword[%1downk],%5 ; Down
|
||||
mov dword[%1leftk],%6 ; Left
|
||||
mov dword[%1rightk],%7 ; Right
|
||||
mov dword[%1startk],%3 ; Start
|
||||
mov dword[%1selk],%2 ; Select
|
||||
mov dword[%1Ak],%9 ; A
|
||||
mov dword[%1Bk],%12 ; B
|
||||
mov dword[%1Xk],%8 ; X
|
||||
mov dword[%1Yk],%11 ; Y
|
||||
mov dword[%1Lk],%10 ; L
|
||||
mov dword[%1Rk],%13 ; R
|
||||
%endmacro
|
||||
|
||||
%macro SetDefaultKey 12
|
||||
cmp bh,0
|
||||
jne %%nopl1
|
||||
SetDefaultKey2 pl1,%1,%2,%3,%4,%5,%6,%7,%8,%9,%10,%11,%12
|
||||
%%nopl1
|
||||
cmp bh,1
|
||||
jne %%nopl2
|
||||
SetDefaultKey2 pl2,%1,%2,%3,%4,%5,%6,%7,%8,%9,%10,%11,%12
|
||||
%%nopl2
|
||||
cmp bh,2
|
||||
jne %%nopl3
|
||||
SetDefaultKey2 pl3,%1,%2,%3,%4,%5,%6,%7,%8,%9,%10,%11,%12
|
||||
%%nopl3
|
||||
cmp bh,3
|
||||
jne %%nopl4
|
||||
SetDefaultKey2 pl4,%1,%2,%3,%4,%5,%6,%7,%8,%9,%10,%11,%12
|
||||
%%nopl4
|
||||
cmp bh,4
|
||||
jne %%nopl5
|
||||
SetDefaultKey2 pl5,%1,%2,%3,%4,%5,%6,%7,%8,%9,%10,%11,%12
|
||||
%%nopl5
|
||||
%endmacro
|
||||
|
||||
NEWSYM SetInputDevice
|
||||
; bl = device #, bh = player # (0-4)
|
||||
; Sets keys according to input device selected
|
||||
cmp bl,0
|
||||
jne near .nozero
|
||||
SetDefaultKey 0,0,0,0,0,0,0,0,0,0,0,0
|
||||
ret
|
||||
.nozero
|
||||
cmp bh,1
|
||||
je near .input2
|
||||
%ifdef __UNIXSDL__
|
||||
SetDefaultKey 54,28,90,96,92,94,31,45,32,30,44,46
|
||||
%else
|
||||
SetDefaultKey 54,28,200,208,203,205,31,45,32,30,44,46
|
||||
%endif
|
||||
ret
|
||||
.input2
|
||||
%ifdef __UNIXSDL__
|
||||
SetDefaultKey 56,29,36,50,49,51,98,89,91,99,95,97
|
||||
%else
|
||||
SetDefaultKey 56,29,36,50,49,51,210,199,201,211,207,209
|
||||
%endif
|
||||
ret
|
||||
|
||||
1351
tools/zsnes/src/linux/sdllink.c
Normal file
1351
tools/zsnes/src/linux/sdllink.c
Normal file
File diff suppressed because it is too large
Load Diff
21
tools/zsnes/src/linux/sockserv.c
Normal file
21
tools/zsnes/src/linux/sockserv.c
Normal file
@@ -0,0 +1,21 @@
|
||||
/*
|
||||
Copyright (C) 1997-2007 ZSNES Team ( zsKnight, _Demo_, pagefault, Nach )
|
||||
|
||||
http://www.zsnes.com
|
||||
http://sourceforge.net/projects/zsnes
|
||||
https://zsnes.bountysource.com
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License
|
||||
version 2 as published by the Free Software Foundation.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
21
tools/zsnes/src/linux/sockserv.h
Normal file
21
tools/zsnes/src/linux/sockserv.h
Normal file
@@ -0,0 +1,21 @@
|
||||
/*
|
||||
Copyright (C) 1997-2007 ZSNES Team ( zsKnight, _Demo_, pagefault, Nach )
|
||||
|
||||
http://www.zsnes.com
|
||||
http://sourceforge.net/projects/zsnes
|
||||
https://zsnes.bountysource.com
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License
|
||||
version 2 as published by the Free Software Foundation.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
237
tools/zsnes/src/linux/sw_draw.c
Normal file
237
tools/zsnes/src/linux/sw_draw.c
Normal file
@@ -0,0 +1,237 @@
|
||||
/*
|
||||
Copyright (C) 1997-2007 ZSNES Team ( zsKnight, _Demo_, pagefault, Nach )
|
||||
|
||||
http://www.zsnes.com
|
||||
http://sourceforge.net/projects/zsnes
|
||||
https://zsnes.bountysource.com
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License
|
||||
version 2 as published by the Free Software Foundation.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
|
||||
#include "../gblhdr.h"
|
||||
#include "../cfg.h"
|
||||
#include "../asm_call.h"
|
||||
|
||||
|
||||
#define BYTE unsigned char
|
||||
#define WORD unsigned short
|
||||
#define DWORD unsigned long
|
||||
|
||||
//C++ style code in C
|
||||
#define bool unsigned char
|
||||
#define true 1
|
||||
#define false 0
|
||||
|
||||
void CheckFrame();
|
||||
// VIDEO VARIABLES
|
||||
extern SDL_Surface *surface;
|
||||
extern int SurfaceX, SurfaceY;
|
||||
extern int SurfaceLocking;
|
||||
|
||||
extern unsigned int vidbuffer;
|
||||
extern DWORD converta;
|
||||
extern unsigned char curblank;
|
||||
extern int frametot;
|
||||
extern BYTE GUIOn,GUIOn2;
|
||||
|
||||
void UpdateVFrame(void);
|
||||
void NTSCFilterInit();
|
||||
void NTSCFilterDraw(int SurfaceX, int SurfaceY, int pitch, unsigned char * buffer);
|
||||
|
||||
bool OGLModeCheck();
|
||||
void initwinvideo();
|
||||
|
||||
bool sw_start(int width, int height, int req_depth, int FullScreen)
|
||||
{
|
||||
//unsigned int color32, p;
|
||||
//int i;
|
||||
#ifndef __MACOSX__
|
||||
Uint32 flags = SDL_DOUBLEBUF | SDL_HWSURFACE;
|
||||
#else
|
||||
Uint32 flags = SDL_SWSURFACE;
|
||||
#endif
|
||||
DWORD GBitMask;
|
||||
|
||||
flags |= (FullScreen ? SDL_FULLSCREEN : 0);
|
||||
|
||||
if (NTSCFilter) NTSCFilterInit();
|
||||
|
||||
SurfaceX = width; SurfaceY = height;
|
||||
surface = SDL_SetVideoMode(SurfaceX, SurfaceY, req_depth, flags);
|
||||
if (surface == NULL) {
|
||||
fprintf (stderr, "Could not set %dx%d video mode: %s\n", SurfaceX, SurfaceY, SDL_GetError ());
|
||||
return false;
|
||||
}
|
||||
|
||||
SurfaceLocking = SDL_MUSTLOCK(surface);
|
||||
SDL_WarpMouse(SurfaceX/4,SurfaceY/4);
|
||||
|
||||
// Grab mouse in fullscreen mode
|
||||
FullScreen ? SDL_WM_GrabInput(SDL_GRAB_ON) : SDL_WM_GrabInput(SDL_GRAB_OFF);
|
||||
|
||||
SDL_WM_SetCaption ("ZSNES","ZSNES");
|
||||
SDL_ShowCursor(0);
|
||||
|
||||
// Check hardware for 565/555
|
||||
GBitMask = surface->format->Gmask;
|
||||
if(GBitMask != 0x07E0) converta = 1;
|
||||
else converta = 0;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void sw_end() {
|
||||
// Do nothing
|
||||
}
|
||||
|
||||
static void LockSurface(void)
|
||||
{
|
||||
if (SurfaceLocking) SDL_LockSurface(surface);
|
||||
}
|
||||
|
||||
static void UnlockSurface(void)
|
||||
{
|
||||
if (SurfaceLocking) SDL_UnlockSurface(surface);
|
||||
SDL_Flip(surface);
|
||||
}
|
||||
|
||||
extern DWORD AddEndBytes;
|
||||
extern DWORD NumBytesPerLine;
|
||||
extern unsigned char *WinVidMemStart;
|
||||
extern unsigned char NGNoTransp;
|
||||
extern unsigned short resolutn;
|
||||
void copy640x480x16bwin(void);
|
||||
void hq2x_16b(void);
|
||||
void hq3x_16b(void);
|
||||
void hq4x_16b(void);
|
||||
void ClearWin16 (void);
|
||||
void DrawWin256x224x16(void);
|
||||
void DrawWin320x240x16(void);
|
||||
DWORD ScreenPtr;
|
||||
DWORD SurfBufD;
|
||||
DWORD pitch;
|
||||
|
||||
void sw_clearwin()
|
||||
{
|
||||
pitch = surface->pitch;
|
||||
SurfBufD = (DWORD) surface->pixels;
|
||||
|
||||
LockSurface();
|
||||
ClearWin16();
|
||||
UnlockSurface();
|
||||
}
|
||||
|
||||
extern unsigned char prevNTSCMode;
|
||||
extern unsigned char changeRes;
|
||||
extern unsigned char prevKeep4_3Ratio;
|
||||
|
||||
void sw_drawwin()
|
||||
{
|
||||
NGNoTransp = 0; // Set this value to 1 within the appropriate
|
||||
// video mode if you want to add a custom
|
||||
// transparency routine or hardware
|
||||
// transparency. This only works if
|
||||
// the value of newengen is equal to 1.
|
||||
// (see ProcessTransparencies in newgfx16.asm
|
||||
// for ZSNES' current transparency code)
|
||||
|
||||
|
||||
UpdateVFrame();
|
||||
|
||||
if (curblank || OGLModeCheck()) return;
|
||||
LockSurface();
|
||||
|
||||
if (NTSCFilter != prevNTSCMode) initwinvideo();
|
||||
|
||||
if (changeRes) initwinvideo();
|
||||
|
||||
if (prevKeep4_3Ratio != Keep4_3Ratio) initwinvideo();
|
||||
|
||||
ScreenPtr = vidbuffer;
|
||||
ScreenPtr += 16*2+32*2+256*2;
|
||||
|
||||
if (resolutn == 239) ScreenPtr+=8*288*2;
|
||||
|
||||
pitch = surface->pitch;
|
||||
SurfBufD = (DWORD) surface->pixels;
|
||||
|
||||
if (SurfBufD == 0) {
|
||||
UnlockSurface();
|
||||
return;
|
||||
}
|
||||
|
||||
if (SurfaceX == 256 && SurfaceY == 224) DrawWin256x224x16();
|
||||
else if (SurfaceX == 320 && SurfaceY == 240) DrawWin320x240x16();
|
||||
else if((SurfaceX == 512 && SurfaceY == 448))
|
||||
{
|
||||
AddEndBytes = pitch-1024;
|
||||
NumBytesPerLine = pitch;
|
||||
WinVidMemStart = (void*)SurfBufD;
|
||||
|
||||
if (hqFilter)
|
||||
{
|
||||
switch (hqFilter)
|
||||
{
|
||||
case 1:
|
||||
hq2x_16b();
|
||||
break;
|
||||
case 2:
|
||||
//hq3x_16b();
|
||||
break;
|
||||
case 3:
|
||||
//hq4x_16b();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
else asm_call(copy640x480x16bwin);
|
||||
}
|
||||
else if ((SurfaceX == 602) && NTSCFilter)
|
||||
{
|
||||
AddEndBytes = pitch-1024;
|
||||
NumBytesPerLine = pitch;
|
||||
WinVidMemStart = (void*)SurfBufD;
|
||||
|
||||
NTSCFilterDraw(SurfaceX, SurfaceY, pitch, WinVidMemStart);
|
||||
}
|
||||
|
||||
else if (SurfaceX == 640 && SurfaceY == 480)
|
||||
{
|
||||
AddEndBytes = pitch-1024;
|
||||
NumBytesPerLine = pitch;
|
||||
WinVidMemStart = (void*) (SurfBufD + 16*640*2 + 64*2);
|
||||
if (hqFilter)
|
||||
{
|
||||
switch (hqFilter)
|
||||
{
|
||||
case 1:
|
||||
hq2x_16b();
|
||||
break;
|
||||
case 2:
|
||||
//hq3x_16b();
|
||||
break;
|
||||
case 3:
|
||||
//hq4x_16b();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (NTSCFilter) NTSCFilterDraw(SurfaceX, SurfaceY, pitch, WinVidMemStart-16*640*2-64*2); else asm_call(copy640x480x16bwin);
|
||||
}
|
||||
|
||||
UnlockSurface();
|
||||
}
|
||||
33
tools/zsnes/src/linux/sw_draw.h
Normal file
33
tools/zsnes/src/linux/sw_draw.h
Normal file
@@ -0,0 +1,33 @@
|
||||
/*
|
||||
Copyright (C) 1997-2007 ZSNES Team ( zsKnight, _Demo_, pagefault, Nach )
|
||||
|
||||
http://www.zsnes.com
|
||||
http://sourceforge.net/projects/zsnes
|
||||
https://zsnes.bountysource.com
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License
|
||||
version 2 as published by the Free Software Foundation.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef SW_DRAW_h
|
||||
#define SW_DRAW_h 1
|
||||
|
||||
int sw_start(int width, int height, int req_depth, int FullScreen);
|
||||
void sw_end();
|
||||
void sw_clearwin();
|
||||
void sw_drawwin();
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
215
tools/zsnes/src/linux/zsnes.1
Normal file
215
tools/zsnes/src/linux/zsnes.1
Normal file
@@ -0,0 +1,215 @@
|
||||
.TH "ZSNES v1.51" 1
|
||||
|
||||
.SH NAME
|
||||
ZSNES - Super Nintendo console emulator
|
||||
.SH SYNOPSIS
|
||||
.B ZSNES
|
||||
[-?] [-1 #] [-2 #] [-dd] [-dh] [-f #] [-g #] [-h | -l] [-j] [-js #] [-k #] [-m] [-mc] [-md] [-ml #] [-n #] [-o] [-p #] [-r #] [-s] [-sa] [-t | -u] [-v #] [-y] [-z] [-zm #] [-zs #] [romname]
|
||||
|
||||
.SH DESCRIPTION
|
||||
.B ZSNES
|
||||
is an emulator for the Super Nintendo video game console. It is written in a combination of x86 assembly, C, C++, and PSR. It is currently available on Windows, DOS, x86 Linux, x86 Mac OS X, and x86 BSD.
|
||||
|
||||
Visit http://www.zsnes.com/ for the latest updates.
|
||||
|
||||
.SH OPTIONS
|
||||
Note: Many of these options can also be set in the GUI.
|
||||
.TP
|
||||
.B -?
|
||||
Display command-line help
|
||||
.TP
|
||||
.B -1 # / -2 #
|
||||
Set controls for Player 1/2
|
||||
.nf
|
||||
\fI0\fP = None \fI1\fP = Keyboard/Gamepad
|
||||
.fi
|
||||
.TP
|
||||
.B -dd
|
||||
Disable sound DSP emulation
|
||||
.TP
|
||||
.B -dh
|
||||
Disable game hacks
|
||||
.TP
|
||||
.B -f #
|
||||
Enable frame skipping, where \fB#\fP is a numerical value from \fI0-9\fP
|
||||
.TP
|
||||
.B -g #
|
||||
Specify gamma correction value, where \fB#\fP is a numerical value from \fI0-15\fP
|
||||
.TP
|
||||
.B -h
|
||||
Force HiROM. Cannot be used with \fB-l\fP
|
||||
.TP
|
||||
.B -j
|
||||
Disable Mouse (Automatically turns off right mouse click)
|
||||
.TP
|
||||
.B -js #
|
||||
Adjust joystick sensitivity, where \fB#\fP is a numerical value from \fI0-32767\fP
|
||||
.TP
|
||||
.B -k #
|
||||
Set volume level, where \fB#\fP is a numerical value from \fI1-100\fP
|
||||
.TP
|
||||
.B -l
|
||||
Force LoROM. Cannot be used with \fB-h\fP
|
||||
.TP
|
||||
.B -m
|
||||
Disable GUI (Must specify ROM filename)
|
||||
.TP
|
||||
.B -mc
|
||||
Exit ZSNES when closing a movie (use with \fB-zm\fP)
|
||||
.TP
|
||||
.B -md
|
||||
Dump raw video (use with \fB-zm\fP)
|
||||
.TP
|
||||
.B -ml
|
||||
Define movie dump length in amount of frames (use with \fB-md\fP)
|
||||
.TP
|
||||
.B -n #
|
||||
Enable scanlines (when available), where
|
||||
.B #
|
||||
is one of:
|
||||
.nf
|
||||
\fl0\fP = none \fI1\fP = full \fI2\fP = 25%
|
||||
\fI3\fP = 50%
|
||||
.fi
|
||||
.TP
|
||||
.B -o
|
||||
Disable MMX support
|
||||
.TP
|
||||
.B -p #
|
||||
Change the clock speed of the main CPU, where
|
||||
.B #
|
||||
is a numerical value from \fI50-150\fP. 100 is the normal speed. Changing this value may have adverse side effects.
|
||||
.TP
|
||||
.B -r #
|
||||
Set audio sampling rate, where
|
||||
.B #
|
||||
is one of:
|
||||
.nf
|
||||
\fI0\fP = 8 KHz \fI1\fP = 11.025 KHz \fI2\fP = 22.05 KHz
|
||||
\fI3\fP = 44.1 KHz \fI4\fP = 16 KHz \fI5\fP = 32 KHz
|
||||
\fI6\fP = 48 KHz
|
||||
.fi
|
||||
.TP
|
||||
.B -s
|
||||
Enable SPC700/DSP emulation (Sound)
|
||||
.TP
|
||||
.B -sa
|
||||
Show files with all extensions (*.*) in GUI. Default is to only show files with one of the extensions listed in
|
||||
.B romname
|
||||
.TP
|
||||
.B -t
|
||||
Force NTSC (60 Hz) timing. Cannot be used with \fB-u\fP
|
||||
.TP
|
||||
.B -u
|
||||
Force PAL (50 Hz) timing. Cannot be used with \fB-t\fP
|
||||
.TP
|
||||
.B -v #
|
||||
Select video mode, where
|
||||
.B #
|
||||
is one of:
|
||||
.nf
|
||||
\fI0\fP = 256x224 R W \fI1\fP = 256x224 R F \fI2\fP = 512x448 DR W
|
||||
\fI3\fP = 512x448 DR F \fI4\fP = 640x480 DR F \fI5\fP = 256x224 OR W
|
||||
\fI6\fP = 512x448 ODR \fI7\fP = 640x480 ODS F \fI8\fP = 640x480 ODS W
|
||||
\fI9\fP = 640x560 ODR W \fI10\fP = 768x672 ODR W \fI11\fP = 800x600 ODS F
|
||||
\fI12\fP = 800x600 ODS W \fI13\fP = 896x784 ODR W \fI14\fP = 1024x768 ODS F
|
||||
\fI15\fP = 1024x768 ODS W \fI16\fP = 1024x896 ODR W \fI17\fP = 1280x960 ODS F
|
||||
\fI18\fP = 1280x1024 ODS F \fI19\fP = 1600x1200 ODS F \fI20\fP = VARIABLE ODR W
|
||||
\fI21\fP = VARIABLE ODS W \fI22\fP = CUSTOM OD F
|
||||
.fi
|
||||
.TP
|
||||
.B -y
|
||||
Enable Interpolation
|
||||
.TP
|
||||
.B -z
|
||||
Disable stereo sound. Stereo sound is enabled by default
|
||||
.TP
|
||||
.B -zm #
|
||||
Auto load specified movie on startup, where \fB#\fP is a numerical value from \fI0-9\fP
|
||||
.TP
|
||||
.B -zs #
|
||||
Auto load specified save state on startup, where \fB#\fP is a numerical value from \fI0-99\fP
|
||||
.TP
|
||||
.B romname
|
||||
Name of ROM to auto-load
|
||||
.B romname
|
||||
is of the format \fBfilename.ext\fP, where
|
||||
.B .ext
|
||||
is one of
|
||||
SMC, SFC, SWC, FIG, MGD, MGH, UFO, BIN, GD3, GD7, USA, EUR, JAP, AUS, ST, BS, DX2, 048, 058, 078, 1 or A. You can also load ROMs which have been compressed with GZip, Zip or JMA.
|
||||
|
||||
|
||||
.SH "FILES AND DIRECTORIES"
|
||||
.TP
|
||||
ZSNES
|
||||
The main program.
|
||||
.TP
|
||||
~/.zsnes
|
||||
This is the directory where ZSNES configuration files are stored. By default, it is also the directory where save states, screenshots, SPC dumps and ZMV movie files are stored, but you can change this behaviour by editing zsnesl.cfg. This directory is created by ZSNES.
|
||||
.TP
|
||||
~/.zsnes/zsnesl.cfg
|
||||
This file is where configuration settings for ZSNES are stored. It is in a human-readable format and can be edited by hand. It is created by ZSNES.
|
||||
.TP
|
||||
~/.zsnes/zmovie.cfg
|
||||
This file is where settings specific to AVI dumping are saved. It is created by ZSNES.
|
||||
.TP
|
||||
~/.zsnes/zfont.txt
|
||||
This file allows you to customize the fonts in the GUI. Enable "Use Custom Font" in the GUI Options menu. It is created by ZSNES.
|
||||
.TP
|
||||
~/.zsnes/zinput.cfg
|
||||
This file is where input configuration settings for ZSNES are stored.
|
||||
|
||||
.B If for some reason you update your version of ZSNES and it keeps crashing before you can do anything, you should try deleting the above .cfg files and let ZSNES create new ones.
|
||||
|
||||
.SH "SPECIAL CHIP GAMES"
|
||||
Many games on the Super Nintendo used custom CPUs in addition to the main SNES CPU. Some of these CPUs have not been fully reverse-engineered, and games that use them may either not work or may experience strange bugs.
|
||||
|
||||
You can find more information about these special CPUs at:
|
||||
|
||||
http://users.tpg.com.au/advlink/dsp/
|
||||
|
||||
http://nsrt.edgeemu.com/INFO/chipinfo.htm
|
||||
|
||||
|
||||
.SH "GRAPHICS PACKS"
|
||||
Some games based on the SPC7110 chip, such as Far East of Eden Zero, can use special graphics packs to work around unemulated portions of their custom CPU. These graphics packs must be stored in individual directories within the save directory, which is specified in zsnesl.cfg. By default, this is ~/.zsnes. The directory name of each graphics pack must be capitalized and all files within that directory must be in lowercase.
|
||||
|
||||
The proper directory name for a given graphics pack can be found in the readme file included with that pack.
|
||||
|
||||
NOTE: As of version 1.40, games which use the S-DD1 chip (Star Ocean and Street Fighter Alpha 2) do not require graphics packs.
|
||||
|
||||
.SH "REPORTING BUGS"
|
||||
You can report bugs using the bug tracker at the ZSNES BountySource page, located at
|
||||
|
||||
http://zsnes.bountysource.com/development/
|
||||
|
||||
.SH AUTHORS
|
||||
Please refer to the "About" section of the documentation.
|
||||
|
||||
.SH ZSNES RELATED WEBSITES
|
||||
.TP
|
||||
ZSNES Home Page:
|
||||
http://www.zsnes.com/
|
||||
.TP
|
||||
ZSNES Board:
|
||||
http://board.zsnes.com/
|
||||
.TP
|
||||
ZSNES Project Page:
|
||||
https://zsnes.bountysource.com/
|
||||
.TP
|
||||
ZSNES Repository (SubVersioN):
|
||||
https://svn.bountysource.com/zsnes/trunk/
|
||||
.TP
|
||||
ZSNES Documentation Online:
|
||||
http://zsnes-docs.sf.net/
|
||||
.TP
|
||||
ZSNES IRC:
|
||||
#zsnes on irc.freenode.net
|
||||
.TP
|
||||
ZSNES Docs IRC:
|
||||
#zsnes-docs on irc.freenode.net
|
||||
|
||||
.SH "COPYRIGHT NOTICE"
|
||||
Copyright \(co 1997-2007 ZSNES Team
|
||||
|
||||
Permission is granted to copy and distribute this manual under the terms of the GNU Free Documentation License.
|
||||
9
tools/zsnes/src/linux/zsnes.desktop
Normal file
9
tools/zsnes/src/linux/zsnes.desktop
Normal file
@@ -0,0 +1,9 @@
|
||||
[Desktop Entry]
|
||||
Encoding=UTF-8
|
||||
Name=ZSNES
|
||||
Type=Application
|
||||
Comment=SNES (Super Nintendo) emulator that uses x86 assembly
|
||||
Exec=zsnes
|
||||
Path=
|
||||
Icon=zsnes.png
|
||||
Categories=Application;Game;Emulator;
|
||||
Reference in New Issue
Block a user